Split conky.h into several smaller header files
[monky] / src / mpd.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
29 void init_mpd_stats(struct mpd_s *mpd)
30 {
31         if (mpd->artist == NULL) {
32                 mpd->artist = malloc(text_buffer_size);
33         }
34         if (mpd->album == NULL) {
35                 mpd->album = malloc(text_buffer_size);
36         }
37         if (mpd->title == NULL) {
38                 mpd->title = malloc(text_buffer_size);
39         }
40         if (mpd->random == NULL) {
41                 mpd->random = malloc(text_buffer_size);
42         }
43         if (mpd->repeat == NULL) {
44                 mpd->repeat = malloc(text_buffer_size);
45         }
46         if (mpd->track == NULL) {
47                 mpd->track = malloc(text_buffer_size);
48         }
49         if (mpd->status == NULL) {
50                 mpd->status = malloc(text_buffer_size);
51         }
52         if (mpd->name == NULL) {
53                 mpd->name = malloc(text_buffer_size);
54         }
55         if (mpd->file == NULL) {
56                 mpd->file = malloc(text_buffer_size);
57         }
58         clear_mpd_stats(mpd);
59 }
60
61 void free_mpd_vars(struct mpd_s *mpd)
62 {
63         if (mpd->title) {
64                 free(mpd->title);
65                 mpd->title = NULL;
66         }
67         if (mpd->artist) {
68                 free(mpd->artist);
69                 mpd->artist = NULL;
70         }
71         if (mpd->album) {
72                 free(mpd->album);
73                 mpd->album = NULL;
74         }
75         if (mpd->random) {
76                 free(mpd->random);
77                 mpd->random = NULL;
78         }
79         if (mpd->repeat) {
80                 free(mpd->repeat);
81                 mpd->repeat = NULL;
82         }
83         if (mpd->track) {
84                 free(mpd->track);
85                 mpd->track = NULL;
86         }
87         if (mpd->name) {
88                 free(mpd->name);
89                 mpd->name = NULL;
90         }
91         if (mpd->file) {
92                 free(mpd->file);
93                 mpd->file = NULL;
94         }
95         if (mpd->status) {
96                 free(mpd->status);
97                 mpd->status = NULL;
98         }
99         if (mpd->conn) {
100                 mpd_closeConnection(mpd->conn);
101                 mpd->conn = 0;
102         }
103 }
104
105 void clear_mpd_stats(struct mpd_s *mpd)
106 {
107         *mpd->name = 0;
108         *mpd->file = 0;
109         *mpd->artist = 0;
110         *mpd->album = 0;
111         *mpd->title = 0;
112         *mpd->random = 0;
113         *mpd->repeat = 0;
114         *mpd->track = 0;
115         *mpd->status = 0;
116         mpd->bitrate = 0;
117         mpd->progress = 0;
118         mpd->elapsed = 0;
119         mpd->length = 0;
120 }
121
122 void *update_mpd(void *arg)
123 {
124         if (arg == NULL) {
125                 CRIT_ERR("update_mpd called with a null argument!");
126         }
127
128         struct mpd_s *mpd = (struct mpd_s *) arg;
129
130         while (1) {
131                 mpd_Status *status;
132                 mpd_InfoEntity *entity;
133
134                 if (!mpd->conn) {
135                         mpd->conn = mpd_newConnection(mpd->host,
136                                 mpd->port, 10);
137                 }
138                 if (strlen(mpd->password) > 1) {
139                         mpd_sendPasswordCommand(mpd->conn,
140                                 mpd->password);
141                         mpd_finishCommand(mpd->conn);
142                 }
143
144                 timed_thread_lock(mpd->timed_thread);
145
146                 if (mpd->conn->error || mpd->conn == NULL) {
147                         ERR("MPD error: %s\n", mpd->conn->errorStr);
148                         mpd_closeConnection(mpd->conn);
149                         mpd->conn = 0;
150                         clear_mpd_stats(mpd);
151
152                         strncpy(mpd->status, "MPD not responding",
153                                 text_buffer_size - 1);
154                         timed_thread_unlock(mpd->timed_thread);
155                         if (timed_thread_test(mpd->timed_thread)) {
156                                 timed_thread_exit(mpd->timed_thread);
157                         }
158                         continue;
159                 }
160
161                 mpd_sendStatusCommand(mpd->conn);
162                 if ((status = mpd_getStatus(mpd->conn)) == NULL) {
163                         ERR("MPD error: %s\n", mpd->conn->errorStr);
164                         mpd_closeConnection(mpd->conn);
165                         mpd->conn = 0;
166                         clear_mpd_stats(mpd);
167
168                         strncpy(mpd->status, "MPD not responding",
169                                 text_buffer_size - 1);
170                         timed_thread_unlock(mpd->timed_thread);
171                         if (timed_thread_test(mpd->timed_thread)) {
172                                 timed_thread_exit(mpd->timed_thread);
173                         }
174                         continue;
175                 }
176                 mpd_finishCommand(mpd->conn);
177                 if (mpd->conn->error) {
178                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
179                         mpd_closeConnection(mpd->conn);
180                         mpd->conn = 0;
181                         timed_thread_unlock(mpd->timed_thread);
182                         if (timed_thread_test(mpd->timed_thread)) {
183                                 timed_thread_exit(mpd->timed_thread);
184                         }
185                         continue;
186                 }
187
188                 mpd->volume = status->volume;
189                 /* if (status->error) {
190                         printf("error: %s\n", status->error);
191                 } */
192
193                 if (status->state == MPD_STATUS_STATE_PLAY) {
194                         strncpy(mpd->status, "Playing", text_buffer_size - 1);
195                 }
196                 if (status->state == MPD_STATUS_STATE_STOP) {
197                         clear_mpd_stats(mpd);
198                         strncpy(mpd->status, "Stopped", text_buffer_size - 1);
199                 }
200                 if (status->state == MPD_STATUS_STATE_PAUSE) {
201                         strncpy(mpd->status, "Paused", text_buffer_size - 1);
202                 }
203                 if (status->state == MPD_STATUS_STATE_UNKNOWN) {
204                         clear_mpd_stats(mpd);
205                         *mpd->status = 0;
206                 }
207                 if (status->state == MPD_STATUS_STATE_PLAY
208                                 || status->state == MPD_STATUS_STATE_PAUSE) {
209                         mpd->bitrate = status->bitRate;
210                         mpd->progress = (float) status->elapsedTime /
211                                 status->totalTime;
212                         mpd->elapsed = status->elapsedTime;
213                         mpd->length = status->totalTime;
214                         if (status->random == 0) {
215                                 strcpy(mpd->random, "Off");
216                         } else if (status->random == 1) {
217                                 strcpy(mpd->random, "On");
218                         } else {
219                                 *mpd->random = 0;
220                         }
221                         if (status->repeat == 0) {
222                                 strcpy(mpd->repeat, "Off");
223                         } else if (status->repeat == 1) {
224                                 strcpy(mpd->repeat, "On");
225                         } else {
226                                 *mpd->repeat = 0;
227                         }
228                 }
229
230                 if (mpd->conn->error) {
231                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
232                         mpd_closeConnection(mpd->conn);
233                         mpd->conn = 0;
234                         timed_thread_unlock(mpd->timed_thread);
235                         if (timed_thread_test(mpd->timed_thread)) {
236                                 timed_thread_exit(mpd->timed_thread);
237                         }
238                         continue;
239                 }
240
241                 mpd_sendCurrentSongCommand(mpd->conn);
242                 while ((entity = mpd_getNextInfoEntity(mpd->conn))) {
243                         mpd_Song *song = entity->info.song;
244
245                         if (entity->type != MPD_INFO_ENTITY_TYPE_SONG) {
246                                 mpd_freeInfoEntity(entity);
247                                 continue;
248                         }
249
250                         if (song->artist) {
251                                 strncpy(mpd->artist, song->artist,
252                                         text_buffer_size - 1);
253                         } else {
254                                 *mpd->artist = 0;
255                         }
256                         if (song->album) {
257                                 strncpy(mpd->album, song->album,
258                                         text_buffer_size - 1);
259                         } else {
260                                 *mpd->album = 0;
261                         }
262                         if (song->title) {
263                                 strncpy(mpd->title, song->title,
264                                         text_buffer_size - 1);
265                         } else {
266                                 *mpd->title = 0;
267                         }
268                         if (song->track) {
269                                 strncpy(mpd->track, song->track,
270                                         text_buffer_size - 1);
271                         } else {
272                                 *mpd->track = 0;
273                         }
274                         if (song->name) {
275                                 strncpy(mpd->name, song->name,
276                                         text_buffer_size - 1);
277                         } else {
278                                 *mpd->name = 0;
279                         }
280                         if (song->file) {
281                                 strncpy(mpd->file, song->file,
282                                         text_buffer_size - 1);
283                         } else {
284                                 *mpd->file = 0;
285                         }
286                         if (entity != NULL) {
287                                 mpd_freeInfoEntity(entity);
288                                 entity = NULL;
289                         }
290                 }
291                 if (entity != NULL) {
292                         mpd_freeInfoEntity(entity);
293                         entity = NULL;
294                 }
295                 mpd_finishCommand(mpd->conn);
296                 if (mpd->conn->error) {
297                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
298                         mpd_closeConnection(mpd->conn);
299                         mpd->conn = 0;
300                         timed_thread_unlock(mpd->timed_thread);
301                         if (timed_thread_test(mpd->timed_thread)) {
302                                 timed_thread_exit(mpd->timed_thread);
303                         }
304                         continue;
305                 }
306
307                 timed_thread_unlock(mpd->timed_thread);
308                 if (mpd->conn->error) {
309                         // fprintf(stderr, "%s\n", mpd->conn->errorStr);
310                         mpd_closeConnection(mpd->conn);
311                         mpd->conn = 0;
312                         if (timed_thread_test(mpd->timed_thread)) {
313                                 timed_thread_exit(mpd->timed_thread);
314                         }
315                         continue;
316                 }
317
318                 mpd_freeStatus(status);
319                 /* if (mpd->conn) {
320                         mpd_closeConnection(mpd->conn);
321                         mpd->conn = 0;
322                 } */
323                 if (timed_thread_test(mpd->timed_thread)) {
324                         timed_thread_exit(mpd->timed_thread);
325                 }
326                 continue;
327         }
328         /* never reached */
329 }