Experimental RSS code.
[monky] / src / xmms2.c
1 /*
2 * xmms2.c: xmms2 stuff for Conky
3 *
4 *
5 */
6
7 #include "conky.h"
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <xmmsclient/xmmsclient.h>
12
13 #define CONN_INIT    0
14 #define CONN_OK      1
15 #define CONN_NO      2
16
17 /* callbacks */
18
19 void connection_lost( void *ptr ) {
20     ((struct information *)ptr)->xmms2_conn_state = CONN_NO;
21
22     if ( ((struct information *)ptr)->xmms2.status == NULL )
23         ((struct information *)ptr)->xmms2.status = malloc( TEXT_BUFFER_SIZE );
24     strncpy( ((struct information *)ptr)->xmms2.status, "xmms2 not responding", TEXT_BUFFER_SIZE - 1 );
25
26
27     if ( ((struct information *)ptr)->xmms2.artist == NULL )
28         ((struct information *)ptr)->xmms2.artist = malloc( TEXT_BUFFER_SIZE );
29     strncpy( ((struct information *)ptr)->xmms2.artist, "", TEXT_BUFFER_SIZE - 1 );
30
31     if ( ((struct information *)ptr)->xmms2.album == NULL )
32         ((struct information *)ptr)->xmms2.album = malloc( TEXT_BUFFER_SIZE );
33     strncpy( ((struct information *)ptr)->xmms2.album, "", TEXT_BUFFER_SIZE - 1 );
34
35     if ( ((struct information *)ptr)->xmms2.title == NULL )
36         ((struct information *)ptr)->xmms2.title = malloc( TEXT_BUFFER_SIZE );
37     strncpy( ((struct information *)ptr)->xmms2.title, "", TEXT_BUFFER_SIZE - 1 );
38
39     if ( ((struct information *)ptr)->xmms2.genre == NULL )
40         ((struct information *)ptr)->xmms2.genre = malloc( TEXT_BUFFER_SIZE );
41     strncpy( ((struct information *)ptr)->xmms2.genre, "", TEXT_BUFFER_SIZE - 1 );
42
43     if ( ((struct information *)ptr)->xmms2.comment == NULL )
44         ((struct information *)ptr)->xmms2.comment = malloc( TEXT_BUFFER_SIZE );
45     strncpy( ((struct information *)ptr)->xmms2.comment, "", TEXT_BUFFER_SIZE - 1 );
46
47     if ( ((struct information *)ptr)->xmms2.decoder == NULL )
48         ((struct information *)ptr)->xmms2.decoder = malloc( TEXT_BUFFER_SIZE );
49     strncpy( ((struct information *)ptr)->xmms2.decoder, "", TEXT_BUFFER_SIZE - 1 );
50
51     if ( ((struct information *)ptr)->xmms2.transport == NULL )
52         ((struct information *)ptr)->xmms2.transport = malloc( TEXT_BUFFER_SIZE );
53     strncpy( ((struct information *)ptr)->xmms2.transport, "", TEXT_BUFFER_SIZE - 1 );
54
55     if ( ((struct information *)ptr)->xmms2.url == NULL )
56         ((struct information *)ptr)->xmms2.url = malloc( TEXT_BUFFER_SIZE );
57     strncpy( ((struct information *)ptr)->xmms2.url, "", TEXT_BUFFER_SIZE - 1 );
58
59     if ( ((struct information *)ptr)->xmms2.date == NULL )
60         ((struct information *)ptr)->xmms2.date = malloc( TEXT_BUFFER_SIZE );
61     strncpy( ((struct information *)ptr)->xmms2.date, "", TEXT_BUFFER_SIZE - 1 );
62
63     ((struct information *)ptr)->xmms2.tracknr = 0;
64     ((struct information *)ptr)->xmms2.id = 0;
65     ((struct information *)ptr)->xmms2.bitrate = 0;
66     ((struct information *)ptr)->xmms2.duration = 0;
67     ((struct information *)ptr)->xmms2.elapsed = 0;
68     ((struct information *)ptr)->xmms2.size = 0;
69     ((struct information *)ptr)->xmms2.progress = 0;
70 }
71
72 void handle_curent_id( xmmsc_result_t *res, void *ptr ) {
73
74     uint current_id;
75
76     if ( xmmsc_result_get_uint( res, &current_id ) ) {
77
78         xmmsc_result_t *res2;
79         res2 = xmmsc_medialib_get_info( ((struct information *)ptr)->xmms2_conn, current_id );
80         xmmsc_result_wait( res2 );
81
82
83         if ( ((struct information *)ptr)->xmms2.artist == NULL )
84             ((struct information *)ptr)->xmms2.artist = malloc( TEXT_BUFFER_SIZE );
85
86         if ( ((struct information *)ptr)->xmms2.album == NULL )
87             ((struct information *)ptr)->xmms2.album = malloc( TEXT_BUFFER_SIZE );
88
89         if ( ((struct information *)ptr)->xmms2.title == NULL )
90             ((struct information *)ptr)->xmms2.title = malloc( TEXT_BUFFER_SIZE );
91
92         if ( ((struct information *)ptr)->xmms2.genre == NULL )
93             ((struct information *)ptr)->xmms2.genre = malloc( TEXT_BUFFER_SIZE );
94
95         if ( ((struct information *)ptr)->xmms2.comment == NULL )
96             ((struct information *)ptr)->xmms2.comment = malloc( TEXT_BUFFER_SIZE );
97
98         if ( ((struct information *)ptr)->xmms2.decoder == NULL )
99             ((struct information *)ptr)->xmms2.decoder = malloc( TEXT_BUFFER_SIZE );
100
101         if ( ((struct information *)ptr)->xmms2.transport == NULL )
102             ((struct information *)ptr)->xmms2.transport = malloc( TEXT_BUFFER_SIZE );
103
104         if ( ((struct information *)ptr)->xmms2.url == NULL )
105             ((struct information *)ptr)->xmms2.url = malloc( TEXT_BUFFER_SIZE );
106
107         if ( ((struct information *)ptr)->xmms2.date == NULL )
108             ((struct information *)ptr)->xmms2.date = malloc( TEXT_BUFFER_SIZE );
109
110
111         ((struct information *)ptr)->xmms2.id = current_id;
112
113         char *temp;
114         xmmsc_result_get_dict_entry_string( res2, "artist", &temp );
115         if ( temp != NULL ) {
116             strncpy( ((struct information *)ptr)->xmms2.artist, temp, TEXT_BUFFER_SIZE - 1 );
117         } else {
118             strncpy( ((struct information *)ptr)->xmms2.artist, "[Unknown]", TEXT_BUFFER_SIZE - 1 );
119         }
120
121
122         xmmsc_result_get_dict_entry_string( res2, "title", &temp );
123         if ( temp != NULL ) {
124             strncpy( ((struct information *)ptr)->xmms2.title, temp, TEXT_BUFFER_SIZE - 1 );
125         } else {
126             strncpy( ((struct information *)ptr)->xmms2.title, "[Unknown]", TEXT_BUFFER_SIZE - 1 );
127         }
128
129         xmmsc_result_get_dict_entry_string( res2, "album", &temp );
130         if ( temp != NULL ) {
131             strncpy( ((struct information *)ptr)->xmms2.album, temp, TEXT_BUFFER_SIZE - 1 );
132         } else {
133             strncpy( ((struct information *)ptr)->xmms2.album, "[Unknown]", TEXT_BUFFER_SIZE - 1 );
134         }
135
136
137         xmmsc_result_get_dict_entry_string( res2, "genre", &temp );
138         if ( temp != NULL ) {
139
140             strncpy( ((struct information *)ptr)->xmms2.genre, temp, TEXT_BUFFER_SIZE - 1 );
141         } else {
142             strncpy( ((struct information *)ptr)->xmms2.genre, "[Unknown]", TEXT_BUFFER_SIZE - 1 );
143         }
144
145
146         xmmsc_result_get_dict_entry_string( res2, "comment", &temp );
147         if ( temp != NULL ) {
148             strncpy( ((struct information *)ptr)->xmms2.comment, temp, TEXT_BUFFER_SIZE - 1 );
149         } else {
150             strncpy( ((struct information *)ptr)->xmms2.comment, "", TEXT_BUFFER_SIZE - 1 );
151         }
152
153
154         xmmsc_result_get_dict_entry_string( res2, "decoder", &temp );
155         if ( temp != NULL ) {
156             strncpy( ((struct information *)ptr)->xmms2.decoder, temp, TEXT_BUFFER_SIZE - 1 );
157         } else {
158             strncpy( ((struct information *)ptr)->xmms2.decoder, "[Unknown]", TEXT_BUFFER_SIZE - 1 );
159         }
160
161
162         xmmsc_result_get_dict_entry_string( res2, "transport", &temp );
163         if ( temp != NULL ) {
164             strncpy( ((struct information *)ptr)->xmms2.transport, temp, TEXT_BUFFER_SIZE - 1 );
165         } else {
166             strncpy( ((struct information *)ptr)->xmms2.transport, "[Unknown]", TEXT_BUFFER_SIZE - 1 );
167         }
168
169
170         xmmsc_result_get_dict_entry_string( res2, "url", &temp );
171         if ( temp != NULL ) {
172             strncpy( ((struct information *)ptr)->xmms2.url, temp, TEXT_BUFFER_SIZE - 1 );
173         } else {
174             strncpy( ((struct information *)ptr)->xmms2.url, "[Unknown]", TEXT_BUFFER_SIZE - 1 );
175         }
176
177
178         xmmsc_result_get_dict_entry_string( res2, "date", &temp );
179         if ( temp != NULL ) {
180             strncpy( ((struct information *)ptr)->xmms2.date, temp, TEXT_BUFFER_SIZE - 1 );
181         } else {
182             strncpy( ((struct information *)ptr)->xmms2.date, "????", TEXT_BUFFER_SIZE - 1 );
183         }
184
185
186         int itemp;
187         xmmsc_result_get_dict_entry_int( res2, "tracknr", &itemp );
188         ((struct information *)ptr)->xmms2.tracknr = itemp;
189
190         xmmsc_result_get_dict_entry_int( res2, "duration", &itemp );
191         ((struct information *)ptr)->xmms2.duration = itemp;
192
193         xmmsc_result_get_dict_entry_int( res2, "bitrate", &itemp );
194         ((struct information *)ptr)->xmms2.bitrate = itemp / 1000;
195
196         xmmsc_result_get_dict_entry_int( res2, "size", &itemp );
197         ((struct information *)ptr)->xmms2.size = (float)itemp / 1048576;
198
199         xmmsc_result_unref( res2 );
200     }
201 }
202
203 void handle_playtime( xmmsc_result_t *res, void *ptr ) {
204     xmmsc_result_t * res2;
205     uint play_time;
206
207     if ( xmmsc_result_iserror( res ) )
208         return;
209
210     if ( !xmmsc_result_get_uint( res, &play_time ) )
211         return;
212
213     res2 = xmmsc_result_restart( res );
214     xmmsc_result_unref( res2 );
215
216     ((struct information *)ptr)->xmms2.elapsed = play_time;
217     ((struct information *)ptr)->xmms2.progress = (float) play_time / ((struct information *)ptr)->xmms2.duration;
218 }
219
220 void handle_playback_state_change( xmmsc_result_t *res, void *ptr ) {
221     uint pb_state = 0;
222     if ( xmmsc_result_iserror( res ) )
223         return;
224
225     if ( !xmmsc_result_get_uint( res, &pb_state ) )
226         return;
227
228     if ( ((struct information *)ptr)->xmms2.status == NULL )
229         ((struct information *)ptr)->xmms2.status = malloc( TEXT_BUFFER_SIZE );
230
231     switch (pb_state) {
232     case XMMS_PLAYBACK_STATUS_PLAY:
233         strncpy( ((struct information *)ptr)->xmms2.status,
234                  "Playing", TEXT_BUFFER_SIZE - 1 );
235         break;
236     case XMMS_PLAYBACK_STATUS_PAUSE:
237         strncpy( ((struct information *)ptr)->xmms2.status,
238                  "Paused", TEXT_BUFFER_SIZE - 1 );
239         break;
240     case XMMS_PLAYBACK_STATUS_STOP:
241         strncpy( ((struct information *)ptr)->xmms2.status,
242                  "Stopped", TEXT_BUFFER_SIZE - 1 );
243         break;
244     default:
245         strncpy( ((struct information *)ptr)->xmms2.status,
246                  "Unknown", TEXT_BUFFER_SIZE - 1 );
247     }
248 }
249
250
251 void update_xmms2() {
252     struct information * current_info = &info;
253
254     /* initialize connection */
255     if ( current_info->xmms2_conn_state == CONN_INIT ) {
256
257         if ( current_info->xmms2_conn == NULL ) {
258             current_info->xmms2_conn = xmmsc_init( "conky" );
259         }
260
261         /* did init fail? */
262         if ( current_info->xmms2_conn == NULL ) {
263             fprintf(stderr,"Conky: xmms2 init failed. %s\n", xmmsc_get_last_error ( current_info->xmms2_conn ));
264             fflush(stderr);
265             return;
266         }
267
268         /* init ok but not connected yet.. */
269         current_info->xmms2_conn_state = CONN_NO;
270
271         /* clear all values */
272         if ( current_info->xmms2.artist == NULL )
273             current_info->xmms2.artist = malloc( TEXT_BUFFER_SIZE );
274         strncpy( current_info->xmms2.artist, "", TEXT_BUFFER_SIZE - 1 );
275
276         if ( current_info->xmms2.album == NULL )
277             current_info->xmms2.album = malloc( TEXT_BUFFER_SIZE );
278         strncpy( current_info->xmms2.album, "", TEXT_BUFFER_SIZE - 1 );
279
280         if ( current_info->xmms2.title == NULL )
281             current_info->xmms2.title = malloc( TEXT_BUFFER_SIZE );
282         strncpy( current_info->xmms2.title, "", TEXT_BUFFER_SIZE - 1 );
283
284         if ( current_info->xmms2.genre == NULL )
285             current_info->xmms2.genre = malloc( TEXT_BUFFER_SIZE );
286         strncpy( current_info->xmms2.genre, "", TEXT_BUFFER_SIZE - 1 );
287
288         if ( current_info->xmms2.comment == NULL )
289             current_info->xmms2.comment = malloc( TEXT_BUFFER_SIZE );
290         strncpy( current_info->xmms2.comment, "", TEXT_BUFFER_SIZE - 1 );
291
292         if ( current_info->xmms2.decoder == NULL )
293             current_info->xmms2.decoder = malloc( TEXT_BUFFER_SIZE );
294         strncpy( current_info->xmms2.decoder, "", TEXT_BUFFER_SIZE - 1 );
295
296         if ( current_info->xmms2.transport == NULL )
297             current_info->xmms2.transport = malloc( TEXT_BUFFER_SIZE );
298         strncpy( current_info->xmms2.transport, "", TEXT_BUFFER_SIZE - 1 );
299
300         if ( current_info->xmms2.url == NULL )
301             current_info->xmms2.url = malloc( TEXT_BUFFER_SIZE );
302         strncpy( current_info->xmms2.url, "", TEXT_BUFFER_SIZE - 1 );
303
304         if ( current_info->xmms2.date == NULL )
305             current_info->xmms2.date = malloc( TEXT_BUFFER_SIZE );
306         strncpy( current_info->xmms2.date, "", TEXT_BUFFER_SIZE - 1 );
307
308
309         current_info->xmms2.tracknr = 0;
310         current_info->xmms2.id = 0;
311         current_info->xmms2.bitrate = 0;
312         current_info->xmms2.duration = 0;
313         current_info->xmms2.elapsed = 0;
314         current_info->xmms2.size = 0;
315         current_info->xmms2.progress = 0;
316
317         /*    fprintf(stderr,"Conky: xmms2 init ok.\n");
318             fflush(stderr); */
319     }
320
321     /* connect */
322     if ( current_info->xmms2_conn_state == CONN_NO ) {
323
324         char *path = getenv ( "XMMS_PATH" );
325         if ( !xmmsc_connect( current_info->xmms2_conn, path ) ) {
326             fprintf(stderr,"Conky: xmms2 connection failed. %s\n",
327                     xmmsc_get_last_error ( current_info->xmms2_conn ));
328             fflush(stderr);
329             current_info->xmms2_conn_state = CONN_NO;
330             return;
331         }
332
333         /* set callbacks */
334         xmmsc_disconnect_callback_set( current_info->xmms2_conn, connection_lost, current_info );
335         XMMS_CALLBACK_SET( current_info->xmms2_conn, xmmsc_playback_current_id, handle_curent_id, current_info );
336         XMMS_CALLBACK_SET( current_info->xmms2_conn, xmmsc_broadcast_playback_current_id, handle_curent_id, current_info );
337         XMMS_CALLBACK_SET( current_info->xmms2_conn, xmmsc_signal_playback_playtime, handle_playtime, current_info );
338         XMMS_CALLBACK_SET( current_info->xmms2_conn, xmmsc_broadcast_playback_status, handle_playback_state_change, current_info );
339
340         /* get playback status, it wont be broadcasted untill it chages */
341         xmmsc_result_t * res = xmmsc_playback_status( current_info->xmms2_conn );
342         xmmsc_result_wait ( res );
343         unsigned int pb_state;
344
345         if ( current_info->xmms2.status == NULL )
346             current_info->xmms2.status = malloc( TEXT_BUFFER_SIZE );
347
348         xmmsc_result_get_uint( res, &pb_state );
349         switch (pb_state) {
350         case XMMS_PLAYBACK_STATUS_PLAY:
351             strncpy( current_info->xmms2.status,
352                      "Playing", TEXT_BUFFER_SIZE - 1 );
353             break;
354         case XMMS_PLAYBACK_STATUS_PAUSE:
355             strncpy( current_info->xmms2.status,
356                      "Paused", TEXT_BUFFER_SIZE - 1 );
357             break;
358         case XMMS_PLAYBACK_STATUS_STOP:
359             strncpy( current_info->xmms2.status,
360                      "Stopped", TEXT_BUFFER_SIZE - 1 );
361             break;
362         default:
363             strncpy( current_info->xmms2.status,
364                      "Unknown", TEXT_BUFFER_SIZE - 1 );
365         }
366         xmmsc_result_unref ( res );
367         
368         /* everything seems to be ok */
369         current_info->xmms2_conn_state = CONN_OK;
370
371         /*   fprintf(stderr,"Conky: xmms2 connected.\n");
372               fflush(stderr);  */
373     }
374
375
376     /* handle callbacks */
377     if ( current_info->xmms2_conn_state == CONN_OK ) {
378         struct timeval tmout;
379         tmout.tv_sec = 0;
380         tmout.tv_usec = 100;
381
382         select( current_info->xmms2_fd + 1, &current_info->xmms2_fdset, NULL, NULL, &tmout );
383
384         xmmsc_io_in_handle(current_info->xmms2_conn);
385         if (xmmsc_io_want_out(current_info->xmms2_conn)) {
386             xmmsc_io_out_handle(current_info->xmms2_conn);
387         }
388     }
389 }