source: roaraudio/plugins/xmms/roar.c @ 459:cd25fa92d002

Last change on this file since 459:cd25fa92d002 was 459:cd25fa92d002, checked in by phi, 16 years ago

added mixer support

File size: 6.5 KB
Line 
1//roar.c:
2
3#include <roaraudio.h>
4
5//#include "xmms/i18n.h"
6#include <gtk/gtk.h>
7#include <stdio.h>
8#include <string.h>
9
10#include "xmms/plugin.h"
11#include "xmms/xmmsctrl.h"
12#include "xmms/dirbrowser.h"
13#include "xmms/configfile.h"
14#include "xmms/util.h"
15
16#define _(x) (x)
17
18gint ctrlsocket_get_session_id(void);
19
20void roar_init(void);
21void roar_about(void);
22void roar_configure(void);
23
24void roar_get_volume(int *l, int *r);
25void roar_set_volume(int l, int r);
26void roar_mixer_init(void);
27void roar_mixer_init_vol(int l, int r);
28
29int roar_playing(void);
30int roar_free(void);
31void roar_write(void *ptr, int length);
32void roar_close(void);
33void roar_flush(int time);
34void roar_pause(short p);
35int roar_open(AFormat fmt, int rate, int nch);
36int roar_get_output_time(void);
37int roar_get_written_time(void);
38
39int roar_update_metadata(void);
40int roar_chk_metadata(void);
41
42OutputPlugin roar_op = {
43        NULL,
44        NULL,
45        "RoarAudio XMMS Plugin", /* Description */
46        roar_init,
47        roar_about,
48        NULL, //roar_configure,
49        roar_get_volume,
50        roar_set_volume,
51        roar_open,
52        roar_write,
53        roar_close,
54        NULL, //roar_flush,
55        roar_pause,
56        roar_free,
57        roar_playing,
58        roar_get_output_time,
59        roar_get_written_time,
60};
61
62#define STATE_CONNECTED 1
63#define STATE_PLAYING   2
64
65struct xmms_roar_out {
66 int state;
67 char * server;
68 struct roar_connection con;
69 struct roar_stream     stream;
70 int data_fh;
71 long unsigned int written;
72 long unsigned int bps;
73 int session;
74 int pause;
75} g_inst;
76
77OutputPlugin *get_oplugin_info(void) {
78 return &roar_op;
79}
80
81void roar_init(void) {
82 g_inst.state = 0;
83 g_inst.server = NULL;
84 g_inst.session = ctrlsocket_get_session_id();
85 ROAR_DBG("roar_init(*) = (void)");
86}
87
88int roar_playing(void) {
89 return g_inst.state & STATE_PLAYING ? TRUE : FALSE;
90}
91
92void roar_write(void *ptr, int length) {
93 int r;
94
95 if ( g_inst.pause )
96  return;
97
98 while (length) {
99  if ( (r = write(g_inst.data_fh, ptr, length >= 17640 ? 17640 : length)) != -1 ) {
100   g_inst.written   += r;
101   ptr              += r;
102   length           -= r;
103  } else {
104   return;
105  }
106 }
107}
108
109int roar_open(AFormat fmt, int rate, int nch) {
110 int codec = ROAR_CODEC_DEFAULT;
111 int bits;
112
113 if ( !(g_inst.state & STATE_CONNECTED) ) {
114  if ( roar_simple_connect(&(g_inst.con), g_inst.server, "XMMS") == -1 ) {
115   return FALSE;
116  }
117  g_inst.state |= STATE_CONNECTED;
118 }
119
120  bits = 16;
121  switch (fmt) {
122   case FMT_S8:
123     bits = 8;
124     codec = ROAR_CODEC_DEFAULT;
125    break;
126   case FMT_U8:
127     bits = 8;
128     codec = ROAR_CODEC_PCM_S_LE; // _LE, _BE, _PDP,... all the same for 8 bit output
129    break;
130   case FMT_U16_LE:
131     codec = ROAR_CODEC_PCM_U_LE;
132    break;
133   case FMT_U16_BE:
134     codec = ROAR_CODEC_PCM_U_BE;
135    break;
136   case FMT_U16_NE:
137#if BYTE_ORDER == BIG_ENDIAN
138     codec = ROAR_CODEC_PCM_U_BE;
139#elif BYTE_ORDER == LITTLE_ENDIAN
140     codec = ROAR_CODEC_PCM_U_LE;
141#else
142     codec = ROAR_CODEC_PCM_U_PDP;
143#endif
144    break;
145   case FMT_S16_LE:
146     codec = ROAR_CODEC_PCM_S_LE;
147    break;
148   case FMT_S16_BE:
149     codec = ROAR_CODEC_PCM_S_BE;
150    break;
151   case FMT_S16_NE:
152     codec = ROAR_CODEC_DEFAULT;
153    break;
154 }
155
156 g_inst.bps       = nch * rate * bits / 8;
157
158 if ( (g_inst.data_fh = roar_simple_new_stream_obj(&(g_inst.con), &(g_inst.stream),
159                              rate, nch, bits, codec, ROAR_DIR_PLAY)) == -1) {
160  return FALSE;
161 }
162 g_inst.state |= STATE_PLAYING;
163
164 g_inst.written = 0;
165 g_inst.pause   = 0;
166
167 roar_update_metadata();
168
169 return TRUE;
170}
171
172void roar_close(void) {
173 close(g_inst.data_fh);
174 g_inst.state |= STATE_PLAYING;
175 g_inst.state -= STATE_PLAYING;
176 g_inst.written = 0;
177}
178
179void roar_pause(short p) {
180 g_inst.pause = p;
181}
182
183int roar_free(void) {
184 return 1000000; // ???
185}
186
187int roar_get_output_time(void) {
188 return roar_get_written_time();
189}
190
191int roar_get_written_time(void) {
192 gint64 r;
193
194 if ( !g_inst.bps ) {
195  ROAR_DBG("roar_get_written_time(void) = 0");
196  return 0;
197 }
198
199 r  = g_inst.written;
200 r *= 1000; // sec -> msec
201 r /= g_inst.bps;
202 ROAR_DBG("roar_get_written_time(void) = %lu", r);
203
204 return r;
205}
206
207
208// ABOUT:
209
210void roar_about(void) {
211 static GtkWidget *dialog;
212
213 if (dialog != NULL)
214  return;
215
216 dialog = xmms_show_message(
217                _("About RoarAudio Plugin"),
218                _("RoarAudio XMMS Plugin..."
219                 ), _("OK"), FALSE, NULL, NULL);
220 gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
221                    GTK_SIGNAL_FUNC(gtk_widget_destroyed),
222                    &dialog);
223}
224
225// CONFIG:
226
227// META DATA:
228
229int roar_update_metadata(void) {
230 struct roar_meta   meta;
231 char empty = 0;
232 char * info;
233 int pos;
234
235 pos     = xmms_remote_get_playlist_pos(g_inst.session);
236
237 meta.value = &empty;
238 meta.key[0] = 0;
239 meta.type = ROAR_META_TYPE_NONE;
240
241 roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_CLEAR, &meta);
242
243 info = xmms_remote_get_playlist_file(g_inst.session, pos);
244
245 if ( info ) {
246  if ( strncmp(info, "http:", 5) == 0 )
247   meta.type = ROAR_META_TYPE_FILEURL;
248  else
249   meta.type = ROAR_META_TYPE_FILENAME;
250
251  meta.value = info;
252  roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta);
253
254  free(info);
255 }
256
257 info = xmms_remote_get_playlist_title(g_inst.session, pos);
258
259 if ( info ) {
260  meta.type = ROAR_META_TYPE_TITLE;
261
262  meta.value = info;
263  roar_stream_meta_set(&(g_inst.con), &(g_inst.stream), ROAR_META_MODE_SET, &meta);
264
265  free(info);
266 }
267
268 return 0;
269}
270
271int roar_chk_metadata(void) {
272 static int    old_pos = -1;
273 static char * old_title = "NEW TITLE";
274 int pos;
275 char * title;
276 int need_update = 0;
277
278 pos     = xmms_remote_get_playlist_pos(g_inst.session);
279
280 if ( pos != old_pos ) {
281  old_pos = pos;
282  need_update = 1;
283 } else {
284  title = xmms_remote_get_playlist_title(g_inst.session, pos);
285
286  if ( strcmp(title, old_title) ) {
287   free(old_title);
288   old_title = title;
289   need_update = 1;
290  } else {
291   free(title);
292  }
293 }
294
295 if ( need_update ) {
296  roar_update_metadata();
297 }
298
299 return 0;
300}
301
302// MIXER:
303
304void roar_get_volume(int *l, int *r) {
305 int channels;
306 struct roar_mixer_settings mixer;
307
308 if ( !(g_inst.state & STATE_CONNECTED) )
309  return;
310
311 if ( roar_get_vol(&(g_inst.con), g_inst.stream.id, &mixer, &channels) == -1 ) {
312  *l = *r = 100;
313  return;
314 }
315
316 if ( channels == 1 ) {
317  *l = *r = mixer.mixer[0]/655.35;
318 } else {
319  *l = mixer.mixer[0]/655.35;
320  *r = mixer.mixer[1]/655.35;
321 }
322}
323
324void roar_set_volume(int l, int r) {
325 struct roar_mixer_settings mixer;
326
327 if ( !(g_inst.state & STATE_CONNECTED) )
328  return;
329
330 mixer.mixer[0] = l * 655.35;
331 mixer.mixer[1] = r * 655.35;
332
333 roar_set_vol(&(g_inst.con), g_inst.stream.id, &mixer, 2);
334}
335
336//ll
Note: See TracBrowser for help on using the repository browser.