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