source: roaraudio/plugins/xmms/roar.c @ 1121:476f1bd5f496

Last change on this file since 1121:476f1bd5f496 was 1121:476f1bd5f496, checked in by phi, 15 years ago

added a small usleep() of 100ms in error case, this improves the stability

File size: 7.0 KB
Line 
1//roar.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of the XMMS RoarAudio output plugin a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "all.h"
26
27OutputPlugin roar_op = {
28        NULL,
29        NULL,
30        "RoarAudio XMMS Plugin", /* Description */
31        roar_init,
32        roar_about,
33        roar_configure,
34        roar_get_volume,
35        roar_set_volume,
36        roar_open,
37        roar_write,
38        roar_close,
39        roar_flush,
40        roar_pause,
41        roar_free,
42        roar_playing,
43        roar_get_output_time,
44        roar_get_written_time,
45};
46
47OutputPlugin *get_oplugin_info(void) {
48 return &roar_op;
49}
50
51void roar_init(void) {
52 ConfigFile * cfgfile;
53
54 cfgfile = xmms_cfg_open_default_file();
55
56 g_inst.state = 0;
57 g_inst.server = NULL;
58 g_inst.session = ctrlsocket_get_session_id();
59
60 xmms_cfg_read_string(cfgfile, "ROAR", "server", &g_inst.server);
61
62 xmms_cfg_read_string(cfgfile, "ROAR", "player_name", &g_inst.cfg.player_name);
63
64 xmms_cfg_free(cfgfile);
65
66 if ( g_inst.cfg.player_name == NULL )
67  g_inst.cfg.player_name = "XMMS";
68
69 ROAR_DBG("roar_init(*) = (void)");
70}
71
72int roar_playing(void) {
73 return FALSE;
74}
75
76void roar_write(void *ptr, int length) {
77 int r;
78
79 if ( g_inst.pause )
80  return;
81
82 ROAR_DBG("roar_write(ptr=%p, length=%i) = (void)", ptr, length);
83
84 while (length) {
85  if ( (r = write(g_inst.data_fh, ptr, length >= 17640 ? 17640 : length)) != -1 ) {
86   g_inst.written   += r;
87   ptr              += r;
88   length           -= r;
89  } else {
90   return;
91  }
92 }
93}
94
95int roar_open(AFormat fmt, int rate, int nch) {
96 int codec = ROAR_CODEC_DEFAULT;
97 int bits;
98
99 if ( !(g_inst.state & STATE_CONNECTED) ) {
100  if ( roar_simple_connect(&(g_inst.con), g_inst.server, g_inst.cfg.player_name) == -1 ) {
101   return FALSE;
102  }
103  g_inst.state |= STATE_CONNECTED;
104 }
105
106  bits = 16;
107  switch (fmt) {
108   case FMT_S8:
109     bits = 8;
110     codec = ROAR_CODEC_DEFAULT;
111    break;
112   case FMT_U8:
113     bits = 8;
114     codec = ROAR_CODEC_PCM_U_LE; // _LE, _BE, _PDP,... all the same for 8 bit output
115    break;
116   case FMT_U16_LE:
117     codec = ROAR_CODEC_PCM_U_LE;
118    break;
119   case FMT_U16_BE:
120     codec = ROAR_CODEC_PCM_U_BE;
121    break;
122   case FMT_U16_NE:
123#if BYTE_ORDER == BIG_ENDIAN
124     codec = ROAR_CODEC_PCM_U_BE;
125#elif BYTE_ORDER == LITTLE_ENDIAN
126     codec = ROAR_CODEC_PCM_U_LE;
127#else
128     codec = ROAR_CODEC_PCM_U_PDP;
129#endif
130    break;
131   case FMT_S16_LE:
132     codec = ROAR_CODEC_PCM_S_LE;
133    break;
134   case FMT_S16_BE:
135     codec = ROAR_CODEC_PCM_S_BE;
136    break;
137   case FMT_S16_NE:
138     codec = ROAR_CODEC_DEFAULT;
139    break;
140 }
141
142 g_inst.bps       = nch * rate * bits / 8;
143
144 roar_close();
145
146 if ( (g_inst.data_fh = roar_simple_new_stream_obj(&(g_inst.con), &(g_inst.stream),
147                              rate, nch, bits, codec, ROAR_DIR_PLAY)) == -1) {
148  roar_disconnect(&(g_inst.con));
149  g_inst.state |= STATE_CONNECTED;
150  g_inst.state -= STATE_CONNECTED;
151  if ( !(g_inst.state & STATE_NORECONNECT) ) {
152   g_inst.state |= STATE_NORECONNECT;
153   usleep(100000);
154   return roar_open(fmt, rate, nch);
155  } else {
156   g_inst.state -= STATE_NORECONNECT;
157   return FALSE;
158  }
159 }
160 g_inst.state |= STATE_PLAYING;
161
162 g_inst.written = 0;
163 g_inst.pause   = 0;
164
165 roar_update_metadata();
166
167 return TRUE;
168}
169
170void roar_close(void) {
171 if ( g_inst.data_fh != -1 )
172  close(g_inst.data_fh);
173 g_inst.data_fh = -1;
174 g_inst.state |= STATE_PLAYING;
175 g_inst.state -= STATE_PLAYING;
176 g_inst.written = 0;
177 ROAR_DBG("roar_close(void) = (void)");
178}
179
180void roar_pause(short p) {
181 g_inst.pause = p;
182}
183
184int roar_free(void) {
185 if ( g_inst.pause )
186  return 0;
187 else
188  return 1000000; // ???
189}
190
191void roar_flush(int time) {
192 gint64 r = time;
193
194 r *= g_inst.bps;
195 r /= 1000;
196
197 g_inst.written = r;
198}
199
200int roar_get_output_time(void) {
201 return roar_get_written_time();
202}
203
204int roar_get_written_time(void) {
205 gint64 r;
206
207 if ( !g_inst.bps ) {
208  ROAR_DBG("roar_get_written_time(void) = 0");
209  return 0;
210 }
211
212 r  = g_inst.written;
213 r *= 1000; // sec -> msec
214 r /= g_inst.bps;
215 ROAR_DBG("roar_get_written_time(void) = %lu", r);
216
217 return r;
218}
219
220
221// META DATA:
222
223int roar_update_metadata(void) {
224 struct roar_meta   meta;
225 char empty = 0;
226 char * info;
227 int pos;
228
229 pos     = xmms_remote_get_playlist_pos(g_inst.session);
230
231 meta.value = ∅
232 meta.key[0] = 0;
233 meta.type = ROAR_META_TYPE_NONE;
234
235 roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_CLEAR, &meta);
236
237 info = xmms_remote_get_playlist_file(g_inst.session, pos);
238
239 if ( info ) {
240  if ( strncmp(info, "http:", 5) == 0 )
241   meta.type = ROAR_META_TYPE_FILEURL;
242  else
243   meta.type = ROAR_META_TYPE_FILENAME;
244
245  meta.value = info;
246  ROAR_DBG("roar_update_metadata(*): setting meta data: type=%i, strlen(value)=%i", meta.type, strlen(info));
247  roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta);
248
249  free(info);
250 }
251
252 info = xmms_remote_get_playlist_title(g_inst.session, pos);
253 if ( info ) {
254  meta.type = ROAR_META_TYPE_TITLE;
255
256  meta.value = info;
257  roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta);
258
259  free(info);
260 }
261
262 meta.value = ∅
263 meta.type = ROAR_META_TYPE_NONE;
264 roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_FINALIZE, &meta);
265
266 return 0;
267}
268
269int roar_chk_metadata(void) {
270 static int    old_pos = -1;
271 static char * old_title = "NEW TITLE";
272 int pos;
273 char * title;
274 int need_update = 0;
275
276 pos     = xmms_remote_get_playlist_pos(g_inst.session);
277
278 if ( pos != old_pos ) {
279  old_pos = pos;
280  need_update = 1;
281 } else {
282  title = xmms_remote_get_playlist_title(g_inst.session, pos);
283
284  if ( strcmp(title, old_title) ) {
285   free(old_title);
286   old_title = title;
287   need_update = 1;
288  } else {
289   free(title);
290  }
291 }
292
293 if ( need_update ) {
294  roar_update_metadata();
295 }
296
297 return 0;
298}
299
300// MIXER:
301
302void roar_get_volume(int *l, int *r) {
303 int channels;
304 struct roar_mixer_settings mixer;
305
306 if ( !(g_inst.state & STATE_CONNECTED) )
307  return;
308
309 if ( roar_get_vol(&(g_inst.con), g_inst.stream.id, &mixer, &channels) == -1 ) {
310  *l = *r = 100;
311  return;
312 }
313
314 if ( channels == 1 ) {
315  *l = *r = mixer.mixer[0]/655.35;
316 } else {
317  *l = mixer.mixer[0]/655.35;
318  *r = mixer.mixer[1]/655.35;
319 }
320}
321
322void roar_set_volume(int l, int r) {
323 struct roar_mixer_settings mixer;
324
325 if ( !(g_inst.state & STATE_CONNECTED) )
326  return;
327
328 mixer.mixer[0] = l * 655.35;
329 mixer.mixer[1] = r * 655.35;
330
331 roar_set_vol(&(g_inst.con), g_inst.stream.id, &mixer, 2);
332}
333
334//ll
Note: See TracBrowser for help on using the repository browser.