static bool ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) { GError *error = NULL; assert(ao != NULL); assert(ao->filter != NULL); if (chunk->tag != NULL) { g_mutex_unlock(ao->mutex); ao_plugin_send_tag(ao->plugin, ao->data, chunk->tag); g_mutex_lock(ao->mutex); } size_t size; const char *data = ao_filter_chunk(ao, chunk, &size); if (data == NULL) { ao_close(ao, false); /* don't automatically reopen this device for 10 seconds */ ao->fail_timer = g_timer_new(); return false; } while (size > 0 && ao->command == AO_COMMAND_NONE) { size_t nbytes; if (!ao_wait(ao)) break; g_mutex_unlock(ao->mutex); nbytes = ao_plugin_play(ao->plugin, ao->data, data, size, &error); g_mutex_lock(ao->mutex); if (nbytes == 0) { /* play()==0 means failure */ g_warning("\"%s\" [%s] failed to play: %s", ao->name, ao->plugin->name, error->message); g_error_free(error); ao_close(ao, false); /* don't automatically reopen this device for 10 seconds */ assert(ao->fail_timer == NULL); ao->fail_timer = g_timer_new(); return false; } assert(nbytes <= size); assert(nbytes % audio_format_frame_size(&ao->out_audio_format) == 0); data += nbytes; size -= nbytes; } return true; }
static bool ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) { const char *data = chunk->data; size_t size = chunk->length; GError *error = NULL; assert(ao != NULL); assert(ao->filter != NULL); assert(!music_chunk_is_empty(chunk)); assert(music_chunk_check_format(chunk, &ao->in_audio_format)); assert(size % audio_format_frame_size(&ao->in_audio_format) == 0); if (chunk->tag != NULL) { g_mutex_unlock(ao->mutex); ao_plugin_send_tag(ao->plugin, ao->data, chunk->tag); g_mutex_lock(ao->mutex); } /* update replay gain */ if (ao->replay_gain_filter != NULL && chunk->replay_gain_serial != ao->replay_gain_serial) { replay_gain_filter_set_info(ao->replay_gain_filter, chunk->replay_gain_serial != 0 ? &chunk->replay_gain_info : NULL); ao->replay_gain_serial = chunk->replay_gain_serial; } if (size == 0) return true; data = filter_filter(ao->filter, data, size, &size, &error); if (data == NULL) { g_warning("\"%s\" [%s] failed to filter: %s", ao->name, ao->plugin->name, error->message); g_error_free(error); ao_close(ao, false); /* don't automatically reopen this device for 10 seconds */ ao->fail_timer = g_timer_new(); return false; } while (size > 0 && ao->command == AO_COMMAND_NONE) { size_t nbytes; g_mutex_unlock(ao->mutex); nbytes = ao_plugin_play(ao->plugin, ao->data, data, size, &error); g_mutex_lock(ao->mutex); if (nbytes == 0) { /* play()==0 means failure */ g_warning("\"%s\" [%s] failed to play: %s", ao->name, ao->plugin->name, error->message); g_error_free(error); ao_close(ao, false); /* don't automatically reopen this device for 10 seconds */ ao->fail_timer = g_timer_new(); return false; } assert(nbytes <= size); assert(nbytes % audio_format_frame_size(&ao->out_audio_format) == 0); data += nbytes; size -= nbytes; } return true; }