aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--test/DumpDatabase.cxx147
-rw-r--r--test/FakeReplayGainConfig.cxx25
-rw-r--r--test/FakeSong.cxx33
-rw-r--r--test/dump_playlist.c255
-rw-r--r--test/dump_playlist.cxx250
-rw-r--r--test/dump_rva2.c9
-rw-r--r--test/dump_text_file.c170
-rw-r--r--test/dump_text_file.cxx167
-rw-r--r--test/read_conf.c72
-rw-r--r--test/read_conf.cxx75
-rw-r--r--test/read_mixer.c154
-rw-r--r--test/read_mixer.cxx166
-rw-r--r--test/read_tags.c245
-rw-r--r--test/read_tags.cxx240
-rw-r--r--test/run_convert.c126
-rw-r--r--test/run_convert.cxx126
-rw-r--r--test/run_decoder.c254
-rw-r--r--test/run_decoder.cxx222
-rw-r--r--test/run_encoder.c134
-rw-r--r--test/run_encoder.cxx133
-rw-r--r--test/run_filter.c201
-rw-r--r--test/run_filter.cxx193
-rw-r--r--test/run_inotify.c93
-rw-r--r--test/run_inotify.cxx94
-rw-r--r--test/run_input.c185
-rw-r--r--test/run_input.cxx181
-rw-r--r--test/run_normalize.c73
-rw-r--r--test/run_normalize.cxx73
-rw-r--r--test/run_output.c253
-rw-r--r--test/run_output.cxx257
-rw-r--r--test/run_tcp_connect.c164
-rw-r--r--test/software_volume.c70
-rw-r--r--test/software_volume.cxx71
-rw-r--r--test/test_pcm_all.h56
-rw-r--r--test/test_pcm_all.hxx80
-rw-r--r--test/test_pcm_channels.c101
-rw-r--r--test/test_pcm_channels.cxx96
-rw-r--r--test/test_pcm_dither.c79
-rw-r--r--test/test_pcm_dither.cxx56
-rw-r--r--test/test_pcm_format.cxx130
-rw-r--r--test/test_pcm_main.c42
-rw-r--r--test/test_pcm_main.cxx52
-rw-r--r--test/test_pcm_mix.cxx84
-rw-r--r--test/test_pcm_pack.c89
-rw-r--r--test/test_pcm_pack.cxx75
-rw-r--r--test/test_pcm_util.hxx85
-rw-r--r--test/test_pcm_volume.c190
-rw-r--r--test/test_pcm_volume.cxx171
-rw-r--r--test/test_queue_priority.c175
-rw-r--r--test/test_queue_priority.cxx188
-rw-r--r--test/test_vorbis_encoder.c111
-rw-r--r--test/test_vorbis_encoder.cxx111
-rw-r--r--test/visit_archive.cxx123
53 files changed, 3710 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(&param, &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..5cd9b2c52
--- /dev/null
+++ b/test/read_mixer.cxx
@@ -0,0 +1,166 @@
+/*
+ * 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"
+
+extern "C" {
+#include "mixer_control.h"
+#include "mixer_list.h"
+}
+
+#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, &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 */
+
+ 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..09d755db2
--- /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 "mixer_control.h"
+#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, &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/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;
+}