diff options
Diffstat (limited to '')
53 files changed, 3706 insertions, 3295 deletions
diff --git a/test/DumpDatabase.cxx b/test/DumpDatabase.cxx new file mode 100644 index 000000000..ba0e74e43 --- /dev/null +++ b/test/DumpDatabase.cxx @@ -0,0 +1,147 @@ +/* + * 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 "config.h" +#include "DatabaseRegistry.hxx" +#include "DatabasePlugin.hxx" +#include "DatabaseSelection.hxx" +#include "Directory.hxx" +#include "song.h" +#include "PlaylistVector.hxx" +#include "conf.h" +#include "tag.h" +#include "fs/Path.hxx" + +#include <iostream> +using std::cout; +using std::cerr; +using std::endl; + +#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 bool +DumpDirectory(const Directory &directory, GError **) +{ + cout << "D " << directory.path << endl; + return true; +} + +static bool +DumpSong(song &song, GError **) +{ + cout << "S " << song.parent->path << "/" << song.uri << endl; + return true; +} + +static bool +DumpPlaylist(const PlaylistInfo &playlist, + const Directory &directory, GError **) +{ + cout << "P " << directory.path << "/" << playlist.name.c_str() << endl; + return true; +} + +int +main(int argc, char **argv) +{ + GError *error = nullptr; + + if (argc != 3) { + cerr << "Usage: DumpDatabase CONFIG PLUGIN" << endl; + return 1; + } + + const Path config_path = Path::FromFS(argv[1]); + const char *const plugin_name = argv[2]; + + const DatabasePlugin *plugin = GetDatabasePluginByName(plugin_name); + if (plugin == NULL) { + cerr << "No such database plugin: " << plugin_name << endl; + return EXIT_FAILURE; + } + + /* initialize GLib */ + + g_thread_init(nullptr); + g_log_set_default_handler(my_log_func, nullptr); + + /* initialize MPD */ + + config_global_init(); + + if (!ReadConfigFile(config_path, &error)) { + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + tag_lib_init(); + + /* do it */ + + const struct config_param *path = config_get_param(CONF_DB_FILE); + config_param param("database", path->line); + if (path != nullptr) + param.AddBlockParam("path", path->value, path->line); + + Database *db = plugin->create(¶m, &error); + + if (db == nullptr) { + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + if (!db->Open(&error)) { + delete db; + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + const DatabaseSelection selection("", true); + + if (!db->Visit(selection, DumpDirectory, DumpSong, DumpPlaylist, + &error)) { + db->Close(); + delete db; + cerr << error->message << endl; + g_error_free(error); + return EXIT_FAILURE; + } + + db->Close(); + delete db; + + /* deinitialize everything */ + + config_global_finish(); + + return EXIT_SUCCESS; +} diff --git a/test/FakeReplayGainConfig.cxx b/test/FakeReplayGainConfig.cxx new file mode 100644 index 000000000..9c2431bf2 --- /dev/null +++ b/test/FakeReplayGainConfig.cxx @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2003-2013 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 "replay_gain_config.h" + +float replay_gain_preamp = 1.0; +float replay_gain_missing_preamp = 1.0; +bool replay_gain_limit = true; diff --git a/test/FakeSong.cxx b/test/FakeSong.cxx new file mode 100644 index 000000000..927a07652 --- /dev/null +++ b/test/FakeSong.cxx @@ -0,0 +1,33 @@ +/* + * 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 "config.h" +#include "song.h" +#include "directory.h" +#include "gcc.h" + +#include <stdlib.h> + +struct directory detached_root; + +struct song * +song_dup_detached(gcc_unused const struct song *src) +{ + abort(); +} diff --git a/test/dump_playlist.c b/test/dump_playlist.c deleted file mode 100644 index 84ac69045..000000000 --- a/test/dump_playlist.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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 "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, - 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); -} - -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; - struct input_stream *is = NULL; - bool success; - GError *error = NULL; - struct playlist_provider *playlist; - struct song *song; - - if (argc != 3) { - g_printerr("Usage: dump_playlist CONFIG URI\n"); - return 1; - } - - uri = argv[2]; - - /* initialize GLib */ - - g_thread_init(NULL); - g_log_set_default_handler(my_log_func, NULL); - - /* initialize MPD */ - - tag_pool_init(); - config_global_init(); - success = config_read_file(argv[1], &error); - if (!success) { - g_printerr("%s\n", error->message); - g_error_free(error); - 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); - return 2; - } - - playlist_list_global_init(); - decoder_plugin_init_all(); - - /* open the playlist */ - - 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, mutex, cond, &error); - if (is == NULL) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } else - g_printerr("input_stream_open() failed\n"); - return 2; - } - - input_stream_lock_wait_ready(is); - - /* open the playlist */ - - playlist = playlist_list_open_stream(is, uri); - if (playlist == NULL) { - input_stream_close(is); - g_printerr("Failed to open playlist\n"); - return 2; - } - } - - /* dump the playlist */ - - while ((song = playlist_plugin_read(playlist)) != NULL) { - g_print("%s\n", song->uri); - - if (song->end_ms > 0) - g_print("range: %u:%02u..%u:%02u\n", - song->start_ms / 60000, - (song->start_ms / 1000) % 60, - song->end_ms / 60000, - (song->end_ms / 1000) % 60); - else if (song->start_ms > 0) - g_print("range: %u:%02u..\n", - song->start_ms / 60000, - (song->start_ms / 1000) % 60); - - if (song->tag != NULL) - tag_save(stdout, song->tag); - - song_free(song); - } - - /* deinitialize everything */ - - 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(); - - return 0; -} diff --git a/test/dump_playlist.cxx b/test/dump_playlist.cxx new file mode 100644 index 000000000..6e1f4858e --- /dev/null +++ b/test/dump_playlist.cxx @@ -0,0 +1,250 @@ +/* + * 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 "TagSave.hxx" +#include "song.h" +#include "Directory.hxx" +#include "input_stream.h" +#include "conf.h" +#include "decoder_api.h" +#include "DecoderList.hxx" +#include "InputInit.hxx" +#include "IOThread.hxx" +#include "PlaylistRegistry.hxx" +#include "PlaylistPlugin.hxx" +#include "fs/Path.hxx" + +#include <glib.h> + +#include <unistd.h> +#include <stdlib.h> + +Directory::Directory() {} +Directory::~Directory() {} + +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); +} + +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; +} + +void +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); +} + +void +decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, + char *mixramp_start, char *mixramp_end) +{ + g_free(mixramp_start); + g_free(mixramp_end); +} + +int main(int argc, char **argv) +{ + const char *uri; + struct input_stream *is = NULL; + GError *error = NULL; + struct playlist_provider *playlist; + struct song *song; + + if (argc != 3) { + g_printerr("Usage: dump_playlist CONFIG URI\n"); + return 1; + } + + const Path config_path = Path::FromFS(argv[1]); + uri = argv[2]; + + /* initialize GLib */ + + g_thread_init(NULL); + g_log_set_default_handler(my_log_func, NULL); + + /* initialize MPD */ + + config_global_init(); + if (!ReadConfigFile(config_path, &error)) { + g_printerr("%s\n", error->message); + g_error_free(error); + 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); + return 2; + } + + playlist_list_global_init(); + decoder_plugin_init_all(); + + /* open the playlist */ + + Mutex mutex; + Cond cond; + + 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, mutex, cond, &error); + if (is == NULL) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } else + g_printerr("input_stream_open() failed\n"); + return 2; + } + + input_stream_lock_wait_ready(is); + + /* open the playlist */ + + playlist = playlist_list_open_stream(is, uri); + if (playlist == NULL) { + input_stream_close(is); + g_printerr("Failed to open playlist\n"); + return 2; + } + } + + /* dump the playlist */ + + while ((song = playlist_plugin_read(playlist)) != NULL) { + g_print("%s\n", song->uri); + + if (song->end_ms > 0) + g_print("range: %u:%02u..%u:%02u\n", + song->start_ms / 60000, + (song->start_ms / 1000) % 60, + song->end_ms / 60000, + (song->end_ms / 1000) % 60); + else if (song->start_ms > 0) + g_print("range: %u:%02u..\n", + song->start_ms / 60000, + (song->start_ms / 1000) % 60); + + if (song->tag != NULL) + tag_save(stdout, song->tag); + + song_free(song); + } + + /* deinitialize everything */ + + playlist_plugin_close(playlist); + if (is != NULL) + input_stream_close(is); + + decoder_plugin_deinit_all(); + playlist_list_global_finish(); + input_stream_global_finish(); + io_thread_deinit(); + config_global_finish(); + + return 0; +} diff --git a/test/dump_rva2.c b/test/dump_rva2.c index 4a726518a..6e978c424 100644 --- a/test/dump_rva2.c +++ b/test/dump_rva2.c @@ -26,6 +26,8 @@ #include <id3tag.h> +#include <glib.h> + #ifdef HAVE_LOCALE_H #include <locale.h> #endif @@ -33,7 +35,8 @@ #include <stdlib.h> const char * -config_get_string(G_GNUC_UNUSED const char *name, const char *default_value) +config_get_string(gcc_unused enum ConfigOption option, + const char *default_value) { return default_value; } @@ -45,8 +48,8 @@ tag_new(void) } void -tag_add_item_n(G_GNUC_UNUSED struct tag *tag, G_GNUC_UNUSED enum tag_type type, - G_GNUC_UNUSED const char *value, G_GNUC_UNUSED size_t len) +tag_add_item_n(gcc_unused struct tag *tag, gcc_unused enum tag_type type, + gcc_unused const char *value, gcc_unused size_t len) { } diff --git a/test/dump_text_file.c b/test/dump_text_file.c deleted file mode 100644 index f14371441..000000000 --- a/test/dump_text_file.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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/dump_text_file.cxx b/test/dump_text_file.cxx new file mode 100644 index 000000000..93b0d0185 --- /dev/null +++ b/test/dump_text_file.cxx @@ -0,0 +1,167 @@ +/* + * 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 "IOThread.hxx" +#include "InputInit.hxx" +#include "InputStream.hxx" +#include "conf.h" +#include "stdbin.h" + +extern "C" { +#include "text_input_stream.h" +} + +#ifdef ENABLE_ARCHIVE +#include "ArchiveList.hxx" +#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 */ + + 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 */ + + Mutex mutex; + Cond cond; + + 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; + } + + /* deinitialize everything */ + + input_stream_global_finish(); + +#ifdef ENABLE_ARCHIVE + archive_plugin_deinit_all(); +#endif + + io_thread_deinit(); + + config_global_finish(); + + return ret; +} diff --git a/test/read_conf.c b/test/read_conf.c deleted file mode 100644 index 4f6005c6f..000000000 --- a/test/read_conf.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 "conf.h" - -#include <glib.h> - -#include <assert.h> - -static void -my_log_func(G_GNUC_UNUSED const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, G_GNUC_UNUSED gpointer user_data) -{ - if (log_level > G_LOG_LEVEL_WARNING) - return; - - g_printerr("%s\n", message); -} - -int main(int argc, char **argv) -{ - if (argc != 3) { - g_printerr("Usage: read_conf FILE SETTING\n"); - return 1; - } - - const char *path = argv[1]; - const char *name = argv[2]; - - g_log_set_default_handler(my_log_func, NULL); - - config_global_init(); - - GError *error = NULL; - bool success = config_read_file(path, &error); - if (!success) { - g_printerr("%s:", error->message); - g_error_free(error); - return 1; - } - - const char *value = config_get_string(name, NULL); - int ret; - if (value != NULL) { - g_print("%s\n", value); - ret = 0; - } else { - g_printerr("No such setting: %s\n", name); - ret = 2; - } - - config_global_finish(); - return ret; -} diff --git a/test/read_conf.cxx b/test/read_conf.cxx new file mode 100644 index 000000000..8759398da --- /dev/null +++ b/test/read_conf.cxx @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2003-2013 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 "conf.h" +#include "fs/Path.hxx" + +#include <glib.h> + +#include <assert.h> + +static void +my_log_func(G_GNUC_UNUSED const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, G_GNUC_UNUSED gpointer user_data) +{ + if (log_level > G_LOG_LEVEL_WARNING) + return; + + g_printerr("%s\n", message); +} + +int main(int argc, char **argv) +{ + if (argc != 3) { + g_printerr("Usage: read_conf FILE SETTING\n"); + return 1; + } + + const Path config_path = Path::FromFS(argv[1]); + const char *name = argv[2]; + + g_log_set_default_handler(my_log_func, NULL); + + config_global_init(); + + GError *error = NULL; + if (!ReadConfigFile(config_path, &error)) { + g_printerr("%s:", error->message); + g_error_free(error); + return 1; + } + + ConfigOption option = ParseConfigOptionName(name); + const char *value = option != CONF_MAX + ? config_get_string(option, nullptr) + : nullptr; + int ret; + if (value != NULL) { + g_print("%s\n", value); + ret = 0; + } else { + g_printerr("No such setting: %s\n", name); + ret = 2; + } + + config_global_finish(); + return ret; +} diff --git a/test/read_mixer.c b/test/read_mixer.c deleted file mode 100644 index f6de8177d..000000000 --- a/test/read_mixer.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 "mixer_control.h" -#include "mixer_list.h" -#include "filter_registry.h" -#include "pcm_volume.h" -#include "event_pipe.h" - -#include <glib.h> - -#include <assert.h> -#include <string.h> -#include <unistd.h> - -#ifdef HAVE_PULSE -#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) -{ -} - -void -pulse_output_clear_mixer(G_GNUC_UNUSED struct pulse_output *po, - G_GNUC_UNUSED struct pulse_mixer *pm) -{ -} - -bool -pulse_output_set_volume(G_GNUC_UNUSED struct pulse_output *po, - G_GNUC_UNUSED const struct pa_cvolume *volume, - G_GNUC_UNUSED GError **error_r) -{ - return false; -} - -#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 - -void -event_pipe_emit(G_GNUC_UNUSED enum pipe_event event) -{ -} - -const struct filter_plugin * -filter_plugin_by_name(G_GNUC_UNUSED const char *name) -{ - assert(false); - return NULL; -} - -bool -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); - return false; -} - -int main(int argc, G_GNUC_UNUSED char **argv) -{ - GError *error = NULL; - struct mixer *mixer; - bool success; - int volume; - - if (argc != 2) { - g_printerr("Usage: read_mixer PLUGIN\n"); - return 1; - } - - g_thread_init(NULL); - - mixer = mixer_new(&alsa_mixer_plugin, NULL, NULL, &error); - if (mixer == NULL) { - g_printerr("mixer_new() failed: %s\n", error->message); - g_error_free(error); - return 2; - } - - success = mixer_open(mixer, &error); - if (!success) { - mixer_free(mixer); - g_printerr("failed to open the mixer: %s\n", error->message); - g_error_free(error); - return 2; - } - - volume = mixer_get_volume(mixer, &error); - mixer_close(mixer); - mixer_free(mixer); - - assert(volume >= -1 && volume <= 100); - - if (volume < 0) { - if (error != NULL) { - g_printerr("failed to read volume: %s\n", - error->message); - g_error_free(error); - } else - g_printerr("failed to read volume\n"); - return 2; - } - - g_print("%d\n", volume); - return 0; -} diff --git a/test/read_mixer.cxx b/test/read_mixer.cxx new file mode 100644 index 000000000..45344a2f6 --- /dev/null +++ b/test/read_mixer.cxx @@ -0,0 +1,162 @@ +/* + * 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 "MixerControl.hxx" +#include "MixerList.hxx" +#include "FilterRegistry.hxx" +#include "PcmVolume.hxx" +#include "GlobalEvents.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" + +#include <glib.h> + +#include <assert.h> +#include <string.h> +#include <unistd.h> + +EventLoop *main_loop; + +#ifdef HAVE_PULSE +#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) +{ +} + +void +pulse_output_clear_mixer(G_GNUC_UNUSED struct pulse_output *po, + G_GNUC_UNUSED struct pulse_mixer *pm) +{ +} + +bool +pulse_output_set_volume(G_GNUC_UNUSED struct pulse_output *po, + G_GNUC_UNUSED const struct pa_cvolume *volume, + G_GNUC_UNUSED GError **error_r) +{ + return false; +} + +#endif + +#ifdef HAVE_ROAR +#include "output/RoarOutputPlugin.hxx" + +int +roar_output_get_volume(gcc_unused RoarOutput *roar) +{ + return -1; +} + +bool +roar_output_set_volume(gcc_unused RoarOutput *roar, + G_GNUC_UNUSED unsigned volume) +{ + return true; +} + +#endif + +void +GlobalEvents::Emit(gcc_unused Event event) +{ +} + +const struct filter_plugin * +filter_plugin_by_name(G_GNUC_UNUSED const char *name) +{ + assert(false); + return NULL; +} + +bool +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); + return false; +} + +int main(int argc, G_GNUC_UNUSED char **argv) +{ + GError *error = NULL; + struct mixer *mixer; + bool success; + int volume; + + if (argc != 2) { + g_printerr("Usage: read_mixer PLUGIN\n"); + return 1; + } + + g_thread_init(NULL); + + main_loop = new EventLoop(EventLoop::Default()); + + mixer = mixer_new(&alsa_mixer_plugin, NULL, NULL, &error); + if (mixer == NULL) { + g_printerr("mixer_new() failed: %s\n", error->message); + g_error_free(error); + return 2; + } + + success = mixer_open(mixer, &error); + if (!success) { + mixer_free(mixer); + g_printerr("failed to open the mixer: %s\n", error->message); + g_error_free(error); + return 2; + } + + volume = mixer_get_volume(mixer, &error); + mixer_close(mixer); + mixer_free(mixer); + + delete main_loop; + + assert(volume >= -1 && volume <= 100); + + if (volume < 0) { + if (error != NULL) { + g_printerr("failed to read volume: %s\n", + error->message); + g_error_free(error); + } else + g_printerr("failed to read volume\n"); + return 2; + } + + g_print("%d\n", volume); + return 0; +} diff --git a/test/read_tags.c b/test/read_tags.c deleted file mode 100644 index faf9a45c0..000000000 --- a/test/read_tags.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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 "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_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> -#endif - -/** - * No-op dummy. - */ -void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - -/** - * No-op dummy. - */ -bool -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; -} - -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 bit_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, - G_GNUC_UNUSED const struct replay_gain_info *replay_gain_info) -{ - 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); -} - -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(enum tag_type type, const char *value, G_GNUC_UNUSED void *ctx) -{ - g_print("[%s]=%s\n", tag_item_names[type], value); - empty = false; -} - -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; - -#ifdef HAVE_LOCALE_H - /* initialize locale */ - setlocale(LC_CTYPE,""); -#endif - - if (argc != 3) { - g_printerr("Usage: read_tags DECODER FILE\n"); - return 1; - } - - 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; - } - - if (!input_stream_global_init(&error)) { - g_warning("%s", error->message); - g_error_free(error); - return 2; - } - - decoder_plugin_init_all(); - - plugin = decoder_plugin_from_name(decoder_name); - if (plugin == NULL) { - g_printerr("No such decoder: %s\n", decoder_name); - return 1; - } - - 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", - path, error->message); - g_error_free(error); - return 1; - } - - 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(); - io_thread_deinit(); - - if (!success) { - g_printerr("Failed to read tags\n"); - return 1; - } - - if (empty) { - tag_ape_scan2(path, &print_handler, NULL); - if (empty) - tag_id3_scan(path, &print_handler, NULL); - } - - return 0; -} diff --git a/test/read_tags.cxx b/test/read_tags.cxx new file mode 100644 index 000000000..1ceddf1d5 --- /dev/null +++ b/test/read_tags.cxx @@ -0,0 +1,240 @@ +/* + * 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 "IOThread.hxx" +#include "DecoderList.hxx" +#include "decoder_api.h" +#include "InputInit.hxx" +#include "InputStream.hxx" +#include "audio_format.h" +extern "C" { +#include "tag_ape.h" +#include "tag_id3.h" +} +#include "tag_handler.h" + +#include <glib.h> + +#include <assert.h> +#include <unistd.h> +#include <stdlib.h> + +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif + +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 bit_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; +} + +void +decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, + G_GNUC_UNUSED const struct replay_gain_info *replay_gain_info) +{ +} + +void +decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, + char *mixramp_start, char *mixramp_end) +{ + g_free(mixramp_start); + 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(enum tag_type type, const char *value, G_GNUC_UNUSED void *ctx) +{ + g_print("[%s]=%s\n", tag_item_names[type], value); + empty = false; +} + +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 = { + print_duration, + print_tag, + print_pair, +}; + +int main(int argc, char **argv) +{ + GError *error = NULL; + const char *decoder_name, *path; + const struct decoder_plugin *plugin; + +#ifdef HAVE_LOCALE_H + /* initialize locale */ + setlocale(LC_CTYPE,""); +#endif + + if (argc != 3) { + g_printerr("Usage: read_tags DECODER FILE\n"); + return 1; + } + + 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; + } + + if (!input_stream_global_init(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return 2; + } + + decoder_plugin_init_all(); + + plugin = decoder_plugin_from_name(decoder_name); + if (plugin == NULL) { + g_printerr("No such decoder: %s\n", decoder_name); + return 1; + } + + bool success = decoder_plugin_scan_file(plugin, path, + &print_handler, NULL); + if (!success && plugin->scan_stream != NULL) { + Mutex mutex; + Cond cond; + + struct input_stream *is = + input_stream_open(path, mutex, cond, &error); + + if (is == NULL) { + g_printerr("Failed to open %s: %s\n", + path, error->message); + g_error_free(error); + return 1; + } + + mutex.lock(); + + while (!is->ready) { + cond.wait(mutex); + input_stream_update(is); + } + + if (!input_stream_check(is, &error)) { + mutex.unlock(); + + g_printerr("Failed to read %s: %s\n", + path, error->message); + g_error_free(error); + + return EXIT_FAILURE; + } + + mutex.unlock(); + + success = decoder_plugin_scan_stream(plugin, is, + &print_handler, NULL); + input_stream_close(is); + } + + decoder_plugin_deinit_all(); + input_stream_global_finish(); + io_thread_deinit(); + + if (!success) { + g_printerr("Failed to read tags\n"); + return 1; + } + + if (empty) { + tag_ape_scan2(path, &print_handler, NULL); + if (empty) + tag_id3_scan(path, &print_handler, NULL); + } + + return 0; +} diff --git a/test/run_convert.c b/test/run_convert.c deleted file mode 100644 index 4f57400fd..000000000 --- a/test/run_convert.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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. - */ - -/* - * This program is a command line interface to MPD's PCM conversion - * library (pcm_convert.c). - * - */ - -#include "config.h" -#include "audio_parser.h" -#include "audio_format.h" -#include "pcm_convert.h" -#include "conf.h" -#include "fifo_buffer.h" -#include "stdbin.h" - -#include <glib.h> - -#include <assert.h> -#include <stddef.h> -#include <unistd.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); -} - -const char * -config_get_string(G_GNUC_UNUSED const char *name, const char *default_value) -{ - return default_value; -} - -int main(int argc, char **argv) -{ - GError *error = NULL; - struct audio_format in_audio_format, out_audio_format; - struct pcm_convert_state state; - const void *output; - ssize_t nbytes; - size_t length; - - if (argc != 3) { - g_printerr("Usage: run_convert IN_FORMAT OUT_FORMAT <IN >OUT\n"); - return 1; - } - - g_log_set_default_handler(my_log_func, NULL); - - if (!audio_format_parse(&in_audio_format, argv[1], - false, &error)) { - g_printerr("Failed to parse audio format: %s\n", - error->message); - return 1; - } - - 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); - - struct fifo_buffer *buffer = fifo_buffer_new(4096); - - while (true) { - void *p = fifo_buffer_write(buffer, &length); - assert(p != NULL); - - nbytes = read(0, p, length); - if (nbytes <= 0) - break; - - fifo_buffer_append(buffer, nbytes); - - const void *src = fifo_buffer_read(buffer, &length); - assert(src != NULL); - - length -= length % in_frame_size; - if (length == 0) - continue; - - fifo_buffer_consume(buffer, length); - - output = pcm_convert(&state, &in_audio_format, src, length, - &out_audio_format, &length, &error); - if (output == NULL) { - g_printerr("Failed to convert: %s\n", error->message); - return 2; - } - - G_GNUC_UNUSED ssize_t ignored = write(1, output, length); - } - - pcm_convert_deinit(&state); -} diff --git a/test/run_convert.cxx b/test/run_convert.cxx new file mode 100644 index 000000000..e66d0be2b --- /dev/null +++ b/test/run_convert.cxx @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2003-2013 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. + */ + +/* + * This program is a command line interface to MPD's PCM conversion + * library (pcm_convert.c). + * + */ + +#include "config.h" +#include "AudioParser.hxx" +#include "audio_format.h" +#include "PcmConvert.hxx" +#include "conf.h" +#include "util/fifo_buffer.h" +#include "stdbin.h" + +#include <glib.h> + +#include <assert.h> +#include <stddef.h> +#include <unistd.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); +} + +const char * +config_get_string(gcc_unused enum ConfigOption option, + const char *default_value) +{ + return default_value; +} + +int main(int argc, char **argv) +{ + GError *error = NULL; + struct audio_format in_audio_format, out_audio_format; + const void *output; + ssize_t nbytes; + size_t length; + + if (argc != 3) { + g_printerr("Usage: run_convert IN_FORMAT OUT_FORMAT <IN >OUT\n"); + return 1; + } + + g_log_set_default_handler(my_log_func, NULL); + + if (!audio_format_parse(&in_audio_format, argv[1], + false, &error)) { + g_printerr("Failed to parse audio format: %s\n", + error->message); + return 1; + } + + 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); + + PcmConvert state; + + struct fifo_buffer *buffer = fifo_buffer_new(4096); + + while (true) { + void *p = fifo_buffer_write(buffer, &length); + assert(p != NULL); + + nbytes = read(0, p, length); + if (nbytes <= 0) + break; + + fifo_buffer_append(buffer, nbytes); + + const void *src = fifo_buffer_read(buffer, &length); + assert(src != NULL); + + length -= length % in_frame_size; + if (length == 0) + continue; + + fifo_buffer_consume(buffer, length); + + output = state.Convert(&in_audio_format, src, length, + &out_audio_format, &length, &error); + if (output == NULL) { + g_printerr("Failed to convert: %s\n", error->message); + return 2; + } + + G_GNUC_UNUSED ssize_t ignored = write(1, output, length); + } + + return EXIT_SUCCESS; +} diff --git a/test/run_decoder.c b/test/run_decoder.c deleted file mode 100644 index e6712c75b..000000000 --- a/test/run_decoder.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * 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 "decoder_list.h" -#include "decoder_api.h" -#include "tag_pool.h" -#include "input_init.h" -#include "input_stream.h" -#include "audio_format.h" -#include "pcm_volume.h" -#include "idle.h" -#include "stdbin.h" - -#include <glib.h> - -#include <assert.h> -#include <unistd.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); -} - -/** - * No-op dummy. - */ -void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - -/** - * No-op dummy. - */ -bool -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; -} - -struct decoder { - const char *uri; - - const struct decoder_plugin *plugin; - - bool initialized; -}; - -void -decoder_initialized(struct decoder *decoder, - const struct audio_format *audio_format, - G_GNUC_UNUSED bool seekable, - G_GNUC_UNUSED float total_time) -{ - struct audio_format_string af_string; - - assert(!decoder->initialized); - assert(audio_format_valid(audio_format)); - - g_printerr("audio_format=%s\n", - audio_format_to_string(audio_format, &af_string)); - - decoder->initialized = true; -} - -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) -{ - GError *error = NULL; - const char *decoder_name; - struct decoder decoder; - - if (argc != 3) { - g_printerr("Usage: run_decoder DECODER URI >OUT\n"); - return 1; - } - - 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; - } - - tag_pool_init(); - - if (!input_stream_global_init(&error)) { - g_warning("%s", error->message); - g_error_free(error); - return 2; - } - - decoder_plugin_init_all(); - - decoder.plugin = decoder_plugin_from_name(decoder_name); - if (decoder.plugin == NULL) { - g_printerr("No such decoder: %s\n", decoder_name); - return 1; - } - - decoder.initialized = false; - - if (decoder.plugin->file_decode != NULL) { - 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, mutex, cond, &error); - if (is == NULL) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } else - g_printerr("input_stream_open() failed\n"); - - return 1; - } - - 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; - } - - decoder_plugin_deinit_all(); - input_stream_global_finish(); - io_thread_deinit(); - - if (!decoder.initialized) { - g_printerr("Decoding failed\n"); - return 1; - } - - tag_pool_deinit(); - - return 0; -} diff --git a/test/run_decoder.cxx b/test/run_decoder.cxx new file mode 100644 index 000000000..d5c7c3139 --- /dev/null +++ b/test/run_decoder.cxx @@ -0,0 +1,222 @@ +/* + * 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 "IOThread.hxx" +#include "DecoderList.hxx" +#include "decoder_api.h" +#include "InputInit.hxx" +#include "input_stream.h" +#include "audio_format.h" +#include "stdbin.h" + +#include <glib.h> + +#include <assert.h> +#include <unistd.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); +} + +struct decoder { + const char *uri; + + const struct decoder_plugin *plugin; + + bool initialized; +}; + +void +decoder_initialized(struct decoder *decoder, + const struct audio_format *audio_format, + G_GNUC_UNUSED bool seekable, + G_GNUC_UNUSED float total_time) +{ + struct audio_format_string af_string; + + assert(!decoder->initialized); + assert(audio_format_valid(audio_format)); + + g_printerr("audio_format=%s\n", + audio_format_to_string(audio_format, &af_string)); + + decoder->initialized = true; +} + +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; +} + +void +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); +} + +void +decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, + char *mixramp_start, char *mixramp_end) +{ + g_free(mixramp_start); + g_free(mixramp_end); +} + +int main(int argc, char **argv) +{ + GError *error = NULL; + const char *decoder_name; + struct decoder decoder; + + if (argc != 3) { + g_printerr("Usage: run_decoder DECODER URI >OUT\n"); + return 1; + } + + 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); + return 2; + } + + decoder_plugin_init_all(); + + decoder.plugin = decoder_plugin_from_name(decoder_name); + if (decoder.plugin == NULL) { + g_printerr("No such decoder: %s\n", decoder_name); + return 1; + } + + decoder.initialized = false; + + if (decoder.plugin->file_decode != NULL) { + decoder_plugin_file_decode(decoder.plugin, &decoder, + decoder.uri); + } else if (decoder.plugin->stream_decode != NULL) { + Mutex mutex; + Cond cond; + + struct input_stream *is = + input_stream_open(decoder.uri, mutex, cond, &error); + if (is == NULL) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } else + g_printerr("input_stream_open() failed\n"); + + return 1; + } + + decoder_plugin_stream_decode(decoder.plugin, &decoder, is); + + input_stream_close(is); + } else { + g_printerr("Decoder plugin is not usable\n"); + return 1; + } + + decoder_plugin_deinit_all(); + input_stream_global_finish(); + io_thread_deinit(); + + if (!decoder.initialized) { + g_printerr("Decoding failed\n"); + return 1; + } + + return 0; +} diff --git a/test/run_encoder.c b/test/run_encoder.c deleted file mode 100644 index db4d3af9b..000000000 --- a/test/run_encoder.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 "encoder_list.h" -#include "encoder_plugin.h" -#include "audio_format.h" -#include "audio_parser.h" -#include "conf.h" -#include "stdbin.h" - -#include <glib.h> - -#include <stddef.h> -#include <unistd.h> - -static void -encoder_to_stdout(struct encoder *encoder) -{ - size_t length; - static char buffer[32768]; - - while ((length = encoder_read(encoder, buffer, sizeof(buffer))) > 0) { - G_GNUC_UNUSED ssize_t ignored = write(1, buffer, length); - } -} - -int main(int argc, char **argv) -{ - GError *error = NULL; - struct audio_format audio_format; - bool ret; - const char *encoder_name; - const struct encoder_plugin *plugin; - struct encoder *encoder; - struct config_param *param; - static char buffer[32768]; - ssize_t nbytes; - - /* parse command line */ - - if (argc > 3) { - g_printerr("Usage: run_encoder [ENCODER] [FORMAT] <IN >OUT\n"); - return 1; - } - - if (argc > 1) - encoder_name = argv[1]; - else - encoder_name = "vorbis"; - - audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); - - /* create the encoder */ - - plugin = encoder_plugin_get(encoder_name); - if (plugin == NULL) { - g_printerr("No such encoder: %s\n", encoder_name); - return 1; - } - - param = config_new_param(NULL, -1); - config_add_block_param(param, "quality", "5.0", -1); - - encoder = encoder_init(plugin, param, &error); - if (encoder == NULL) { - g_printerr("Failed to initialize encoder: %s\n", - error->message); - g_error_free(error); - return 1; - } - - /* open the encoder */ - - if (argc > 2) { - ret = audio_format_parse(&audio_format, argv[2], - false, &error); - if (!ret) { - g_printerr("Failed to parse audio format: %s\n", - error->message); - g_error_free(error); - return 1; - } - } - - if (!encoder_open(encoder, &audio_format, &error)) { - g_printerr("Failed to open encoder: %s\n", - error->message); - g_error_free(error); - return 1; - } - - encoder_to_stdout(encoder); - - /* do it */ - - while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { - ret = encoder_write(encoder, buffer, nbytes, &error); - if (!ret) { - g_printerr("encoder_write() failed: %s\n", - error->message); - g_error_free(error); - return 1; - } - - encoder_to_stdout(encoder); - } - - ret = encoder_end(encoder, &error); - if (!ret) { - g_printerr("encoder_flush() failed: %s\n", - error->message); - g_error_free(error); - return 1; - } - - encoder_to_stdout(encoder); -} diff --git a/test/run_encoder.cxx b/test/run_encoder.cxx new file mode 100644 index 000000000..9039f2db5 --- /dev/null +++ b/test/run_encoder.cxx @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2003-2013 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 "encoder_list.h" +#include "encoder_plugin.h" +#include "audio_format.h" +#include "AudioParser.hxx" +#include "conf.h" +#include "stdbin.h" + +#include <glib.h> + +#include <stddef.h> +#include <unistd.h> + +static void +encoder_to_stdout(struct encoder *encoder) +{ + size_t length; + static char buffer[32768]; + + while ((length = encoder_read(encoder, buffer, sizeof(buffer))) > 0) { + G_GNUC_UNUSED ssize_t ignored = write(1, buffer, length); + } +} + +int main(int argc, char **argv) +{ + GError *error = NULL; + struct audio_format audio_format; + bool ret; + const char *encoder_name; + const struct encoder_plugin *plugin; + struct encoder *encoder; + static char buffer[32768]; + + /* parse command line */ + + if (argc > 3) { + g_printerr("Usage: run_encoder [ENCODER] [FORMAT] <IN >OUT\n"); + return 1; + } + + if (argc > 1) + encoder_name = argv[1]; + else + encoder_name = "vorbis"; + + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); + + /* create the encoder */ + + plugin = encoder_plugin_get(encoder_name); + if (plugin == NULL) { + g_printerr("No such encoder: %s\n", encoder_name); + return 1; + } + + config_param param; + param.AddBlockParam("quality", "5.0", -1); + + encoder = encoder_init(plugin, ¶m, &error); + if (encoder == NULL) { + g_printerr("Failed to initialize encoder: %s\n", + error->message); + g_error_free(error); + return 1; + } + + /* open the encoder */ + + if (argc > 2) { + ret = audio_format_parse(&audio_format, argv[2], + false, &error); + if (!ret) { + g_printerr("Failed to parse audio format: %s\n", + error->message); + g_error_free(error); + return 1; + } + } + + if (!encoder_open(encoder, &audio_format, &error)) { + g_printerr("Failed to open encoder: %s\n", + error->message); + g_error_free(error); + return 1; + } + + encoder_to_stdout(encoder); + + /* do it */ + + ssize_t nbytes; + while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { + ret = encoder_write(encoder, buffer, nbytes, &error); + if (!ret) { + g_printerr("encoder_write() failed: %s\n", + error->message); + g_error_free(error); + return 1; + } + + encoder_to_stdout(encoder); + } + + ret = encoder_end(encoder, &error); + if (!ret) { + g_printerr("encoder_flush() failed: %s\n", + error->message); + g_error_free(error); + return 1; + } + + encoder_to_stdout(encoder); +} diff --git a/test/run_filter.c b/test/run_filter.c deleted file mode 100644 index 8e793b768..000000000 --- a/test/run_filter.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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 "conf.h" -#include "audio_parser.h" -#include "audio_format.h" -#include "filter_plugin.h" -#include "pcm_volume.h" -#include "idle.h" -#include "mixer_control.h" -#include "playlist.h" -#include "stdbin.h" - -#include <glib.h> - -#include <assert.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -struct playlist g_playlist; - -void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - -bool -mixer_set_volume(G_GNUC_UNUSED struct mixer *mixer, - G_GNUC_UNUSED unsigned volume, G_GNUC_UNUSED GError **error_r) -{ - return true; -} - -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 const struct config_param * -find_named_config_block(const char *block, const char *name) -{ - const struct config_param *param = NULL; - - while ((param = config_get_next_param(block, param)) != NULL) { - const char *current_name = - config_get_block_string(param, "name", NULL); - if (current_name != NULL && strcmp(current_name, name) == 0) - return param; - } - - return NULL; -} - -static struct filter * -load_filter(const char *name) -{ - const struct config_param *param; - struct filter *filter; - GError *error = NULL; - - param = find_named_config_block("filter", name); - if (param == NULL) { - g_printerr("No such configured filter: %s\n", name); - return false; - } - - filter = filter_configured_new(param, &error); - if (filter == NULL) { - g_printerr("Failed to load filter: %s\n", error->message); - g_error_free(error); - return NULL; - } - - return filter; -} - -int main(int argc, char **argv) -{ - struct audio_format audio_format; - struct audio_format_string af_string; - bool success; - GError *error = NULL; - struct filter *filter; - const struct audio_format *out_audio_format; - char buffer[4096]; - - if (argc < 3 || argc > 4) { - g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n"); - return 1; - } - - audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); - - /* initialize GLib */ - - g_thread_init(NULL); - g_log_set_default_handler(my_log_func, NULL); - - /* read configuration file (mpd.conf) */ - - config_global_init(); - success = config_read_file(argv[1], &error); - if (!success) { - g_printerr("%s:", error->message); - g_error_free(error); - return 1; - } - - /* parse the audio format */ - - if (argc > 3) { - success = audio_format_parse(&audio_format, argv[3], - false, &error); - if (!success) { - g_printerr("Failed to parse audio format: %s\n", - error->message); - g_error_free(error); - return 1; - } - } - - /* initialize the filter */ - - filter = load_filter(argv[2]); - if (filter == NULL) - return 1; - - /* open the filter */ - - out_audio_format = filter_open(filter, &audio_format, &error); - if (out_audio_format == NULL) { - g_printerr("Failed to open filter: %s\n", error->message); - g_error_free(error); - filter_free(filter); - return 1; - } - - g_printerr("audio_format=%s\n", - audio_format_to_string(out_audio_format, &af_string)); - - /* play */ - - while (true) { - ssize_t nbytes; - size_t length; - const void *dest; - - nbytes = read(0, buffer, sizeof(buffer)); - if (nbytes <= 0) - break; - - dest = filter_filter(filter, buffer, (size_t)nbytes, - &length, &error); - if (dest == NULL) { - g_printerr("Filter failed: %s\n", error->message); - filter_close(filter); - filter_free(filter); - return 1; - } - - nbytes = write(1, dest, length); - if (nbytes < 0) { - g_printerr("Failed to write: %s\n", g_strerror(errno)); - filter_close(filter); - filter_free(filter); - return 1; - } - } - - /* cleanup and exit */ - - filter_close(filter); - filter_free(filter); - - config_global_finish(); - - return 0; -} diff --git a/test/run_filter.cxx b/test/run_filter.cxx new file mode 100644 index 000000000..9ea50ff55 --- /dev/null +++ b/test/run_filter.cxx @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2003-2013 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 "conf.h" +#include "fs/Path.hxx" +#include "AudioParser.hxx" +#include "audio_format.h" +#include "FilterPlugin.hxx" +#include "FilterInternal.hxx" +#include "PcmVolume.hxx" +#include "MixerControl.hxx" +#include "stdbin.h" + +#include <glib.h> + +#include <assert.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +bool +mixer_set_volume(G_GNUC_UNUSED struct mixer *mixer, + G_GNUC_UNUSED unsigned volume, G_GNUC_UNUSED GError **error_r) +{ + return true; +} + +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 const struct config_param * +find_named_config_block(ConfigOption option, const char *name) +{ + const struct config_param *param = NULL; + + while ((param = config_get_next_param(option, param)) != NULL) { + const char *current_name = + config_get_block_string(param, "name", NULL); + if (current_name != NULL && strcmp(current_name, name) == 0) + return param; + } + + return NULL; +} + +static Filter * +load_filter(const char *name) +{ + const struct config_param *param; + GError *error = NULL; + + param = find_named_config_block(CONF_AUDIO_FILTER, name); + if (param == NULL) { + g_printerr("No such configured filter: %s\n", name); + return nullptr; + } + + Filter *filter = filter_configured_new(param, &error); + if (filter == NULL) { + g_printerr("Failed to load filter: %s\n", error->message); + g_error_free(error); + return NULL; + } + + return filter; +} + +int main(int argc, char **argv) +{ + struct audio_format audio_format; + struct audio_format_string af_string; + bool success; + GError *error = NULL; + const struct audio_format *out_audio_format; + char buffer[4096]; + + if (argc < 3 || argc > 4) { + g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n"); + return 1; + } + + const Path config_path = Path::FromFS(argv[1]); + + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); + + /* initialize GLib */ + + g_thread_init(NULL); + g_log_set_default_handler(my_log_func, NULL); + + /* read configuration file (mpd.conf) */ + + config_global_init(); + if (!ReadConfigFile(config_path, &error)) { + g_printerr("%s:", error->message); + g_error_free(error); + return 1; + } + + /* parse the audio format */ + + if (argc > 3) { + success = audio_format_parse(&audio_format, argv[3], + false, &error); + if (!success) { + g_printerr("Failed to parse audio format: %s\n", + error->message); + g_error_free(error); + return 1; + } + } + + /* initialize the filter */ + + Filter *filter = load_filter(argv[2]); + if (filter == NULL) + return 1; + + /* open the filter */ + + out_audio_format = filter->Open(audio_format, &error); + if (out_audio_format == NULL) { + g_printerr("Failed to open filter: %s\n", error->message); + g_error_free(error); + delete filter; + return 1; + } + + g_printerr("audio_format=%s\n", + audio_format_to_string(out_audio_format, &af_string)); + + /* play */ + + while (true) { + ssize_t nbytes; + size_t length; + const void *dest; + + nbytes = read(0, buffer, sizeof(buffer)); + if (nbytes <= 0) + break; + + dest = filter->FilterPCM(buffer, (size_t)nbytes, + &length, &error); + if (dest == NULL) { + g_printerr("Filter failed: %s\n", error->message); + filter->Close(); + delete filter; + return 1; + } + + nbytes = write(1, dest, length); + if (nbytes < 0) { + g_printerr("Failed to write: %s\n", g_strerror(errno)); + filter->Close(); + delete filter; + return 1; + } + } + + /* cleanup and exit */ + + filter->Close(); + delete filter; + + config_global_finish(); + + return 0; +} diff --git a/test/run_inotify.c b/test/run_inotify.c deleted file mode 100644 index 3e7c70dba..000000000 --- a/test/run_inotify.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 "inotify_source.h" - -#include <stdbool.h> -#include <sys/inotify.h> -#include <signal.h> - -static GMainLoop *main_loop; - -static void -exit_signal_handler(G_GNUC_UNUSED int signum) -{ - g_main_loop_quit(main_loop); -} - -enum { - IN_MASK = IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF - |IN_MOVE|IN_MOVE_SELF -#ifdef IN_ONLYDIR - |IN_ONLYDIR -#endif -}; - -static void -my_inotify_callback(G_GNUC_UNUSED int wd, unsigned mask, - const char *name, G_GNUC_UNUSED void *ctx) -{ - g_print("mask=0x%x name='%s'\n", mask, name); -} - -int main(int argc, char **argv) -{ - GError *error = NULL; - const char *path; - - if (argc != 2) { - g_printerr("Usage: run_inotify PATH\n"); - return 1; - } - - path = argv[1]; - - struct mpd_inotify_source *source = - mpd_inotify_source_new(my_inotify_callback, NULL, - &error); - if (source == NULL) { - g_warning("%s", error->message); - g_error_free(error); - return 2; - } - - int descriptor = mpd_inotify_source_add(source, path, - IN_MASK, &error); - if (descriptor < 0) { - mpd_inotify_source_free(source); - g_warning("%s", error->message); - g_error_free(error); - return 2; - } - - main_loop = g_main_loop_new(NULL, false); - - struct sigaction sa; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = exit_signal_handler; - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - - g_main_loop_run(main_loop); - g_main_loop_unref(main_loop); - - mpd_inotify_source_free(source); -} diff --git a/test/run_inotify.cxx b/test/run_inotify.cxx new file mode 100644 index 000000000..29fcf70ab --- /dev/null +++ b/test/run_inotify.cxx @@ -0,0 +1,94 @@ +/* + * 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 "InotifySource.hxx" +#include "event/Loop.hxx" + +#include <glib.h> + +#include <sys/inotify.h> +#include <signal.h> + +static EventLoop *event_loop; + +static void +exit_signal_handler(G_GNUC_UNUSED int signum) +{ + event_loop->Break(); +} + +enum { + IN_MASK = IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF + |IN_MOVE|IN_MOVE_SELF +#ifdef IN_ONLYDIR + |IN_ONLYDIR +#endif +}; + +static void +my_inotify_callback(G_GNUC_UNUSED int wd, unsigned mask, + const char *name, G_GNUC_UNUSED void *ctx) +{ + g_print("mask=0x%x name='%s'\n", mask, name); +} + +int main(int argc, char **argv) +{ + GError *error = NULL; + const char *path; + + if (argc != 2) { + g_printerr("Usage: run_inotify PATH\n"); + return 1; + } + + path = argv[1]; + + event_loop = new EventLoop(EventLoop::Default()); + + InotifySource *source = InotifySource::Create(*event_loop, + my_inotify_callback, + nullptr, &error); + if (source == NULL) { + g_warning("%s", error->message); + g_error_free(error); + return 2; + } + + int descriptor = source->Add(path, IN_MASK, &error); + if (descriptor < 0) { + delete source; + g_warning("%s", error->message); + g_error_free(error); + return 2; + } + + struct sigaction sa; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = exit_signal_handler; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + event_loop->Run(); + + delete source; + delete event_loop; +} diff --git a/test/run_input.c b/test/run_input.c deleted file mode 100644 index 676e4e618..000000000 --- a/test/run_input.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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 "tag_pool.h" -#include "tag_save.h" -#include "conf.h" -#include "stdbin.h" - -#ifdef ENABLE_ARCHIVE -#include "archive_list.h" -#endif - -#include <glib.h> - -#include <unistd.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 int -dump_input_stream(struct input_stream *is) -{ - GError *error = NULL; - char buffer[4096]; - size_t num_read; - ssize_t num_written; - - 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; - } - - /* print meta data */ - - if (is->mime != NULL) - g_printerr("MIME type: %s\n", is->mime); - - /* read data and tags from the stream */ - - while (!input_stream_eof(is)) { - struct tag *tag = input_stream_tag(is); - if (tag != NULL) { - g_printerr("Received a tag:\n"); - tag_save(stderr, tag); - tag_free(tag); - } - - num_read = input_stream_read(is, buffer, sizeof(buffer), - &error); - if (num_read == 0) { - if (error != NULL) { - g_warning("%s", error->message); - g_error_free(error); - } - - break; - } - - num_written = write(1, buffer, num_read); - if (num_written <= 0) - 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; -} - -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/run_input.cxx b/test/run_input.cxx new file mode 100644 index 000000000..157613dbc --- /dev/null +++ b/test/run_input.cxx @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2003-2013 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 "TagSave.hxx" +#include "stdbin.h" +#include "tag.h" +#include "conf.h" +#include "input_stream.h" +#include "InputStream.hxx" +#include "InputInit.hxx" +#include "IOThread.hxx" + +#ifdef ENABLE_ARCHIVE +#include "ArchiveList.hxx" +#endif + +#include <glib.h> + +#include <unistd.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 int +dump_input_stream(struct input_stream *is) +{ + GError *error = NULL; + char buffer[4096]; + size_t num_read; + ssize_t num_written; + + 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; + } + + /* print meta data */ + + if (!is->mime.empty()) + g_printerr("MIME type: %s\n", is->mime.c_str()); + + /* read data and tags from the stream */ + + while (!input_stream_eof(is)) { + struct tag *tag = input_stream_tag(is); + if (tag != NULL) { + g_printerr("Received a tag:\n"); + tag_save(stderr, tag); + tag_free(tag); + } + + num_read = input_stream_read(is, buffer, sizeof(buffer), + &error); + if (num_read == 0) { + if (error != NULL) { + g_warning("%s", error->message); + g_error_free(error); + } + + break; + } + + num_written = write(1, buffer, num_read); + if (num_written <= 0) + 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; +} + +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 */ + + 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 */ + + Mutex mutex; + Cond cond; + + 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; + } + + /* deinitialize everything */ + + input_stream_global_finish(); + +#ifdef ENABLE_ARCHIVE + archive_plugin_deinit_all(); +#endif + + io_thread_deinit(); + + config_global_finish(); + + return ret; +} diff --git a/test/run_normalize.c b/test/run_normalize.c deleted file mode 100644 index fc26829ed..000000000 --- a/test/run_normalize.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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. - */ - -/* - * This program is a command line interface to MPD's normalize library - * (based on AudioCompress). - * - */ - -#include "config.h" -#include "AudioCompress/compress.h" -#include "audio_parser.h" -#include "audio_format.h" -#include "stdbin.h" - -#include <glib.h> - -#include <stddef.h> -#include <unistd.h> -#include <string.h> - -int main(int argc, char **argv) -{ - GError *error = NULL; - struct audio_format audio_format; - bool ret; - struct Compressor *compressor; - static char buffer[4096]; - ssize_t nbytes; - - if (argc > 2) { - g_printerr("Usage: run_normalize [FORMAT] <IN >OUT\n"); - return 1; - } - - if (argc > 1) { - ret = audio_format_parse(&audio_format, argv[1], - false, &error); - if (!ret) { - g_printerr("Failed to parse audio format: %s\n", - error->message); - return 1; - } - } else - audio_format_init(&audio_format, 48000, 16, 2); - - compressor = Compressor_new(0); - - while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { - Compressor_Process_int16(compressor, - (int16_t *)buffer, nbytes / 2); - - G_GNUC_UNUSED ssize_t ignored = write(1, buffer, nbytes); - } - - Compressor_delete(compressor); -} diff --git a/test/run_normalize.cxx b/test/run_normalize.cxx new file mode 100644 index 000000000..070dbaf5a --- /dev/null +++ b/test/run_normalize.cxx @@ -0,0 +1,73 @@ +/* + * 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. + */ + +/* + * This program is a command line interface to MPD's normalize library + * (based on AudioCompress). + * + */ + +#include "config.h" +#include "AudioCompress/compress.h" +#include "AudioParser.hxx" +#include "audio_format.h" +#include "stdbin.h" + +#include <glib.h> + +#include <stddef.h> +#include <unistd.h> +#include <string.h> + +int main(int argc, char **argv) +{ + GError *error = NULL; + struct audio_format audio_format; + bool ret; + struct Compressor *compressor; + static char buffer[4096]; + ssize_t nbytes; + + if (argc > 2) { + g_printerr("Usage: run_normalize [FORMAT] <IN >OUT\n"); + return 1; + } + + if (argc > 1) { + ret = audio_format_parse(&audio_format, argv[1], + false, &error); + if (!ret) { + g_printerr("Failed to parse audio format: %s\n", + error->message); + return 1; + } + } else + audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, 2); + + compressor = Compressor_new(0); + + while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { + Compressor_Process_int16(compressor, + (int16_t *)buffer, nbytes / 2); + + G_GNUC_UNUSED ssize_t ignored = write(1, buffer, nbytes); + } + + Compressor_delete(compressor); +} diff --git a/test/run_output.c b/test/run_output.c deleted file mode 100644 index bbb1be7d2..000000000 --- a/test/run_output.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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 "output_plugin.h" -#include "output_internal.h" -#include "output_control.h" -#include "conf.h" -#include "audio_parser.h" -#include "filter_registry.h" -#include "pcm_convert.h" -#include "event_pipe.h" -#include "idle.h" -#include "playlist.h" -#include "player_control.h" -#include "stdbin.h" - -#include <glib.h> - -#include <assert.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> - -struct playlist g_playlist; - -void -idle_add(G_GNUC_UNUSED unsigned flags) -{ -} - -void -event_pipe_emit(G_GNUC_UNUSED enum pipe_event event) -{ -} - -void pcm_convert_init(G_GNUC_UNUSED struct pcm_convert_state *state) -{ -} - -void pcm_convert_deinit(G_GNUC_UNUSED struct pcm_convert_state *state) -{ -} - -const void * -pcm_convert(G_GNUC_UNUSED struct pcm_convert_state *state, - G_GNUC_UNUSED const struct audio_format *src_format, - G_GNUC_UNUSED const void *src, G_GNUC_UNUSED size_t src_size, - G_GNUC_UNUSED const struct audio_format *dest_format, - G_GNUC_UNUSED size_t *dest_size_r, - GError **error_r) -{ - g_set_error(error_r, pcm_convert_quark(), 0, - "Not implemented"); - return NULL; -} - -const struct filter_plugin * -filter_plugin_by_name(G_GNUC_UNUSED const char *name) -{ - assert(false); - return NULL; -} - -static const struct config_param * -find_named_config_block(const char *block, const char *name) -{ - const struct config_param *param = NULL; - - while ((param = config_get_next_param(block, param)) != NULL) { - const char *current_name = - config_get_block_string(param, "name", NULL); - if (current_name != NULL && strcmp(current_name, name) == 0) - return param; - } - - return NULL; -} - -static struct audio_output * -load_audio_output(const char *name) -{ - const struct config_param *param; - GError *error = NULL; - - param = find_named_config_block(CONF_AUDIO_OUTPUT, name); - if (param == NULL) { - g_printerr("No such configured audio output: %s\n", name); - return false; - } - - 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 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_format audio_format; - bool success; - GError *error = NULL; - - if (argc < 3 || argc > 4) { - g_printerr("Usage: run_output CONFIG NAME [FORMAT] <IN\n"); - return 1; - } - - audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); - - g_thread_init(NULL); - - /* read configuration file (mpd.conf) */ - - config_global_init(); - success = config_read_file(argv[1], &error); - if (!success) { - g_printerr("%s:", error->message); - g_error_free(error); - return 1; - } - - io_thread_init(); - if (!io_thread_start(&error)) { - g_warning("%s", error->message); - g_error_free(error); - return EXIT_FAILURE; - } - - /* initialize the audio output */ - - struct audio_output *ao = load_audio_output(argv[2]); - if (ao == NULL) - return 1; - - /* parse the audio format */ - - if (argc > 3) { - success = audio_format_parse(&audio_format, argv[3], - false, &error); - if (!success) { - g_printerr("Failed to parse audio format: %s\n", - error->message); - g_error_free(error); - return 1; - } - } - - /* do it */ - - success = run_output(ao, &audio_format); - - /* cleanup and exit */ - - audio_output_free(ao); - - io_thread_deinit(); - - config_global_finish(); - - return success ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/test/run_output.cxx b/test/run_output.cxx new file mode 100644 index 000000000..5b6d54a11 --- /dev/null +++ b/test/run_output.cxx @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2003-2013 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 "OutputControl.hxx" +#include "conf.h" +#include "Idle.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" +#include "GlobalEvents.hxx" +#include "IOThread.hxx" +#include "fs/Path.hxx" +#include "AudioParser.hxx" +#include "PcmConvert.hxx" + +extern "C" { +#include "output_plugin.h" +#include "output_internal.h" +} + +#include "FilterRegistry.hxx" +#include "PlayerControl.hxx" +#include "stdbin.h" + +#include <glib.h> + +#include <assert.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> + +EventLoop *main_loop; + +void +GlobalEvents::Emit(gcc_unused Event event) +{ +} + +PcmConvert::PcmConvert() {} +PcmConvert::~PcmConvert() {} + +const void * +PcmConvert::Convert(gcc_unused const audio_format *src_format, + gcc_unused const void *src, gcc_unused size_t src_size, + gcc_unused const audio_format *dest_format, + gcc_unused size_t *dest_size_r, + gcc_unused GError **error_r) +{ + g_set_error(error_r, pcm_convert_quark(), 0, + "Not implemented"); + return NULL; +} + +const struct filter_plugin * +filter_plugin_by_name(G_GNUC_UNUSED const char *name) +{ + assert(false); + return NULL; +} + +static const struct config_param * +find_named_config_block(ConfigOption option, const char *name) +{ + const struct config_param *param = NULL; + + while ((param = config_get_next_param(option, param)) != NULL) { + const char *current_name = + config_get_block_string(param, "name", NULL); + if (current_name != NULL && strcmp(current_name, name) == 0) + return param; + } + + return NULL; +} + +player_control::player_control(gcc_unused unsigned _buffer_chunks, + gcc_unused unsigned _buffered_before_play) {} +player_control::~player_control() {} + +static struct audio_output * +load_audio_output(const char *name) +{ + const struct config_param *param; + GError *error = NULL; + + param = find_named_config_block(CONF_AUDIO_OUTPUT, name); + if (param == NULL) { + g_printerr("No such configured audio output: %s\n", name); + return nullptr; + } + + static struct player_control dummy_player_control(32, 4); + + 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 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_format audio_format; + bool success; + GError *error = NULL; + + if (argc < 3 || argc > 4) { + g_printerr("Usage: run_output CONFIG NAME [FORMAT] <IN\n"); + return 1; + } + + const Path config_path = Path::FromFS(argv[1]); + + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); + + g_thread_init(NULL); + + /* read configuration file (mpd.conf) */ + + config_global_init(); + if (!ReadConfigFile(config_path, &error)) { + g_printerr("%s:", error->message); + g_error_free(error); + return 1; + } + + main_loop = new EventLoop(EventLoop::Default()); + + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + /* initialize the audio output */ + + struct audio_output *ao = load_audio_output(argv[2]); + if (ao == NULL) + return 1; + + /* parse the audio format */ + + if (argc > 3) { + success = audio_format_parse(&audio_format, argv[3], + false, &error); + if (!success) { + g_printerr("Failed to parse audio format: %s\n", + error->message); + g_error_free(error); + return 1; + } + } + + /* do it */ + + success = run_output(ao, &audio_format); + + /* cleanup and exit */ + + audio_output_free(ao); + + io_thread_deinit(); + + delete main_loop; + + config_global_finish(); + + return success ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/run_tcp_connect.c b/test/run_tcp_connect.c deleted file mode 100644 index bf8d9b82f..000000000 --- a/test/run_tcp_connect.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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/software_volume.c b/test/software_volume.c deleted file mode 100644 index 2357da672..000000000 --- a/test/software_volume.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ - -/* - * This program is a command line interface to MPD's software volume - * library (pcm_volume.c). - * - */ - -#include "config.h" -#include "pcm_volume.h" -#include "audio_parser.h" -#include "audio_format.h" -#include "stdbin.h" - -#include <glib.h> - -#include <stddef.h> -#include <unistd.h> - -int main(int argc, char **argv) -{ - GError *error = NULL; - struct audio_format audio_format; - bool ret; - static char buffer[4096]; - ssize_t nbytes; - - if (argc > 2) { - g_printerr("Usage: software_volume [FORMAT] <IN >OUT\n"); - return 1; - } - - if (argc > 1) { - ret = audio_format_parse(&audio_format, argv[1], - false, &error); - if (!ret) { - g_printerr("Failed to parse audio format: %s\n", - error->message); - return 1; - } - } else - 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.format, - PCM_VOLUME_1 / 2)) { - g_printerr("pcm_volume() has failed\n"); - return 2; - } - - G_GNUC_UNUSED ssize_t ignored = write(1, buffer, nbytes); - } -} diff --git a/test/software_volume.cxx b/test/software_volume.cxx new file mode 100644 index 000000000..929932398 --- /dev/null +++ b/test/software_volume.cxx @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003-2013 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. + */ + +/* + * This program is a command line interface to MPD's software volume + * library (pcm_volume.c). + * + */ + +#include "config.h" +#include "PcmVolume.hxx" +#include "AudioParser.hxx" +#include "audio_format.h" +#include "stdbin.h" + +#include <glib.h> + +#include <stddef.h> +#include <unistd.h> + +int main(int argc, char **argv) +{ + GError *error = NULL; + struct audio_format audio_format; + bool ret; + static char buffer[4096]; + ssize_t nbytes; + + if (argc > 2) { + g_printerr("Usage: software_volume [FORMAT] <IN >OUT\n"); + return 1; + } + + if (argc > 1) { + ret = audio_format_parse(&audio_format, argv[1], + false, &error); + if (!ret) { + g_printerr("Failed to parse audio format: %s\n", + error->message); + return 1; + } + } else + audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, 2); + + while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { + if (!pcm_volume(buffer, nbytes, + sample_format(audio_format.format), + PCM_VOLUME_1 / 2)) { + g_printerr("pcm_volume() has failed\n"); + return 2; + } + + G_GNUC_UNUSED ssize_t ignored = write(1, buffer, nbytes); + } +} diff --git a/test/test_pcm_all.h b/test/test_pcm_all.h deleted file mode 100644 index 493619b55..000000000 --- a/test/test_pcm_all.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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_volume_8(void); - -void -test_pcm_volume_16(void); - -void -test_pcm_volume_24(void); - -void -test_pcm_volume_32(void); - -void -test_pcm_volume_float(void); - -#endif diff --git a/test/test_pcm_all.hxx b/test/test_pcm_all.hxx new file mode 100644 index 000000000..18202454b --- /dev/null +++ b/test/test_pcm_all.hxx @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2003-2013 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_HXX +#define MPD_TEST_PCM_ALL_HXX + +void +test_pcm_dither_24(); + +void +test_pcm_dither_32(); + +void +test_pcm_pack_24(); + +void +test_pcm_unpack_24(); + +void +test_pcm_channels_16(); + +void +test_pcm_channels_32(); + +void +test_pcm_volume_8(); + +void +test_pcm_volume_16(); + +void +test_pcm_volume_24(); + +void +test_pcm_volume_32(); + +void +test_pcm_volume_float(); + +void +test_pcm_format_8_to_16(); + +void +test_pcm_format_16_to_24(); + +void +test_pcm_format_16_to_32(); + +void +test_pcm_format_float(); + +void +test_pcm_mix_8(); + +void +test_pcm_mix_16(); + +void +test_pcm_mix_24(); + +void +test_pcm_mix_32(); + +#endif diff --git a/test/test_pcm_channels.c b/test/test_pcm_channels.c deleted file mode 100644 index fb3ec5c3e..000000000 --- a/test/test_pcm_channels.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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_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_channels.cxx b/test/test_pcm_channels.cxx new file mode 100644 index 000000000..8e013d5af --- /dev/null +++ b/test/test_pcm_channels.cxx @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2003-2013 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.hxx" +#include "test_pcm_util.hxx" +#include "PcmChannels.hxx" +#include "pcm_buffer.h" + +#include <glib.h> + +void +test_pcm_channels_16() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int16_t, N * 2>(); + + 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() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int32_t, N * 2>(); + + 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 deleted file mode 100644 index 44d105207..000000000 --- a/test/test_pcm_dither.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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_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_dither.cxx b/test/test_pcm_dither.cxx new file mode 100644 index 000000000..2fb976db5 --- /dev/null +++ b/test/test_pcm_dither.cxx @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2003-2013 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.hxx" +#include "test_pcm_util.hxx" +#include "PcmDither.hxx" + +#include <glib.h> + +void +test_pcm_dither_24() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int32_t, N>(GlibRandomInt24()); + + int16_t dest[N]; + PcmDither dither; + dither.Dither24To16(dest, src.begin(), src.end()); + + 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() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int32_t, N>(); + + int16_t dest[N]; + PcmDither dither; + dither.Dither32To16(dest, src.begin(), src.end()); + + 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_format.cxx b/test/test_pcm_format.cxx new file mode 100644 index 000000000..f175a850c --- /dev/null +++ b/test/test_pcm_format.cxx @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2003-2013 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.hxx" +#include "test_pcm_util.hxx" +#include "PcmFormat.hxx" +#include "PcmDither.hxx" +#include "PcmUtils.hxx" +#include "pcm_buffer.h" +#include "audio_format.h" + +#include <glib.h> + +void +test_pcm_format_8_to_16() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int8_t, N>(); + + struct pcm_buffer buffer; + pcm_buffer_init(&buffer); + + size_t d_size; + PcmDither dither; + auto d = pcm_convert_to_16(&buffer, dither, SAMPLE_FORMAT_S8, + src, sizeof(src), &d_size); + auto d_end = pcm_end_pointer(d, d_size); + g_assert_cmpint(d_end - d, ==, N); + + for (size_t i = 0; i < N; ++i) + g_assert_cmpint(src[i], ==, d[i] >> 8); + + pcm_buffer_deinit(&buffer); +} + +void +test_pcm_format_16_to_24() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int16_t, N>(); + + struct pcm_buffer buffer; + pcm_buffer_init(&buffer); + + size_t d_size; + auto d = pcm_convert_to_24(&buffer, SAMPLE_FORMAT_S16, + src, sizeof(src), &d_size); + auto d_end = pcm_end_pointer(d, d_size); + g_assert_cmpint(d_end - d, ==, N); + + for (size_t i = 0; i < N; ++i) + g_assert_cmpint(src[i], ==, d[i] >> 8); + + pcm_buffer_deinit(&buffer); +} + +void +test_pcm_format_16_to_32() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int16_t, N>(); + + struct pcm_buffer buffer; + pcm_buffer_init(&buffer); + + size_t d_size; + auto d = pcm_convert_to_32(&buffer, SAMPLE_FORMAT_S16, + src, sizeof(src), &d_size); + auto d_end = pcm_end_pointer(d, d_size); + g_assert_cmpint(d_end - d, ==, N); + + for (size_t i = 0; i < N; ++i) + g_assert_cmpint(src[i], ==, d[i] >> 16); + + pcm_buffer_deinit(&buffer); +} + +void +test_pcm_format_float() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int16_t, N>(); + + struct pcm_buffer buffer1, buffer2; + pcm_buffer_init(&buffer1); + pcm_buffer_init(&buffer2); + + size_t f_size; + auto f = pcm_convert_to_float(&buffer1, SAMPLE_FORMAT_S16, + src, sizeof(src), &f_size); + auto f_end = pcm_end_pointer(f, f_size); + g_assert_cmpint(f_end - f, ==, N); + + for (auto i = f; i != f_end; ++i) { + g_assert(*i >= -1.); + g_assert(*i <= 1.); + } + + PcmDither dither; + + size_t d_size; + auto d = pcm_convert_to_16(&buffer2, dither, + SAMPLE_FORMAT_FLOAT, + f, f_size, &d_size); + auto d_end = pcm_end_pointer(d, d_size); + g_assert_cmpint(d_end - d, ==, N); + + for (size_t i = 0; i < N; ++i) + g_assert_cmpint(src[i], ==, d[i]); + + pcm_buffer_deinit(&buffer1); + pcm_buffer_deinit(&buffer2); +} diff --git a/test/test_pcm_main.c b/test/test_pcm_main.c deleted file mode 100644 index a483baaab..000000000 --- a/test/test_pcm_main.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 <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/volume/8", test_pcm_volume_8); - g_test_add_func("/pcm/volume/16", test_pcm_volume_16); - g_test_add_func("/pcm/volume/24", test_pcm_volume_24); - g_test_add_func("/pcm/volume/32", test_pcm_volume_32); - g_test_add_func("/pcm/volume/float", test_pcm_volume_float); - - g_test_run(); -} diff --git a/test/test_pcm_main.cxx b/test/test_pcm_main.cxx new file mode 100644 index 000000000..a221b26af --- /dev/null +++ b/test/test_pcm_main.cxx @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2003-2013 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.hxx" + +#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/volume/8", test_pcm_volume_8); + g_test_add_func("/pcm/volume/16", test_pcm_volume_16); + g_test_add_func("/pcm/volume/24", test_pcm_volume_24); + g_test_add_func("/pcm/volume/32", test_pcm_volume_32); + g_test_add_func("/pcm/volume/float", test_pcm_volume_float); + + g_test_add_func("/pcm/format/8_to_16", test_pcm_format_8_to_16); + g_test_add_func("/pcm/format/16_to_24", test_pcm_format_16_to_24); + g_test_add_func("/pcm/format/16_to_32", test_pcm_format_16_to_32); + g_test_add_func("/pcm/format/float", test_pcm_format_float); + + g_test_add_func("/pcm/mix/8", test_pcm_mix_8); + g_test_add_func("/pcm/mix/16", test_pcm_mix_16); + g_test_add_func("/pcm/mix/24", test_pcm_mix_24); + g_test_add_func("/pcm/mix/32", test_pcm_mix_32); + + g_test_run(); +} diff --git a/test/test_pcm_mix.cxx b/test/test_pcm_mix.cxx new file mode 100644 index 000000000..a6e01d20f --- /dev/null +++ b/test/test_pcm_mix.cxx @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2003-2013 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.hxx" +#include "test_pcm_util.hxx" +#include "PcmMix.hxx" + +#include <glib.h> + +template<typename T, sample_format format, typename G=GlibRandomInt<T>> +void +TestPcmMix(G g=G()) +{ + constexpr unsigned N = 256; + const auto src1 = TestDataBuffer<T, N>(g); + const auto src2 = TestDataBuffer<T, N>(g); + + /* portion1=1.0: result must be equal to src1 */ + auto result = src1; + bool success = pcm_mix(result.begin(), src2.begin(), sizeof(result), + format, 1.0); + g_assert(success); + AssertEqualWithTolerance(result, src1, 1); + + /* portion1=0.0: result must be equal to src2 */ + result = src1; + success = pcm_mix(result.begin(), src2.begin(), sizeof(result), + format, 0.0); + g_assert(success); + AssertEqualWithTolerance(result, src2, 1); + + /* portion1=0.5 */ + result = src1; + success = pcm_mix(result.begin(), src2.begin(), sizeof(result), + format, 0.5); + g_assert(success); + + auto expected = src1; + for (unsigned i = 0; i < N; ++i) + expected[i] = (int64_t(src1[i]) + int64_t(src2[i])) / 2; + + AssertEqualWithTolerance(result, expected, 1); +} + +void +test_pcm_mix_8() +{ + TestPcmMix<int8_t, SAMPLE_FORMAT_S8>(); +} + +void +test_pcm_mix_16() +{ + TestPcmMix<int16_t, SAMPLE_FORMAT_S16>(); +} + +void +test_pcm_mix_24() +{ + TestPcmMix<int32_t, SAMPLE_FORMAT_S24_P32>(GlibRandomInt24()); +} + +void +test_pcm_mix_32() +{ + TestPcmMix<int32_t, SAMPLE_FORMAT_S32>(); +} diff --git a/test/test_pcm_pack.c b/test/test_pcm_pack.c deleted file mode 100644 index 5127536fb..000000000 --- a/test/test_pcm_pack.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 <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_pcm_pack.cxx b/test/test_pcm_pack.cxx new file mode 100644 index 000000000..e23acad58 --- /dev/null +++ b/test/test_pcm_pack.cxx @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2003-2013 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.hxx" +#include "test_pcm_util.hxx" + +extern "C" { +#include "pcm_pack.h" +} + +#include <glib.h> + +void +test_pcm_pack_24() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<int32_t, N>(GlibRandomInt24()); + + uint8_t dest[N * 3]; + pcm_pack_24(dest, src.begin(), src.end()); + + 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() +{ + constexpr unsigned N = 256; + const auto src = TestDataBuffer<uint8_t, N * 3>(); + + int32_t dest[N]; + pcm_unpack_24(dest, src.begin(), src.end()); + + 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_pcm_util.hxx b/test/test_pcm_util.hxx new file mode 100644 index 000000000..84ba074fd --- /dev/null +++ b/test/test_pcm_util.hxx @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2003-2013 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 <glib.h> + +#include <array> + +#include <stddef.h> +#include <stdint.h> + +template<typename T> +struct GlibRandomInt { + T operator()() const { + return T(g_random_int()); + } +}; + +struct GlibRandomInt24 : GlibRandomInt<int32_t> { + int32_t operator()() const { + auto t = GlibRandomInt::operator()(); + t &= 0xffffff; + if (t & 0x800000) + t |= 0xff000000; + return t; + } +}; + +struct GlibRandomFloat { + float operator()() const { + return g_random_double_range(-1.0, 1.0); + } +}; + +template<typename T, size_t N> +class TestDataBuffer : std::array<T, N> { +public: + using typename std::array<T, N>::const_pointer; + using std::array<T, N>::size; + using std::array<T, N>::begin; + using std::array<T, N>::end; + using std::array<T, N>::operator[]; + + template<typename G=GlibRandomInt<T>> + TestDataBuffer(G g=G()):std::array<T, N>() { + for (auto &i : *this) + i = g(); + + } + + operator typename std::array<T, N>::const_pointer() const { + return begin(); + } +}; + +template<typename T> +bool +AssertEqualWithTolerance(const T &a, const T &b, unsigned tolerance) +{ + g_assert_cmpint(a.size(), ==, b.size()); + + for (unsigned i = 0; i < a.size(); ++i) { + int64_t x = a[i], y = b[i]; + + g_assert_cmpint(x, >=, y - int64_t(tolerance)); + g_assert_cmpint(x, <=, y + int64_t(tolerance)); + } + + return true; +} diff --git a/test/test_pcm_volume.c b/test/test_pcm_volume.c deleted file mode 100644 index 713645cf1..000000000 --- a/test/test_pcm_volume.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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 "test_pcm_all.h" -#include "pcm_volume.h" - -#include <glib.h> - -#include <string.h> - -void -test_pcm_volume_8(void) -{ - enum { N = 256 }; - static const int8_t zero[N]; - int8_t src[N]; - for (unsigned i = 0; i < N; ++i) - src[i] = g_random_int(); - - int8_t dest[N]; - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S8, - 0), ==, true); - g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S8, - PCM_VOLUME_1), ==, true); - g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S8, - PCM_VOLUME_1 / 2), ==, true); - - for (unsigned i = 0; i < N; ++i) { - g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); - g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); - } -} - -void -test_pcm_volume_16(void) -{ - enum { N = 256 }; - static const int16_t zero[N]; - int16_t src[N]; - for (unsigned i = 0; i < N; ++i) - src[i] = g_random_int(); - - int16_t dest[N]; - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S16, - 0), ==, true); - g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S16, - PCM_VOLUME_1), ==, true); - g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S16, - PCM_VOLUME_1 / 2), ==, true); - - for (unsigned i = 0; i < N; ++i) { - g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); - g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); - } -} - -/** - * 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_volume_24(void) -{ - enum { N = 256 }; - static const int32_t zero[N]; - int32_t src[N]; - for (unsigned i = 0; i < N; ++i) - src[i] = random24(); - - int32_t dest[N]; - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S24_P32, - 0), ==, true); - g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S24_P32, - PCM_VOLUME_1), ==, true); - g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S24_P32, - PCM_VOLUME_1 / 2), ==, true); - - for (unsigned i = 0; i < N; ++i) { - g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); - g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); - } -} - -void -test_pcm_volume_32(void) -{ - enum { N = 256 }; - static const int32_t zero[N]; - int32_t src[N]; - for (unsigned i = 0; i < N; ++i) - src[i] = g_random_int(); - - int32_t dest[N]; - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S32, - 0), ==, true); - g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S32, - PCM_VOLUME_1), ==, true); - g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S32, - PCM_VOLUME_1 / 2), ==, true); - - for (unsigned i = 0; i < N; ++i) { - g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); - g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); - } -} - -void -test_pcm_volume_float(void) -{ - enum { N = 256 }; - static const float zero[N]; - float src[N]; - for (unsigned i = 0; i < N; ++i) - src[i] = g_random_double_range(-1.0, 1.0); - - float dest[N]; - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_FLOAT, - 0), ==, true); - g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_FLOAT, - PCM_VOLUME_1), ==, true); - g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); - - memcpy(dest, src, sizeof(src)); - g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_FLOAT, - PCM_VOLUME_1 / 2), ==, true); - - for (unsigned i = 0; i < N; ++i) - g_assert_cmpfloat(dest[i], ==, src[i] / 2); -} diff --git a/test/test_pcm_volume.cxx b/test/test_pcm_volume.cxx new file mode 100644 index 000000000..1ab590490 --- /dev/null +++ b/test/test_pcm_volume.cxx @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2003-2013 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.hxx" +#include "PcmVolume.hxx" +#include "test_pcm_util.hxx" + +#include <glib.h> + +#include <algorithm> + +#include <string.h> + +void +test_pcm_volume_8() +{ + constexpr unsigned N = 256; + static int8_t zero[N]; + const auto src = TestDataBuffer<int8_t, N>(); + + int8_t dest[N]; + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S8, + 0), ==, true); + g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S8, + PCM_VOLUME_1), ==, true); + g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S8, + PCM_VOLUME_1 / 2), ==, true); + + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); + g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); + } +} + +void +test_pcm_volume_16() +{ + constexpr unsigned N = 256; + static int16_t zero[N]; + const auto src = TestDataBuffer<int16_t, N>(); + + int16_t dest[N]; + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S16, + 0), ==, true); + g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S16, + PCM_VOLUME_1), ==, true); + g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S16, + PCM_VOLUME_1 / 2), ==, true); + + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); + g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); + } +} + +void +test_pcm_volume_24() +{ + constexpr unsigned N = 256; + static int32_t zero[N]; + const auto src = TestDataBuffer<int32_t, N>(GlibRandomInt24()); + + int32_t dest[N]; + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S24_P32, + 0), ==, true); + g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S24_P32, + PCM_VOLUME_1), ==, true); + g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S24_P32, + PCM_VOLUME_1 / 2), ==, true); + + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); + g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); + } +} + +void +test_pcm_volume_32() +{ + constexpr unsigned N = 256; + static int32_t zero[N]; + const auto src = TestDataBuffer<int32_t, N>(); + + int32_t dest[N]; + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S32, + 0), ==, true); + g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S32, + PCM_VOLUME_1), ==, true); + g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_S32, + PCM_VOLUME_1 / 2), ==, true); + + for (unsigned i = 0; i < N; ++i) { + g_assert_cmpint(dest[i], >=, (src[i] - 1) / 2); + g_assert_cmpint(dest[i], <=, src[i] / 2 + 1); + } +} + +void +test_pcm_volume_float() +{ + constexpr unsigned N = 256; + static float zero[N]; + const auto src = TestDataBuffer<float, N>(GlibRandomFloat()); + + float dest[N]; + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_FLOAT, + 0), ==, true); + g_assert_cmpint(memcmp(dest, zero, sizeof(zero)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_FLOAT, + PCM_VOLUME_1), ==, true); + g_assert_cmpint(memcmp(dest, src, sizeof(src)), ==, 0); + + std::copy(src.begin(), src.end(), dest); + g_assert_cmpint(pcm_volume(dest, sizeof(dest), SAMPLE_FORMAT_FLOAT, + PCM_VOLUME_1 / 2), ==, true); + + for (unsigned i = 0; i < N; ++i) + g_assert_cmpfloat(dest[i], ==, src[i] / 2); +} diff --git a/test/test_queue_priority.c b/test/test_queue_priority.c deleted file mode 100644 index 5543edbba..000000000 --- a/test/test_queue_priority.c +++ /dev/null @@ -1,175 +0,0 @@ -#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], 0); - - 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_queue_priority.cxx b/test/test_queue_priority.cxx new file mode 100644 index 000000000..8dd1c3f5f --- /dev/null +++ b/test/test_queue_priority.cxx @@ -0,0 +1,188 @@ +#include "config.h" +#include "Queue.hxx" +#include "song.h" +#include "Directory.hxx" + +#include <glib.h> + +Directory detached_root; + +Directory::Directory() {} +Directory::~Directory() {} + +struct song * +song_dup_detached(const struct song *src) +{ + return const_cast<song *>(src); +} + +void +song_free(gcc_unused struct song *song) +{ +} + +gcc_unused +static void +dump_order(const struct queue *queue) +{ + g_printerr("queue length=%u, order:\n", queue->GetLength()); + for (unsigned i = 0; i < queue->GetLength(); ++i) + g_printerr(" [%u] -> %u (prio=%u)\n", i, queue->order[i], + queue->items[queue->order[i]].priority); +} + +static void +check_descending_priority(const struct queue *queue, + unsigned start_order) +{ + assert(start_order < queue->GetLength()); + + uint8_t last_priority = 0xff; + for (unsigned order = start_order; order < queue->GetLength(); ++order) { + unsigned position = queue->OrderToPosition(order); + uint8_t priority = queue->items[position].priority; + assert(priority <= last_priority); + (void)last_priority; + last_priority = priority; + } +} + +int +main(gcc_unused int argc, gcc_unused char **argv) +{ + static struct song songs[16]; + + struct queue queue(32); + + for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i) + queue.Append(&songs[i], 0); + + assert(queue.GetLength() == G_N_ELEMENTS(songs)); + + /* priority=10 for 4 items */ + + queue.SetPriorityRange(4, 8, 10, -1); + + queue.random = true; + queue.ShuffleOrder(); + check_descending_priority(&queue, 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue.PositionToOrder(i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue.PositionToOrder(i) < 4); + } + + for (unsigned i = 8; i < G_N_ELEMENTS(songs); ++i) { + assert(queue.PositionToOrder(i) >= 4); + } + + /* priority=50 one more item */ + + queue.SetPriorityRange(15, 16, 50, -1); + check_descending_priority(&queue, 0); + + assert(queue.PositionToOrder(15) == 0); + + for (unsigned i = 0; i < 4; ++i) { + assert(queue.PositionToOrder(i) >= 4); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue.PositionToOrder(i) >= 1 && + queue.PositionToOrder(i) < 5); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue.PositionToOrder(i) >= 5); + } + + /* priority=20 for one of the 4 priority=10 items */ + + queue.SetPriorityRange(3, 4, 20, -1); + check_descending_priority(&queue, 0); + + assert(queue.PositionToOrder(3) == 1); + assert(queue.PositionToOrder(15) == 0); + + for (unsigned i = 0; i < 3; ++i) { + assert(queue.PositionToOrder(i) >= 5); + } + + for (unsigned i = 4; i < 8; ++i) { + assert(queue.PositionToOrder(i) >= 2 && + queue.PositionToOrder(i) < 6); + } + + for (unsigned i = 8; i < 15; ++i) { + assert(queue.PositionToOrder(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.OrderToPosition(current_order); + + unsigned a_order = 3; + unsigned a_position = queue.OrderToPosition(a_order); + assert(queue.items[a_position].priority == 10); + queue.SetPriority(a_position, 20, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + a_order = queue.PositionToOrder(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.OrderToPosition(b_order); + assert(queue.items[b_position].priority == 0); + queue.SetPriority(b_position, 70, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + b_order = queue.PositionToOrder(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.OrderToPosition(c_order); + assert(queue.items[c_position].priority == 50); + queue.SetPriority(c_position, 60, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + c_order = queue.PositionToOrder(c_position); + assert(c_order == 0); + + /* move the prio=20 item back */ + + a_order = queue.PositionToOrder(a_position); + assert(a_order == 5); + assert(queue.items[a_position].priority == 20); + queue.SetPriority(a_position, 5, current_order); + + current_order = queue.PositionToOrder(current_position); + assert(current_order == 3); + + a_order = queue.PositionToOrder(a_position); + assert(a_order == 6); +} diff --git a/test/test_vorbis_encoder.c b/test/test_vorbis_encoder.c deleted file mode 100644 index 619399159..000000000 --- a/test/test_vorbis_encoder.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 "config.h" -#include "encoder_list.h" -#include "encoder_plugin.h" -#include "audio_format.h" -#include "conf.h" -#include "stdbin.h" -#include "tag.h" - -#include <glib.h> - -#include <stddef.h> -#include <unistd.h> - -static uint8_t zero[256]; - -static void -encoder_to_stdout(struct encoder *encoder) -{ - size_t length; - static char buffer[32768]; - - while ((length = encoder_read(encoder, buffer, sizeof(buffer))) > 0) { - G_GNUC_UNUSED ssize_t ignored = write(1, buffer, length); - } -} - -int -main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) -{ - G_GNUC_UNUSED bool success; - - /* create the encoder */ - - const struct encoder_plugin *plugin = encoder_plugin_get("vorbis"); - assert(plugin != NULL); - - struct config_param *param = config_new_param(NULL, -1); - config_add_block_param(param, "quality", "5.0", -1); - - struct encoder *encoder = encoder_init(plugin, param, NULL); - assert(encoder != NULL); - - /* open the encoder */ - - struct audio_format audio_format; - - audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); - success = encoder_open(encoder, &audio_format, NULL); - assert(success); - - encoder_to_stdout(encoder); - - /* write a block of data */ - - success = encoder_write(encoder, zero, sizeof(zero), NULL); - assert(success); - - encoder_to_stdout(encoder); - - /* write a tag */ - - success = encoder_pre_tag(encoder, NULL); - assert(success); - - encoder_to_stdout(encoder); - - struct tag *tag = tag_new(); - tag_add_item(tag, TAG_ARTIST, "Foo"); - tag_add_item(tag, TAG_TITLE, "Bar"); - - success = encoder_tag(encoder, tag, NULL); - assert(success); - - tag_free(tag); - - encoder_to_stdout(encoder); - - /* write another block of data */ - - success = encoder_write(encoder, zero, sizeof(zero), NULL); - assert(success); - - /* finish */ - - success = encoder_end(encoder, NULL); - assert(success); - - encoder_to_stdout(encoder); - - encoder_close(encoder); - encoder_finish(encoder); -} diff --git a/test/test_vorbis_encoder.cxx b/test/test_vorbis_encoder.cxx new file mode 100644 index 000000000..0e502b154 --- /dev/null +++ b/test/test_vorbis_encoder.cxx @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2003-2013 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 "encoder_list.h" +#include "encoder_plugin.h" +#include "audio_format.h" +#include "conf.h" +#include "stdbin.h" +#include "tag.h" + +#include <glib.h> + +#include <stddef.h> +#include <unistd.h> + +static uint8_t zero[256]; + +static void +encoder_to_stdout(struct encoder *encoder) +{ + size_t length; + static char buffer[32768]; + + while ((length = encoder_read(encoder, buffer, sizeof(buffer))) > 0) { + G_GNUC_UNUSED ssize_t ignored = write(1, buffer, length); + } +} + +int +main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv) +{ + G_GNUC_UNUSED bool success; + + /* create the encoder */ + + const struct encoder_plugin *plugin = encoder_plugin_get("vorbis"); + assert(plugin != NULL); + + config_param param; + param.AddBlockParam("quality", "5.0", -1); + + struct encoder *encoder = encoder_init(plugin, ¶m, NULL); + assert(encoder != NULL); + + /* open the encoder */ + + struct audio_format audio_format; + + audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); + success = encoder_open(encoder, &audio_format, NULL); + assert(success); + + encoder_to_stdout(encoder); + + /* write a block of data */ + + success = encoder_write(encoder, zero, sizeof(zero), NULL); + assert(success); + + encoder_to_stdout(encoder); + + /* write a tag */ + + success = encoder_pre_tag(encoder, NULL); + assert(success); + + encoder_to_stdout(encoder); + + struct tag *tag = tag_new(); + tag_add_item(tag, TAG_ARTIST, "Foo"); + tag_add_item(tag, TAG_TITLE, "Bar"); + + success = encoder_tag(encoder, tag, NULL); + assert(success); + + tag_free(tag); + + encoder_to_stdout(encoder); + + /* write another block of data */ + + success = encoder_write(encoder, zero, sizeof(zero), NULL); + assert(success); + + /* finish */ + + success = encoder_end(encoder, NULL); + assert(success); + + encoder_to_stdout(encoder); + + encoder_close(encoder); + encoder_finish(encoder); +} diff --git a/test/visit_archive.cxx b/test/visit_archive.cxx new file mode 100644 index 000000000..6faf4f3ae --- /dev/null +++ b/test/visit_archive.cxx @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2003-2013 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 "stdbin.h" +#include "tag.h" +#include "conf.h" +#include "IOThread.hxx" +#include "InputInit.hxx" +#include "ArchiveList.hxx" +#include "ArchivePlugin.hxx" +#include "ArchiveFile.hxx" +#include "ArchiveVisitor.hxx" +#include "fs/Path.hxx" + +#include <glib.h> + +#include <unistd.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); +} + +class MyArchiveVisitor final : public ArchiveVisitor { + public: + virtual void VisitArchiveEntry(const char *path_utf8) override { + printf("%s\n", path_utf8); + } +}; + +int +main(int argc, char **argv) +{ + GError *error = nullptr; + + if (argc != 3) { + fprintf(stderr, "Usage: visit_archive PLUGIN PATH\n"); + return EXIT_FAILURE; + } + + const char *plugin_name = argv[1]; + const Path path = Path::FromFS(argv[2]); + + /* initialize GLib */ + + g_thread_init(NULL); + g_log_set_default_handler(my_log_func, NULL); + + /* initialize MPD */ + + config_global_init(); + + io_thread_init(); + if (!io_thread_start(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + + archive_plugin_init_all(); + + if (!input_stream_global_init(&error)) { + g_warning("%s", error->message); + g_error_free(error); + return 2; + } + + /* open the archive and dump it */ + + const archive_plugin *plugin = archive_plugin_from_name(plugin_name); + if (plugin == nullptr) { + fprintf(stderr, "No such plugin: %s\n", plugin_name); + return EXIT_FAILURE; + } + + int result = EXIT_SUCCESS; + + ArchiveFile *file = archive_file_open(plugin, path.c_str(), &error); + if (file != nullptr) { + MyArchiveVisitor visitor; + file->Visit(visitor); + file->Close(); + } else { + fprintf(stderr, "%s\n", error->message); + g_error_free(error); + result = EXIT_FAILURE; + } + + /* deinitialize everything */ + + input_stream_global_finish(); + + archive_plugin_deinit_all(); + + io_thread_deinit(); + + config_global_finish(); + + return result; +} |