static void ao_reopen_filter(struct audio_output *ao) { const struct audio_format *filter_audio_format; GError *error = NULL; ao_filter_close(ao); filter_audio_format = ao_filter_open(ao, &ao->in_audio_format, &error); if (filter_audio_format == NULL) { g_warning("Failed to open filter for \"%s\" [%s]: %s", ao->name, ao->plugin->name, error->message); g_error_free(error); /* this is a little code duplication fro ao_close(), but we cannot call this function because we must not call filter_close(ao->filter) again */ ao->pipe = NULL; ao->chunk = NULL; ao->open = false; ao->fail_timer = g_timer_new(); g_mutex_unlock(ao->mutex); ao_plugin_close(ao->plugin, ao->data); g_mutex_lock(ao->mutex); return; } convert_filter_set(ao->convert_filter, &ao->out_audio_format); }
static void ao_close(struct audio_output *ao, bool drain) { assert(ao->open); ao->pipe = NULL; ao->chunk = NULL; ao->open = false; g_mutex_unlock(ao->mutex); if (drain) ao_plugin_drain(ao->plugin, ao->data); else ao_plugin_cancel(ao->plugin, ao->data); ao_plugin_close(ao->plugin, ao->data); ao_filter_close(ao); g_mutex_lock(ao->mutex); g_debug("closed plugin=%s name=\"%s\"", ao->plugin->name, ao->name); }
int main(int argc, char **argv) { struct audio_output ao; struct audio_format audio_format; struct audio_format_string af_string; bool success; GError *error = NULL; char buffer[4096]; ssize_t nbytes; size_t frame_size, length = 0, play_length, consumed; if (argc < 3 || argc > 4) { g_printerr("Usage: run_output CONFIG NAME [FORMAT] <IN\n"); return 1; } audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); g_thread_init(NULL); /* read configuration file (mpd.conf) */ config_global_init(); success = config_read_file(argv[1], &error); if (!success) { g_printerr("%s:", error->message); g_error_free(error); return 1; } /* initialize the audio output */ if (!load_audio_output(&ao, argv[2])) return 1; /* parse the audio format */ if (argc > 3) { success = audio_format_parse(&audio_format, argv[3], false, &error); if (!success) { g_printerr("Failed to parse audio format: %s\n", error->message); g_error_free(error); return 1; } } /* open the audio output */ success = ao_plugin_open(ao.plugin, ao.data, &audio_format, &error); if (!success) { g_printerr("Failed to open audio output: %s\n", error->message); g_error_free(error); return 1; } g_printerr("audio_format=%s\n", audio_format_to_string(&audio_format, &af_string)); frame_size = audio_format_frame_size(&audio_format); /* play */ while (true) { if (length < sizeof(buffer)) { nbytes = read(0, buffer + length, sizeof(buffer) - length); if (nbytes <= 0) break; length += (size_t)nbytes; } play_length = (length / frame_size) * frame_size; if (play_length > 0) { consumed = ao_plugin_play(ao.plugin, ao.data, buffer, play_length, &error); if (consumed == 0) { g_printerr("Failed to play: %s\n", error->message); g_error_free(error); return 1; } assert(consumed <= length); assert(consumed % frame_size == 0); length -= consumed; memmove(buffer, buffer + consumed, length); } } /* cleanup and exit */ ao_plugin_close(ao.plugin, ao.data); ao_plugin_finish(ao.plugin, ao.data); g_mutex_free(ao.mutex); config_global_finish(); return 0; }