source: roaraudio/plugins/audacious/roar.c @ 6052:d48765b2475e

Last change on this file since 6052:d48765b2475e was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

File size: 9.2 KB
Line 
1//roar.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft    - 2008-2015,
5 *                    Daniel Duntemann <dauxx@dauxx.org> - 2009
6 *
7 *  This file is part of the Audacious RoarAudio output plugin a part of RoarAudio,
8 *  a cross-platform sound system for both, home and professional use.
9 *  See README for details.
10 *
11 *  This file is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License version 3
13 *  as published by the Free Software Foundation.
14 *
15 *  RoarAudio is distributed in the hope that it will be useful,
16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *  GNU General Public License for more details.
19 *
20 *  You should have received a copy of the GNU General Public License
21 *  along with this software; see the file COPYING.  If not, write to
22 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 *  Boston, MA 02110-1301, USA.
24 *
25 */
26
27#include "all.h"
28
29// FIXME: This interface has been changed
30gint ctrlsocket_get_session_id(void) {
31 return -1;
32}
33
34OutputPlugin roar_op = {
35    .description = "RoarAudio Output Plugin",         
36    .init = roar_init,
37    .cleanup = NULL,
38    .about = roar_about,
39    .configure = roar_configure, 
40    .get_volume = roar_get_volume,
41    .set_volume = roar_set_volume,
42    .open_audio = roar_open, 
43    .write_audio = roar_write,
44    .close_audio = roar_close,
45    .flush = roar_flush,
46    .pause = roar_pause,
47    .buffer_free = roar_free,
48    .buffer_playing = roar_playing,
49    .output_time = roar_get_output_time, 
50    .written_time = roar_get_written_time,
51    .tell_audio = NULL
52};
53
54OutputPlugin *roar_oplist[] = { &roar_op, NULL };
55
56
57SIMPLE_OUTPUT_PLUGIN("RoarAudio Audacious Plugin",roar_oplist);
58
59OutputPlugin *get_oplugin_info(void) {
60 return &roar_op;
61}
62
63void roar_init(void) {
64 mcs_handle_t * cfgfile;
65
66 cfgfile = aud_cfg_db_open();
67
68 g_inst.state = 0;
69 g_inst.server = NULL;
70 g_inst.session = ctrlsocket_get_session_id();
71
72 aud_cfg_db_get_string(cfgfile, "ROAR", "server", &g_inst.server);
73
74 aud_cfg_db_get_string(cfgfile, "ROAR", "player_name", &g_inst.cfg.player_name);
75
76 aud_cfg_db_close(cfgfile);
77
78 if ( g_inst.cfg.player_name == NULL )
79  g_inst.cfg.player_name = "Audacious";
80
81 ROAR_DBG("roar_init(*) = (void)");
82}
83
84int roar_playing(void) {
85 return FALSE;
86}
87
88void roar_write(void *ptr, int length) {
89 int r;
90
91 if ( g_inst.pause )
92  return;
93
94 ROAR_DBG("roar_write(ptr=%p, length=%i) = (void)", ptr, length);
95
96 while (length) {
97  if ( (r = write(g_inst.data_fh, ptr, length >= 17640 ? 17640 : length)) != -1 ) {
98   g_inst.written   += r;
99   ptr              += r;
100   length           -= r;
101  } else {
102   return;
103  }
104 }
105}
106
107int roar_open(AFormat fmt, int rate, int nch) {
108 int codec = ROAR_CODEC_DEFAULT;
109 int bits;
110
111 if ( !(g_inst.state & STATE_CONNECTED) ) {
112  if ( roar_simple_connect(&(g_inst.con), g_inst.server, g_inst.cfg.player_name) == -1 ) {
113   return FALSE;
114  }
115  g_inst.state |= STATE_CONNECTED;
116 }
117
118  bits = 16;
119  switch (fmt) {
120   case FMT_S8:
121     bits = 8;
122     codec = ROAR_CODEC_DEFAULT;
123    break;
124   case FMT_U8:
125     bits = 8;
126     codec = ROAR_CODEC_PCM_U_LE; // _LE, _BE, _PDP,... all the same for 8 bit output
127    break;
128   case FMT_U16_LE:
129     codec = ROAR_CODEC_PCM_U_LE;
130    break;
131   case FMT_U16_BE:
132     codec = ROAR_CODEC_PCM_U_BE;
133    break;
134   case FMT_U16_NE:
135#if BYTE_ORDER == BIG_ENDIAN
136     codec = ROAR_CODEC_PCM_U_BE;
137#elif BYTE_ORDER == LITTLE_ENDIAN
138     codec = ROAR_CODEC_PCM_U_LE;
139#else
140     codec = ROAR_CODEC_PCM_U_PDP;
141#endif
142    break;
143   case FMT_S16_LE:
144     codec = ROAR_CODEC_PCM_S_LE;
145    break;
146   case FMT_S16_BE:
147     codec = ROAR_CODEC_PCM_S_BE;
148    break;
149   case FMT_S16_NE:
150     codec = ROAR_CODEC_DEFAULT;
151    break;
152    case FMT_U24_LE: /* stored in lower 3 bytes of 32-bit value, highest byte must be 0 */
153     codec = ROAR_CODEC_PCM_U_LE;
154     bits = 24;
155     break;
156    case FMT_U24_BE:
157     codec = ROAR_CODEC_PCM_U_BE;
158     bits = 24;
159     break;
160    case FMT_U24_NE:
161     bits = 24;
162#if BYTE_ORDER == BIG_ENDIAN
163     codec = ROAR_CODEC_PCM_U_BE;
164#elif BYTE_ORDER == LITTLE_ENDIAN
165     codec = ROAR_CODEC_PCM_U_LE;
166#else
167     codec = ROAR_CODEC_PCM_U_PDP;
168#endif     
169     break;
170    case FMT_S24_LE:
171     bits = 24;
172     codec = ROAR_CODEC_PCM_S_LE;
173     break;
174    case FMT_S24_BE:
175     bits = 24;
176     codec = ROAR_CODEC_PCM_S_BE;
177     break;
178    case FMT_S24_NE:
179     codec = ROAR_CODEC_DEFAULT;
180     bits= 24;
181     break;
182    case FMT_U32_LE: /* highest byte must be 0 */
183     codec = ROAR_CODEC_PCM_U_LE;
184     bits = 32;
185     break;
186    case FMT_U32_BE:
187     codec = ROAR_CODEC_PCM_U_BE;
188     bits = 32;
189     break;
190    case FMT_U32_NE:
191     bits = 32;
192#if BYTE_ORDER == BIG_ENDIAN
193     codec = ROAR_CODEC_PCM_U_BE;
194#elif BYTE_ORDER == LITTLE_ENDIAN
195     codec = ROAR_CODEC_PCM_U_LE;
196#else
197     codec = ROAR_CODEC_PCM_U_PDP;
198#endif     
199     break;
200    case FMT_S32_LE:
201     bits = 32;
202     codec = ROAR_CODEC_PCM_S_LE;
203     break;
204    case FMT_S32_BE:
205     bits = 32;
206     codec = ROAR_CODEC_PCM_S_BE;
207     break;
208    case FMT_S32_NE:
209     codec = ROAR_CODEC_DEFAULT;
210     bits= 32;
211     break;
212    case FMT_FLOAT:
213    ROAR_DBG("roar_open(*): FMT_FLOAT");
214    break;
215    case FMT_FIXED32:
216     ROAR_DBG("roar_open(*): FMT_FIXED32");
217     break;
218     
219 }
220
221 ROAR_DBG("roar_open(*): fmt %i", fmt);
222
223 g_inst.bps       = nch * rate * bits / 8;
224
225 roar_close();
226
227 if ( (g_inst.data_fh = roar_simple_new_stream_obj(&(g_inst.con), &(g_inst.stream),
228                              rate, nch, bits, codec, ROAR_DIR_PLAY)) == -1) {
229  roar_disconnect(&(g_inst.con));
230  g_inst.state |= STATE_CONNECTED;
231  g_inst.state -= STATE_CONNECTED;
232  if ( !(g_inst.state & STATE_NORECONNECT) ) {
233   g_inst.state |= STATE_NORECONNECT;
234   usleep(100000);
235   return roar_open(fmt, rate, nch);
236  } else {
237   g_inst.state -= STATE_NORECONNECT;
238   return FALSE;
239  }
240 }
241 g_inst.state |= STATE_PLAYING;
242
243 g_inst.written = 0;
244 g_inst.pause   = 0;
245
246#ifdef _WITH_BROKEN_CODE
247 roar_update_metadata();
248#endif
249
250 return TRUE;
251}
252
253void roar_close(void) {
254 if ( g_inst.data_fh != -1 )
255  close(g_inst.data_fh);
256 g_inst.data_fh = -1;
257 g_inst.state |= STATE_PLAYING;
258 g_inst.state -= STATE_PLAYING;
259 g_inst.written = 0;
260 ROAR_DBG("roar_close(void) = (void)");
261}
262
263void roar_pause(short p) {
264 g_inst.pause = p;
265}
266
267int roar_free(void) {
268 if ( g_inst.pause )
269  return 0;
270 else
271  return 1000000; // ???
272}
273
274void roar_flush(int time) {
275 gint64 r = time;
276
277 r *= g_inst.bps;
278 r /= 1000;
279
280 g_inst.written = r;
281}
282
283int roar_get_output_time(void) {
284 return roar_get_written_time();
285}
286
287int roar_get_written_time(void) {
288 gint64 r;
289
290 if ( !g_inst.bps ) {
291  ROAR_DBG("roar_get_written_time(void) = 0");
292  return 0;
293 }
294
295 r  = g_inst.written;
296 r *= 1000; // sec -> msec
297 r /= g_inst.bps;
298 ROAR_DBG("roar_get_written_time(void) = %lu", r);
299
300 return r;
301}
302
303
304// META DATA:
305
306int roar_update_metadata(void) {
307#ifdef _WITH_BROKEN_CODE
308 struct roar_meta   meta;
309 char empty = 0;
310 char * info = NULL;
311 int pos;
312
313 pos     = audacious_remote_get_playlist_pos(g_inst.session);
314
315 meta.value = &empty;
316 meta.key[0] = 0;
317 meta.type = ROAR_META_TYPE_NONE;
318
319 roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_CLEAR, &meta);
320
321 info = audacious_remote_get_playlist_file(g_inst.session, pos);
322
323 if ( info ) {
324  if ( strncmp(info, "http:", 5) == 0 )
325   meta.type = ROAR_META_TYPE_FILEURL;
326  else
327   meta.type = ROAR_META_TYPE_FILENAME;
328
329  meta.value = info;
330  ROAR_DBG("roar_update_metadata(*): setting meta data: type=%i, strlen(value)=%i", meta.type, strlen(info));
331  roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta);
332
333  free(info);
334 }
335
336 info = audacious_remote_get_playlist_title(g_inst.session, pos);
337 if ( info ) {
338  meta.type = ROAR_META_TYPE_TITLE;
339
340  meta.value = info;
341  roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta);
342
343  free(info);
344 }
345
346 meta.value = &empty;
347 meta.type = ROAR_META_TYPE_NONE;
348 roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_FINALIZE, &meta);
349
350#endif
351 return 0;
352}
353
354int roar_chk_metadata(void) {
355#ifdef _WITH_BROKEN_CODE
356 static int    old_pos = -1;
357 static char * old_title = "NEW TITLE";
358 int pos;
359 char * title;
360 int need_update = 0;
361
362 pos     = audacious_remote_get_playlist_pos(g_inst.session);
363
364 if ( pos != old_pos ) {
365  old_pos = pos;
366  need_update = 1;
367 } else {
368  title = audacious_remote_get_playlist_title(g_inst.session, pos);
369
370  if ( strcmp(title, old_title) ) {
371   free(old_title);
372   old_title = title;
373   need_update = 1;
374  } else {
375   free(title);
376  }
377 }
378
379 if ( need_update ) {
380  roar_update_metadata();
381 }
382
383#endif
384 return 0;
385}
386
387// MIXER:
388
389
390void roar_get_volume(int *l, int *r) {
391 struct roar_mixer_settings mixer;
392 int channels;
393 float fs;
394
395 if ( !(g_inst.state & STATE_CONNECTED) )
396  return;
397
398 if ( roar_get_vol(&(g_inst.con), g_inst.stream.id, &mixer, &channels) == -1 ) {
399  *l = *r = 100;
400  return;
401 }
402
403 fs = (float)mixer.scale/100.;
404
405 if ( channels == 1 ) {
406  *l = *r = mixer.mixer[0]/fs;
407 } else {
408  *l = mixer.mixer[0]/fs;
409  *r = mixer.mixer[1]/fs;
410 }
411}
412
413void roar_set_volume(int l, int r) {
414 struct roar_mixer_settings mixer;
415
416 if ( !(g_inst.state & STATE_CONNECTED) )
417  return;
418
419 mixer.mixer[0] = l;
420 mixer.mixer[1] = r;
421
422 mixer.scale    = 100;
423
424 roar_set_vol(&(g_inst.con), g_inst.stream.id, &mixer, 2);
425}
426
427//ll
Note: See TracBrowser for help on using the repository browser.