From: Lennart P. <mz...@0p...> - 2008-04-04 00:58:17
|
# HG changeset patch # User Lennart Poettering <mz...@0p...> # Date 1207269340 -3600 # Node ID fe893c26369269df01e40445e5e92b6e83962a13 # Parent 7c68c1957abb124d7882e011e086d6e83c1338a9 Updated PulseAudio driver (fixup) The problem was basically that detection if PA was available happened in open() instead of open_plugin(). diff -r fe893c26369269df01e40445e5e92b6e83962a13 -r 7c68c1957abb124d7882e011e086d6e83c1338a9 src/audio_out/audio_pulse_out.c --- a/src/audio_out/audio_pulse_out.c Fri Apr 04 01:35:40 2008 +0100 +++ b/src/audio_out/audio_pulse_out.c Fri Apr 04 00:42:57 2008 +0100 @@ -51,9 +51,6 @@ typedef struct { typedef struct { audio_driver_class_t driver_class; xine_t *xine; - - struct pa_context *context; /*< Pulseaudio connection context */ - struct pa_threaded_mainloop *mainloop; /*< Main event loop object */ } pulse_class_t; typedef struct pulse_driver_s { @@ -64,7 +61,10 @@ typedef struct pulse_driver_s { char *host; /*< The host to connect to */ char *sink; /*< The sink to connect to */ - struct pa_stream *stream; /*< Pulseaudio playback stream object */ + + pa_threaded_mainloop *mainloop; /*< Main event loop object */ + pa_context *context; /*< Pulseaudio connection context */ + pa_stream *stream; /*< Pulseaudio playback stream object */ pa_volume_t swvolume; int muted; @@ -88,7 +88,7 @@ typedef struct pulse_driver_s { */ static void __xine_pa_context_state_callback(pa_context *c, void *this_gen) { - pulse_class_t * this = (pulse_class_t*) this_gen; + pulse_driver_t * this = (pulse_driver_t*) this_gen; switch (pa_context_get_state(c)) { @@ -121,7 +121,7 @@ static void __xine_pa_stream_state_callb case PA_STREAM_READY: case PA_STREAM_TERMINATED: case PA_STREAM_FAILED: - pa_threaded_mainloop_signal(this->pa_class->mainloop, 0); + pa_threaded_mainloop_signal(this->mainloop, 0); break; case PA_STREAM_UNCONNECTED: @@ -141,7 +141,7 @@ static void __xine_pa_stream_request_cal { pulse_driver_t * this = (pulse_driver_t*) this_gen; - pa_threaded_mainloop_signal(this->pa_class->mainloop, 0); + pa_threaded_mainloop_signal(this->mainloop, 0); } /** @@ -154,7 +154,7 @@ static void __xine_pa_stream_notify_call { pulse_driver_t * this = (pulse_driver_t*) this_gen; - pa_threaded_mainloop_signal(this->pa_class->mainloop, 0); + pa_threaded_mainloop_signal(this->mainloop, 0); } /** @@ -169,9 +169,9 @@ static void __xine_pa_stream_success_cal pulse_driver_t * this = (pulse_driver_t*) this_gen; if (!success) - xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: stream operation failed: %s\n", pa_strerror(pa_context_errno(this->pa_class->context))); - - pa_threaded_mainloop_signal(this->pa_class->mainloop, 0); + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: stream operation failed: %s\n", pa_strerror(pa_context_errno(this->context))); + + pa_threaded_mainloop_signal(this->mainloop, 0); } /** @@ -183,7 +183,7 @@ static void __xine_pa_stream_success_cal */ static void __xine_pa_context_success_callback(pa_context *c, int success, void *this_gen) { - pulse_class_t *this = (pulse_class_t*) this_gen; + pulse_driver_t *this = (pulse_driver_t*) this_gen; if (!success) xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: context operation failed: %s\n", pa_strerror(pa_context_errno(this->context))); @@ -209,7 +209,7 @@ static void __xine_pa_sink_info_callback if (is_last < 0) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to get sink input info: %s\n", - pa_strerror(pa_context_errno(this->pa_class->context))); + pa_strerror(pa_context_errno(this->context))); return; } @@ -221,6 +221,53 @@ static void __xine_pa_sink_info_callback this->muted = info->mute; } +static int connect_context(pulse_driver_t *this) { + + if (this->context && (pa_context_get_state(this->context) == PA_CONTEXT_FAILED || + pa_context_get_state(this->context) == PA_CONTEXT_TERMINATED)) { + pa_context_unref(this->context); + this->context = NULL; + } + + if (!this->context) { + char fn[PATH_MAX], *p; + + if (pa_get_binary_name(fn, sizeof(fn))) + p = pa_path_get_filename(fn); + else + p = "Xine"; + + this->context = pa_context_new(pa_threaded_mainloop_get_api(this->mainloop), p); + _x_assert(this->context); + + pa_context_set_state_callback(this->context, __xine_pa_context_state_callback, this); + } + + if (pa_context_get_state(this->context) == PA_CONTEXT_UNCONNECTED) { + + if (pa_context_connect(this->context, this->host, 0, NULL) < 0) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object %s\n", pa_strerror(pa_context_errno(this->context))); + return -1; + } + } + + for (;;) { + pa_context_state_t state = pa_context_get_state(this->context); [... 347 lines omitted ...] @@ -660,13 +681,13 @@ static int ao_pulse_ctrl(ao_driver_t *th pulse_driver_t *this = (pulse_driver_t *) this_gen; pa_operation *o = NULL; - pa_threaded_mainloop_lock(this->pa_class->mainloop); + pa_threaded_mainloop_lock(this->mainloop); if (!this->stream || - !this->pa_class->context || - pa_context_get_state(this->pa_class->context) != PA_CONTEXT_READY || + !this->context || + pa_context_get_state(this->context) != PA_CONTEXT_READY || pa_stream_get_state(this->stream) != PA_STREAM_READY) { - pa_threaded_mainloop_unlock(this->pa_class->mainloop); + pa_threaded_mainloop_unlock(this->mainloop); return 0; } @@ -689,7 +710,7 @@ static int ao_pulse_ctrl(ao_driver_t *th pa_operation_unref(o); } - pa_threaded_mainloop_unlock(this->pa_class->mainloop); + pa_threaded_mainloop_unlock(this->mainloop); return 0; } @@ -697,7 +718,8 @@ static ao_driver_t *open_plugin (audio_d static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) { pulse_class_t *class = (pulse_class_t *) class_gen; pulse_driver_t *this; - char *device; + const char* device; + int r; lprintf ("audio_pulse_out: open_plugin called\n"); @@ -708,15 +730,17 @@ static ao_driver_t *open_plugin (audio_d this->xine = class->xine; this->host = NULL; this->sink = NULL; - - device = this->xine->config->register_string(this->xine->config, - "audio.pulseaudio_device", - "", - _("device used for pulseaudio"), - _("use 'server[:sink]' for setting the " - "pulseaudio sink device."), - 10, NULL, - NULL); + this->context = NULL; + this->mainloop = NULL; + + device = class->xine->config->register_string(class->xine->config, + "audio.pulseaudio_device", + "", + _("device used for pulseaudio"), + _("use 'server[:sink]' for setting the " + "pulseaudio sink device."), + 10, NULL, + NULL); if (device && *device) { char *sep = strrchr(device, ':'); @@ -739,6 +763,10 @@ static ao_driver_t *open_plugin (audio_d } } } + + this->mainloop = pa_threaded_mainloop_new(); + _x_assert(this->mainloop); + pa_threaded_mainloop_start(this->mainloop); /* * set capabilities @@ -769,6 +797,15 @@ static ao_driver_t *open_plugin (audio_d this->pa_class = class; + pa_threaded_mainloop_lock(this->mainloop); + r = connect_context(this); + pa_threaded_mainloop_unlock(this->mainloop); + + if (r < 0) { + ao_pulse_exit((ao_driver_t *) this); + return NULL; + } + return &this->ao_driver; } @@ -788,16 +825,7 @@ static void dispose_class (audio_driver_ pulse_class_t *this = (pulse_class_t *) this_gen; - pa_threaded_mainloop_stop(this->mainloop); - - if (this->context) { - pa_context_disconnect(this->context); - pa_context_unref(this->context); - } - - pa_threaded_mainloop_free(this->mainloop); - - free (this); + free(this); } static void *init_class (xine_t *xine, void *data) { @@ -810,17 +838,11 @@ static void *init_class (xine_t *xine, v if (!this) return NULL; + this->xine = xine; this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; this->driver_class.get_description = get_description; this->driver_class.dispose = dispose_class; - - this->xine = xine; - this->context = NULL; - - this->mainloop = pa_threaded_mainloop_new(); - _x_assert(this->mainloop); - pa_threaded_mainloop_start(this->mainloop); return this; } |