Search code examples
csdl-2pulseaudiopipewire

Change name of Application in Pipewire/Pulseaudio


I am currently trying to build a very simple Audio-Tool, which needs to change its name in pavucontrol and qjackctl on runtime. When an Application produces Audio, its name is shown in pavucontrol. E.g. if I use firefox it is shown as "Firefox". I tried the most commonly suggested solutions: Editing argv and using prctl both did not succeed.

I also searched the pipewire documentation but I didn't find anything useful (but maybe I am just blind).

Is it even possible? From where does pipewire get the name of the Application?

Here is a little test-script in C with SDL2:

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <SDL2/SDL.h>

Uint8* audio_buffer = NULL;
Uint32 audio_length = 0;

void audio_callback(void* userdata, Uint8* stream, int n) {
    memset(stream, 0, n);
}

int main(int argc, char** argv) {

    SDL_Event evt;
    SDL_AudioSpec desired;

    SDL_Init(SDL_INIT_AUDIO|SDL_INIT_EVENTS);

    SDL_LoadWAV("suil.wav", &desired, &audio_buffer, &audio_length);
    desired.callback = audio_callback;

    SDL_OpenAudio(&desired, NULL);
    SDL_PauseAudio(0);


    while (1) {
        while (SDL_PollEvent(&evt)) {
            switch (evt.type) {
                case SDL_QUIT:
                    exit(EXIT_SUCCESS);
            }
        }
    }
}

And a picture of what I would like to have changed on runtime:

enter image description here

(Note: The "test" would be the name in question.)

Disclaimer: I'm not sure if this would maybe sdl-2 specific, so I added the SDL tag.


Solution

  • SDL's Pipewire backend grabs the application name in this block:

    /* Get the hints for the application name, stream name and role */
    app_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME);
    if (!app_name || *app_name == '\0') {
        app_name = SDL_GetHint(SDL_HINT_APP_NAME);
        if (!app_name || *app_name == '\0') {
            app_name = "SDL Application";
        }
    }
    

    ...via the hint system:

    • SDL_HINT_APP_NAME:

      /**
       *  \brief Specify an application name.
       * 
       * This hint lets you specify the application name sent to the OS when
       * required. For example, this will often appear in volume control applets for
       * audio streams, and in lists of applications which are inhibiting the
       * screensaver.  You should use a string that describes your program ("My Game
       * 2: The Revenge")
       *
       * Setting this to "" or leaving it unset will have SDL use a reasonable
       * default: probably the application's name or "SDL Application" if SDL
       * doesn't have any better information.
       *
       * Note that, for audio streams, this can be overridden with
       * SDL_HINT_AUDIO_DEVICE_APP_NAME.
       *
       * On targets where this is not supported, this hint does nothing.
       */
      #define SDL_HINT_APP_NAME "SDL_APP_NAME"
      
    • SDL_HINT_AUDIO_DEVICE_APP_NAME:

      /**
       *  \brief Specify an application name for an audio device.
       *
       * Some audio backends (such as PulseAudio) allow you to describe your audio
       * stream. Among other things, this description might show up in a system
       * control panel that lets the user adjust the volume on specific audio
       * streams instead of using one giant master volume slider.
       *
       * This hints lets you transmit that information to the OS. The contents of
       * this hint are used while opening an audio device. You should use a string
       * that describes your program ("My Game 2: The Revenge")
       *
       * Setting this to "" or leaving it unset will have SDL use a reasonable
       * default: this will be the name set with SDL_HINT_APP_NAME, if that hint is
       * set. Otherwise, it'll probably the application's name or "SDL Application"
       * if SDL doesn't have any better information.
       *
       * On targets where this is not supported, this hint does nothing.
       */
      #define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME"
      

    ...and then passes the app name into Pipewire using PW_KEY_APP_NAME, here:

    PIPEWIRE_pw_properties_set(props, PW_KEY_APP_NAME, app_name);
    

    ...where SDL's PIPEWIRE_pw_properties_set() is just a pointer to Pipewire's pw_properties_set().