summaryrefslogtreecommitdiff
path: root/plugins/nullout
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/nullout')
-rw-r--r--plugins/nullout/Makefile.am5
-rw-r--r--plugins/nullout/nullout.c265
2 files changed, 270 insertions, 0 deletions
diff --git a/plugins/nullout/Makefile.am b/plugins/nullout/Makefile.am
new file mode 100644
index 00000000..da914823
--- /dev/null
+++ b/plugins/nullout/Makefile.am
@@ -0,0 +1,5 @@
+nulloutdir = $(libdir)/$(PACKAGE)
+pkglib_LTLIBRARIES = nullout.la
+nullout_la_SOURCES = nullout.c
+nullout_la_LDFLAGS = -module
+AM_CFLAGS = $(CFLAGS) -std=c99
diff --git a/plugins/nullout/nullout.c b/plugins/nullout/nullout.c
new file mode 100644
index 00000000..57980d60
--- /dev/null
+++ b/plugins/nullout/nullout.c
@@ -0,0 +1,265 @@
+/*
+ DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Copyright (C) 2009 Alexey Yakovenko
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/prctl.h>
+#include <stdio.h>
+#include "deadbeef.h"
+
+#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+//#define trace(fmt,...)
+
+static DB_output_t plugin;
+DB_functions_t *deadbeef;
+
+static intptr_t null_tid;
+static int null_terminate;
+static int null_rate;
+static int state;
+
+static void
+pnull_callback (char *stream, int len);
+
+static void
+pnull_thread (void *context);
+
+static int
+pnull_init (void);
+
+static int
+pnull_free (void);
+
+static int
+pnull_change_rate (int rate);
+
+static int
+pnull_play (void);
+
+static int
+pnull_stop (void);
+
+static int
+pnull_isstopped (void);
+
+static int
+pnull_ispaused (void);
+
+static int
+pnull_pause (void);
+
+static int
+pnull_unpause (void);
+
+static int
+pnull_get_rate (void);
+
+static int
+pnull_get_bps (void);
+
+static int
+pnull_get_channels (void);
+
+static int
+pnull_get_endianness (void);
+
+static void
+pnull_enum_soundcards (void (*callback)(const char *name, const char *desc, void*), void *userdata);
+
+int
+pnull_init (void) {
+ state = OUTPUT_STATE_STOPPED;
+ null_rate = 44100;
+ null_terminate = 0;
+ null_tid = deadbeef->thread_start (pnull_thread, NULL);
+ return 0;
+}
+
+int
+pnull_change_rate (int rate) {
+ null_rate = rate;
+ return null_rate;
+}
+
+int
+pnull_free (void) {
+ trace ("pnull_free\n");
+ if (!null_terminate) {
+ null_terminate = 1;
+ deadbeef->thread_join (null_tid);
+ null_tid = 0;
+ state = OUTPUT_STATE_STOPPED;
+ null_terminate = 0;
+ }
+ return 0;
+}
+
+int
+pnull_play (void) {
+ state = OUTPUT_STATE_PLAYING;
+ return 0;
+}
+
+int
+pnull_stop (void) {
+ state = OUTPUT_STATE_STOPPED;
+ deadbeef->streamer_reset (1);
+ return 0;
+}
+
+int
+pnull_isstopped (void) {
+ return (state == OUTPUT_STATE_STOPPED);
+}
+
+int
+pnull_ispaused (void) {
+ // return pause state
+ return (state == OUTPUT_STATE_PAUSED);
+}
+
+int
+pnull_pause (void) {
+ if (state == OUTPUT_STATE_STOPPED) {
+ return -1;
+ }
+ // set pause state
+ state = OUTPUT_STATE_PAUSED;
+ return 0;
+}
+
+int
+pnull_unpause (void) {
+ // unset pause state
+ if (state == OUTPUT_STATE_PAUSED) {
+ state = OUTPUT_STATE_PLAYING;
+ }
+ return 0;
+}
+
+int
+pnull_get_rate (void) {
+ return null_rate;
+}
+
+int
+pnull_get_bps (void) {
+ return 16;
+}
+
+int
+pnull_get_channels (void) {
+ return 2;
+}
+
+static int
+pnull_get_endianness (void) {
+#if WORDS_BIGENDIAN
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+static void
+pnull_thread (void *context) {
+ prctl (PR_SET_NAME, "deadbeef-null", 0, 0, 0, 0);
+ int err;
+ for (;;) {
+ if (null_terminate) {
+ break;
+ }
+ if (state != OUTPUT_STATE_PLAYING) {
+ usleep (10000);
+ continue;
+ }
+
+
+ char buf[4096];
+ pnull_callback (buf, 1024);
+ usleep (1000); // this must be here to prevent mutex deadlock
+ }
+}
+
+static void
+pnull_callback (char *stream, int len) {
+ if (!deadbeef->streamer_ok_to_read (len)) {
+ memset (stream, 0, len);
+ return;
+ }
+ int bytesread = deadbeef->streamer_read (stream, len);
+
+ if (bytesread < len) {
+ memset (stream + bytesread, 0, len-bytesread);
+ }
+}
+
+// derived from null-utils/aplay.c
+void
+pnull_enum_soundcards (void (*callback)(const char *name, const char *desc, void *), void *userdata) {
+ callback ("NULL output", "NULL output", userdata);
+}
+
+int
+pnull_get_state (void) {
+ return state;
+}
+
+int
+null_start (void) {
+ return 0;
+}
+
+int
+null_stop (void) {
+ return 0;
+}
+
+DB_plugin_t *
+nullout_load (DB_functions_t *api) {
+ deadbeef = api;
+ return DB_PLUGIN (&plugin);
+}
+
+// define plugin interface
+static DB_output_t plugin = {
+ DB_PLUGIN_SET_API_VERSION
+ .plugin.version_major = 0,
+ .plugin.version_minor = 1,
+ .plugin.nostop = 1,
+ .plugin.type = DB_PLUGIN_OUTPUT,
+ .plugin.name = "null output plugin",
+ .plugin.descr = "doesn't play anything",
+ .plugin.author = "Alexey Yakovenko",
+ .plugin.email = "waker@users.sourceforge.net",
+ .plugin.website = "http://deadbeef.sf.net",
+ .plugin.start = null_start,
+ .plugin.stop = null_stop,
+ .init = pnull_init,
+ .free = pnull_free,
+ .change_rate = pnull_change_rate,
+ .play = pnull_play,
+ .stop = pnull_stop,
+ .pause = pnull_pause,
+ .unpause = pnull_unpause,
+ .state = pnull_get_state,
+ .samplerate = pnull_get_rate,
+ .bitspersample = pnull_get_bps,
+ .channels = pnull_get_channels,
+ .endianness = pnull_get_endianness,
+ .enum_soundcards = pnull_enum_soundcards,
+};