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