clangen / musikcube

a cross-platform, terminal-based music player, audio engine, metadata indexer, and server in c++
https://musikcube.com
BSD 3-Clause "New" or "Revised" License
4.24k stars 292 forks source link

Pipewire: stream node.name is not set #628

Open bvr-yr opened 1 year ago

bvr-yr commented 1 year ago

musikcubed version: 3.0.1 #d2f83f75 Archlinux AUR build (though tested on -bin and -git packages, the same)

its not harmful by itself, stream is being connected as it should, but some DSP (i.e. Easyeffects) can't catch sink due to node.name being null, though data is bypassed directly to output, pipeline effects are not applied

wpctl inspect: id , type PipeWire:Interface:Node adapt.follower.spa-node = "" audio.adapt.follower = "" * client.id = "90" clock.quantum-limit = "8192" * factory.id = "7" factory.mode = "split" library.name = "audioconvert/libspa-audioconvert" * media.category = "Playback" * media.class = "Stream/Output/Audio" media.name = "musikcube" * media.role = "Music" * media.type = "Audio" node.autoconnect = "true" node.want-driver = "true" object.register = "false" * object.serial = "375" resample.quality = "10" stream.is-live = "true"

while mpv: ... * media.type = "Audio" node.always-process = "true" node.autoconnect = "true" node.description = "mpv" node.name = "mpv" node.rate = "1/48000" node.want-driver = "true" ...

mpd: ... * node.name = "mpd.pipewire" #custom in mpd.conf node.rate = "1/192000" node.want-driver = "true" object.register = "false" ...

seems like smth like that for reference mpv (C):

static int init(struct ao *ao)
{
    struct priv *p = ao->priv;
    uint8_t buffer[1024];
    struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
    const struct spa_pod *params[1];
    struct pw_properties *props = pw_properties_new(
        PW_KEY_MEDIA_TYPE, "Audio",
        PW_KEY_MEDIA_CATEGORY, "Playback",
        PW_KEY_MEDIA_ROLE, ao->init_flags & AO_INIT_MEDIA_ROLE_MUSIC ?  "Music" : "Movie",
        PW_KEY_NODE_NAME, ao->client_name,
        PW_KEY_NODE_DESCRIPTION, ao->client_name,
        PW_KEY_APP_NAME, ao->client_name,
        PW_KEY_APP_ID, ao->client_name,
        PW_KEY_APP_ICON_NAME, ao->client_name,
        PW_KEY_NODE_ALWAYS_PROCESS, "true",
        PW_KEY_TARGET_OBJECT, ao->device,
        NULL
    );

mpd (C++):

void
PipeWireOutput::Open(AudioFormat &audio_format)
{
    error_message.clear();
    disconnected = false;
    restore_volume = true;

    paused = false;

    /* stay inactive (PW_STREAM_FLAG_INACTIVE) until the ring
       buffer has been filled */
    active = false;

    drain_requested = false;
    drained = true;

    auto props = pw_properties_new(PW_KEY_MEDIA_TYPE, "Audio",
                       PW_KEY_MEDIA_CATEGORY, "Playback",
                       PW_KEY_MEDIA_ROLE, "Music",
                       PW_KEY_APP_NAME, "Music Player Daemon",
                       PW_KEY_APP_ICON_NAME, "mpd",
                       nullptr);

    pw_properties_setf(props, PW_KEY_NODE_NAME, "mpd.%s", name);

    if (remote != nullptr && target_id == PW_ID_ANY)
        pw_properties_setf(props, PW_KEY_REMOTE_NAME, "%s", remote);

    if (target != nullptr && target_id == PW_ID_ANY)
        pw_properties_setf(props,
#if PW_CHECK_VERSION(0, 3, 64)
                   PW_KEY_TARGET_OBJECT,
#else
                   PW_KEY_NODE_TARGET,
#endif
                   "%s", target);