Ticket #8693: mythtv-pulseaudio.diff

File mythtv-pulseaudio.diff, 4.8 KB (added by pmhahn+mythtv@…, 16 years ago)

Add support for controlling PulseAudio stream volume.

  • mythtv/libs/libmyth/audiooutputpulse.cpp

    Add support for controlling PulseAudio stream volume.
    
    PulseAudio can controll the individual stream volume in addition to controlling
    the sink volume. Since I use MythTV on my desktop computer, muting and changing
    the sink-volume changes all sounds, including other sounds like desktop events
    and other audio streams.
    This patch adds support to controlling the stream volume by selecting "PCM" for
    the MixerControl. Selecting "Master" uses the old schema of controlling the
    sink volume.
    
    The second part of this patch also sets several properties which help in
    identifying the right stream with PulseAudio enabled applications.
     
    288288        (float)volume / 100.0f * (float)PA_VOLUME_NORM;
    289289    volume = min(100, volume);
    290290    volume = max(0, volume);
    291     uint32_t sink_index = pa_stream_get_device_index(pstream);
    292     pa_threaded_mainloop_lock(mainloop);
    293     pa_operation *op =
    294         pa_context_set_sink_volume_by_index(pcontext, sink_index,
    295                                             &volume_control,
    296                                             OpCompletionCallback, this);
    297     pa_threaded_mainloop_unlock(mainloop);
    298     if (op)
    299         pa_operation_unref(op);
     291
     292    if (gContext->GetSetting("MixerControl", "PCM").toLower() == "pcm")
     293    {
     294        uint32_t stream_index = pa_stream_get_index(pstream);
     295        pa_threaded_mainloop_lock(mainloop);
     296        pa_operation *op =
     297            pa_context_set_sink_input_volume(pcontext, stream_index,
     298                                             &volume_control,
     299                                             OpCompletionCallback, this);
     300        pa_threaded_mainloop_unlock(mainloop);
     301        if (op)
     302            pa_operation_unref(op);
     303        else
     304            VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
     305                    QString("set stream volume operation failed, stream: %1, "
     306                            "error: %2 ")
     307                    .arg(stream_index)
     308                    .arg(pa_strerror(pa_context_errno(pcontext))));
     309    }
    300310    else
    301         VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
    302                 QString("set sink volume operation failed, sink: %1, "
    303                         "error: %2 ")
    304                 .arg(sink_index)
    305                 .arg(pa_strerror(pa_context_errno(pcontext))));
     311    {
     312        uint32_t sink_index = pa_stream_get_device_index(pstream);
     313        pa_threaded_mainloop_lock(mainloop);
     314        pa_operation *op =
     315            pa_context_set_sink_volume_by_index(pcontext, sink_index,
     316                                                &volume_control,
     317                                                OpCompletionCallback, this);
     318        pa_threaded_mainloop_unlock(mainloop);
     319        if (op)
     320            pa_operation_unref(op);
     321        else
     322            VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
     323                    QString("set sink volume operation failed, sink: %1, "
     324                            "error: %2 ")
     325                    .arg(sink_index)
     326                    .arg(pa_strerror(pa_context_errno(pcontext))));
     327    }
    306328}
    307329
    308330void AudioOutputPulseAudio::Pause(bool paused)
     
    417439        pcontext = NULL;
    418440        return false;
    419441    }
    420     pcontext = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "MythTV");
     442    pa_proplist *proplist = pa_proplist_new();
     443    if (!proplist)
     444    {
     445        VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
     446                QString("failed to create new proplist"));
     447        return false;
     448    }
     449    pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "MythTV");
     450    pa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "mythtv");
     451    pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "video");
     452    pcontext = pa_context_new_with_proplist(pa_threaded_mainloop_get_api(mainloop), "MythTV", proplist);
    421453    if (!pcontext)
    422454    {
    423455        VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
     
    533565bool AudioOutputPulseAudio::ConnectPlaybackStream(void)
    534566{
    535567    QString fn_log_tag = "ConnectPlaybackStream, ";
    536     pstream = pa_stream_new(pcontext, "MythTV playback", &sample_spec,
    537                             &channel_map);
     568    pa_proplist *proplist = pa_proplist_new();
     569    if (!proplist)
     570    {
     571        VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +
     572                QString("failed to create new proplist"));
     573        return false;
     574    }
     575    pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "video");
     576    pstream = pa_stream_new_with_proplist(pcontext, "MythTV playback", &sample_spec,
     577                            &channel_map, proplist);
    538578    if (!pstream)
    539579    {
    540580        VERBOSE(VB_IMPORTANT, LOC_ERR + fn_log_tag +