1 /* libmpd (high level libmpdclient library)
2 * Copyright (C) 2004-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpcwiki.sarine.nl/
4
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <assert.h>
23 #define __USE_GNU
24
25 #include <string.h>
26 #include <stdarg.h>
27 #include <config.h>
28 #include "debug_printf.h"
29 #include "libmpd.h"
30 #include "libmpd-internal.h"
31
32 int mpd_stats_update_real(MpdObj *mi, ChangedStatusType* what_changed);
33
mpd_status_queue_update(MpdObj * mi)34 int mpd_status_queue_update(MpdObj *mi)
35 {
36
37 if(!mpd_check_connected(mi))
38 {
39 debug_printf(DEBUG_INFO,"not connected\n");
40 return MPD_NOT_CONNECTED;
41 }
42 if(mi->status != NULL)
43 {
44 mpd_freeStatus(mi->status);
45 mi->status = NULL;
46 }
47 return MPD_OK;
48 }
49
50
mpd_status_update(MpdObj * mi)51 int mpd_status_update(MpdObj *mi)
52 {
53 ChangedStatusType what_changed=0;
54 if(!mpd_check_connected(mi))
55 {
56 debug_printf(DEBUG_INFO,"not connected\n");
57 return MPD_NOT_CONNECTED;
58 }
59 if(mpd_lock_conn(mi))
60 {
61 debug_printf(DEBUG_ERROR,"lock failed\n");
62 return MPD_LOCK_FAILED;
63 }
64
65
66
67 if(mi->status != NULL)
68 {
69 mpd_freeStatus(mi->status);
70 mi->status = NULL;
71 }
72 mpd_sendStatusCommand(mi->connection);
73 mi->status = mpd_getStatus(mi->connection);
74 if(mi->status == NULL)
75 {
76 debug_printf(DEBUG_ERROR,"Failed to grab status from mpd\n");
77 mpd_unlock_conn(mi);
78 return MPD_STATUS_FAILED;
79 }
80 if(mpd_unlock_conn(mi))
81 {
82 debug_printf(DEBUG_ERROR, "Failed to unlock");
83 return MPD_LOCK_FAILED;
84 }
85 /*
86 * check for changes
87 */
88 /* first save the old status */
89 memcpy(&(mi->OldState), &(mi->CurrentState), sizeof(MpdServerState));
90
91 /* playlist change */
92 if(mi->CurrentState.playlistid != mi->status->playlist)
93 {
94 /* print debug message */
95 debug_printf(DEBUG_INFO, "Playlist has changed!");
96
97 /* We can't trust the current song anymore. so we remove it */
98 /* tags might have been updated */
99 if(mi->CurrentSong != NULL)
100 {
101 mpd_freeSong(mi->CurrentSong);
102 mi->CurrentSong = NULL;
103 }
104
105 /* set MPD_CST_PLAYLIST to be changed */
106 what_changed |= MPD_CST_PLAYLIST;
107
108 if(mi->CurrentState.playlistLength == mi->status->playlistLength)
109 {
110 // what_changed |= MPD_CST_SONGID;
111 }
112 /* save new id */
113 mi->CurrentState.playlistid = mi->status->playlist;
114 }
115
116 if(mi->CurrentState.storedplaylistid != mi->status->storedplaylist)
117 {
118 /* set MPD_CST_QUEUE to be changed */
119 what_changed |= MPD_CST_STORED_PLAYLIST;
120
121
122 /* save new id */
123 mi->CurrentState.storedplaylistid = mi->status->storedplaylist;
124 }
125
126
127 /* state change */
128 if(mi->CurrentState.state != mi->status->state)
129 {
130 what_changed |= MPD_CST_STATE;
131 mi->CurrentState.state = mi->status->state;
132 }
133
134 if(mi->CurrentState.songid != mi->status->songid)
135 {
136 /* print debug message */
137 debug_printf(DEBUG_INFO, "Songid has changed %i %i!", mi->OldState.songid, mi->status->songid);
138
139 what_changed |= MPD_CST_SONGID;
140 /* save new songid */
141 mi->CurrentState.songid = mi->status->songid;
142
143 }
144 if(mi->CurrentState.songpos != mi->status->song)
145 {
146 /* print debug message */
147 debug_printf(DEBUG_INFO, "Songpos has changed %i %i!", mi->OldState.songpos, mi->status->song);
148
149 what_changed |= MPD_CST_SONGPOS;
150 /* save new songid */
151 mi->CurrentState.songpos = mi->status->song;
152
153 }
154 if(mi->CurrentState.nextsongid != mi->status->nextsongid || mi->CurrentState.nextsongpos != mi->status->nextsong)
155 {
156 what_changed |= MPD_CST_NEXTSONG;
157 /* save new songid */
158 mi->CurrentState.nextsongpos = mi->status->nextsong;
159 mi->CurrentState.nextsongid = mi->status->nextsongid;
160 }
161
162 if(mi->CurrentState.single != mi->status->single)
163 {
164 what_changed |= MPD_CST_SINGLE_MODE;
165 mi->CurrentState.single = mi->status->single;
166 }
167 if(mi->CurrentState.consume != mi->status->consume)
168 {
169 what_changed |= MPD_CST_CONSUME_MODE;
170 mi->CurrentState.consume = mi->status->consume;
171 }
172 if(mi->CurrentState.repeat != mi->status->repeat)
173 {
174 what_changed |= MPD_CST_REPEAT;
175 mi->CurrentState.repeat = mi->status->repeat;
176 }
177 if(mi->CurrentState.random != mi->status->random)
178 {
179 what_changed |= MPD_CST_RANDOM;
180 mi->CurrentState.random = mi->status->random;
181 }
182 if(mi->CurrentState.volume != mi->status->volume)
183 {
184 what_changed |= MPD_CST_VOLUME;
185 mi->CurrentState.volume = mi->status->volume;
186 }
187 if(mi->CurrentState.xfade != mi->status->crossfade)
188 {
189 what_changed |= MPD_CST_CROSSFADE;
190 mi->CurrentState.xfade = mi->status->crossfade;
191 }
192 if(mi->CurrentState.totaltime != mi->status->totalTime)
193 {
194 what_changed |= MPD_CST_TOTAL_TIME;
195 mi->CurrentState.totaltime = mi->status->totalTime;
196 }
197 if(mi->CurrentState.elapsedtime != mi->status->elapsedTime)
198 {
199 what_changed |= MPD_CST_ELAPSED_TIME;
200 mi->CurrentState.elapsedtime = mi->status->elapsedTime;
201 }
202
203 /* Check if bitrate changed, happens with vbr encodings. */
204 if(mi->CurrentState.bitrate != mi->status->bitRate)
205 {
206 what_changed |= MPD_CST_BITRATE;
207 mi->CurrentState.bitrate = mi->status->bitRate;
208 }
209
210 /* The following 3 probly only happen on a song change, or is it possible in one song/stream? */
211 /* Check if the sample rate changed */
212 if(mi->CurrentState.samplerate != mi->status->sampleRate)
213 {
214 what_changed |= MPD_CST_AUDIOFORMAT;
215 mi->CurrentState.samplerate = mi->status->sampleRate;
216 }
217
218 /* check if the sampling depth changed */
219 if(mi->CurrentState.bits != mi->status->bits)
220 {
221 what_changed |= MPD_CST_AUDIOFORMAT;
222 mi->CurrentState.bits = mi->status->bits;
223 }
224
225 /* Check if the amount of audio channels changed */
226 if(mi->CurrentState.channels != mi->status->channels)
227 {
228 what_changed |= MPD_CST_AUDIOFORMAT;
229 mi->CurrentState.channels = mi->status->channels;
230 }
231
232 if(mi->status->error)
233 {
234 what_changed |= MPD_CST_SERVER_ERROR;
235 strcpy(mi->CurrentState.error,mi->status->error);
236 mpd_sendClearErrorCommand(mi->connection);
237 mpd_finishCommand(mi->connection);
238 }
239 else
240 {
241 mi->CurrentState.error[0] ='\0';
242 }
243
244 /* Check if the updating changed,
245 * If it stopped, also update the stats for the new db-time.
246 */
247 if(mi->CurrentState.updatingDb != mi->status->updatingDb )
248 {
249 what_changed |= MPD_CST_UPDATING;
250 if(!mi->status->updatingDb)
251 {
252 mpd_stats_update_real(mi, &what_changed);
253 }
254 mi->CurrentState.updatingDb = mi->status->updatingDb;
255 }
256
257
258 mi->CurrentState.playlistLength = mi->status->playlistLength;
259
260
261 /* Detect changed outputs */
262 if(!mi->has_idle)
263 {
264 if(mi->num_outputs >0 )
265 {
266 mpd_OutputEntity *output = NULL;
267 mpd_sendOutputsCommand(mi->connection);
268 while (( output = mpd_getNextOutput(mi->connection)) != NULL)
269 {
270 if(mi->num_outputs < output->id)
271 {
272 mi->num_outputs++;
273 mi->output_states = realloc(mi->output_states,mi->num_outputs*sizeof(int));
274 mi->output_states[mi->num_outputs] = output->enabled;
275 what_changed |= MPD_CST_OUTPUT;
276 }
277 if(mi->output_states[output->id] != output->enabled)
278 {
279 mi->output_states[output->id] = output->enabled;
280 what_changed |= MPD_CST_OUTPUT;
281 }
282 mpd_freeOutputElement(output);
283 }
284 mpd_finishCommand(mi->connection);
285 }
286 else
287 {
288 /* if no outputs, lets fetch them */
289 mpd_server_update_outputs(mi);
290 if(mi->num_outputs == 0)
291 {
292 assert("No outputs defined? that cannot be\n");
293 }
294 what_changed |= MPD_CST_OUTPUT;
295 }
296 }else {
297 char *name;
298 int update_stats = 0;
299 mpd_sendGetEventsCommand(mi->connection);
300 while((name = mpd_getNextEvent(mi->connection))){
301 if(strcmp(name, "output") == 0){
302 what_changed |= MPD_CST_OUTPUT;
303 }else if (strcmp(name, "database") == 0) {
304 if((what_changed&MPD_CST_DATABASE) == 0)
305 {
306 update_stats = 1;
307 }
308 what_changed |= MPD_CST_DATABASE;
309 }else if (strcmp(name, "stored_playlist")==0) {
310 what_changed |= MPD_CST_STORED_PLAYLIST;
311 }else if (strcmp(name, "tag") == 0) {
312 what_changed |= MPD_CST_PLAYLIST;
313 }else if (strcmp (name, "sticker") == 0) {
314 what_changed |= MPD_CST_STICKER;
315 /* This means repeat,random, replaygain or crossface changed */
316 }else if (strcmp (name, "options") == 0) {
317 what_changed |= MPD_CST_REPLAYGAIN;
318 }
319
320 free(name);
321 }
322 mpd_finishCommand(mi->connection);
323 if(update_stats) {
324 mpd_stats_update_real(mi, &what_changed);
325 }
326 }
327
328
329 /* Run the callback */
330 if((mi->the_status_changed_callback != NULL) && what_changed)
331 {
332 mi->the_status_changed_callback( mi, what_changed, mi->the_status_changed_signal_userdata );
333 }
334
335 /* We could have lost connection again during signal handling... so before we return check again if we are connected */
336 if(!mpd_check_connected(mi))
337 {
338 return MPD_NOT_CONNECTED;
339 }
340 return MPD_OK;
341 }
342
343 /* returns TRUE when status is availible, when not availible and connected it tries to grab it */
mpd_status_check(MpdObj * mi)344 int mpd_status_check(MpdObj *mi)
345 {
346 if(!mpd_check_connected(mi))
347 {
348 debug_printf(DEBUG_INFO,"not connected\n");
349 return MPD_NOT_CONNECTED;
350 }
351 if(mi->status == NULL)
352 {
353 /* try to update */
354 if(mpd_status_update(mi))
355 {
356 debug_printf(DEBUG_INFO, "failed to update status\n");
357 return MPD_STATUS_FAILED;
358 }
359 }
360 return MPD_OK;
361 }
362
363
mpd_stats_get_total_songs(MpdObj * mi)364 int mpd_stats_get_total_songs(MpdObj *mi)
365 {
366 if(mi == NULL)
367 {
368 debug_printf(DEBUG_ERROR, "failed to check mi == NULL\n");
369 return MPD_ARGS_ERROR;
370 }
371 if(mpd_stats_check(mi) != MPD_OK)
372 {
373 debug_printf(DEBUG_ERROR,"Failed to get status\n");
374 return MPD_STATUS_FAILED;
375 }
376 return mi->stats->numberOfSongs;
377 }
378
mpd_stats_get_total_artists(MpdObj * mi)379 int mpd_stats_get_total_artists(MpdObj *mi)
380 {
381 if(mi == NULL)
382 {
383 debug_printf(DEBUG_ERROR, "failed to check mi == NULL\n");
384 return MPD_ARGS_ERROR;
385 }
386 if(mpd_stats_check(mi) != MPD_OK)
387 {
388 debug_printf(DEBUG_ERROR,"Failed to get status\n");
389 return MPD_STATS_FAILED;
390 }
391 return mi->stats->numberOfArtists;
392 }
393
mpd_stats_get_total_albums(MpdObj * mi)394 int mpd_stats_get_total_albums(MpdObj *mi)
395 {
396 if(mi == NULL)
397 {
398 debug_printf(DEBUG_ERROR,"failed to check mi == NULL\n");
399 return MPD_ARGS_ERROR;
400 }
401 if(mpd_stats_check(mi) != MPD_OK)
402 {
403 debug_printf(DEBUG_WARNING,"Failed to get status\n");
404 return MPD_STATS_FAILED;
405 }
406 return mi->stats->numberOfAlbums;
407 }
408
409
mpd_stats_get_uptime(MpdObj * mi)410 int mpd_stats_get_uptime(MpdObj *mi)
411 {
412 if(mi == NULL)
413 {
414 debug_printf(DEBUG_ERROR,"failed to check mi == NULL\n");
415 return MPD_ARGS_ERROR;
416 }
417 if(mpd_stats_check(mi) != MPD_OK)
418 {
419 debug_printf(DEBUG_WARNING,"Failed to get status\n");
420 return MPD_STATS_FAILED;
421 }
422 return mi->stats->uptime;
423 }
424
mpd_stats_get_playtime(MpdObj * mi)425 int mpd_stats_get_playtime(MpdObj *mi)
426 {
427 if(mi == NULL)
428 {
429 debug_printf(DEBUG_ERROR, "failed to check mi == NULL\n");
430 return MPD_ARGS_ERROR;
431 }
432 if(mpd_stats_check(mi) != MPD_OK)
433 {
434 debug_printf(DEBUG_WARNING,"Failed to get status\n");
435 return MPD_STATS_FAILED;
436 }
437 return mi->stats->playTime;
438 }
439
mpd_stats_get_db_playtime(MpdObj * mi)440 int mpd_stats_get_db_playtime(MpdObj *mi)
441 {
442 if(mi == NULL)
443 {
444 debug_printf(DEBUG_ERROR, "failed to check mi == NULL\n");
445 return MPD_ARGS_ERROR;
446 }
447 if(mpd_stats_check(mi) != MPD_OK)
448 {
449 debug_printf(DEBUG_WARNING,"Failed to get stats\n");
450 return MPD_STATS_FAILED;
451 }
452 return mi->stats->dbPlayTime;
453 }
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
mpd_status_get_volume(MpdObj * mi)471 int mpd_status_get_volume(MpdObj *mi)
472 {
473 if(mi == NULL)
474 {
475 debug_printf(DEBUG_ERROR, "failed to check mi == NULL\n");
476 return MPD_ARGS_ERROR;
477 }
478 if(mpd_status_check(mi) != MPD_OK)
479 {
480 debug_printf(DEBUG_WARNING, "Failed to get status\n");
481 return MPD_STATUS_FAILED;
482 }
483 return mi->status->volume;
484 }
485
486
mpd_status_get_bitrate(MpdObj * mi)487 int mpd_status_get_bitrate(MpdObj *mi)
488 {
489 if(mi == NULL)
490 {
491 debug_printf(DEBUG_ERROR,"failed to check mi == NULL\n");
492 return MPD_ARGS_ERROR;
493 }
494 if(mpd_status_check(mi) != MPD_OK)
495 {
496 debug_printf(DEBUG_WARNING, "Failed to get status\n");
497 return MPD_STATUS_FAILED;
498 }
499 return mi->CurrentState.bitrate;
500 }
501
mpd_status_get_channels(MpdObj * mi)502 int mpd_status_get_channels(MpdObj *mi)
503 {
504 if(mi == NULL)
505 {
506 debug_printf(DEBUG_ERROR,"failed to check mi == NULL\n");
507 return MPD_ARGS_ERROR;
508 }
509 if(mpd_status_check(mi) != MPD_OK)
510 {
511 debug_printf(DEBUG_WARNING, "Failed to get status\n");
512 return MPD_STATUS_FAILED;
513 }
514 return mi->CurrentState.channels;
515 }
516
mpd_status_get_samplerate(MpdObj * mi)517 unsigned int mpd_status_get_samplerate(MpdObj *mi)
518 {
519 if(mi == NULL)
520 {
521 debug_printf(DEBUG_ERROR,"failed to check mi == NULL\n");
522 return MPD_ARGS_ERROR;
523 }
524 if(mpd_status_check(mi) != MPD_OK)
525 {
526 debug_printf(DEBUG_WARNING, "Failed to get status\n");
527 return MPD_STATUS_FAILED;
528 }
529 return mi->CurrentState.samplerate;
530 }
531
mpd_status_get_bits(MpdObj * mi)532 int mpd_status_get_bits(MpdObj *mi)
533 {
534 if(mi == NULL)
535 {
536 debug_printf(DEBUG_WARNING,"failed to check mi == NULL\n");
537 return MPD_ARGS_ERROR;
538 }
539 if(mpd_status_check(mi) != MPD_OK)
540 {
541 debug_printf(DEBUG_WARNING, "Failed to get status\n");
542 return MPD_STATUS_FAILED;
543 }
544 return mi->CurrentState.bits;
545 }
546
mpd_status_get_mpd_error(MpdObj * mi)547 char * mpd_status_get_mpd_error(MpdObj *mi)
548 {
549 if(mi->CurrentState.error[0] != '\0')
550 {
551 return strdup(mi->CurrentState.error);
552 }
553 return NULL;
554 }
555
mpd_status_db_is_updating(MpdObj * mi)556 int mpd_status_db_is_updating(MpdObj *mi)
557 {
558 if(!mpd_check_connected(mi))
559 {
560 debug_printf(DEBUG_WARNING, "mpd_check_connected failed.\n");
561 return FALSE;
562 }
563 return mi->CurrentState.updatingDb;
564 }
565
566
mpd_status_get_total_song_time(MpdObj * mi)567 int mpd_status_get_total_song_time(MpdObj *mi)
568 {
569 if(!mpd_check_connected(mi))
570 {
571 debug_printf(DEBUG_ERROR, "failed to check mi == NULL\n");
572 return MPD_ARGS_ERROR;
573 }
574 if(mpd_status_check(mi) != MPD_OK)
575 {
576 debug_printf(DEBUG_WARNING, "Failed to get status\n");
577 return MPD_STATUS_FAILED;
578 }
579 return mi->status->totalTime;
580 }
581
582
mpd_status_get_elapsed_song_time(MpdObj * mi)583 int mpd_status_get_elapsed_song_time(MpdObj *mi)
584 {
585 if(!mpd_check_connected(mi))
586 {
587 debug_printf(DEBUG_WARNING,"failed to check mi == NULL\n");
588 return MPD_NOT_CONNECTED;
589 }
590 if(mpd_status_check(mi) != MPD_OK)
591 {
592 debug_printf(DEBUG_WARNING,"Failed to get status\n");
593 return MPD_STATUS_FAILED;
594 }
595 return mi->status->elapsedTime;
596 }
597
mpd_status_set_volume(MpdObj * mi,int volume)598 int mpd_status_set_volume(MpdObj *mi,int volume)
599 {
600 if(!mpd_check_connected(mi))
601 {
602 debug_printf(DEBUG_WARNING,"not connected\n");
603 return MPD_NOT_CONNECTED;
604 }
605 /* making sure volume is between 0 and 100 */
606 volume = (volume < 0)? 0:(volume>100)? 100:volume;
607
608 if(mpd_lock_conn(mi))
609 {
610 debug_printf(DEBUG_ERROR,"lock failed\n");
611 return MPD_LOCK_FAILED;
612 }
613
614 /* send the command */
615 mpd_sendSetvolCommand(mi->connection , volume);
616 mpd_finishCommand(mi->connection);
617 /* check for errors */
618
619 mpd_unlock_conn(mi);
620 /* update status, because we changed it */
621 mpd_status_queue_update(mi);
622 /* return current volume */
623 return mpd_status_get_volume(mi);
624 }
625
mpd_status_get_crossfade(MpdObj * mi)626 int mpd_status_get_crossfade(MpdObj *mi)
627 {
628 if(!mpd_check_connected(mi))
629 {
630 debug_printf(DEBUG_WARNING,"not connected\n");
631 return MPD_NOT_CONNECTED;
632 }
633 if(mpd_status_check(mi) != MPD_OK)
634 {
635 debug_printf(DEBUG_WARNING,"Failed grabbing status\n");
636 return MPD_NOT_CONNECTED;
637 }
638 return mi->status->crossfade;
639 }
640
mpd_status_set_crossfade(MpdObj * mi,int crossfade_time)641 int mpd_status_set_crossfade(MpdObj *mi,int crossfade_time)
642 {
643 if(!mpd_check_connected(mi))
644 {
645 debug_printf(DEBUG_WARNING,"not connected\n");
646 return MPD_NOT_CONNECTED;
647 }
648 if(mpd_lock_conn(mi))
649 {
650 debug_printf(DEBUG_ERROR,"lock failed\n");
651 return MPD_LOCK_FAILED;
652 }
653 mpd_sendCrossfadeCommand(mi->connection, crossfade_time);
654 mpd_finishCommand(mi->connection);
655
656 mpd_unlock_conn(mi);
657 mpd_status_queue_update(mi);
658 return MPD_OK;
659 }
660
661
mpd_status_set_volume_as_float(MpdObj * mi,float fvol)662 float mpd_status_set_volume_as_float(MpdObj *mi, float fvol)
663 {
664 int volume = mpd_status_set_volume(mi, (int)(fvol*100.0));
665 if(volume > -1)
666 {
667 return (float)volume/100.0;
668 }
669 return (float)volume;
670 }
671
mpd_stats_update(MpdObj * mi)672 int mpd_stats_update(MpdObj *mi)
673 {
674 return mpd_stats_update_real(mi, NULL);
675 }
676
mpd_stats_update_real(MpdObj * mi,ChangedStatusType * what_changed)677 int mpd_stats_update_real(MpdObj *mi, ChangedStatusType* what_changed)
678 {
679 ChangedStatusType what_changed_here = 0;
680 if ( what_changed == NULL ) {
681 /* we need to save the current state, because we're called standalone */
682 memcpy(&(mi->OldState), &(mi->CurrentState), sizeof(MpdServerState));
683 }
684
685 if(!mpd_check_connected(mi))
686 {
687 debug_printf(DEBUG_INFO,"not connected\n");
688 return MPD_NOT_CONNECTED;
689 }
690 if(mpd_lock_conn(mi))
691 {
692 debug_printf(DEBUG_ERROR,"lock failed\n");
693 return MPD_LOCK_FAILED;
694 }
695
696 if(mi->stats != NULL)
697 {
698 mpd_freeStats(mi->stats);
699 }
700 mpd_sendStatsCommand(mi->connection);
701 mi->stats = mpd_getStats(mi->connection);
702 if(mi->stats == NULL)
703 {
704 debug_printf(DEBUG_ERROR,"Failed to grab stats from mpd\n");
705 }
706 else if(mi->stats->dbUpdateTime != mi->OldState.dbUpdateTime)
707 {
708 debug_printf(DEBUG_INFO, "database updated\n");
709 what_changed_here |= MPD_CST_DATABASE;
710
711 mi->CurrentState.dbUpdateTime = mi->stats->dbUpdateTime;
712 }
713
714 if (what_changed) {
715 (*what_changed) |= what_changed_here;
716 } else {
717 if((mi->the_status_changed_callback != NULL) & what_changed_here)
718 {
719 mi->the_status_changed_callback(mi, what_changed_here, mi->the_status_changed_signal_userdata);
720 }
721 }
722
723 if(mpd_unlock_conn(mi))
724 {
725 debug_printf(DEBUG_ERROR, "unlock failed");
726 return MPD_LOCK_FAILED;
727 }
728 return MPD_OK;
729 }
730
731
mpd_stats_check(MpdObj * mi)732 int mpd_stats_check(MpdObj *mi)
733 {
734 if(!mpd_check_connected(mi))
735 {
736 debug_printf(DEBUG_WARNING,"not connected\n");
737 return MPD_NOT_CONNECTED;
738 }
739 if(mi->stats == NULL)
740 {
741 /* try to update */
742 if(mpd_stats_update(mi))
743 {
744 debug_printf(DEBUG_ERROR,"failed to update status\n");
745 return MPD_STATUS_FAILED;
746 }
747 }
748 return MPD_OK;
749 }
750