35adf05b37268c30cd29dec6d90b12b9e2e2611a
[monky] / src / xmms2.c
1 /* Conky, a system monitor, based on torsmo
2  *
3  * Any original torsmo code is licensed under the BSD license
4  *
5  * All code written since the fork of torsmo is licensed under the GPL
6  *
7  * Please see COPYING for details
8  *
9  * Copyright (c) 2005-2008 Brenden Matthews, Philip Kovacs, et. al.
10  *      (see AUTHORS)
11  * All rights reserved.
12  *
13  * This program is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * You should have received a copy of the GNU General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26
27 #include "conky.h"
28 #include <xmmsclient/xmmsclient.h>
29
30 #define CONN_INIT       0
31 #define CONN_OK         1
32 #define CONN_NO         2
33
34 /* callbacks */
35
36 static void xmms_alloc(struct information *ptr)
37 {
38         if (ptr->xmms2.status == NULL) {
39                 ptr->xmms2.status = malloc(text_buffer_size);
40                 ptr->xmms2.status[0] = '\0';
41         }
42
43         if (ptr->xmms2.artist == NULL) {
44                 ptr->xmms2.artist = malloc(text_buffer_size);
45                 ptr->xmms2.artist[0] = '\0';
46         }
47
48         if (ptr->xmms2.album == NULL) {
49                 ptr->xmms2.album = malloc(text_buffer_size);
50                 ptr->xmms2.album[0] = '\0';
51         }
52
53         if (ptr->xmms2.title == NULL) {
54                 ptr->xmms2.title = malloc(text_buffer_size);
55                 ptr->xmms2.title[0] = '\0';
56         }
57
58         if (ptr->xmms2.genre == NULL) {
59                 ptr->xmms2.genre = malloc(text_buffer_size);
60                 ptr->xmms2.genre[0] = '\0';
61         }
62
63         if (ptr->xmms2.comment == NULL) {
64                 ptr->xmms2.comment = malloc(text_buffer_size);
65                 ptr->xmms2.comment[0] = '\0';
66         }
67
68         if (ptr->xmms2.url == NULL) {
69                 ptr->xmms2.url = malloc(text_buffer_size);
70                 ptr->xmms2.url[0] = '\0';
71         }
72
73         if (ptr->xmms2.date == NULL) {
74                 ptr->xmms2.date = malloc(text_buffer_size);
75                 ptr->xmms2.date[0] = '\0';
76         }
77 }
78
79 static void xmms_clear(struct information *ptr)
80 {
81         xmms_alloc(ptr);
82         ptr->xmms2.artist[0] = '\0';
83         ptr->xmms2.album[0] = '\0';
84         ptr->xmms2.title[0] = '\0';
85         ptr->xmms2.genre[0] = '\0';
86         ptr->xmms2.comment[0] = '\0';
87         ptr->xmms2.url[0] = '\0';
88         ptr->xmms2.date[0] = '\0';
89
90         ptr->xmms2.tracknr = 0;
91         ptr->xmms2.id = 0;
92         ptr->xmms2.bitrate = 0;
93         ptr->xmms2.duration = 0;
94         ptr->xmms2.elapsed = 0;
95         ptr->xmms2.size = 0;
96         ptr->xmms2.progress = 0;
97         ptr->xmms2.timesplayed = -1;
98 }
99
100 void connection_lost(void *p)
101 {
102         struct information *ptr = p;
103         ptr->xmms2_conn_state = CONN_NO;
104
105         fprintf(stderr,PACKAGE_NAME": xmms2 connection failed. %s\n",
106                     xmmsc_get_last_error ( ptr->xmms2_conn ));
107         fflush(stderr);
108
109         xmms_clear(ptr);
110 }
111
112 void handle_curent_id(xmmsc_result_t *res, void *p)
113 {
114         uint current_id;
115         struct information *ptr = p;
116
117         if (xmmsc_result_get_uint(res, &current_id)) {
118
119                 xmmsc_result_t *res2;
120
121                 res2 = xmmsc_medialib_get_info(ptr->xmms2_conn, current_id);
122                 xmmsc_result_wait(res2);
123
124                 xmms_clear(ptr);
125
126                 ptr->xmms2.id = current_id;
127
128                 char *temp;
129
130                 xmmsc_result_get_dict_entry_string(res2, "artist", &temp);
131                 if (temp != NULL) {
132                         strncpy(ptr->xmms2.artist, temp, text_buffer_size - 1);
133                 } else {
134                         strncpy(ptr->xmms2.artist, "[Unknown]", text_buffer_size - 1);
135                 }
136
137                 xmmsc_result_get_dict_entry_string(res2, "title", &temp);
138                 if (temp != NULL) {
139                         strncpy(ptr->xmms2.title, temp, text_buffer_size - 1);
140                 } else {
141                         strncpy(ptr->xmms2.title, "[Unknown]", text_buffer_size - 1);
142                 }
143
144                 xmmsc_result_get_dict_entry_string(res2, "album", &temp);
145                 if (temp != NULL) {
146                         strncpy(ptr->xmms2.album, temp, text_buffer_size - 1);
147                 } else {
148                         strncpy(ptr->xmms2.album, "[Unknown]", text_buffer_size - 1);
149                 }
150
151                 xmmsc_result_get_dict_entry_string(res2, "genre", &temp);
152                 if (temp != NULL) {
153
154                         strncpy(ptr->xmms2.genre, temp, text_buffer_size - 1);
155                 } else {
156                         strncpy(ptr->xmms2.genre, "[Unknown]", text_buffer_size - 1);
157                 }
158
159                 xmmsc_result_get_dict_entry_string(res2, "comment", &temp);
160                 if (temp != NULL) {
161                         strncpy(ptr->xmms2.comment, temp, text_buffer_size - 1);
162                 } else {
163                         strncpy(ptr->xmms2.comment, "", text_buffer_size - 1);
164                 }
165
166                 xmmsc_result_get_dict_entry_string(res2, "url", &temp);
167                 if (temp != NULL) {
168                         strncpy(ptr->xmms2.url, temp, text_buffer_size - 1);
169                 } else {
170                         strncpy(ptr->xmms2.url, "[Unknown]", text_buffer_size - 1);
171                 }
172
173                 xmmsc_result_get_dict_entry_string(res2, "date", &temp);
174                 if (temp != NULL) {
175                         strncpy(ptr->xmms2.date, temp, text_buffer_size - 1);
176                 } else {
177                         strncpy(ptr->xmms2.date, "????", text_buffer_size - 1);
178                 }
179
180                 int itemp;
181
182                 xmmsc_result_get_dict_entry_int(res2, "tracknr", &itemp);
183                 ptr->xmms2.tracknr = itemp;
184
185                 xmmsc_result_get_dict_entry_int(res2, "duration", &itemp);
186                 ptr->xmms2.duration = itemp;
187
188                 xmmsc_result_get_dict_entry_int(res2, "bitrate", &itemp);
189                 ptr->xmms2.bitrate = itemp / 1000;
190
191                 xmmsc_result_get_dict_entry_int(res2, "size", &itemp);
192                 ptr->xmms2.size = (float) itemp / 1048576;
193
194                 xmmsc_result_get_dict_entry_int( res2, "timesplayed", &itemp );
195                 ptr->xmms2.timesplayed = itemp;
196
197                 xmmsc_result_unref(res2);
198         }
199 }
200
201 void handle_playtime(xmmsc_result_t *res, void *p)
202 {
203         struct information *ptr = p;
204         xmmsc_result_t *res2;
205         uint play_time;
206
207         if (xmmsc_result_iserror(res)) {
208                 return;
209         }
210
211         if (!xmmsc_result_get_uint(res, &play_time)) {
212                 return;
213         }
214
215         res2 = xmmsc_result_restart(res);
216         xmmsc_result_unref(res2);
217
218         ptr->xmms2.elapsed = play_time;
219         ptr->xmms2.progress = (float) play_time / ptr->xmms2.duration;
220 }
221
222 void handle_playback_state_change(xmmsc_result_t *res, void *p)
223 {
224         struct information *ptr = p;
225         uint pb_state = 0;
226
227         if (xmmsc_result_iserror(res)) {
228                 return;
229         }
230
231         if (!xmmsc_result_get_uint(res, &pb_state)) {
232                 return;
233         }
234
235         switch (pb_state) {
236                 case XMMS_PLAYBACK_STATUS_PLAY:
237                         strncpy(ptr->xmms2.status, "Playing", text_buffer_size - 1);
238                         break;
239                 case XMMS_PLAYBACK_STATUS_PAUSE:
240                         strncpy(ptr->xmms2.status, "Paused", text_buffer_size - 1);
241                         break;
242                 case XMMS_PLAYBACK_STATUS_STOP:
243                         strncpy(ptr->xmms2.status, "Stopped", text_buffer_size - 1);
244                         break;
245                 default:
246                         strncpy(ptr->xmms2.status, "Unknown", text_buffer_size - 1);
247         }
248 }
249
250 void handle_playlist_loaded(xmmsc_result_t *res, void *p) {
251         struct information *ptr = p;
252
253         if (ptr->xmms2.playlist == NULL) {
254                 ptr->xmms2.playlist = malloc(text_buffer_size);
255                 ptr->xmms2.playlist[0] = '\0';
256         }
257
258         if (!xmmsc_result_get_string(res, &ptr->xmms2.playlist))  {
259                 ptr->xmms2.playlist[0] = '\0';
260         }
261
262 }
263
264 void update_xmms2()
265 {
266         struct information *current_info = &info;
267
268         /* initialize connection */
269         if (current_info->xmms2_conn_state == CONN_INIT) {
270
271                 if (current_info->xmms2_conn == NULL) {
272                         current_info->xmms2_conn = xmmsc_init(PACKAGE);
273                 }
274
275                 /* did init fail? */
276                 if (current_info->xmms2_conn == NULL) {
277                         fprintf(stderr, PACKAGE_NAME": xmms2 init failed. %s\n",
278                                         xmmsc_get_last_error(current_info->xmms2_conn));
279                         fflush(stderr);
280                         return;
281                 }
282
283                 /* init ok but not connected yet.. */
284                 current_info->xmms2_conn_state = CONN_NO;
285
286                 /* clear all values */
287                 xmms_clear(current_info);
288
289                 /* fprintf(stderr, PACKAGE_NAME": xmms2 init ok.\n");
290                 fflush(stderr); */
291         }
292
293         /* connect */
294         if (current_info->xmms2_conn_state == CONN_NO) {
295
296                 char *path = getenv("XMMS_PATH");
297
298                 if (!xmmsc_connect(current_info->xmms2_conn, path)) {
299                         fprintf(stderr, PACKAGE_NAME": xmms2 connection failed. %s\n",
300                                 xmmsc_get_last_error(current_info->xmms2_conn));
301                         fflush(stderr);
302                         current_info->xmms2_conn_state = CONN_NO;
303                         return;
304                 }
305
306                 /* set callbacks */
307                 xmmsc_disconnect_callback_set(current_info->xmms2_conn, connection_lost,
308                         current_info);
309                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
310                         xmmsc_broadcast_playback_current_id, handle_curent_id,
311                         current_info);
312                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
313                         xmmsc_signal_playback_playtime, handle_playtime, current_info);
314                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
315                         xmmsc_broadcast_playback_status, handle_playback_state_change,
316                         current_info);
317                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
318                         xmmsc_broadcast_playlist_loaded, handle_playlist_loaded,
319                         current_info);
320                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
321                         xmmsc_broadcast_medialib_entry_changed, handle_curent_id,
322                         current_info);
323
324                 /* get playback status, current id and active playlist */
325                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
326                                 xmmsc_playback_current_id, handle_curent_id, current_info);
327                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
328                                 xmmsc_playback_status, handle_playback_state_change, current_info);
329                 XMMS_CALLBACK_SET(current_info->xmms2_conn,
330                                 xmmsc_playlist_current_active, handle_playlist_loaded, current_info);
331
332                 /* everything seems to be ok */
333                 current_info->xmms2_conn_state = CONN_OK;
334
335                 /* fprintf(stderr, PACKAGE_NAME": xmms2 connected.\n");
336                 fflush(stderr); */
337         }
338
339         /* handle callbacks */
340         if (current_info->xmms2_conn_state == CONN_OK) {
341                 
342                 xmmsc_io_in_handle(current_info->xmms2_conn);
343                 if (xmmsc_io_want_out(current_info->xmms2_conn)) {
344                         xmmsc_io_out_handle(current_info->xmms2_conn);
345                 }
346         }
347 }