Merge branch 'v0.17.x'

This commit is contained in:
Max Kellermann
2012-08-14 23:58:54 +02:00
14 changed files with 278 additions and 139 deletions

View File

@@ -53,6 +53,31 @@ httpd_output_quark(void)
return g_quark_from_static_string("httpd_output");
}
/**
* Check whether there is at least one client.
*
* Caller must lock the mutex.
*/
G_GNUC_PURE
static bool
httpd_output_has_clients(const struct httpd_output *httpd)
{
return httpd->clients != NULL;
}
/**
* Check whether there is at least one client.
*/
G_GNUC_PURE
static bool
httpd_output_lock_has_clients(const struct httpd_output *httpd)
{
g_mutex_lock(httpd->mutex);
bool result = httpd_output_has_clients(httpd);
g_mutex_unlock(httpd->mutex);
return result;
}
static void
httpd_listen_in_event(int fd, const struct sockaddr *address,
size_t address_length, int uid, void *ctx);
@@ -397,6 +422,19 @@ httpd_output_delay(struct audio_output *ao)
{
struct httpd_output *httpd = (struct httpd_output *)ao;
if (!httpd_output_lock_has_clients(httpd) && httpd->base.pause) {
/* if there's no client and this output is paused,
then httpd_output_pause() will not do anything, it
will not fill the buffer and it will not update the
timer; therefore, we reset the timer here */
timer_reset(httpd->timer);
/* some arbitrary delay that is long enough to avoid
consuming too much CPU, and short enough to notice
new clients quickly enough */
return 1000;
}
return httpd->timer->started
? timer_delay(httpd->timer)
: 0;
@@ -475,13 +513,8 @@ httpd_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
{
struct httpd_output *httpd = (struct httpd_output *)ao;
bool has_clients;
g_mutex_lock(httpd->mutex);
has_clients = httpd->clients != NULL;
g_mutex_unlock(httpd->mutex);
if (has_clients) {
if (httpd_output_lock_has_clients(httpd)) {
bool success;
success = httpd_output_encode_and_play(httpd, chunk, size,
@@ -502,16 +535,11 @@ httpd_output_pause(struct audio_output *ao)
{
struct httpd_output *httpd = (struct httpd_output *)ao;
g_mutex_lock(httpd->mutex);
bool has_clients = httpd->clients != NULL;
g_mutex_unlock(httpd->mutex);
if (has_clients) {
if (httpd_output_lock_has_clients(httpd)) {
static const char silence[1020];
return httpd_output_play(ao, silence, sizeof(silence),
NULL) > 0;
} else {
g_usleep(100000);
return true;
}
}

View File

@@ -608,6 +608,16 @@ mpd_jack_close(G_GNUC_UNUSED struct audio_output *ao)
mpd_jack_stop(jd);
}
static unsigned
mpd_jack_delay(struct audio_output *ao)
{
struct jack_data *jd = (struct jack_data *)ao;
return jd->base.pause && jd->pause && !jd->shutdown
? 1000
: 0;
}
static inline jack_default_audio_sample_t
sample_16_to_jack(int16_t sample)
{
@@ -727,10 +737,6 @@ mpd_jack_pause(struct audio_output *ao)
jd->pause = true;
/* due to a MPD API limitation, we have to sleep a little bit
here, to avoid hogging the CPU */
g_usleep(50000);
return true;
}
@@ -742,6 +748,7 @@ const struct audio_output_plugin jack_output_plugin = {
.enable = mpd_jack_enable,
.disable = mpd_jack_disable,
.open = mpd_jack_open,
.delay = mpd_jack_delay,
.play = mpd_jack_play,
.pause = mpd_jack_pause,
.close = mpd_jack_close,

View File

@@ -681,35 +681,6 @@ pulse_output_close(struct audio_output *ao)
pa_threaded_mainloop_unlock(po->mainloop);
}
/**
* Check if the stream is (already) connected, and waits for a signal
* if not. The mainloop must be locked before calling this function.
*
* @return the current stream state
*/
static pa_stream_state_t
pulse_output_check_stream(struct pulse_output *po)
{
pa_stream_state_t state = pa_stream_get_state(po->stream);
assert(po->mainloop != NULL);
switch (state) {
case PA_STREAM_READY:
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
case PA_STREAM_UNCONNECTED:
break;
case PA_STREAM_CREATING:
pa_threaded_mainloop_wait(po->mainloop);
state = pa_stream_get_state(po->stream);
break;
}
return state;
}
/**
* Check if the stream is (already) connected, and waits if not. The
* mainloop must be locked before calling this function.
@@ -719,35 +690,25 @@ pulse_output_check_stream(struct pulse_output *po)
static bool
pulse_output_wait_stream(struct pulse_output *po, GError **error_r)
{
pa_stream_state_t state = pa_stream_get_state(po->stream);
while (true) {
switch (pa_stream_get_state(po->stream)) {
case PA_STREAM_READY:
return true;
switch (state) {
case PA_STREAM_READY:
return true;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
case PA_STREAM_UNCONNECTED:
g_set_error(error_r, pulse_output_quark(),
pa_context_errno(po->context),
"failed to connect the stream: %s",
pa_strerror(pa_context_errno(po->context)));
return false;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
case PA_STREAM_UNCONNECTED:
g_set_error(error_r, pulse_output_quark(), 0,
"disconnected");
return false;
case PA_STREAM_CREATING:
break;
case PA_STREAM_CREATING:
pa_threaded_mainloop_wait(po->mainloop);
break;
}
}
do {
state = pulse_output_check_stream(po);
} while (state == PA_STREAM_CREATING);
if (state != PA_STREAM_READY) {
g_set_error(error_r, pulse_output_quark(), 0,
"failed to connect the stream: %s",
pa_strerror(pa_context_errno(po->context)));
return false;
}
return true;
}
/**
@@ -801,6 +762,24 @@ pulse_output_stream_pause(struct pulse_output *po, bool pause,
return true;
}
static unsigned
pulse_output_delay(struct audio_output *ao)
{
struct pulse_output *po = (struct pulse_output *)ao;
unsigned result = 0;
pa_threaded_mainloop_lock(po->mainloop);
if (po->base.pause && pulse_output_stream_is_paused(po) &&
pa_stream_get_state(po->stream) == PA_STREAM_READY)
/* idle while paused */
result = 1000;
pa_threaded_mainloop_unlock(po->mainloop);
return result;
}
static size_t
pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r)
@@ -928,13 +907,8 @@ pulse_output_pause(struct audio_output *ao)
/* cork the stream */
if (pulse_output_stream_is_paused(po)) {
/* already paused; due to a MPD API limitation, we
have to sleep a little bit here, to avoid hogging
the CPU */
g_usleep(50000);
} else if (!pulse_output_stream_pause(po, true, &error)) {
if (!pulse_output_stream_is_paused(po) &&
!pulse_output_stream_pause(po, true, &error)) {
pa_threaded_mainloop_unlock(po->mainloop);
g_warning("%s", error->message);
g_error_free(error);
@@ -971,6 +945,7 @@ const struct audio_output_plugin pulse_output_plugin = {
.enable = pulse_output_enable,
.disable = pulse_output_disable,
.open = pulse_output_open,
.delay = pulse_output_delay,
.play = pulse_output_play,
.cancel = pulse_output_cancel,
.pause = pulse_output_pause,