int pa_simple_flush(pa_simple *p, int *rerror) { pa_operation *o = NULL; pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); pa_threaded_mainloop_lock(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); o = pa_stream_flush(p->stream, success_cb, p); CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail); p->operation_success = 0; while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail); pa_operation_unref(o); pa_threaded_mainloop_unlock(p->mainloop); return 0; unlock_and_fail: if (o) { pa_operation_cancel(o); pa_operation_unref(o); } pa_threaded_mainloop_unlock(p->mainloop); return -1; }
static void pulse_drain(void) { pa_operation *o = NULL; int success = 0; CHECK_CONNECTED(); pa_threaded_mainloop_lock(mainloop); CHECK_DEAD_GOTO(fail, 0); if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) { AUDDBG("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } if (!success) AUDDBG("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context))); fail: if (o) pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); }
int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) { pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1); CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1); CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1); pa_threaded_mainloop_lock(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); while (length > 0) { size_t l; while (!p->read_data) { int r; r = pa_stream_peek(p->stream, &p->read_data, &p->read_length); CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail); if (p->read_length <= 0) { pa_threaded_mainloop_wait(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } else if (!p->read_data) { /* There's a hole in the stream, skip it. We could generate * silence, but that wouldn't work for compressed streams. */ r = pa_stream_drop(p->stream); CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail); } else p->read_index = 0; } l = p->read_length < length ? p->read_length : length; memcpy(data, (const uint8_t*) p->read_data+p->read_index, l); data = (uint8_t*) data + l; length -= l; p->read_index += l; p->read_length -= l; if (!p->read_length) { int r; r = pa_stream_drop(p->stream); p->read_data = NULL; p->read_length = 0; p->read_index = 0; CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail); } } pa_threaded_mainloop_unlock(p->mainloop); return 0; unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); return -1; }
static void pulse_flush(int time) { pa_operation *o = NULL; int success = 0; CHECK_CONNECTED(); pa_threaded_mainloop_lock(mainloop); CHECK_DEAD_GOTO(fail, 1); written = time * (int64_t) bytes_per_second / 1000; flush_time = time; if (!(o = pa_stream_flush(stream, stream_success_cb, &success))) { AUDDBG("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } if (!success) AUDDBG("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context))); fail: if (o) pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); }
int pa_simple_cork(pa_simple *p, int cork, int *rerror) { pa_operation *o = NULL; pa_assert(p); pa_threaded_mainloop_lock(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); o = pa_stream_cork(p->stream, cork, success_context_cb, p); CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail); p->operation_success = 0; while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail); pa_operation_unref(o); pa_threaded_mainloop_unlock(p->mainloop); return 0; unlock_and_fail: if (o) { pa_operation_cancel(o); pa_operation_unref(o); } pa_threaded_mainloop_unlock(p->mainloop); return -1; }
static int pulse_free(void) { ENTER(__FUNCTION__); size_t l = 0; pa_operation *o = NULL; CHECK_CONNECTED(0); SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop_lock"); pa_threaded_mainloop_lock(mainloop); CHECK_DEAD_GOTO(fail, 1); if ((l = pa_stream_writable_size(stream)) == (size_t) -1) { SHOW("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context))); l = 0; goto fail; } SHOW("pulse_free: %s (ret=%d)\n", "pa_stream_writable_size", l); /* If this function is called twice with no pulse_write() call in * between this means we should trigger the playback */ if (do_trigger) { int success = 0; SHOW("pulse_free: %s (call)\n", "pa_stream_trigger"); if (!(o = pa_stream_trigger(stream, stream_success_cb, &success))) { SHOW("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop"); while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } SHOW("pulse_free: %s (ret)\n", "pa_threaded_main_loop"); if (!success) SHOW("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); } fail: SHOW("pulse_free: %s (call)\n", "pa_operation_unref"); if (o) pa_operation_unref(o); SHOW("pulse_free: %s (call)\n", "pa_threaded_main_loop_unlock"); pa_threaded_mainloop_unlock(mainloop); do_trigger = !!l; SHOW("pulse_free: %d (ret)\n", (int)l); return (int) l; }
static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror) { paaudio *g = p->g; pa_threaded_mainloop_lock (g->mainloop); CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); while (length > 0) { size_t l; while (!p->read_data) { int r; r = pa_stream_peek (p->stream, &p->read_data, &p->read_length); CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail); if (!p->read_data) { pa_threaded_mainloop_wait (g->mainloop); CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); } else { p->read_index = 0; } } l = p->read_length < length ? p->read_length : length; memcpy (data, (const uint8_t *) p->read_data+p->read_index, l); data = (uint8_t *) data + l; length -= l; p->read_index += l; p->read_length -= l; if (!p->read_length) { int r; r = pa_stream_drop (p->stream); p->read_data = NULL; p->read_length = 0; p->read_index = 0; CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail); } } pa_threaded_mainloop_unlock (g->mainloop); return 0; unlock_and_fail: pa_threaded_mainloop_unlock (g->mainloop); return -1; }
int pa_simple_set_volume(pa_simple *p, int volume, int *rerror) { pa_operation *o = NULL; pa_stream *s = NULL; uint32_t idx; pa_cvolume cv; pa_volume_t v; pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); CHECK_VALIDITY_RETURN_ANY(rerror, volume >= 0, PA_ERR_INVALID, -1); CHECK_VALIDITY_RETURN_ANY(rerror, volume <= 65535, PA_ERR_INVALID, -1); pa_threaded_mainloop_lock(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); CHECK_SUCCESS_GOTO(p, rerror, ((idx = pa_stream_get_index (p->stream)) != PA_INVALID_INDEX), unlock_and_fail); s = p->stream; pa_assert(s); pa_cvolume_set(&cv, s->sample_spec.channels, volume); o = pa_context_set_sink_input_volume (p->context, idx, &cv, success_context_cb, p); CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail); p->operation_success = 0; while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail); pa_operation_unref(o); pa_threaded_mainloop_unlock(p->mainloop); return 0; unlock_and_fail: if (o) { pa_operation_cancel(o); pa_operation_unref(o); } pa_threaded_mainloop_unlock(p->mainloop); return -1; }
/***************************************************************************** * Close: close the audio device *****************************************************************************/ static void Close ( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; msg_Dbg(p_aout, "Pulse Close"); if(p_sys->stream){ pa_operation *o; pa_threaded_mainloop_lock(p_sys->mainloop); pa_stream_set_write_callback(p_sys->stream, NULL, NULL); if((o = pa_stream_drain(p_sys->stream, success_cb, p_aout))){ while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail); pa_threaded_mainloop_wait(p_sys->mainloop); } fail: pa_operation_unref(o); } pa_threaded_mainloop_unlock(p_sys->mainloop); } uninit(p_aout); }
pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) { pa_usec_t t; int negative; pa_assert(p); pa_threaded_mainloop_lock(p->mainloop); for (;;) { CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); if (pa_stream_get_latency(p->stream, &t, &negative) >= 0) break; CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail); /* Wait until latency data is available again */ pa_threaded_mainloop_wait(p->mainloop); } pa_threaded_mainloop_unlock(p->mainloop); return negative ? 0 : t; unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); return (pa_usec_t) -1; }
static void pulse_write(void* ptr, int length) { int writeoffs, remain, writable; CHECK_CONNECTED(); pa_threaded_mainloop_lock(mainloop); CHECK_DEAD_GOTO(fail, 1); /* break large fragments into smaller fragments. --nenolod */ for (writeoffs = 0, remain = length; writeoffs < length; writeoffs += writable, remain -= writable) { void * pptr = (char *) ptr + writeoffs; writable = length - writeoffs; size_t fragsize = pa_stream_writable_size(stream); /* don't write more than what PA is willing to handle right now. */ if (writable > fragsize) writable = fragsize; if (pa_stream_write(stream, pptr, writable, NULL, PA_SEEK_RELATIVE, 0) < 0) { AUDDBG("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } } do_trigger = 0; written += length; fail: pa_threaded_mainloop_unlock(mainloop); }
static void pulse_set_volume(int l, int r) { if (! connected) return; pa_threaded_mainloop_lock (mainloop); CHECK_DEAD_GOTO (fail, 1); /* sanitize output volumes. */ l = CLAMP(l, 0, 100); r = CLAMP(r, 0, 100); if (!volume_valid || volume.channels != 1) { volume.values[0] = ((pa_volume_t) l * PA_VOLUME_NORM + 50) / 100; volume.values[1] = ((pa_volume_t) r * PA_VOLUME_NORM + 50) / 100; volume.channels = 2; } else { volume.values[0] = ((pa_volume_t) MAX (l, r) * PA_VOLUME_NORM + 50) / 100; volume.channels = 1; } volume_valid = 1; if (connected && !volume_time_event) { struct timeval tv; pa_mainloop_api *api = pa_threaded_mainloop_get_api(mainloop); volume_time_event = api->time_new(api, pa_timeval_add(pa_gettimeofday(&tv), 100000), volume_time_cb, NULL); } fail: if (connected) pa_threaded_mainloop_unlock(mainloop); }
static int pulse_free(void) { size_t l = 0; pa_operation *o = NULL; CHECK_CONNECTED(0); pa_threaded_mainloop_lock(mainloop); CHECK_DEAD_GOTO(fail, 1); if ((l = pa_stream_writable_size(stream)) == (size_t) -1) { AUDDBG("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context))); l = 0; goto fail; } /* If this function is called twice with no pulse_write() call in * between this means we should trigger the playback */ if (do_trigger) { int success = 0; if (!(o = pa_stream_trigger(stream, stream_success_cb, &success))) { AUDDBG("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } if (!success) AUDDBG("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context))); } fail: if (o) pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); do_trigger = !!l; return (int) l; }
static int drain(void) { pa_operation *o = NULL; int success = 0; int ret = PULSE_ERROR; ENTER(__FUNCTION__); CHECK_CONNECTED(ret); pa_threaded_mainloop_lock(mainloop); CHECK_DEAD_GOTO(fail, 0); SHOW_TIME("pa_stream_drain (call)"); if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) { SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } SHOW_TIME("pa_threaded_mainloop_wait (call)"); while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } SHOW_TIME("pa_threaded_mainloop_wait (ret)"); if (!success) { SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context))); } else { ret = PULSE_OK; } fail: SHOW_TIME("pa_operation_unref (call)"); if (o) pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); SHOW_TIME("drain (ret)"); return ret; }
int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) { pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1); CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1); CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1); pa_threaded_mainloop_lock(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); while (length > 0) { size_t l; int r; while (!(l = pa_stream_writable_size(p->stream))) { pa_threaded_mainloop_wait(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); } CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail); if (l > length) l = length; r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail); data = (const uint8_t*) data + l; length -= l; } pa_threaded_mainloop_unlock(p->mainloop); return 0; unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); return -1; }
static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror) { paaudio *g = p->g; pa_threaded_mainloop_lock (g->mainloop); CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); while (length > 0) { size_t l; int r; while (!(l = pa_stream_writable_size (p->stream))) { pa_threaded_mainloop_wait (g->mainloop); CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); } CHECK_SUCCESS_GOTO (g, rerror, l != (size_t) -1, unlock_and_fail); if (l > length) { l = length; } r = pa_stream_write (p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); CHECK_SUCCESS_GOTO (g, rerror, r >= 0, unlock_and_fail); data = (const uint8_t *) data + l; length -= l; } pa_threaded_mainloop_unlock (g->mainloop); return 0; unlock_and_fail: pa_threaded_mainloop_unlock (g->mainloop); return -1; }
int pa_simple_get_stream_index(pa_simple *p, unsigned int *idx, int *rerror) { pa_assert(p); CHECK_VALIDITY_RETURN_ANY(rerror, idx != NULL, PA_ERR_INVALID, -1); pa_threaded_mainloop_lock(p->mainloop); CHECK_DEAD_GOTO(p, rerror, unlock_and_fail); *idx = pa_stream_get_index(p->stream); pa_threaded_mainloop_unlock(p->mainloop); return 0; unlock_and_fail: pa_threaded_mainloop_unlock(p->mainloop); return -1; }
static void pulse_get_volume (int * l, int * r) { * l = * r = 0; if (! connected || ! volume_valid) return; pa_threaded_mainloop_lock (mainloop); CHECK_DEAD_GOTO (fail, 1); if (volume.channels == 2) { * l = (volume.values[0] * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM; * r = (volume.values[1] * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM; } else * l = * r = (pa_cvolume_avg (& volume) * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM; fail: pa_threaded_mainloop_unlock (mainloop); }
static void pulse_write(void* ptr, int length) { ENTER(__FUNCTION__); SHOW("pulse_write > length=%d\n", length); CHECK_CONNECTED_NO_RETVAL(); pa_threaded_mainloop_lock(mainloop); CHECK_DEAD_GOTO(fail, 1); if (pa_stream_write(stream, ptr, length, NULL, PA_SEEK_RELATIVE, (pa_seek_mode_t)0) < 0) { SHOW("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } do_trigger = 0; written += length; fail: pa_threaded_mainloop_unlock(mainloop); }
static int pulse_playing(const pa_timing_info *the_timing_info) { ENTER(__FUNCTION__); int r = 0; const pa_timing_info *i; assert(the_timing_info); CHECK_CONNECTED(0); pa_threaded_mainloop_lock(mainloop); for (;;) { CHECK_DEAD_GOTO(fail, 1); if ((i = pa_stream_get_timing_info(stream))) { break; } if (pa_context_errno(context) != PA_ERR_NODATA) { SHOW("pa_stream_get_timing_info() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } pa_threaded_mainloop_wait(mainloop); } r = i->playing; memcpy((void*)the_timing_info, (void*)i, sizeof(pa_timing_info)); // display_timing_info(i); fail: pa_threaded_mainloop_unlock(mainloop); return r; }
static int pulse_open() { ENTER(__FUNCTION__); pa_sample_spec ss; pa_operation *o = NULL; int success; int ret = PULSE_ERROR; assert(!mainloop); assert(!context); assert(!stream); assert(!connected); pthread_mutex_init( &pulse_mutex, (const pthread_mutexattr_t *)NULL); ss.format = ESPEAK_FORMAT; ss.rate = wave_samplerate; ss.channels = ESPEAK_CHANNEL; if (!pa_sample_spec_valid(&ss)) return false; SHOW_TIME("pa_threaded_mainloop_new (call)"); if (!(mainloop = pa_threaded_mainloop_new())) { SHOW("Failed to allocate main loop\n",""); goto fail; } pa_threaded_mainloop_lock(mainloop); SHOW_TIME("pa_context_new (call)"); if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "eSpeak"))) { SHOW("Failed to allocate context\n",""); goto unlock_and_fail; } pa_context_set_state_callback(context, context_state_cb, NULL); pa_context_set_subscribe_callback(context, subscribe_cb, NULL); SHOW_TIME("pa_context_connect (call)"); if (pa_context_connect(context, NULL, (pa_context_flags_t)0, NULL) < 0) { SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); ret = PULSE_NO_CONNECTION; goto unlock_and_fail; } SHOW_TIME("pa_threaded_mainloop_start (call)"); if (pa_threaded_mainloop_start(mainloop) < 0) { SHOW("Failed to start main loop",""); goto unlock_and_fail; } /* Wait until the context is ready */ SHOW_TIME("pa_threaded_mainloop_wait"); pa_threaded_mainloop_wait(mainloop); if (pa_context_get_state(context) != PA_CONTEXT_READY) { SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); ret = PULSE_NO_CONNECTION; if (mainloop) pa_threaded_mainloop_stop(mainloop); goto unlock_and_fail; } SHOW_TIME("pa_stream_new"); if (!(stream = pa_stream_new(context, "unknown", &ss, NULL))) { SHOW("Failed to create stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } pa_stream_set_state_callback(stream, stream_state_cb, NULL); pa_stream_set_write_callback(stream, stream_request_cb, NULL); pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL); pa_buffer_attr a_attr; a_attr.maxlength = MAXLENGTH; a_attr.tlength = TLENGTH; a_attr.prebuf = PREBUF; a_attr.minreq = MINREQ; a_attr.fragsize = 0; SHOW_TIME("pa_connect_playback"); if (pa_stream_connect_playback(stream, NULL, &a_attr, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL) < 0) { SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } /* Wait until the stream is ready */ SHOW_TIME("pa_threaded_mainloop_wait"); pa_threaded_mainloop_wait(mainloop); if (pa_stream_get_state(stream) != PA_STREAM_READY) { SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } /* Now subscribe to events */ SHOW_TIME("pa_context_subscribe"); if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } success = 0; SHOW_TIME("pa_threaded_mainloop_wait"); while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } pa_operation_unref(o); if (!success) { SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } do_trigger = 0; written = 0; time_offset_msec = 0; just_flushed = 0; connected = 1; pa_threaded_mainloop_unlock(mainloop); SHOW_TIME("pulse_open (ret true)"); return PULSE_OK; unlock_and_fail: if (o) pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); fail: // pulse_close(); if (ret == PULSE_NO_CONNECTION) { if (context) { SHOW_TIME("pa_context_disconnect (call)"); pa_context_disconnect(context); pa_context_unref(context); context = NULL; } if (mainloop) { SHOW_TIME("pa_threaded_mainloop_free (call)"); pa_threaded_mainloop_free(mainloop); mainloop = NULL; } } else { pulse_close(); } SHOW_TIME("pulse_open (ret false)"); return ret; }
static gboolean gst_pulsemixer_ctrl_open (GstPulseMixerCtrl * c) { int e; gchar *name = gst_pulse_client_name (); pa_operation *o = NULL; g_assert (c); c->mainloop = pa_threaded_mainloop_new (); g_assert (c->mainloop); e = pa_threaded_mainloop_start (c->mainloop); g_assert (e == 0); pa_threaded_mainloop_lock (c->mainloop); if (!(c->context = pa_context_new (pa_threaded_mainloop_get_api (c->mainloop), name))) { GST_WARNING_OBJECT (c->object, "Failed to create context"); goto unlock_and_fail; } pa_context_set_state_callback (c->context, gst_pulsemixer_ctrl_context_state_cb, c); pa_context_set_subscribe_callback (c->context, gst_pulsemixer_ctrl_subscribe_cb, c); if (pa_context_connect (c->context, c->server, 0, NULL) < 0) { GST_WARNING_OBJECT (c->object, "Failed to connect context: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } /* Wait until the context is ready */ pa_threaded_mainloop_wait (c->mainloop); if (pa_context_get_state (c->context) != PA_CONTEXT_READY) { GST_WARNING_OBJECT (c->object, "Failed to connect context: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } /* Subscribe to events */ if (!(o = pa_context_subscribe (c->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, gst_pulsemixer_ctrl_success_cb, c))) { GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } c->operation_success = 0; while (pa_operation_get_state (o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait (c->mainloop); CHECK_DEAD_GOTO (c, unlock_and_fail); } if (!c->operation_success) { GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } pa_operation_unref (o); o = NULL; /* Get sink info */ if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SINK) { if (!(o = pa_context_get_sink_info_by_name (c->context, c->device, gst_pulsemixer_ctrl_sink_info_cb, c))) { GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } c->operation_success = 0; while (pa_operation_get_state (o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait (c->mainloop); CHECK_DEAD_GOTO (c, unlock_and_fail); } pa_operation_unref (o); o = NULL; if (!c->operation_success && (c->type == GST_PULSEMIXER_SINK || pa_context_errno (c->context) != PA_ERR_NOENTITY)) { GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } } if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SOURCE) { if (!(o = pa_context_get_source_info_by_name (c->context, c->device, gst_pulsemixer_ctrl_source_info_cb, c))) { GST_WARNING_OBJECT (c->object, "Failed to get source info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } c->operation_success = 0; while (pa_operation_get_state (o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait (c->mainloop); CHECK_DEAD_GOTO (c, unlock_and_fail); } pa_operation_unref (o); o = NULL; if (!c->operation_success) { GST_WARNING_OBJECT (c->object, "Failed to get source info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } } g_assert (c->type != GST_PULSEMIXER_UNKNOWN); c->track = gst_pulsemixer_track_new (c); c->tracklist = g_list_append (c->tracklist, c->track); pa_threaded_mainloop_unlock (c->mainloop); g_free (name); return TRUE; unlock_and_fail: if (o) pa_operation_unref (o); if (c->mainloop) pa_threaded_mainloop_unlock (c->mainloop); g_free (name); return FALSE; }
static int pulse_open(int fmt, int rate, int nch) { pa_sample_spec ss; pa_operation *o = NULL; int success; assert(!mainloop); assert(!context); assert(!stream); assert(!connected); switch(fmt) { case FMT_U8: ss.format = PA_SAMPLE_U8; break; case FMT_S16_LE: ss.format = PA_SAMPLE_S16LE; break; case FMT_S16_BE: ss.format = PA_SAMPLE_S16BE; break; #ifdef PA_SAMPLE_S24_32LE case FMT_S24_LE: ss.format = PA_SAMPLE_S24_32LE; break; case FMT_S24_BE: ss.format = PA_SAMPLE_S24_32BE; break; #endif #ifdef PA_SAMPLE_S32LE case FMT_S32_LE: ss.format = PA_SAMPLE_S32LE; break; case FMT_S32_BE: ss.format = PA_SAMPLE_S32BE; break; #endif case FMT_FLOAT: ss.format = PA_SAMPLE_FLOAT32NE; break; default: return FALSE; } ss.rate = rate; ss.channels = nch; if (!pa_sample_spec_valid(&ss)) return FALSE; if (!(mainloop = pa_threaded_mainloop_new())) { ERROR ("Failed to allocate main loop"); goto fail; } pa_threaded_mainloop_lock(mainloop); if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Audacious"))) { ERROR ("Failed to allocate context"); goto unlock_and_fail; } pa_context_set_state_callback(context, context_state_cb, NULL); pa_context_set_subscribe_callback(context, subscribe_cb, NULL); if (pa_context_connect(context, NULL, 0, NULL) < 0) { ERROR ("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } if (pa_threaded_mainloop_start(mainloop) < 0) { ERROR ("Failed to start main loop"); goto unlock_and_fail; } /* Wait until the context is ready */ pa_threaded_mainloop_wait(mainloop); if (pa_context_get_state(context) != PA_CONTEXT_READY) { ERROR ("Failed to connect to server: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } if (!(stream = pa_stream_new(context, "Audacious", &ss, NULL))) { ERROR ("Failed to create stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } pa_stream_set_state_callback(stream, stream_state_cb, NULL); pa_stream_set_write_callback(stream, stream_request_cb, NULL); pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL); /* Connect stream with sink and default volume */ /* Buffer struct */ int aud_buffer = aud_get_int(NULL, "output_buffer_size"); size_t buffer_size = pa_usec_to_bytes(aud_buffer, &ss) * 1000; pa_buffer_attr buffer = {(uint32_t) -1, buffer_size, (uint32_t) -1, (uint32_t) -1, buffer_size}; if (pa_stream_connect_playback(stream, NULL, &buffer, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { ERROR ("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } /* Wait until the stream is ready */ pa_threaded_mainloop_wait(mainloop); if (pa_stream_get_state(stream) != PA_STREAM_READY) { ERROR ("Failed to connect stream: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } /* Now subscribe to events */ if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) { ERROR ("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } success = 0; while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } if (!success) { ERROR ("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } pa_operation_unref(o); /* Now request the initial stream info */ if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, NULL))) { ERROR ("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } while (pa_operation_get_state(o) != PA_OPERATION_DONE) { CHECK_DEAD_GOTO(fail, 1); pa_threaded_mainloop_wait(mainloop); } if (!volume_valid) { ERROR ("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); goto unlock_and_fail; } pa_operation_unref(o); do_trigger = 0; written = 0; flush_time = 0; bytes_per_second = FMT_SIZEOF (fmt) * nch * rate; connected = 1; volume_time_event = NULL; pa_threaded_mainloop_unlock(mainloop); return TRUE; unlock_and_fail: if (o) pa_operation_unref(o); pa_threaded_mainloop_unlock(mainloop); fail: pulse_close(); return FALSE; }