diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/dump_playlist.c | 37 | ||||
-rw-r--r-- | test/read_conf.c | 2 | ||||
-rw-r--r-- | test/read_mixer.c | 53 | ||||
-rw-r--r-- | test/read_tags.c | 34 | ||||
-rw-r--r-- | test/run_convert.c | 2 | ||||
-rw-r--r-- | test/run_decoder.c | 27 | ||||
-rw-r--r-- | test/run_encoder.c | 4 | ||||
-rw-r--r-- | test/run_filter.c | 2 | ||||
-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 | 146 | ||||
-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_glib_compat.h | 57 | ||||
-rw-r--r-- | test/test_pcm_all.h | 47 | ||||
-rw-r--r-- | test/test_pcm_byteswap.c | 64 | ||||
-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 | 39 | ||||
-rw-r--r-- | test/test_pcm_pack.c | 90 | ||||
-rw-r--r-- | test/test_queue_priority.c | 175 |
27 files changed, 1299 insertions, 113 deletions
diff --git a/test/dump_playlist.c b/test/dump_playlist.c index a8cb4d750..079fdeac0 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,6 +18,7 @@ */ #include "config.h" +#include "io_thread.h" #include "input_init.h" #include "input_stream.h" #include "tag_pool.h" @@ -30,6 +31,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, @@ -73,6 +75,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); @@ -83,11 +92,14 @@ int main(int argc, char **argv) /* 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 +109,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 +148,13 @@ 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); + playlist_list_global_finish(); input_stream_global_finish(); + io_thread_deinit(); config_global_finish(); tag_pool_deinit(); 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 3e5e523bf..86d508a5c 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,12 +18,14 @@ */ #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 "idle.h" @@ -32,6 +34,7 @@ #include <assert.h> #include <unistd.h> +#include <stdlib.h> #ifdef HAVE_LOCALE_H #include <locale.h> @@ -49,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; @@ -88,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 @@ -164,6 +167,16 @@ int main(int argc, char **argv) decoder_name = argv[1]; path = argv[2]; + g_thread_init(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)) { g_warning("%s", error->message); g_error_free(error); @@ -180,7 +193,11 @@ int main(int argc, char **argv) tag = decoder_plugin_tag_dup(plugin, path); if (tag == NULL && plugin->stream_tag != NULL) { - struct input_stream *is = input_stream_open(path, &error); + 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", @@ -191,10 +208,15 @@ int main(int argc, char **argv) tag = decoder_plugin_stream_tag(plugin, is); input_stream_close(is); + + g_cond_free(cond); + g_mutex_free(mutex); } decoder_plugin_deinit_all(); input_stream_global_finish(); + io_thread_deinit(); + if (tag == NULL) { g_printerr("Failed to read tags\n"); return 1; @@ -215,5 +237,7 @@ int main(int argc, char **argv) } } + tag_pool_deinit(); + return 0; } diff --git a/test/run_convert.c b/test/run_convert.c index 415d7535c..57a3a2f7f 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 diff --git a/test/run_decoder.c b/test/run_decoder.c index c997ebf8f..01bf66aae 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 "input_init.h" @@ -31,6 +32,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, @@ -54,8 +56,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; @@ -110,7 +112,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 @@ -178,8 +180,16 @@ int main(int argc, char **argv) decoder_name = argv[1]; decoder.uri = argv[2]; + 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; + } + if (!input_stream_global_init(&error)) { g_warning("%s", error->message); g_error_free(error); @@ -200,8 +210,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); @@ -215,6 +228,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; @@ -222,6 +238,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 4b512d46a..5e6b158c6 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 @@ -75,7 +75,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..d1dffc190 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 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..0fe5a01f0 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; + g_mutex_lock(is->mutex); + /* 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); + g_mutex_unlock(is->mutex); + 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); + g_mutex_unlock(is->mutex); + return EXIT_FAILURE; + } + + g_mutex_unlock(is->mutex); + 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 dd1140782..d16ed60ea 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..5e688f2c7 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,81 @@ 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_open(ao, audio_format, &error)) { + 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); + 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); + 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 +201,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 +227,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; - - 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; - } + /* do it */ - 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..5f5d336f3 --- /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", 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 c4de69328..1e068be41 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_glib_compat.h b/test/test_glib_compat.h new file mode 100644 index 000000000..1d54ec89a --- /dev/null +++ b/test/test_glib_compat.h @@ -0,0 +1,57 @@ +/* + * 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) + +#define g_assert_cmpint(n1, cmp, n2) g_assert((n1) cmp (n2)) + +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..2217baf39 --- /dev/null +++ b/test/test_pcm_all.h @@ -0,0 +1,47 @@ +/* + * 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); + +void +test_pcm_byteswap_16(void); + +void +test_pcm_byteswap_32(void); + +#endif diff --git a/test/test_pcm_byteswap.c b/test/test_pcm_byteswap.c new file mode 100644 index 000000000..f49991606 --- /dev/null +++ b/test/test_pcm_byteswap.c @@ -0,0 +1,64 @@ +/* + * 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 "pcm_byteswap.h" +#include "pcm_buffer.h" +#include "test_glib_compat.h" + +#include <glib.h> + +void +test_pcm_byteswap_16(void) +{ + enum { N = 256 }; + int16_t src[N]; + + for (unsigned i = 0; i < G_N_ELEMENTS(src); ++i) + src[i] = g_random_int(); + + struct pcm_buffer buffer; + pcm_buffer_init(&buffer); + + const int16_t *dest = pcm_byteswap_16(&buffer, src, sizeof(src)); + g_assert(dest != NULL); + for (unsigned i = 0; i < N; ++i) + g_assert_cmpint(dest[i], ==, + (int16_t)GUINT16_SWAP_LE_BE(src[i])); +} + +void +test_pcm_byteswap_32(void) +{ + enum { N = 256 }; + int32_t src[N]; + + for (unsigned i = 0; i < G_N_ELEMENTS(src); ++i) + src[i] = g_random_int(); + + struct pcm_buffer buffer; + pcm_buffer_init(&buffer); + + const int32_t *dest = pcm_byteswap_32(&buffer, src, sizeof(src)); + g_assert(dest != NULL); + for (unsigned i = 0; i < N; ++i) + g_assert_cmpint(dest[i], ==, + (int32_t)GUINT32_SWAP_LE_BE(src[i])); +} 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..4e64b443f --- /dev/null +++ b/test/test_pcm_main.c @@ -0,0 +1,39 @@ +/* + * 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_add_func("/pcm/byteswap/16", test_pcm_byteswap_16); + g_test_add_func("/pcm/byteswap/32", test_pcm_byteswap_32); + + g_test_run(); +} diff --git a/test/test_pcm_pack.c b/test/test_pcm_pack.c new file mode 100644 index 000000000..85cbe5bfc --- /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, false); + + 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), false); + + 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); +} |