1 /*
2     Null output plugin for DeaDBeeF Player
3     Copyright (C) 2009-2014 Alexey Yakovenko
4 
5     This software is provided 'as-is', without any express or implied
6     warranty.  In no event will the authors be held liable for any damages
7     arising from the use of this software.
8 
9     Permission is granted to anyone to use this software for any purpose,
10     including commercial applications, and to alter it and redistribute it
11     freely, subject to the following restrictions:
12 
13     1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17 
18     2. Altered source versions must be plainly marked as such, and must not be
19      misrepresented as being the original software.
20 
21     3. This notice may not be removed or altered from any source distribution.
22 */
23 
24 #include <stdint.h>
25 #include <unistd.h>
26 #ifdef __linux__
27 #include <sys/prctl.h>
28 #endif
29 #include <stdio.h>
30 #include <string.h>
31 #include "../../deadbeef.h"
32 
33 //#define trace(...) { fprintf(stderr, __VA_ARGS__); }
34 #define trace(fmt,...)
35 
36 static DB_output_t plugin;
37 DB_functions_t *deadbeef;
38 
39 static intptr_t null_tid;
40 static int null_terminate;
41 static int state;
42 
43 static void
44 pnull_callback (char *stream, int len);
45 
46 static void
47 pnull_thread (void *context);
48 
49 static int
50 pnull_init (void);
51 
52 static int
53 pnull_free (void);
54 
55 int
56 pnull_setformat (ddb_waveformat_t *fmt);
57 
58 static int
59 pnull_play (void);
60 
61 static int
62 pnull_stop (void);
63 
64 static int
65 pnull_pause (void);
66 
67 static int
68 pnull_unpause (void);
69 
70 int
pnull_init(void)71 pnull_init (void) {
72     trace ("pnull_init\n");
73     state = OUTPUT_STATE_STOPPED;
74     null_terminate = 0;
75     null_tid = deadbeef->thread_start (pnull_thread, NULL);
76     return 0;
77 }
78 
79 int
pnull_setformat(ddb_waveformat_t * fmt)80 pnull_setformat (ddb_waveformat_t *fmt) {
81     memcpy (&plugin.fmt, fmt, sizeof (ddb_waveformat_t));
82     return 0;
83 }
84 
85 int
pnull_free(void)86 pnull_free (void) {
87     trace ("pnull_free\n");
88     if (!null_terminate) {
89         if (null_tid) {
90             null_terminate = 1;
91             deadbeef->thread_join (null_tid);
92         }
93         null_tid = 0;
94         state = OUTPUT_STATE_STOPPED;
95         null_terminate = 0;
96     }
97     return 0;
98 }
99 
100 int
pnull_play(void)101 pnull_play (void) {
102     if (!null_tid) {
103         pnull_init ();
104     }
105     state = OUTPUT_STATE_PLAYING;
106     return 0;
107 }
108 
109 int
pnull_stop(void)110 pnull_stop (void) {
111     state = OUTPUT_STATE_STOPPED;
112     deadbeef->streamer_reset (1);
113     return 0;
114 }
115 
116 int
pnull_pause(void)117 pnull_pause (void) {
118     if (state == OUTPUT_STATE_STOPPED) {
119         return -1;
120     }
121     // set pause state
122     state = OUTPUT_STATE_PAUSED;
123     return 0;
124 }
125 
126 int
pnull_unpause(void)127 pnull_unpause (void) {
128     // unset pause state
129     if (state == OUTPUT_STATE_PAUSED) {
130         state = OUTPUT_STATE_PLAYING;
131     }
132     return 0;
133 }
134 
135 static int
pnull_get_endianness(void)136 pnull_get_endianness (void) {
137 #if WORDS_BIGENDIAN
138     return 1;
139 #else
140     return 0;
141 #endif
142 }
143 
144 static void
pnull_thread(void * context)145 pnull_thread (void *context) {
146 #ifdef __linux__
147     prctl (PR_SET_NAME, "deadbeef-null", 0, 0, 0, 0);
148 #endif
149     for (;;) {
150         if (null_terminate) {
151             break;
152         }
153         if (state != OUTPUT_STATE_PLAYING) {
154             usleep (10000);
155             continue;
156         }
157 
158         char buf[4096];
159         pnull_callback (buf, 1024);
160     }
161 }
162 
163 static void
pnull_callback(char * stream,int len)164 pnull_callback (char *stream, int len) {
165     if (!deadbeef->streamer_ok_to_read (len)) {
166         memset (stream, 0, len);
167         return;
168     }
169     int bytesread = deadbeef->streamer_read (stream, len);
170 
171     if (bytesread < len) {
172         memset (stream + bytesread, 0, len-bytesread);
173     }
174 }
175 
176 int
pnull_get_state(void)177 pnull_get_state (void) {
178     return state;
179 }
180 
181 int
null_start(void)182 null_start (void) {
183     return 0;
184 }
185 
186 int
null_stop(void)187 null_stop (void) {
188     return 0;
189 }
190 
191 DB_plugin_t *
nullout_load(DB_functions_t * api)192 nullout_load (DB_functions_t *api) {
193     deadbeef = api;
194     return DB_PLUGIN (&plugin);
195 }
196 
197 // define plugin interface
198 static DB_output_t plugin = {
199     .plugin.api_vmajor = 1,
200     .plugin.api_vminor = 0,
201     .plugin.version_major = 1,
202     .plugin.version_minor = 0,
203     .plugin.type = DB_PLUGIN_OUTPUT,
204     .plugin.id = "nullout",
205     .plugin.name = "Null output plugin",
206     .plugin.descr = "This plugin takes the audio data, and discards it,\nso nothing will play.\nThis is useful for testing.",
207     .plugin.copyright =
208     "Null output plugin for DeaDBeeF Player\n"
209     "Copyright (C) 2009-2014 Alexey Yakovenko\n"
210     "\n"
211     "This software is provided 'as-is', without any express or implied\n"
212     "warranty.  In no event will the authors be held liable for any damages\n"
213     "arising from the use of this software.\n"
214     "\n"
215     "Permission is granted to anyone to use this software for any purpose,\n"
216     "including commercial applications, and to alter it and redistribute it\n"
217     "freely, subject to the following restrictions:\n"
218     "\n"
219     "1. The origin of this software must not be misrepresented; you must not\n"
220     " claim that you wrote the original software. If you use this software\n"
221     " in a product, an acknowledgment in the product documentation would be\n"
222     " appreciated but is not required.\n"
223     "\n"
224     "2. Altered source versions must be plainly marked as such, and must not be\n"
225     " misrepresented as being the original software.\n"
226     "\n"
227     "3. This notice may not be removed or altered from any source distribution.\n"
228     ,
229     .plugin.website = "http://deadbeef.sf.net",
230     .plugin.start = null_start,
231     .plugin.stop = null_stop,
232     .init = pnull_init,
233     .free = pnull_free,
234     .setformat = pnull_setformat,
235     .play = pnull_play,
236     .stop = pnull_stop,
237     .pause = pnull_pause,
238     .unpause = pnull_unpause,
239     .state = pnull_get_state,
240     .fmt = {.samplerate = 44100, .channels = 2, .bps = 16, .channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT}
241 };
242