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