diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/dump_playlist.c | 130 | ||||
-rw-r--r-- | test/dump_text_file.c | 170 | ||||
-rw-r--r-- | test/read_conf.c | 2 | ||||
-rw-r--r-- | test/read_mixer.c | 53 | ||||
-rw-r--r-- | test/read_tags.c | 88 | ||||
-rw-r--r-- | test/run_convert.c | 10 | ||||
-rw-r--r-- | test/run_decoder.c | 26 | ||||
-rw-r--r-- | test/run_encoder.c | 4 | ||||
-rw-r--r-- | test/run_filter.c | 4 | ||||
-rw-r--r-- | test/run_inotify.c | 2 | ||||
-rw-r--r-- | test/run_input.c | 49 | ||||
-rw-r--r-- | test/run_normalize.c | 2 | ||||
-rw-r--r-- | test/run_ntp_server.c | 71 | ||||
-rw-r--r-- | test/run_output.c | 156 | ||||
-rw-r--r-- | test/run_resolver.c | 66 | ||||
-rw-r--r-- | test/run_tcp_connect.c | 164 | ||||
-rw-r--r-- | test/signals.c | 62 | ||||
-rw-r--r-- | test/signals.h | 29 | ||||
-rw-r--r-- | test/software_volume.c | 4 | ||||
-rw-r--r-- | test/stdbin.h | 2 | ||||
-rw-r--r-- | test/test_byte_reverse.c | 83 | ||||
-rw-r--r-- | test/test_glib_compat.h | 60 | ||||
-rw-r--r-- | test/test_pcm_all.h | 41 | ||||
-rw-r--r-- | test/test_pcm_channels.c | 102 | ||||
-rw-r--r-- | test/test_pcm_dither.c | 80 | ||||
-rw-r--r-- | test/test_pcm_main.c | 37 | ||||
-rw-r--r-- | test/test_pcm_pack.c | 90 | ||||
-rw-r--r-- | test/test_queue_priority.c | 175 | ||||
-rw-r--r-- | test/test_vorbis_encoder.c | 2 |
29 files changed, 1618 insertions, 146 deletions
diff --git a/test/dump_playlist.c b/test/dump_playlist.c index a8cb4d750..0570f6e49 100644 --- a/test/dump_playlist.c +++ b/test/dump_playlist.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,18 +18,22 @@ */ #include "config.h" +#include "io_thread.h" #include "input_init.h" #include "input_stream.h" #include "tag_pool.h" #include "tag_save.h" #include "conf.h" #include "song.h" +#include "decoder_api.h" +#include "decoder_list.h" #include "playlist_list.h" #include "playlist_plugin.h" #include <glib.h> #include <unistd.h> +#include <stdlib.h> static void my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, @@ -41,6 +45,95 @@ my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, g_printerr("%s\n", message); } +void +decoder_initialized(G_GNUC_UNUSED struct decoder *decoder, + G_GNUC_UNUSED const struct audio_format *audio_format, + G_GNUC_UNUSED bool seekable, + G_GNUC_UNUSED float total_time) +{ +} + +enum decoder_command +decoder_get_command(G_GNUC_UNUSED struct decoder *decoder) +{ + return DECODE_COMMAND_NONE; +} + +void +decoder_command_finished(G_GNUC_UNUSED struct decoder *decoder) +{ +} + +double +decoder_seek_where(G_GNUC_UNUSED struct decoder *decoder) +{ + return 1.0; +} + +void +decoder_seek_error(G_GNUC_UNUSED struct decoder *decoder) +{ +} + +size_t +decoder_read(G_GNUC_UNUSED struct decoder *decoder, + struct input_stream *is, + void *buffer, size_t length) +{ + return input_stream_lock_read(is, buffer, length, NULL); +} + +void +decoder_timestamp(G_GNUC_UNUSED struct decoder *decoder, + G_GNUC_UNUSED double t) +{ +} + +enum decoder_command +decoder_data(G_GNUC_UNUSED struct decoder *decoder, + G_GNUC_UNUSED struct input_stream *is, + const void *data, size_t datalen, + G_GNUC_UNUSED uint16_t kbit_rate) +{ + G_GNUC_UNUSED ssize_t nbytes = write(1, data, datalen); + return DECODE_COMMAND_NONE; +} + +enum decoder_command +decoder_tag(G_GNUC_UNUSED struct decoder *decoder, + G_GNUC_UNUSED struct input_stream *is, + G_GNUC_UNUSED const struct tag *tag) +{ + return DECODE_COMMAND_NONE; +} + +float +decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, + const struct replay_gain_info *replay_gain_info) +{ + const struct replay_gain_tuple *tuple = + &replay_gain_info->tuples[REPLAY_GAIN_ALBUM]; + if (replay_gain_tuple_defined(tuple)) + g_printerr("replay_gain[album]: gain=%f peak=%f\n", + tuple->gain, tuple->peak); + + tuple = &replay_gain_info->tuples[REPLAY_GAIN_TRACK]; + if (replay_gain_tuple_defined(tuple)) + g_printerr("replay_gain[track]: gain=%f peak=%f\n", + tuple->gain, tuple->peak); + + return 0.0; +} + +void +decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, + G_GNUC_UNUSED float replay_gain_db, + char *mixramp_start, char *mixramp_end) +{ + g_free(mixramp_start); + g_free(mixramp_end); +} + int main(int argc, char **argv) { const char *uri; @@ -73,6 +166,13 @@ int main(int argc, char **argv) return 1; } + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + if (!input_stream_global_init(&error)) { g_warning("%s", error->message); g_error_free(error); @@ -80,14 +180,18 @@ int main(int argc, char **argv) } playlist_list_global_init(); + decoder_plugin_init_all(); /* open the playlist */ - playlist = playlist_list_open_uri(uri); + GMutex *mutex = g_mutex_new(); + GCond *cond = g_cond_new(); + + playlist = playlist_list_open_uri(uri, mutex, cond); if (playlist == NULL) { /* open the stream and wait until it becomes ready */ - is = input_stream_open(uri, &error); + is = input_stream_open(uri, mutex, cond, &error); if (is == NULL) { if (error != NULL) { g_warning("%s", error->message); @@ -97,19 +201,7 @@ int main(int argc, char **argv) return 2; } - while (!is->ready) { - int ret = input_stream_buffer(is, &error); - if (ret < 0) { - /* error */ - g_warning("%s", error->message); - g_error_free(error); - return 2; - } - - if (ret == 0) - /* nothing was buffered - wait */ - g_usleep(10000); - } + input_stream_lock_wait_ready(is); /* open the playlist */ @@ -148,8 +240,14 @@ int main(int argc, char **argv) playlist_plugin_close(playlist); if (is != NULL) input_stream_close(is); + + g_cond_free(cond); + g_mutex_free(mutex); + + decoder_plugin_deinit_all(); playlist_list_global_finish(); input_stream_global_finish(); + io_thread_deinit(); config_global_finish(); tag_pool_deinit(); diff --git a/test/dump_text_file.c b/test/dump_text_file.c new file mode 100644 index 000000000..f14371441 --- /dev/null +++ b/test/dump_text_file.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "io_thread.h" +#include "input_init.h" +#include "input_stream.h" +#include "text_input_stream.h" +#include "tag_pool.h" +#include "conf.h" +#include "stdbin.h" + +#ifdef ENABLE_ARCHIVE +#include "archive_list.h" +#endif + +#include <glib.h> + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +static void +my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, + const gchar *message, G_GNUC_UNUSED gpointer user_data) +{ + if (log_domain != NULL) + g_printerr("%s: %s\n", log_domain, message); + else + g_printerr("%s\n", message); +} + +static void +dump_text_file(struct text_input_stream *is) +{ + const char *line; + while ((line = text_input_stream_read(is)) != NULL) + printf("'%s'\n", line); +} + +static int +dump_input_stream(struct input_stream *is) +{ + GError *error = NULL; + + input_stream_lock(is); + + /* wait until the stream becomes ready */ + + input_stream_wait_ready(is); + + if (!input_stream_check(is, &error)) { + g_warning("%s", error->message); + g_error_free(error); + input_stream_unlock(is); + return EXIT_FAILURE; + } + + /* read data and tags from the stream */ + + input_stream_unlock(is); + + struct text_input_stream *tis = text_input_stream_new(is); + dump_text_file(tis); + text_input_stream_free(tis); + + input_stream_lock(is); + + if (!input_stream_check(is, &error)) { + g_warning("%s", error->message); + g_error_free(error); + input_stream_unlock(is); + return EXIT_FAILURE; + } + + input_stream_unlock(is); + + return 0; +} + +int main(int argc, char **argv) +{ + GError *error = NULL; + struct input_stream *is; + int ret; + + if (argc != 2) { + g_printerr("Usage: run_input URI\n"); + return 1; + } + + /* initialize GLib */ + + g_thread_init(NULL); + g_log_set_default_handler(my_log_func, NULL); + + /* initialize MPD */ + + tag_pool_init(); + config_global_init(); + + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + +#ifdef ENABLE_ARCHIVE + archive_plugin_init_all(); +#endif + + if (!input_stream_global_init(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return 2; + } + + /* open the stream and dump it */ + + GMutex *mutex = g_mutex_new(); + GCond *cond = g_cond_new(); + + is = input_stream_open(argv[1], mutex, cond, &error); + if (is != NULL) { + ret = dump_input_stream(is); + input_stream_close(is); + } else { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } else + g_printerr("input_stream_open() failed\n"); + ret = 2; + } + + g_cond_free(cond); + g_mutex_free(mutex); + + /* deinitialize everything */ + + input_stream_global_finish(); + +#ifdef ENABLE_ARCHIVE + archive_plugin_deinit_all(); +#endif + + io_thread_deinit(); + + config_global_finish(); + tag_pool_deinit(); + + return ret; +} diff --git a/test/read_conf.c b/test/read_conf.c index f1b38cafe..4f6005c6f 100644 --- a/test/read_conf.c +++ b/test/read_conf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/test/read_mixer.c b/test/read_mixer.c index 1b5b093a3..0a0719460 100644 --- a/test/read_mixer.c +++ b/test/read_mixer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -34,6 +34,16 @@ #include "output/pulse_output_plugin.h" void +pulse_output_lock(G_GNUC_UNUSED struct pulse_output *po) +{ +} + +void +pulse_output_unlock(G_GNUC_UNUSED struct pulse_output *po) +{ +} + +void pulse_output_set_mixer(G_GNUC_UNUSED struct pulse_output *po, G_GNUC_UNUSED struct pulse_mixer *pm) { @@ -55,6 +65,43 @@ pulse_output_set_volume(G_GNUC_UNUSED struct pulse_output *po, #endif +#ifdef HAVE_ROAR +#include "output/roar_output_plugin.h" + +int +roar_output_get_volume(G_GNUC_UNUSED struct roar *roar) +{ + return -1; +} + +bool +roar_output_set_volume(G_GNUC_UNUSED struct roar *roar, + G_GNUC_UNUSED unsigned volume) +{ + return true; +} + +#endif + +#ifdef ENABLE_RAOP_OUTPUT +#include "output/raop_output_plugin.h" + +bool +raop_set_volume(G_GNUC_UNUSED struct raop_data *rd, + G_GNUC_UNUSED unsigned volume, + G_GNUC_UNUSED GError **error_r) +{ + return false; +} + +int +raop_get_volume(G_GNUC_UNUSED struct raop_data *rd) +{ + return -1; +} + +#endif + void event_pipe_emit(G_GNUC_UNUSED enum pipe_event event) { @@ -68,8 +115,8 @@ filter_plugin_by_name(G_GNUC_UNUSED const char *name) } bool -pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED int length, - G_GNUC_UNUSED const struct audio_format *format, +pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED size_t length, + G_GNUC_UNUSED enum sample_format format, G_GNUC_UNUSED int volume) { assert(false); diff --git a/test/read_tags.c b/test/read_tags.c index 8906e1c8a..faf9a45c0 100644 --- a/test/read_tags.c +++ b/test/read_tags.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,21 +18,23 @@ */ #include "config.h" +#include "io_thread.h" #include "decoder_list.h" #include "decoder_api.h" #include "input_init.h" #include "input_stream.h" #include "audio_format.h" #include "pcm_volume.h" -#include "tag_pool.h" #include "tag_ape.h" #include "tag_id3.h" +#include "tag_handler.h" #include "idle.h" #include <glib.h> #include <assert.h> #include <unistd.h> +#include <stdlib.h> #ifdef HAVE_LOCALE_H #include <locale.h> @@ -50,8 +52,8 @@ idle_add(G_GNUC_UNUSED unsigned flags) * No-op dummy. */ bool -pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED int length, - G_GNUC_UNUSED const struct audio_format *format, +pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED size_t length, + G_GNUC_UNUSED enum sample_format format, G_GNUC_UNUSED int volume) { return true; @@ -89,7 +91,7 @@ decoder_read(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is, void *buffer, size_t length) { - return input_stream_read(is, buffer, length, NULL); + return input_stream_lock_read(is, buffer, length, NULL); } void @@ -132,25 +134,38 @@ decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, g_free(mixramp_end); } +static bool empty = true; + +static void +print_duration(unsigned seconds, G_GNUC_UNUSED void *ctx) +{ + g_print("duration=%d\n", seconds); +} + static void -print_tag(const struct tag *tag) +print_tag(enum tag_type type, const char *value, G_GNUC_UNUSED void *ctx) { - if (tag->time >= 0) - g_print("time=%d\n", tag->time); + g_print("[%s]=%s\n", tag_item_names[type], value); + empty = false; +} - for (unsigned i = 0; i < tag->num_items; ++i) - g_print("%s=%s\n", - tag_item_names[tag->items[i]->type], - tag->items[i]->value); +static void +print_pair(const char *name, const char *value, G_GNUC_UNUSED void *ctx) +{ + g_print("\"%s\"=%s\n", name, value); } +static const struct tag_handler print_handler = { + .duration = print_duration, + .tag = print_tag, + .pair = print_pair, +}; + int main(int argc, char **argv) { GError *error = NULL; const char *decoder_name, *path; const struct decoder_plugin *plugin; - struct tag *tag; - bool empty; #ifdef HAVE_LOCALE_H /* initialize locale */ @@ -166,7 +181,12 @@ int main(int argc, char **argv) path = argv[2]; g_thread_init(NULL); - tag_pool_init(); + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } if (!input_stream_global_init(&error)) { g_warning("%s", error->message); @@ -182,9 +202,14 @@ int main(int argc, char **argv) return 1; } - tag = decoder_plugin_tag_dup(plugin, path); - if (tag == NULL && plugin->stream_tag != NULL) { - struct input_stream *is = input_stream_open(path, &error); + bool success = decoder_plugin_scan_file(plugin, path, + &print_handler, NULL); + if (!success && plugin->scan_stream != NULL) { + GMutex *mutex = g_mutex_new(); + GCond *cond = g_cond_new(); + + struct input_stream *is = + input_stream_open(path, mutex, cond, &error); if (is == NULL) { g_printerr("Failed to open %s: %s\n", @@ -193,33 +218,28 @@ int main(int argc, char **argv) return 1; } - tag = decoder_plugin_stream_tag(plugin, is); + success = decoder_plugin_scan_stream(plugin, is, + &print_handler, NULL); input_stream_close(is); + + g_cond_free(cond); + g_mutex_free(mutex); } decoder_plugin_deinit_all(); input_stream_global_finish(); - if (tag == NULL) { + io_thread_deinit(); + + if (!success) { g_printerr("Failed to read tags\n"); return 1; } - print_tag(tag); - - empty = tag_is_empty(tag); - tag_free(tag); - if (empty) { - tag = tag_ape_load(path); - if (tag == NULL) - tag = tag_id3_load(path); - if (tag != NULL) { - print_tag(tag); - tag_free(tag); - } + tag_ape_scan2(path, &print_handler, NULL); + if (empty) + tag_id3_scan(path, &print_handler, NULL); } - tag_pool_deinit(); - return 0; } diff --git a/test/run_convert.c b/test/run_convert.c index ae76bc367..4f57400fd 100644 --- a/test/run_convert.c +++ b/test/run_convert.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -76,13 +76,17 @@ int main(int argc, char **argv) return 1; } - if (!audio_format_parse(&out_audio_format, argv[2], - false, &error)) { + struct audio_format out_audio_format_mask; + if (!audio_format_parse(&out_audio_format_mask, argv[2], + true, &error)) { g_printerr("Failed to parse audio format: %s\n", error->message); return 1; } + out_audio_format = in_audio_format; + audio_format_mask_apply(&out_audio_format, &out_audio_format_mask); + const size_t in_frame_size = audio_format_frame_size(&in_audio_format); pcm_convert_init(&state); diff --git a/test/run_decoder.c b/test/run_decoder.c index 154b47324..e6712c75b 100644 --- a/test/run_decoder.c +++ b/test/run_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,6 +18,7 @@ */ #include "config.h" +#include "io_thread.h" #include "decoder_list.h" #include "decoder_api.h" #include "tag_pool.h" @@ -32,6 +33,7 @@ #include <assert.h> #include <unistd.h> +#include <stdlib.h> static void my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, @@ -55,8 +57,8 @@ idle_add(G_GNUC_UNUSED unsigned flags) * No-op dummy. */ bool -pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED int length, - G_GNUC_UNUSED const struct audio_format *format, +pcm_volume(G_GNUC_UNUSED void *buffer, G_GNUC_UNUSED size_t length, + G_GNUC_UNUSED enum sample_format format, G_GNUC_UNUSED int volume) { return true; @@ -111,7 +113,7 @@ decoder_read(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is, void *buffer, size_t length) { - return input_stream_read(is, buffer, length, NULL); + return input_stream_lock_read(is, buffer, length, NULL); } void @@ -182,6 +184,13 @@ int main(int argc, char **argv) g_thread_init(NULL); g_log_set_default_handler(my_log_func, NULL); + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + tag_pool_init(); if (!input_stream_global_init(&error)) { @@ -204,8 +213,11 @@ int main(int argc, char **argv) decoder_plugin_file_decode(decoder.plugin, &decoder, decoder.uri); } else if (decoder.plugin->stream_decode != NULL) { + GMutex *mutex = g_mutex_new(); + GCond *cond = g_cond_new(); + struct input_stream *is = - input_stream_open(decoder.uri, &error); + input_stream_open(decoder.uri, mutex, cond, &error); if (is == NULL) { if (error != NULL) { g_warning("%s", error->message); @@ -219,6 +231,9 @@ int main(int argc, char **argv) decoder_plugin_stream_decode(decoder.plugin, &decoder, is); input_stream_close(is); + + g_cond_free(cond); + g_mutex_free(mutex); } else { g_printerr("Decoder plugin is not usable\n"); return 1; @@ -226,6 +241,7 @@ int main(int argc, char **argv) decoder_plugin_deinit_all(); input_stream_global_finish(); + io_thread_deinit(); if (!decoder.initialized) { g_printerr("Decoding failed\n"); diff --git a/test/run_encoder.c b/test/run_encoder.c index 4c05a06c7..6a4108620 100644 --- a/test/run_encoder.c +++ b/test/run_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -76,7 +76,7 @@ int main(int argc, char **argv) } param = config_new_param(NULL, -1); - config_add_block_param(param, "quality", "5.0", -1, NULL); + config_add_block_param(param, "quality", "5.0", -1); encoder = encoder_init(plugin, param, &error); if (encoder == NULL) { diff --git a/test/run_filter.c b/test/run_filter.c index 3758eb5bb..8e793b768 100644 --- a/test/run_filter.c +++ b/test/run_filter.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -183,7 +183,7 @@ int main(int argc, char **argv) nbytes = write(1, dest, length); if (nbytes < 0) { - g_printerr("Failed to write: %s\n", strerror(errno)); + g_printerr("Failed to write: %s\n", g_strerror(errno)); filter_close(filter); filter_free(filter); return 1; diff --git a/test/run_inotify.c b/test/run_inotify.c index 9f3c30b8c..3e7c70dba 100644 --- a/test/run_inotify.c +++ b/test/run_inotify.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/test/run_input.c b/test/run_input.c index a50cd70ab..676e4e618 100644 --- a/test/run_input.c +++ b/test/run_input.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,6 +18,7 @@ */ #include "config.h" +#include "io_thread.h" #include "input_init.h" #include "input_stream.h" #include "tag_pool.h" @@ -32,6 +33,7 @@ #include <glib.h> #include <unistd.h> +#include <stdlib.h> static void my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level, @@ -51,20 +53,17 @@ dump_input_stream(struct input_stream *is) size_t num_read; ssize_t num_written; + input_stream_lock(is); + /* wait until the stream becomes ready */ - while (!is->ready) { - int ret = input_stream_buffer(is, &error); - if (ret < 0) { - /* error */ - g_warning("%s", error->message); - g_error_free(error); - return 2; - } + input_stream_wait_ready(is); - if (ret == 0) - /* nothing was buffered - wait */ - g_usleep(10000); + if (!input_stream_check(is, &error)) { + g_warning("%s", error->message); + g_error_free(error); + input_stream_unlock(is); + return EXIT_FAILURE; } /* print meta data */ @@ -98,6 +97,15 @@ dump_input_stream(struct input_stream *is) break; } + if (!input_stream_check(is, &error)) { + g_warning("%s", error->message); + g_error_free(error); + input_stream_unlock(is); + return EXIT_FAILURE; + } + + input_stream_unlock(is); + return 0; } @@ -122,6 +130,13 @@ int main(int argc, char **argv) tag_pool_init(); config_global_init(); + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + #ifdef ENABLE_ARCHIVE archive_plugin_init_all(); #endif @@ -134,7 +149,10 @@ int main(int argc, char **argv) /* open the stream and dump it */ - is = input_stream_open(argv[1], &error); + GMutex *mutex = g_mutex_new(); + GCond *cond = g_cond_new(); + + is = input_stream_open(argv[1], mutex, cond, &error); if (is != NULL) { ret = dump_input_stream(is); input_stream_close(is); @@ -147,6 +165,9 @@ int main(int argc, char **argv) ret = 2; } + g_cond_free(cond); + g_mutex_free(mutex); + /* deinitialize everything */ input_stream_global_finish(); @@ -155,6 +176,8 @@ int main(int argc, char **argv) archive_plugin_deinit_all(); #endif + io_thread_deinit(); + config_global_finish(); tag_pool_deinit(); diff --git a/test/run_normalize.c b/test/run_normalize.c index 958015973..fc26829ed 100644 --- a/test/run_normalize.c +++ b/test/run_normalize.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/test/run_ntp_server.c b/test/run_ntp_server.c new file mode 100644 index 000000000..842d1852e --- /dev/null +++ b/test/run_ntp_server.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "ntp_server.h" +#include "signals.h" +#include "io_thread.h" + +#include <glib.h> + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#ifdef WIN32 +#include <ws2tcpip.h> +#include <winsock.h> +#else +#include <sys/socket.h> +#include <netdb.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif + +void +on_quit(void) +{ + io_thread_quit(); +} + +int +main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) +{ + g_thread_init(NULL); + signals_init(); + io_thread_init(); + + struct ntp_server ntp; + ntp_server_init(&ntp); + + GError *error = NULL; + if (!ntp_server_open(&ntp, &error)) { + io_thread_deinit(); + g_printerr("%s\n", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + io_thread_run(); + + ntp_server_close(&ntp); + io_thread_deinit(); + return EXIT_SUCCESS; +} diff --git a/test/run_output.c b/test/run_output.c index 5028068ff..bbb1be7d2 100644 --- a/test/run_output.c +++ b/test/run_output.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,6 +18,7 @@ */ #include "config.h" +#include "io_thread.h" #include "output_plugin.h" #include "output_internal.h" #include "output_control.h" @@ -28,6 +29,7 @@ #include "event_pipe.h" #include "idle.h" #include "playlist.h" +#include "player_control.h" #include "stdbin.h" #include <glib.h> @@ -35,6 +37,7 @@ #include <assert.h> #include <string.h> #include <unistd.h> +#include <stdlib.h> struct playlist g_playlist; @@ -91,11 +94,10 @@ find_named_config_block(const char *block, const char *name) return NULL; } -static bool -load_audio_output(struct audio_output *ao, const char *name) +static struct audio_output * +load_audio_output(const char *name) { const struct config_param *param; - bool success; GError *error = NULL; param = find_named_config_block(CONF_AUDIO_OUTPUT, name); @@ -104,25 +106,91 @@ load_audio_output(struct audio_output *ao, const char *name) return false; } - success = audio_output_init(ao, param, &error); - if (!success) { + static struct player_control dummy_player_control; + + struct audio_output *ao = + audio_output_new(param, &dummy_player_control, &error); + if (ao == NULL) { g_printerr("%s\n", error->message); g_error_free(error); } - return success; + return ao; +} + +static bool +run_output(struct audio_output *ao, struct audio_format *audio_format) +{ + /* open the audio output */ + + GError *error = NULL; + if (!ao_plugin_enable(ao, &error)) { + g_printerr("Failed to enable audio output: %s\n", + error->message); + g_error_free(error); + return false; + } + + if (!ao_plugin_open(ao, audio_format, &error)) { + ao_plugin_disable(ao); + g_printerr("Failed to open audio output: %s\n", + error->message); + g_error_free(error); + return false; + } + + struct audio_format_string af_string; + g_printerr("audio_format=%s\n", + audio_format_to_string(audio_format, &af_string)); + + size_t frame_size = audio_format_frame_size(audio_format); + + /* play */ + + size_t length = 0; + char buffer[4096]; + while (true) { + if (length < sizeof(buffer)) { + ssize_t nbytes = read(0, buffer + length, + sizeof(buffer) - length); + if (nbytes <= 0) + break; + + length += (size_t)nbytes; + } + + size_t play_length = (length / frame_size) * frame_size; + if (play_length > 0) { + size_t consumed = ao_plugin_play(ao, + buffer, play_length, + &error); + if (consumed == 0) { + ao_plugin_close(ao); + ao_plugin_disable(ao); + g_printerr("Failed to play: %s\n", + error->message); + g_error_free(error); + return false; + } + + assert(consumed <= length); + assert(consumed % frame_size == 0); + + length -= consumed; + memmove(buffer, buffer + consumed, length); + } + } + + ao_plugin_close(ao); + ao_plugin_disable(ao); + return true; } 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"); @@ -143,9 +211,17 @@ int main(int argc, char **argv) return 1; } + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + /* initialize the audio output */ - if (!load_audio_output(&ao, argv[2])) + struct audio_output *ao = load_audio_output(argv[2]); + if (ao == NULL) return 1; /* parse the audio format */ @@ -161,59 +237,17 @@ int main(int argc, char **argv) } } - /* 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; + /* do it */ - 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); - } - } + success = run_output(ao, &audio_format); /* cleanup and exit */ - ao_plugin_close(ao.plugin, ao.data); - ao_plugin_finish(ao.plugin, ao.data); - g_mutex_free(ao.mutex); + audio_output_free(ao); + + io_thread_deinit(); config_global_finish(); - return 0; + return success ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/test/run_resolver.c b/test/run_resolver.c new file mode 100644 index 000000000..ee0bc0172 --- /dev/null +++ b/test/run_resolver.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "resolver.h" + +#ifdef WIN32 +#include <ws2tcpip.h> +#include <winsock.h> +#else +#include <sys/socket.h> +#include <netdb.h> +#endif + +#include <stdlib.h> + +int main(int argc, char **argv) +{ + if (argc != 2) { + g_printerr("Usage: run_resolver HOST\n"); + return EXIT_FAILURE; + } + + GError *error = NULL; + struct addrinfo *ai = + resolve_host_port(argv[1], 80, AI_PASSIVE, SOCK_STREAM, + &error); + if (ai == NULL) { + g_printerr("%s\n", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + for (const struct addrinfo *i = ai; i != NULL; i = i->ai_next) { + char *p = sockaddr_to_string(i->ai_addr, i->ai_addrlen, + &error); + if (p == NULL) { + freeaddrinfo(ai); + g_printerr("%s\n", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + g_print("%s\n", p); + g_free(p); + } + + freeaddrinfo(ai); + return EXIT_SUCCESS; +} diff --git a/test/run_tcp_connect.c b/test/run_tcp_connect.c new file mode 100644 index 000000000..bf8d9b82f --- /dev/null +++ b/test/run_tcp_connect.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "resolver.h" +#include "io_thread.h" +#include "tcp_connect.h" +#include "fd_util.h" + +#include <assert.h> +#include <stdlib.h> + +#ifdef WIN32 +#include <ws2tcpip.h> +#include <winsock.h> +#else +#include <sys/socket.h> +#include <netdb.h> +#endif + +static struct tcp_connect *handle; +static GMutex *mutex; +static GCond *cond; +static bool done, success; + +static void +my_tcp_connect_success(int fd, G_GNUC_UNUSED void *ctx) +{ + assert(!done); + assert(!success); + + close_socket(fd); + g_print("success\n"); + + g_mutex_lock(mutex); + done = success = true; + g_cond_signal(cond); + g_mutex_unlock(mutex); +} + +static void +my_tcp_connect_error(GError *error, G_GNUC_UNUSED void *ctx) +{ + assert(!done); + assert(!success); + + g_printerr("error: %s\n", error->message); + g_error_free(error); + + g_mutex_lock(mutex); + done = true; + g_cond_signal(cond); + g_mutex_unlock(mutex); +} + +static void +my_tcp_connect_timeout(G_GNUC_UNUSED void *ctx) +{ + assert(!done); + assert(!success); + + g_printerr("timeout\n"); + + g_mutex_lock(mutex); + done = true; + g_cond_signal(cond); + g_mutex_unlock(mutex); +} + +static void +my_tcp_connect_canceled(G_GNUC_UNUSED void *ctx) +{ + assert(!done); + assert(!success); + + g_printerr("canceled\n"); + + g_mutex_lock(mutex); + done = true; + g_cond_signal(cond); + g_mutex_unlock(mutex); +} + +static const struct tcp_connect_handler my_tcp_connect_handler = { + .success = my_tcp_connect_success, + .error = my_tcp_connect_error, + .timeout = my_tcp_connect_timeout, + .canceled = my_tcp_connect_canceled, +}; + +int main(int argc, char **argv) +{ + if (argc != 2) { + g_printerr("Usage: run_tcp_connect IP:PORT\n"); + return 1; + } + + GError *error = NULL; + struct addrinfo *ai = resolve_host_port(argv[1], 80, 0, SOCK_STREAM, + &error); + if (ai == NULL) { + g_printerr("%s\n", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + /* initialize GLib */ + + g_thread_init(NULL); + + /* initialize MPD */ + + io_thread_init(); + if (!io_thread_start(&error)) { + freeaddrinfo(ai); + g_printerr("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + /* open the connection */ + + mutex = g_mutex_new(); + cond = g_cond_new(); + + tcp_connect_address(ai->ai_addr, ai->ai_addrlen, 5000, + &my_tcp_connect_handler, NULL, + &handle); + freeaddrinfo(ai); + + if (handle != NULL) { + g_mutex_lock(mutex); + while (!done) + g_cond_wait(cond, mutex); + g_mutex_unlock(mutex); + + tcp_connect_free(handle); + } + + g_cond_free(cond); + g_mutex_free(mutex); + + /* deinitialize everything */ + + io_thread_deinit(); + + return EXIT_SUCCESS; +} diff --git a/test/signals.c b/test/signals.c new file mode 100644 index 000000000..15761f6b0 --- /dev/null +++ b/test/signals.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "signals.h" +#ifndef WIN32 + +#include "mpd_error.h" + +#include <glib.h> + +#include <signal.h> +#include <errno.h> +#include <string.h> + +static void +quit_signal_handler(G_GNUC_UNUSED int signum) +{ + on_quit(); +} + +static void +x_sigaction(int signum, const struct sigaction *act) +{ + if (sigaction(signum, act, NULL) < 0) + MPD_ERROR("sigaction() failed: %s", g_strerror(errno)); +} + +#endif + +void +signals_init(void) +{ +#ifndef WIN32 + struct sigaction sa; + + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + x_sigaction(SIGPIPE, &sa); + + sa.sa_handler = quit_signal_handler; + x_sigaction(SIGINT, &sa); + x_sigaction(SIGTERM, &sa); +#endif +} diff --git a/test/signals.h b/test/signals.h new file mode 100644 index 000000000..e524d35e2 --- /dev/null +++ b/test/signals.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SIGNALS_H +#define MPD_SIGNALS_H + +void +on_quit(void); + +void +signals_init(void); + +#endif diff --git a/test/software_volume.c b/test/software_volume.c index 789fffe61..2357da672 100644 --- a/test/software_volume.c +++ b/test/software_volume.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -59,7 +59,7 @@ int main(int argc, char **argv) audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, 2); while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { - if (!pcm_volume(buffer, nbytes, &audio_format, + if (!pcm_volume(buffer, nbytes, audio_format.format, PCM_VOLUME_1 / 2)) { g_printerr("pcm_volume() has failed\n"); return 2; diff --git a/test/stdbin.h b/test/stdbin.h index 362605ad9..48cac7338 100644 --- a/test/stdbin.h +++ b/test/stdbin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/test/test_byte_reverse.c b/test/test_byte_reverse.c new file mode 100644 index 000000000..7678e9cef --- /dev/null +++ b/test/test_byte_reverse.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2003-2012 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "util/byte_reverse.h" +#include "test_glib_compat.h" + +#include <glib.h> + +static void +test_byte_reverse_2(void) +{ + static const char src[] = "123456"; + static const char result[] = "214365"; + static uint8_t dest[G_N_ELEMENTS(src)]; + + reverse_bytes(dest, (const uint8_t *)src, + (const uint8_t *)(src + G_N_ELEMENTS(src) - 1), 2); + g_assert_cmpstr((const char *)dest, ==, result); +} + +static void +test_byte_reverse_3(void) +{ + static const char src[] = "123456"; + static const char result[] = "321654"; + static uint8_t dest[G_N_ELEMENTS(src)]; + + reverse_bytes(dest, (const uint8_t *)src, + (const uint8_t *)(src + G_N_ELEMENTS(src) - 1), 3); + g_assert_cmpstr((const char *)dest, ==, result); +} + +static void +test_byte_reverse_4(void) +{ + static const char src[] = "12345678"; + static const char result[] = "43218765"; + static uint8_t dest[G_N_ELEMENTS(src)]; + + reverse_bytes(dest, (const uint8_t *)src, + (const uint8_t *)(src + G_N_ELEMENTS(src) - 1), 4); + g_assert_cmpstr((const char *)dest, ==, result); +} + +static void +test_byte_reverse_5(void) +{ + static const char src[] = "1234567890"; + static const char result[] = "5432109876"; + static uint8_t dest[G_N_ELEMENTS(src)]; + + reverse_bytes(dest, (const uint8_t *)src, + (const uint8_t *)(src + G_N_ELEMENTS(src) - 1), 5); + g_assert_cmpstr((const char *)dest, ==, result); +} + +int +main(int argc, char **argv) +{ + g_test_init (&argc, &argv, NULL); + g_test_add_func("/util/byte_reverse/2", test_byte_reverse_2); + g_test_add_func("/util/byte_reverse/3", test_byte_reverse_3); + g_test_add_func("/util/byte_reverse/4", test_byte_reverse_4); + g_test_add_func("/util/byte_reverse/5", test_byte_reverse_5); + + g_test_run(); +} diff --git a/test/test_glib_compat.h b/test/test_glib_compat.h new file mode 100644 index 000000000..2e4ab123c --- /dev/null +++ b/test/test_glib_compat.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Compatibility header for GLib before 2.16. + */ + +#ifndef MPD_TEST_GLIB_COMPAT_H +#define MPD_TEST_GLIB_COMPAT_H + +#include <glib.h> + +#if !GLIB_CHECK_VERSION(2,16,0) + +#include <string.h> + +#define g_assert_cmpint(n1, cmp, n2) g_assert((n1) cmp (n2)) +#define g_assert_cmpstr(a, cmp, b) g_assert(strcmp(a, b) cmp 0) + +static void (*test_functions[256])(void); +static unsigned num_test_functions; + +static inline void +g_test_init(G_GNUC_UNUSED int *argc, G_GNUC_UNUSED char ***argv, ...) +{ +} + +static inline void +g_test_add_func(G_GNUC_UNUSED const char *testpath, void (test_funcvoid)(void)) +{ + test_functions[num_test_functions++] = test_funcvoid; +} + +static inline int +g_test_run(void) +{ + for (unsigned i = 0; i < num_test_functions; ++i) + test_functions[i](); + return 0; +} + +#endif /* !2.16 */ + +#endif diff --git a/test/test_pcm_all.h b/test/test_pcm_all.h new file mode 100644 index 000000000..14e4c2980 --- /dev/null +++ b/test/test_pcm_all.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_TEST_PCM_ALL_H +#define MPD_TEST_PCM_ALL_H + +void +test_pcm_dither_24(void); + +void +test_pcm_dither_32(void); + +void +test_pcm_pack_24(void); + +void +test_pcm_unpack_24(void); + +void +test_pcm_channels_16(void); + +void +test_pcm_channels_32(void); + +#endif diff --git a/test/test_pcm_channels.c b/test/test_pcm_channels.c new file mode 100644 index 000000000..877ae3262 --- /dev/null +++ b/test/test_pcm_channels.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "test_pcm_all.h" +#include "test_glib_compat.h" +#include "pcm_channels.h" +#include "pcm_buffer.h" + +#include <glib.h> + +void +test_pcm_channels_16(void) +{ + enum { N = 256 }; + int16_t src[N * 2]; + + for (unsigned i = 0; i < G_N_ELEMENTS(src); ++i) + src[i] = g_random_int(); + + struct pcm_buffer buffer; + pcm_buffer_init(&buffer); + + /* stereo to mono */ + + size_t dest_size; + const int16_t *dest = + pcm_convert_channels_16(&buffer, 1, 2, src, sizeof(src), + &dest_size); + g_assert(dest != NULL); + g_assert_cmpint(dest_size, ==, sizeof(src) / 2); + for (unsigned i = 0; i < N; ++i) + g_assert_cmpint(dest[i], ==, + (src[i * 2] + src[i * 2 + 1]) / 2); + + /* mono to stereo */ + + dest = pcm_convert_channels_16(&buffer, 2, 1, src, sizeof(src), + &dest_size); + g_assert(dest != NULL); + g_assert_cmpint(dest_size, ==, sizeof(src) * 2); + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i * 2], ==, src[i]); + g_assert_cmpint(dest[i * 2 + 1], ==, src[i]); + } + + pcm_buffer_deinit(&buffer); +} + +void +test_pcm_channels_32(void) +{ + enum { N = 256 }; + int32_t src[N * 2]; + + for (unsigned i = 0; i < G_N_ELEMENTS(src); ++i) + src[i] = g_random_int(); + + struct pcm_buffer buffer; + pcm_buffer_init(&buffer); + + /* stereo to mono */ + + size_t dest_size; + const int32_t *dest = + pcm_convert_channels_32(&buffer, 1, 2, src, sizeof(src), + &dest_size); + g_assert(dest != NULL); + g_assert_cmpint(dest_size, ==, sizeof(src) / 2); + for (unsigned i = 0; i < N; ++i) + g_assert_cmpint(dest[i], ==, + ((int64_t)src[i * 2] + (int64_t)src[i * 2 + 1]) / 2); + + /* mono to stereo */ + + dest = pcm_convert_channels_32(&buffer, 2, 1, src, sizeof(src), + &dest_size); + g_assert(dest != NULL); + g_assert_cmpint(dest_size, ==, sizeof(src) * 2); + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i * 2], ==, src[i]); + g_assert_cmpint(dest[i * 2 + 1], ==, src[i]); + } + + pcm_buffer_deinit(&buffer); +} diff --git a/test/test_pcm_dither.c b/test/test_pcm_dither.c new file mode 100644 index 000000000..24b0dd040 --- /dev/null +++ b/test/test_pcm_dither.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "test_pcm_all.h" +#include "test_glib_compat.h" +#include "pcm_dither.h" + +#include <glib.h> + +/** + * Generate a random 24 bit PCM sample. + */ +static int32_t +random24(void) +{ + int32_t x = g_random_int() & 0xffffff; + if (x & 0x800000) + x |= 0xff000000; + return x; +} + +void +test_pcm_dither_24(void) +{ + struct pcm_dither dither; + + pcm_dither_24_init(&dither); + + enum { N = 256 }; + int32_t src[N]; + for (unsigned i = 0; i < N; ++i) + src[i] = random24(); + + int16_t dest[N]; + + pcm_dither_24_to_16(&dither, dest, src, src + N); + + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i], >=, (src[i] >> 8) - 8); + g_assert_cmpint(dest[i], <, (src[i] >> 8) + 8); + } +} + +void +test_pcm_dither_32(void) +{ + struct pcm_dither dither; + + pcm_dither_24_init(&dither); + + enum { N = 256 }; + int32_t src[N]; + for (unsigned i = 0; i < N; ++i) + src[i] = g_random_int(); + + int16_t dest[N]; + + pcm_dither_32_to_16(&dither, dest, src, src + N); + + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i], >=, (src[i] >> 16) - 8); + g_assert_cmpint(dest[i], <, (src[i] >> 16) + 8); + } +} diff --git a/test/test_pcm_main.c b/test/test_pcm_main.c new file mode 100644 index 000000000..7047b5251 --- /dev/null +++ b/test/test_pcm_main.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "test_pcm_all.h" +#include "test_glib_compat.h" + +#include <glib.h> + +int +main(int argc, char **argv) +{ + g_test_init (&argc, &argv, NULL); + g_test_add_func("/pcm/dither/24", test_pcm_dither_24); + g_test_add_func("/pcm/dither/32", test_pcm_dither_32); + g_test_add_func("/pcm/pack/pack24", test_pcm_pack_24); + g_test_add_func("/pcm/pack/unpack24", test_pcm_unpack_24); + g_test_add_func("/pcm/channels/16", test_pcm_channels_16); + g_test_add_func("/pcm/channels/32", test_pcm_channels_32); + + g_test_run(); +} diff --git a/test/test_pcm_pack.c b/test/test_pcm_pack.c new file mode 100644 index 000000000..de5d8b6e5 --- /dev/null +++ b/test/test_pcm_pack.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2003-2011 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "test_pcm_all.h" +#include "pcm_pack.h" +#include "test_glib_compat.h" + +#include <glib.h> + +/** + * Generate a random 24 bit PCM sample. + */ +static int32_t +random24(void) +{ + int32_t x = g_random_int() & 0xffffff; + if (x & 0x800000) + x |= 0xff000000; + return x; +} + +void +test_pcm_pack_24(void) +{ + enum { N = 256 }; + int32_t src[N * 3]; + for (unsigned i = 0; i < N; ++i) + src[i] = random24(); + + uint8_t dest[N * 3]; + + pcm_pack_24(dest, src, src + N); + + for (unsigned i = 0; i < N; ++i) { + int32_t d; + if (G_BYTE_ORDER == G_BIG_ENDIAN) + d = (dest[i * 3] << 16) | (dest[i * 3 + 1] << 8) + | dest[i * 3 + 2]; + else + d = (dest[i * 3 + 2] << 16) | (dest[i * 3 + 1] << 8) + | dest[i * 3]; + if (d & 0x800000) + d |= 0xff000000; + + g_assert_cmpint(d, ==, src[i]); + } +} + +void +test_pcm_unpack_24(void) +{ + enum { N = 256 }; + uint8_t src[N * 3]; + for (unsigned i = 0; i < G_N_ELEMENTS(src); ++i) + src[i] = g_random_int_range(0, 256); + + int32_t dest[N]; + + pcm_unpack_24(dest, src, src + G_N_ELEMENTS(src)); + + for (unsigned i = 0; i < N; ++i) { + int32_t s; + if (G_BYTE_ORDER == G_BIG_ENDIAN) + s = (src[i * 3] << 16) | (src[i * 3 + 1] << 8) + | src[i * 3 + 2]; + else + s = (src[i * 3 + 2] << 16) | (src[i * 3 + 1] << 8) + | src[i * 3]; + if (s & 0x800000) + s |= 0xff000000; + + g_assert_cmpint(s, ==, dest[i]); + } +} diff --git a/test/test_queue_priority.c b/test/test_queue_priority.c new file mode 100644 index 000000000..a7106a8e9 --- /dev/null +++ b/test/test_queue_priority.c @@ -0,0 +1,175 @@ +#include "queue.h" +#include "song.h" + +void +song_free(G_GNUC_UNUSED struct song *song) +{ +} + +G_GNUC_UNUSED +static void +dump_order(const struct queue *queue) +{ + g_printerr("queue length=%u, order:\n", queue_length(queue)); + for (unsigned i = 0; i < queue_length(queue); ++i) + g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], + queue->items[queue->order[i]].priority); +} + +static void +check_descending_priority(G_GNUC_UNUSED const struct queue *queue, + unsigned start_order) +{ + assert(start_order < queue_length(queue)); + + uint8_t last_priority = 0xff; + for (unsigned order = start_order; order < queue_length(queue); ++order) { + unsigned position = queue_order_to_position(queue, order); + uint8_t priority = queue->items[position].priority; + assert(priority <= last_priority); + (void)last_priority; + last_priority = priority; + } +} + +int +main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) +{ + struct song songs[16]; + + struct queue queue; + queue_init(&queue, 32); + + for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i) + queue_append(&queue, &songs[i]); + + assert(queue_length(&queue) == G_N_ELEMENTS(songs)); + + /* priority=10 for 4 items */ + + queue_set_priority_range(&queue, 4, 8, 10, -1); + + queue.random = true; + queue_shuffle_order(&queue); + check_descending_priority(&queue, 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue_position_to_order(&queue, i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue_position_to_order(&queue, i) < 4); + } + + for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) { + assert(queue_position_to_order(&queue, i) >= 4); + } + + /* priority=50 one more item */ + + queue_set_priority_range(&queue, 15, 16, 50, -1); + check_descending_priority(&queue, 0); + + assert(queue_position_to_order(&queue, 15) == 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue_position_to_order(&queue, i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue_position_to_order(&queue, i) >= 1 && + queue_position_to_order(&queue, i) < 5); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue_position_to_order(&queue, i) >= 5); + } + + /* priority=20 for one of the 4 priority=10 items */ + + queue_set_priority_range(&queue, 3, 4, 20, -1); + check_descending_priority(&queue, 0); + + assert(queue_position_to_order(&queue, 3) == 1); + assert(queue_position_to_order(&queue, 15) == 0); + + for (unsigned i = 0; i < 3; ++i) { + assert(queue_position_to_order(&queue, i) >= 5); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue_position_to_order(&queue, i) >= 2 && + queue_position_to_order(&queue, i) < 6); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue_position_to_order(&queue, i) >= 6); + } + + /* priority=20 for another one of the 4 priority=10 items; + pass "after_order" (with priority=10) and see if it's moved + after that one */ + + unsigned current_order = 4; + unsigned current_position = + queue_order_to_position(&queue, current_order); + + unsigned a_order = 3; + unsigned a_position = queue_order_to_position(&queue, a_order); + assert(queue.items[a_position].priority == 10); + queue_set_priority(&queue, a_position, 20, current_order); + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + a_order = queue_position_to_order(&queue, a_position); + assert(a_order == 4); + + check_descending_priority(&queue, current_order + 1); + + /* priority=70 for one of the last items; must be inserted + right after the current song, before the priority=20 one we + just created */ + + unsigned b_order = 10; + unsigned b_position = queue_order_to_position(&queue, b_order); + assert(queue.items[b_position].priority == 0); + queue_set_priority(&queue, b_position, 70, current_order); + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + b_order = queue_position_to_order(&queue, b_position); + assert(b_order == 4); + + check_descending_priority(&queue, current_order + 1); + + /* priority=60 for the old prio50 item; must not be moved, + because it's before the current song, and it's status + hasn't changed (it was already higher before) */ + + unsigned c_order = 0; + unsigned c_position = queue_order_to_position(&queue, c_order); + assert(queue.items[c_position].priority == 50); + queue_set_priority(&queue, c_position, 60, current_order); + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + c_order = queue_position_to_order(&queue, c_position); + assert(c_order == 0); + + /* move the prio=20 item back */ + + a_order = queue_position_to_order(&queue, a_position); + assert(a_order == 5); + assert(queue.items[a_position].priority == 20); + queue_set_priority(&queue, a_position, 5, current_order); + + + current_order = queue_position_to_order(&queue, current_position); + assert(current_order == 3); + + a_order = queue_position_to_order(&queue, a_position); + assert(a_order == 6); +} diff --git a/test/test_vorbis_encoder.c b/test/test_vorbis_encoder.c index 969ab7687..048d26f0a 100644 --- a/test/test_vorbis_encoder.c +++ b/test/test_vorbis_encoder.c @@ -54,7 +54,7 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) assert(plugin != NULL); struct config_param *param = config_new_param(NULL, -1); - config_add_block_param(param, "quality", "5.0", -1, NULL); + config_add_block_param(param, "quality", "5.0", -1); struct encoder *encoder = encoder_init(plugin, param, NULL); assert(encoder != NULL); |