valapulseaudiomeson-build

Cannot create an array of SinkInputInfo


I cannot make an array of SinkInputInfo objects. I've posted this to the appropriate repo but got no response.

Minimal reproduction:

using PulseAudio;

public void main () {
    SinkInputInfo[] sink_inputs;
}

Outputs

/tmp/test.vala.PFQW80.c: In function ‘_vala_pa_sink_input_info_array_free’:
/tmp/test.vala.PFQW80.c:18:4: warning: implicit declaration of function ‘pulse_audio_sink_input_info_destroy’ [-Wimplicit-function-declaration]
   18 |    pulse_audio_sink_input_info_destroy (&array[i]);
      |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/ld: /tmp/ccZQGm6J.o: in function `_vala_pa_sink_input_info_array_free':
test.vala.PFQW80.c:(.text+0x3f): undefined reference to `pulse_audio_sink_input_info_destroy'
collect2: error: ld returned 1 exit status
error: cc exited with status 256

Solution

  • You can not create an instance of SinkInputInfo. You can also not store instances of it anywhere.

    The reason is that it is intended to be only valid inside the callbacks:

    https://www.freedesktop.org/software/pulseaudio/doxygen/introspect.html#query_sec

    Data members in the information structures are only valid during the duration of the callback. If they are required after the callback is finished, a deep copy of the information structure must be performed.

    libpulse does not provide any means to copy or free the SinkInputInfo pointer type.

    You can however use anything inside the struct:

    Gee.ArrayList<string> sink_inputs;
    
    public void cb(PulseAudio.Context c, PulseAudio.SinkInputInfo? i, int eol) {
            sink_inputs.add(i.name);
    }
    
    public void main () {
        var loop = new PulseAudio.MainLoop();
        var context = new PulseAudio.Context(loop.get_api(), null);
        sink_inputs = new Gee.ArrayList<string>();
        context.get_sink_input_info_list(cb);
    }
    

    Here I only store the name property. You could extend this by creating your own data type in vala and copying over anything you are interested in.

    Also the vapi file is incomplete, there are ways to tell the Vala compiler that copying and memory management is not available. See https://wiki.gnome.org/Projects/Vala/ManualBindings#Structs

    I haven't done any Vala code in a while, but I think the vapi file should set the destroy_function to an empty string.

    In summary: Do not try to store the SinkInputInfo argument of the callback anywhere, just copy the fields of the struct you are interested in.