diff options
author | Chris Robinson <[email protected]> | 2010-05-27 22:12:54 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2010-05-27 22:12:54 -0700 |
commit | f89c9f7ea4cf1cb05dedb61355873c51e80fddef (patch) | |
tree | 7ad2addabdc89721bffff48459f7dacd0880a97c /Alc/pulseaudio.c | |
parent | 27a4c871fd9c339de8de36587dec204bc0b3c7c2 (diff) |
Connect a pulse stream on device open, to make sure the device isn't suspended
Also use the opportunity to get the stream's device's name, so later reset
calls will use the same device
Diffstat (limited to 'Alc/pulseaudio.c')
-rw-r--r-- | Alc/pulseaudio.c | 169 |
1 files changed, 98 insertions, 71 deletions
diff --git a/Alc/pulseaudio.c b/Alc/pulseaudio.c index b2c73e7b..9b09fce4 100644 --- a/Alc/pulseaudio.c +++ b/Alc/pulseaudio.c @@ -76,6 +76,8 @@ MAKE_FUNC(pa_stream_connect_record); MAKE_FUNC(pa_stream_connect_playback); MAKE_FUNC(pa_stream_readable_size); MAKE_FUNC(pa_stream_cork); +MAKE_FUNC(pa_stream_is_suspended); +MAKE_FUNC(pa_stream_get_device_name); MAKE_FUNC(pa_path_get_filename); MAKE_FUNC(pa_get_binary_name); MAKE_FUNC(pa_threaded_mainloop_free); @@ -124,6 +126,7 @@ typedef struct { pa_buffer_attr attr; pa_sample_spec spec; + char *device_name; char path_name[PATH_MAX]; const char *context_name; const char *stream_name; @@ -218,6 +221,8 @@ LOAD_FUNC(pa_stream_connect_record); LOAD_FUNC(pa_stream_connect_playback); LOAD_FUNC(pa_stream_readable_size); LOAD_FUNC(pa_stream_cork); +LOAD_FUNC(pa_stream_is_suspended); +LOAD_FUNC(pa_stream_get_device_name); LOAD_FUNC(pa_path_get_filename); LOAD_FUNC(pa_get_binary_name); LOAD_FUNC(pa_threaded_mainloop_free); @@ -349,18 +354,6 @@ static void stream_success_callback(pa_stream *stream, int success, void *pdata) ppa_threaded_mainloop_signal(data->loop, 0); }//}}} -static void server_info_callback(pa_context *context, const pa_server_info *info, void *pdata) //{{{ -{ - struct { - pa_threaded_mainloop *loop; - char *name; - } *data = pdata; - (void)context; - - data->name = strdup(info->default_sink_name); - ppa_threaded_mainloop_signal(data->loop, 0); -}//}}} - static void sink_info_callback(pa_context *context, const pa_sink_info *info, int eol, void *pdata) //{{{ { ALCdevice *device = pdata; @@ -441,6 +434,49 @@ static void stream_write_callback(pa_stream *stream, size_t len, void *pdata) // } //}}} //}}} +static pa_stream *connect_playback_stream(ALCdevice *device, + pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, + pa_channel_map *chanmap) +{ + pulse_data *data = device->ExtraData; + pa_stream_state_t state; + pa_stream *stream; + + stream = ppa_stream_new(data->context, data->stream_name, spec, chanmap); + if(!stream) + { + AL_PRINT("pa_stream_new() failed: %s\n", + ppa_strerror(ppa_context_errno(data->context))); + return NULL; + } + + ppa_stream_set_state_callback(stream, stream_state_callback, device); + + if(ppa_stream_connect_playback(stream, data->device_name, attr, flags, NULL, NULL) < 0) + { + AL_PRINT("Stream did not connect: %s\n", + ppa_strerror(ppa_context_errno(data->context))); + ppa_stream_unref(stream); + return NULL; + } + + while((state=ppa_stream_get_state(stream)) != PA_STREAM_READY) + { + if(!PA_STREAM_IS_GOOD(state)) + { + AL_PRINT("Stream did not get ready: %s\n", + ppa_strerror(ppa_context_errno(data->context))); + ppa_stream_unref(stream); + return NULL; + } + + ppa_threaded_mainloop_wait(data->loop); + } + ppa_stream_set_state_callback(stream, NULL, NULL); + + return stream; +} + static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{{ { pulse_data *data = ppa_xmalloc(sizeof(pulse_data)); @@ -548,6 +584,7 @@ static void pulse_close(ALCdevice *device) //{{{ ppa_threaded_mainloop_free(data->loop); DestroyRingBuffer(data->ring); + free(data->device_name); device->ExtraData = NULL; ppa_xfree(data); @@ -557,6 +594,10 @@ static void pulse_close(ALCdevice *device) //{{{ // OpenAL {{{ static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_name) //{{{ { + pa_sample_spec spec; + pulse_data *data; + ALuint len; + if(!device_name) device_name = pulse_device; else if(strcmp(device_name, pulse_device) != 0) @@ -565,17 +606,52 @@ static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_n if(!pulse_load()) return ALC_FALSE; - if(pulse_open(device, device_name) != ALC_FALSE) + if(pulse_open(device, device_name) == ALC_FALSE) + { + pulse_unload(); + return ALC_FALSE; + } + + data = device->ExtraData; + + ppa_threaded_mainloop_lock(data->loop); + + data->stream_name = "Playback Stream"; + spec.format = PA_SAMPLE_S16NE; + spec.rate = 44100; + spec.channels = 2; + + pa_stream *stream = connect_playback_stream(device, 0, NULL, &spec, NULL); + if(!stream) { - ALuint len = GetConfigValueInt("pulse", "buffer-length", 2048); - if(len != 0) - { - device->UpdateSize = len; - device->NumUpdates = 1; - } - return ALC_TRUE; + ppa_threaded_mainloop_unlock(data->loop); + goto fail; + } + + if(ppa_stream_is_suspended(stream)) + { + ppa_stream_disconnect(stream); + ppa_stream_unref(stream); + ppa_threaded_mainloop_unlock(data->loop); + goto fail; + } + data->device_name = strdup(ppa_stream_get_device_name(stream)); + + ppa_stream_disconnect(stream); + ppa_stream_unref(stream); + + ppa_threaded_mainloop_unlock(data->loop); + + len = GetConfigValueInt("pulse", "buffer-length", 2048); + if(len != 0) + { + device->UpdateSize = len; + device->NumUpdates = 1; } + return ALC_TRUE; +fail: + pulse_close(device); pulse_unload(); return ALC_FALSE; } //}}} @@ -590,7 +666,6 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{ { pulse_data *data = device->ExtraData; pa_stream_flags_t flags = 0; - pa_stream_state_t state; pa_channel_map chanmap; ppa_threaded_mainloop_lock(data->loop); @@ -598,25 +673,10 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{ if(!ConfigValueExists(NULL, "format")) { pa_operation *o; - struct { - pa_threaded_mainloop *loop; - char *name; - } server_data; - server_data.loop = data->loop; - server_data.name = NULL; - - o = ppa_context_get_server_info(data->context, server_info_callback, &server_data); + o = ppa_context_get_sink_info_by_name(data->context, data->device_name, sink_info_callback, device); while(ppa_operation_get_state(o) == PA_OPERATION_RUNNING) ppa_threaded_mainloop_wait(data->loop); ppa_operation_unref(o); - if(server_data.name) - { - o = ppa_context_get_sink_info_by_name(data->context, server_data.name, sink_info_callback, device); - while(ppa_operation_get_state(o) == PA_OPERATION_RUNNING) - ppa_threaded_mainloop_wait(data->loop); - ppa_operation_unref(o); - free(server_data.name); - } } if(!ConfigValueExists(NULL, "frequency")) flags |= PA_STREAM_FIX_RATE; @@ -664,46 +724,13 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{ } SetDefaultWFXChannelOrder(device); - data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, &chanmap); + data->stream = connect_playback_stream(device, flags, &data->attr, &data->spec, &chanmap); if(!data->stream) { - AL_PRINT("pa_stream_new() failed: %s\n", - ppa_strerror(ppa_context_errno(data->context))); - - ppa_threaded_mainloop_unlock(data->loop); - return ALC_FALSE; - } - - ppa_stream_set_state_callback(data->stream, stream_state_callback, device); - - if(ppa_stream_connect_playback(data->stream, NULL, &data->attr, flags, NULL, NULL) < 0) - { - AL_PRINT("Stream did not connect: %s\n", - ppa_strerror(ppa_context_errno(data->context))); - - ppa_stream_unref(data->stream); - data->stream = NULL; - ppa_threaded_mainloop_unlock(data->loop); return ALC_FALSE; } - while((state=ppa_stream_get_state(data->stream)) != PA_STREAM_READY) - { - if(!PA_STREAM_IS_GOOD(state)) - { - AL_PRINT("Stream did not get ready: %s\n", - ppa_strerror(ppa_context_errno(data->context))); - - ppa_stream_unref(data->stream); - data->stream = NULL; - - ppa_threaded_mainloop_unlock(data->loop); - return ALC_FALSE; - } - - ppa_threaded_mainloop_wait(data->loop); - } ppa_stream_set_state_callback(data->stream, stream_state_callback2, device); data->spec = *(ppa_stream_get_sample_spec(data->stream)); |