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