diff options
author | Max Kellermann <max@duempel.org> | 2009-03-10 15:46:55 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2009-03-10 15:46:55 +0100 |
commit | 79ef9166df2cf1c431e2bbbd4e19de3de7773324 (patch) | |
tree | 63ef1db845fcf34efd408c95568444d3ae7eda90 | |
parent | 296c1bb3b696b0e57d2d70aedb85cdecd231a787 (diff) | |
download | mpd-79ef9166df2cf1c431e2bbbd4e19de3de7773324.tar.gz mpd-79ef9166df2cf1c431e2bbbd4e19de3de7773324.tar.xz mpd-79ef9166df2cf1c431e2bbbd4e19de3de7773324.zip |
test: added program "run_output"
The "run_output" program can be used to test an audio output plugin in
an isolated environment.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 16 | ||||
-rw-r--r-- | test/run_output.c | 174 |
3 files changed, 191 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index 43aaf5bbb..22a1986e2 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ test/software_volume test/run_decoder test/read_tags test/run_encoder +test/run_output diff --git a/Makefile.am b/Makefile.am index b6d95030d..d406220eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -531,6 +531,7 @@ noinst_PROGRAMS = \ test/run_decoder \ test/read_tags \ test/run_encoder \ + test/run_output \ test/software_volume test_run_decoder_CPPFLAGS = $(AM_CPPFLAGS) \ @@ -575,6 +576,21 @@ test_software_volume_SOURCES = test/software_volume.c \ src/audio_parser.c \ src/pcm_volume.c +test_run_output_CPPFLAGS = $(AM_CPPFLAGS) \ + $(ENCODER_CFLAGS) \ + $(OUTPUT_CFLAGS) +test_run_output_LDADD = $(MPD_LIBS) \ + $(ENCODER_LIBS) \ + $(OUTPUT_LIBS) +test_run_output_SOURCES = test/run_output.c \ + src/conf.c src/buffer2array.c src/utils.c src/log.c \ + src/audio_parser.c \ + src/timer.c \ + src/output_init.c src/output_list.c \ + $(ENCODER_SRC) \ + $(MIXER_SRC) \ + $(OUTPUT_SRC) + if HAVE_ID3TAG test_run_decoder_SOURCES += src/tag_id3.c src/riff.c src/aiff.c test_read_tags_SOURCES += src/tag_id3.c src/riff.c src/aiff.c diff --git a/test/run_output.c b/test/run_output.c new file mode 100644 index 000000000..f14cfb8e5 --- /dev/null +++ b/test/run_output.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "output_plugin.h" +#include "output_internal.h" +#include "output_control.h" +#include "conf.h" +#include "audio_parser.h" + +#include <glib.h> + +#include <assert.h> +#include <string.h> +#include <unistd.h> + +void pcm_convert_init(G_GNUC_UNUSED struct pcm_convert_state *state) +{ +} + +void notify_init(G_GNUC_UNUSED struct notify *notify) +{ +} + +static const struct config_param * +find_named_config_block(const char *block, const char *name) +{ + const struct config_param *param = NULL; + + while ((param = config_get_next_param(block, param)) != NULL) { + const char *current_name = + config_get_block_string(param, "name", NULL); + if (current_name != NULL && strcmp(current_name, name) == 0) + return param; + } + + return NULL; +} + +static bool +load_audio_output(struct audio_output *ao, const char *name) +{ + const struct config_param *param; + bool success; + GError *error = NULL; + + param = find_named_config_block(CONF_AUDIO_OUTPUT, name); + if (param == NULL) { + g_printerr("No such configured audio output: %s\n", name); + return false; + } + + success = audio_output_init(ao, param, &error); + if (!success) { + g_printerr("%s\n", error->message); + g_error_free(error); + } + + return success; +} + +int main(int argc, char **argv) +{ + struct audio_output ao; + struct audio_format audio_format = { + .sample_rate = 44100, + .bits = 16, + .channels = 2, + }; + 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; + } + + g_thread_init(NULL); + + /* read configuration file (mpd.conf) */ + + config_global_init(); + config_read_file(argv[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], &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=%u:%u:%u\n", audio_format.sample_rate, + audio_format.bits, audio_format.channels); + + 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; +} |