1 /*
2  *  Copyright (C) 2005 Marc Pavot <marc.pavot@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2, or (at your option)
7  *  any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  */
19 
20 #include "servers/ario-server.h"
21 #include <gtk/gtk.h>
22 #include <config.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <limits.h>
27 #include <glib/gi18n.h>
28 #include "lib/ario-conf.h"
29 #include "servers/ario-mpd.h"
30 #include "ario-util.h"
31 #ifdef ENABLE_XMMS2
32 #include "servers/ario-xmms.h"
33 #endif
34 #include "preferences/ario-preferences.h"
35 #include "ario-debug.h"
36 #include "ario-profiles.h"
37 
38 #define NORMAL_TIMEOUT 500
39 #define LAZY_TIMEOUT 12000
40 
41 static guint ario_server_signals[SERVER_LAST_SIGNAL] = { 0 };
42 
43 char * ArioServerItemNames[ARIO_TAG_COUNT] =
44 {
45         N_("Artist"),           // ARIO_TAG_ARTIST
46         N_("Album"),            // ARIO_TAG_ALBUM
47         N_("Album Artist"),     // ARIO_TAG_ALBUM_ARTIST
48         N_("Title"),            // ARIO_TAG_TITLE
49         N_("Track"),            // ARIO_TAG_TRACK
50         NULL,                   // ARIO_TAG_NAME
51         N_("Genre"),            // ARIO_TAG_GENRE
52         N_("Date"),             // ARIO_TAG_DATE
53         N_("Composer"),         // ARIO_TAG_COMPOSER
54         N_("Performer"),        // ARIO_TAG_PERFORMER
55         NULL,                   // ARIO_TAG_COMMENT
56         NULL,                   // ARIO_TAG_DISC
57         N_("Filename"),         // ARIO_TAG_FILENAME
58         N_("Any")               // ARIO_TAG_ANY
59 };
60 
61 G_DEFINE_TYPE (ArioServer, ario_server, G_TYPE_OBJECT)
62 
63         static ArioServer *instance = NULL;
64         static ArioServerInterface *interface = NULL;
65 
66 static void
ario_server_class_init(ArioServerClass * klass)67 ario_server_class_init (ArioServerClass *klass)
68 {
69         ARIO_LOG_FUNCTION_START;
70         GObjectClass *object_class = G_OBJECT_CLASS (klass);
71 
72         /* Object Signals */
73         ario_server_signals[SERVER_SONG_CHANGED] =
74                 g_signal_new ("song_changed",
75                               G_OBJECT_CLASS_TYPE (object_class),
76                               G_SIGNAL_RUN_LAST,
77                               G_STRUCT_OFFSET (ArioServerClass, song_changed),
78                               NULL, NULL,
79                               g_cclosure_marshal_VOID__VOID,
80                               G_TYPE_NONE,
81                               0);
82 
83         ario_server_signals[SERVER_ALBUM_CHANGED] =
84                 g_signal_new ("album_changed",
85                               G_OBJECT_CLASS_TYPE (object_class),
86                               G_SIGNAL_RUN_LAST,
87                               G_STRUCT_OFFSET (ArioServerClass, album_changed),
88                               NULL, NULL,
89                               g_cclosure_marshal_VOID__VOID,
90                               G_TYPE_NONE,
91                               0);
92 
93         ario_server_signals[SERVER_CONNECTIVITY_CHANGED] =
94                 g_signal_new ("connectivity_changed",
95                               G_OBJECT_CLASS_TYPE (object_class),
96                               G_SIGNAL_RUN_LAST,
97                               G_STRUCT_OFFSET (ArioServerClass, connectivity_changed),
98                               NULL, NULL,
99                               g_cclosure_marshal_VOID__VOID,
100                               G_TYPE_NONE,
101                               0);
102 
103         ario_server_signals[SERVER_STATE_CHANGED] =
104                 g_signal_new ("state_changed",
105                               G_OBJECT_CLASS_TYPE (object_class),
106                               G_SIGNAL_RUN_LAST,
107                               G_STRUCT_OFFSET (ArioServerClass, state_changed),
108                               NULL, NULL,
109                               g_cclosure_marshal_VOID__VOID,
110                               G_TYPE_NONE,
111                               0);
112 
113         ario_server_signals[SERVER_VOLUME_CHANGED] =
114                 g_signal_new ("volume_changed",
115                               G_OBJECT_CLASS_TYPE (object_class),
116                               G_SIGNAL_RUN_LAST,
117                               G_STRUCT_OFFSET (ArioServerClass, volume_changed),
118                               NULL, NULL,
119                               g_cclosure_marshal_VOID__INT,
120                               G_TYPE_NONE,
121                               1,
122                               G_TYPE_INT);
123 
124         ario_server_signals[SERVER_ELAPSED_CHANGED] =
125                 g_signal_new ("elapsed_changed",
126                               G_OBJECT_CLASS_TYPE (object_class),
127                               G_SIGNAL_RUN_LAST,
128                               G_STRUCT_OFFSET (ArioServerClass, elapsed_changed),
129                               NULL, NULL,
130                               g_cclosure_marshal_VOID__INT,
131                               G_TYPE_NONE,
132                               1,
133                               G_TYPE_INT);
134 
135         ario_server_signals[SERVER_PLAYLIST_CHANGED] =
136                 g_signal_new ("playlist_changed",
137                               G_OBJECT_CLASS_TYPE (object_class),
138                               G_SIGNAL_RUN_LAST,
139                               G_STRUCT_OFFSET (ArioServerClass, playlist_changed),
140                               NULL, NULL,
141                               g_cclosure_marshal_VOID__VOID,
142                               G_TYPE_NONE,
143                               0);
144 
145         ario_server_signals[SERVER_CONSUME_CHANGED] =
146                 g_signal_new ("consume_changed",
147                               G_OBJECT_CLASS_TYPE (object_class),
148                               G_SIGNAL_RUN_LAST,
149                               G_STRUCT_OFFSET (ArioServerClass, consume_changed),
150                               NULL, NULL,
151                               g_cclosure_marshal_VOID__VOID,
152                               G_TYPE_NONE,
153                               0);
154 
155         ario_server_signals[SERVER_RANDOM_CHANGED] =
156                 g_signal_new ("random_changed",
157                               G_OBJECT_CLASS_TYPE (object_class),
158                               G_SIGNAL_RUN_LAST,
159                               G_STRUCT_OFFSET (ArioServerClass, random_changed),
160                               NULL, NULL,
161                               g_cclosure_marshal_VOID__VOID,
162                               G_TYPE_NONE,
163                               0);
164 
165         ario_server_signals[SERVER_REPEAT_CHANGED] =
166                 g_signal_new ("repeat_changed",
167                               G_OBJECT_CLASS_TYPE (object_class),
168                               G_SIGNAL_RUN_LAST,
169                               G_STRUCT_OFFSET (ArioServerClass, repeat_changed),
170                               NULL, NULL,
171                               g_cclosure_marshal_VOID__VOID,
172                               G_TYPE_NONE,
173                               0);
174 
175         ario_server_signals[SERVER_UPDATINGDB_CHANGED] =
176                 g_signal_new ("updatingdb_changed",
177                               G_OBJECT_CLASS_TYPE (object_class),
178                               G_SIGNAL_RUN_LAST,
179                               G_STRUCT_OFFSET (ArioServerClass, updatingdb_changed),
180                               NULL, NULL,
181                               g_cclosure_marshal_VOID__VOID,
182                               G_TYPE_NONE,
183                               0);
184 
185         ario_server_signals[SERVER_STOREDPLAYLISTS_CHANGED] =
186                 g_signal_new ("storedplaylists_changed",
187                               G_OBJECT_CLASS_TYPE (object_class),
188                               G_SIGNAL_RUN_LAST,
189                               G_STRUCT_OFFSET (ArioServerClass, storedplaylists_changed),
190                               NULL, NULL,
191                               g_cclosure_marshal_VOID__VOID,
192                               G_TYPE_NONE,
193                               0);
194 }
195 
196 static void
ario_server_init(ArioServer * server)197 ario_server_init (ArioServer *server)
198 {
199         ARIO_LOG_FUNCTION_START;
200 }
201 
202 static void
ario_server_reset_interface(void)203 ario_server_reset_interface (void)
204 {
205         ARIO_LOG_FUNCTION_START;
206         static ArioServerType interface_type = -1;
207         ArioServerType new_interface_type;
208 
209         /* Get new interface type */
210         new_interface_type = ario_profiles_get_current (ario_profiles_get ())->type;
211 
212         /* Same type as before: do nothing */
213         if (new_interface_type == interface_type)
214                 return;
215 
216         /* Change type */
217         interface_type = new_interface_type;
218 
219         /* destroy previous insterface */
220         if (interface) {
221                 ario_server_disconnect ();
222                 g_object_unref (interface);
223         }
224 
225         /* Create new interface */
226         if (interface_type == ArioServerMpd) {
227                 /* MPD interface */
228                 interface = ARIO_SERVER_INTERFACE (ario_mpd_get_instance (instance));
229 #ifdef ENABLE_XMMS2
230         } else if (interface_type == ArioServerXmms) {
231                 /* XMMS2 interface */
232                 interface = ARIO_SERVER_INTERFACE (ario_xmms_get_instance (instance));
233 #endif
234         } else {
235                 /* Unknown interface */
236                 ARIO_LOG_ERROR ("Unknown server type: %d", interface_type);
237                 interface = ARIO_SERVER_INTERFACE (ario_mpd_get_instance (instance));
238         }
239 }
240 
241 ArioServer *
ario_server_get_instance(void)242 ario_server_get_instance (void)
243 {
244         ARIO_LOG_FUNCTION_START;
245         /* Singleton instanciation if needed */
246         if (!instance) {
247                 instance = g_object_new (ARIO_TYPE_SERVER, NULL);
248         }
249         if (!interface) {
250                 ario_server_reset_interface ();
251         }
252 
253         return instance;
254 }
255 
256 gboolean
ario_server_connect(void)257 ario_server_connect (void)
258 {
259         ARIO_LOG_FUNCTION_START;
260 
261         /* Make sure we have the right interface type */
262         ario_server_reset_interface ();
263 
264         /* check if there is a connection */
265         if (ario_server_is_connected () || interface->connecting)
266                 return FALSE;
267 
268         interface->connecting = TRUE;
269 
270         /* Call virtual method */
271         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->connect ();
272         g_signal_emit (G_OBJECT (instance), ario_server_signals[SERVER_CONNECTIVITY_CHANGED], 0);
273         return FALSE;
274 }
275 
276 void
ario_server_disconnect(void)277 ario_server_disconnect (void)
278 {
279         ARIO_LOG_FUNCTION_START;
280         /* Call virtual method */
281         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->disconnect ();
282         g_signal_emit (G_OBJECT (instance), ario_server_signals[SERVER_CONNECTIVITY_CHANGED], 0);
283 }
284 
285 void
ario_server_reconnect(void)286 ario_server_reconnect (void)
287 {
288         ARIO_LOG_FUNCTION_START;
289         ario_server_disconnect ();
290         ario_server_connect ();
291 }
292 
293 void
ario_server_shutdown(void)294 ario_server_shutdown (void)
295 {
296         ARIO_LOG_FUNCTION_START;
297         g_object_unref (interface);
298 }
299 
300 void
ario_server_update_db(const gchar * path)301 ario_server_update_db (const gchar *path)
302 {
303         ARIO_LOG_FUNCTION_START;
304         interface->updatingdb = 1;
305         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->update_db (path);
306 }
307 
308 gboolean
ario_server_is_connected(void)309 ario_server_is_connected (void)
310 {
311         // desactivated to make the logs more readable
312         //ARIO_LOG_FUNCTION_START;
313 
314         /* Call virtual method */
315         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->is_connected ();
316 }
317 
318 GSList *
ario_server_list_tags(const ArioServerTag tag,const ArioServerCriteria * criteria)319 ario_server_list_tags (const ArioServerTag tag,
320                        const ArioServerCriteria *criteria)
321 {
322         ARIO_LOG_FUNCTION_START;
323         /* Call virtual method */
324         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->list_tags (tag, criteria);
325 }
326 
327 GSList *
ario_server_get_albums(const ArioServerCriteria * criteria)328 ario_server_get_albums (const ArioServerCriteria *criteria)
329 {
330         ARIO_LOG_FUNCTION_START;
331         /* Call virtual method */
332         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_albums (criteria);
333 }
334 
335 GSList *
ario_server_get_songs(const ArioServerCriteria * criteria,const gboolean exact)336 ario_server_get_songs (const ArioServerCriteria *criteria,
337                        const gboolean exact)
338 {
339         ARIO_LOG_FUNCTION_START;
340         /* Call virtual method */
341         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_songs (criteria, exact);
342 }
343 
344 GSList *
ario_server_get_songs_from_playlist(char * playlist)345 ario_server_get_songs_from_playlist (char *playlist)
346 {
347         ARIO_LOG_FUNCTION_START;
348         /* Call virtual method */
349         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_songs_from_playlist (playlist);
350 }
351 
352 GSList *
ario_server_get_playlists(void)353 ario_server_get_playlists (void)
354 {
355         ARIO_LOG_FUNCTION_START;
356         /* Call virtual method */
357         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_playlists ();
358 }
359 
360 GSList *
ario_server_get_playlist_changes(gint64 playlist_id)361 ario_server_get_playlist_changes (gint64 playlist_id)
362 {
363         ARIO_LOG_FUNCTION_START;
364         /* Call virtual method */
365         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_playlist_changes (playlist_id);
366 }
367 
368 gboolean
ario_server_update_status(void)369 ario_server_update_status (void)
370 {
371         /* Call virtual method */
372         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->update_status ();
373 }
374 
375 ArioServerSong *
ario_server_get_current_song_on_server(void)376 ario_server_get_current_song_on_server (void)
377 {
378         ARIO_LOG_FUNCTION_START;
379         /* Call virtual method */
380         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_current_song_on_server ();
381 }
382 
383 ArioServerSong *
ario_server_get_current_song(void)384 ario_server_get_current_song (void)
385 {
386         ARIO_LOG_FUNCTION_START;
387         if (interface->server_song)
388                 return interface->server_song;
389         else
390                 return NULL;
391 }
392 
393 char *
ario_server_get_current_artist(void)394 ario_server_get_current_artist (void)
395 {
396         ARIO_LOG_FUNCTION_START;
397         if (interface->server_song)
398                 return interface->server_song->artist;
399         else
400                 return NULL;
401 }
402 
403 char *
ario_server_get_current_album(void)404 ario_server_get_current_album (void)
405 {
406         ARIO_LOG_FUNCTION_START;
407         if (interface->server_song)
408                 return interface->server_song->album;
409         else
410                 return NULL;
411 }
412 
413 char *
ario_server_get_current_song_path(void)414 ario_server_get_current_song_path (void)
415 {
416         ARIO_LOG_FUNCTION_START;
417         if (interface->server_song)
418                 return interface->server_song->file;
419         else
420                 return NULL;
421 }
422 
423 int
ario_server_get_current_song_id(void)424 ario_server_get_current_song_id (void)
425 {
426         ARIO_LOG_FUNCTION_START;
427         return interface->song_id;
428 }
429 
430 int
ario_server_get_current_state(void)431 ario_server_get_current_state (void)
432 {
433         ARIO_LOG_FUNCTION_START;
434         return interface->state;
435 }
436 
437 int
ario_server_get_current_elapsed(void)438 ario_server_get_current_elapsed (void)
439 {
440         ARIO_LOG_FUNCTION_START;
441         return interface->elapsed;
442 }
443 
444 int
ario_server_get_current_volume(void)445 ario_server_get_current_volume (void)
446 {
447         ARIO_LOG_FUNCTION_START;
448         return interface->volume;
449 }
450 
451 int
ario_server_get_current_total_time(void)452 ario_server_get_current_total_time (void)
453 {
454         ARIO_LOG_FUNCTION_START;
455         if (interface->server_song)
456                 return interface->server_song->time;
457         else
458                 return 0;
459 }
460 
461 gint64
ario_server_get_current_playlist_id(void)462 ario_server_get_current_playlist_id (void)
463 {
464         ARIO_LOG_FUNCTION_START;
465         return interface->playlist_id;
466 }
467 
468 int
ario_server_get_current_playlist_length(void)469 ario_server_get_current_playlist_length (void)
470 {
471         ARIO_LOG_FUNCTION_START;
472         return interface->playlist_length;
473 }
474 
475 int
ario_server_get_current_playlist_total_time(void)476 ario_server_get_current_playlist_total_time (void)
477 {
478         ARIO_LOG_FUNCTION_START;
479         /* Call virtual method */
480         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_current_playlist_total_time ();
481 }
482 
483 int
ario_server_get_crossfadetime(void)484 ario_server_get_crossfadetime (void)
485 {
486         ARIO_LOG_FUNCTION_START;
487         if (ario_server_is_connected ())
488                 return interface->crossfade;
489         else
490                 return 0;
491 }
492 
493 gboolean
ario_server_get_current_consume(void)494 ario_server_get_current_consume (void)
495 {
496         ARIO_LOG_FUNCTION_START;
497         return interface->consume;
498 }
499 
500 gboolean
ario_server_get_current_random(void)501 ario_server_get_current_random (void)
502 {
503         ARIO_LOG_FUNCTION_START;
504         return interface->random;
505 }
506 
507 gboolean
ario_server_get_current_repeat(void)508 ario_server_get_current_repeat (void)
509 {
510         ARIO_LOG_FUNCTION_START;
511         return interface->repeat;
512 }
513 
514 gboolean
ario_server_get_updating(void)515 ario_server_get_updating (void)
516 {
517         ARIO_LOG_FUNCTION_START;
518         return ario_server_is_connected () && interface->updatingdb;
519 }
520 
521 unsigned long
ario_server_get_last_update(void)522 ario_server_get_last_update (void)
523 {
524         /* Call virtual method */
525         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_last_update ();
526 }
527 
528 gboolean
ario_server_is_paused(void)529 ario_server_is_paused (void)
530 {
531         ARIO_LOG_FUNCTION_START;
532         return (interface->state == ARIO_STATE_PAUSE) || (interface->state == ARIO_STATE_STOP);
533 }
534 
535 void
ario_server_do_next(void)536 ario_server_do_next (void)
537 {
538         ARIO_LOG_FUNCTION_START;
539         /* Call virtual method */
540         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->do_next ();
541 }
542 
543 void
ario_server_do_prev(void)544 ario_server_do_prev (void)
545 {
546         ARIO_LOG_FUNCTION_START;
547         /* Call virtual method */
548         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->do_prev ();
549 }
550 
551 void
ario_server_do_play(void)552 ario_server_do_play (void)
553 {
554         ARIO_LOG_FUNCTION_START;
555         /* Call virtual method */
556         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->do_play ();
557 }
558 
559 void
ario_server_do_play_pos(gint id)560 ario_server_do_play_pos (gint id)
561 {
562         ARIO_LOG_FUNCTION_START;
563         /* Call virtual method */
564         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->do_play_pos (id);
565 }
566 
567 void
ario_server_do_pause(void)568 ario_server_do_pause (void)
569 {
570         ARIO_LOG_FUNCTION_START;
571         /* Call virtual method */
572         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->do_pause ();
573 }
574 
575 void
ario_server_do_stop(void)576 ario_server_do_stop (void)
577 {
578         ARIO_LOG_FUNCTION_START;
579         /* Call virtual method */
580         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->do_stop ();
581 }
582 
583 void
ario_server_free_album(ArioServerAlbum * server_album)584 ario_server_free_album (ArioServerAlbum *server_album)
585 {
586         ARIO_LOG_FUNCTION_START;
587         if (server_album) {
588                 g_free (server_album->album);
589                 g_free (server_album->artist);
590                 g_free (server_album->path);
591                 g_free (server_album->date);
592                 g_free (server_album);
593         }
594 }
595 
596 ArioServerAlbum*
ario_server_copy_album(const ArioServerAlbum * server_album)597 ario_server_copy_album (const ArioServerAlbum *server_album)
598 {
599         ARIO_LOG_FUNCTION_START;
600         ArioServerAlbum *ret = NULL;
601 
602         if (server_album) {
603                 ret = (ArioServerAlbum *) g_malloc (sizeof (ArioServerAlbum));
604                 ret->album = g_strdup (server_album->album);
605                 ret->artist = g_strdup (server_album->artist);
606                 ret->path = g_strdup (server_album->path);
607                 ret->date = g_strdup (server_album->date);
608         }
609 
610         return ret;
611 }
612 
613 void
ario_server_set_current_elapsed(const gint elapsed)614 ario_server_set_current_elapsed (const gint elapsed)
615 {
616         ARIO_LOG_FUNCTION_START;
617         /* Call virtual method */
618         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->set_current_elapsed (elapsed);
619 }
620 
621 void
ario_server_set_current_volume(const gint volume)622 ario_server_set_current_volume (const gint volume)
623 {
624         ARIO_LOG_FUNCTION_START;
625         /* Call virtual method */
626         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->set_current_volume (volume);
627 }
628 
629 void
ario_server_set_current_consume(const gboolean consume)630 ario_server_set_current_consume (const gboolean consume)
631 {
632         ARIO_LOG_FUNCTION_START;
633         /* Call virtual method */
634         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->set_current_consume (consume);
635 }
636 
637 void
ario_server_set_current_random(const gboolean random)638 ario_server_set_current_random (const gboolean random)
639 {
640         ARIO_LOG_FUNCTION_START;
641         /* Call virtual method */
642         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->set_current_random (random);
643 }
644 
645 void
ario_server_set_current_repeat(const gboolean repeat)646 ario_server_set_current_repeat (const gboolean repeat)
647 {
648         ARIO_LOG_FUNCTION_START;
649         /* Call virtual method */
650         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->set_current_repeat (repeat);
651 }
652 
653 void
ario_server_set_crossfadetime(const int crossfadetime)654 ario_server_set_crossfadetime (const int crossfadetime)
655 {
656         ARIO_LOG_FUNCTION_START;
657         /* Call virtual method */
658         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->set_crossfadetime (crossfadetime);
659 }
660 
661 void
ario_server_clear(void)662 ario_server_clear (void)
663 {
664         ARIO_LOG_FUNCTION_START;
665         /* Call virtual method */
666         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->clear ();
667 }
668 
669 void
ario_server_shuffle(void)670 ario_server_shuffle (void)
671 {
672         ARIO_LOG_FUNCTION_START;
673         /* Call virtual method */
674         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->shuffle ();
675 }
676 
677 void
ario_server_queue_add(const char * path)678 ario_server_queue_add (const char *path)
679 {
680         ARIO_LOG_FUNCTION_START;
681 
682         /* Append a queue action to list */
683         ArioServerQueueAction *queue_action = (ArioServerQueueAction *) g_malloc (sizeof (ArioServerQueueAction));
684         queue_action->type = ARIO_SERVER_ACTION_ADD;
685         queue_action->path = path;
686 
687         interface->queue = g_slist_append (interface->queue, queue_action);
688 }
689 
690 void
ario_server_queue_delete_id(const int id)691 ario_server_queue_delete_id (const int id)
692 {
693         /* Append a queue action to list */
694         ArioServerQueueAction *queue_action = (ArioServerQueueAction *) g_malloc (sizeof (ArioServerQueueAction));
695         queue_action->type = ARIO_SERVER_ACTION_DELETE_ID;
696         queue_action->id = id;
697 
698         interface->queue = g_slist_append (interface->queue, queue_action);
699 }
700 
701 void
ario_server_queue_delete_pos(const int pos)702 ario_server_queue_delete_pos (const int pos)
703 {
704         ARIO_LOG_FUNCTION_START;
705         /* Append a queue action to list */
706         ArioServerQueueAction *queue_action = (ArioServerQueueAction *) g_malloc (sizeof (ArioServerQueueAction));
707         queue_action->type = ARIO_SERVER_ACTION_DELETE_POS;
708         queue_action->pos = pos;
709 
710         interface->queue = g_slist_append (interface->queue, queue_action);
711 }
712 
713 void
ario_server_queue_move(const int old_pos,const int new_pos)714 ario_server_queue_move (const int old_pos,
715                         const int new_pos)
716 {
717         ARIO_LOG_FUNCTION_START;
718         /* Append a queue action to list */
719         ArioServerQueueAction *queue_action = (ArioServerQueueAction *) g_malloc (sizeof (ArioServerQueueAction));
720         queue_action->type = ARIO_SERVER_ACTION_MOVE;
721         queue_action->old_pos = old_pos;
722         queue_action->new_pos = new_pos;
723 
724         interface->queue = g_slist_append (interface->queue, queue_action);
725 }
726 
727 void
ario_server_queue_moveid(const int id,const int pos)728 ario_server_queue_moveid (const int id,
729                           const int pos)
730 {
731         ARIO_LOG_FUNCTION_START;
732         /* Append a queue action to list */
733         ArioServerQueueAction *queue_action = (ArioServerQueueAction *) g_malloc (sizeof (ArioServerQueueAction));
734         queue_action->type = ARIO_SERVER_ACTION_MOVEID;
735         queue_action->old_pos = id;
736         queue_action->new_pos = pos;
737 
738         interface->queue = g_slist_append (interface->queue, queue_action);
739 }
740 
741 void
ario_server_queue_commit(void)742 ario_server_queue_commit (void)
743 {
744         ARIO_LOG_FUNCTION_START;
745         /* Call virtual method */
746         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->queue_commit ();
747 }
748 
749 void
ario_server_insert_at(const GSList * songs,const gint pos)750 ario_server_insert_at (const GSList *songs,
751                        const gint pos)
752 {
753         ARIO_LOG_FUNCTION_START;
754         /* Call virtual method */
755         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->insert_at (songs, pos);
756 }
757 
758 int
ario_server_save_playlist(const char * name)759 ario_server_save_playlist (const char *name)
760 {
761         ARIO_LOG_FUNCTION_START;
762         /* Call virtual method */
763         int ret = ARIO_SERVER_INTERFACE_GET_CLASS (interface)->save_playlist (name);
764 
765 #ifndef ENABLE_MPDIDLE
766         g_signal_emit (G_OBJECT (instance), ario_server_signals[SERVER_STOREDPLAYLISTS_CHANGED], 0);
767 #endif
768 
769         return ret;
770 }
771 
772 void
ario_server_delete_playlist(const char * name)773 ario_server_delete_playlist (const char *name)
774 {
775         ARIO_LOG_FUNCTION_START;
776         /* Call virtual method */
777         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->delete_playlist (name);
778 
779 #ifndef ENABLE_MPDIDLE
780         g_signal_emit (G_OBJECT (instance), ario_server_signals[SERVER_STOREDPLAYLISTS_CHANGED], 0);
781 #endif
782 }
783 
784 GSList *
ario_server_get_outputs(void)785 ario_server_get_outputs (void)
786 {
787         ARIO_LOG_FUNCTION_START;
788         /* Call virtual method */
789         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_outputs ();
790 }
791 
792 void
ario_server_enable_output(int id,gboolean enabled)793 ario_server_enable_output (int id,
794                            gboolean enabled)
795 {
796         ARIO_LOG_FUNCTION_START;
797         /* Call virtual method */
798         ARIO_SERVER_INTERFACE_GET_CLASS (interface)->enable_output (id, enabled);
799 }
800 
801 ArioServerStats *
ario_server_get_stats(void)802 ario_server_get_stats (void)
803 {
804         ARIO_LOG_FUNCTION_START;
805         /* Call virtual method */
806         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_stats ();
807 }
808 
809 GList *
ario_server_get_songs_info(GSList * paths)810 ario_server_get_songs_info (GSList *paths)
811 {
812         ARIO_LOG_FUNCTION_START;
813         /* Call virtual method */
814         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->get_songs_info (paths);
815 }
816 
817 ArioServerFileList *
ario_server_list_files(const char * path,gboolean recursive)818 ario_server_list_files (const char *path,
819                         gboolean recursive)
820 {
821         ARIO_LOG_FUNCTION_START;
822         /* Call virtual method */
823         return ARIO_SERVER_INTERFACE_GET_CLASS (interface)->list_files (path, recursive);
824 }
825 
826 void
ario_server_free_file_list(ArioServerFileList * files)827 ario_server_free_file_list (ArioServerFileList *files)
828 {
829         ARIO_LOG_FUNCTION_START;
830         if (files) {
831                 g_slist_foreach (files->directories, (GFunc) g_free, NULL);
832                 g_slist_free (files->directories);
833                 g_slist_foreach (files->songs, (GFunc) ario_server_free_song, NULL);
834                 g_slist_free (files->songs);
835                 g_free (files);
836         }
837 }
838 
839 void
ario_server_criteria_free(ArioServerCriteria * criteria)840 ario_server_criteria_free (ArioServerCriteria *criteria)
841 {
842         ARIO_LOG_FUNCTION_START;
843         GSList *tmp;
844         ArioServerAtomicCriteria *atomic_criteria;
845 
846         for (tmp = criteria; tmp; tmp = g_slist_next (tmp)) {
847                 atomic_criteria = tmp->data;
848                 g_free (atomic_criteria->value);
849                 g_free (atomic_criteria);
850         }
851         g_slist_free (criteria);
852 }
853 
854 ArioServerCriteria *
ario_server_criteria_copy(const ArioServerCriteria * criteria)855 ario_server_criteria_copy (const ArioServerCriteria *criteria)
856 {
857         ARIO_LOG_FUNCTION_START;
858         ArioServerCriteria *ret = NULL;
859         const GSList *tmp;
860         ArioServerAtomicCriteria *atomic_criteria;
861         ArioServerAtomicCriteria *new_atomic_criteria;
862 
863         for (tmp = criteria; tmp; tmp = g_slist_next (tmp)) {
864                 atomic_criteria = tmp->data;
865                 if (criteria) {
866                         new_atomic_criteria = (ArioServerAtomicCriteria *) g_malloc0 (sizeof (ArioServerAtomicCriteria));
867                         new_atomic_criteria->tag = atomic_criteria->tag;
868                         new_atomic_criteria->value = g_strdup (atomic_criteria->value);
869                         ret = g_slist_append (ret, new_atomic_criteria);
870                 }
871         }
872         return ret;
873 }
874 
875 gchar **
ario_server_get_items_names(void)876 ario_server_get_items_names (void)
877 {
878         return ArioServerItemNames;
879 }
880 
881 const gchar*
ario_server_song_get_tag(const ArioServerSong * song,ArioServerTag tag)882 ario_server_song_get_tag (const ArioServerSong *song,
883                           ArioServerTag tag)
884 {
885         ARIO_LOG_FUNCTION_START;
886         switch (tag) {
887         case ARIO_TAG_ARTIST: return song->artist;
888         case ARIO_TAG_ALBUM: return song->album;
889         case ARIO_TAG_ALBUM_ARTIST: return song->album_artist;
890         case ARIO_TAG_TITLE: return song->title;
891         case ARIO_TAG_TRACK: return song->track;
892         case ARIO_TAG_NAME: return song->name;
893         case ARIO_TAG_GENRE: return song->genre;
894         case ARIO_TAG_DATE: return song->date;
895         case ARIO_TAG_COMPOSER: return song->composer;
896         case ARIO_TAG_PERFORMER: return song->performer;
897         case ARIO_TAG_COMMENT: return song->comment;
898         case ARIO_TAG_DISC: return song->disc;
899         case ARIO_TAG_FILENAME: return song->file;
900         default: return NULL;
901         }
902 }
903 
904 void
ario_server_playlist_add_songs(const GSList * songs,const gint pos,const PlaylistAction action)905 ario_server_playlist_add_songs (const GSList *songs,
906                                 const gint pos,
907                                 const PlaylistAction action)
908 {
909         ARIO_LOG_FUNCTION_START;
910         const GSList *tmp;
911         int end;
912         int song_pos = pos;
913 
914         /* Clear playlist if needed */
915         if (action == PLAYLIST_REPLACE)  {
916                 ario_server_clear ();
917         }
918 
919         /* Get current song position */
920         if (action == PLAYLIST_ADD_AFTER_PLAYING
921             && (interface->state == ARIO_STATE_PLAY
922                 || interface->state == ARIO_STATE_PAUSE))  {
923                 song_pos = ario_server_get_current_song()->pos;
924         }
925 
926         end = ario_server_get_current_playlist_length ();
927 
928         if (song_pos >= 0) {
929                 /* Insert songs at a given position */
930                 ario_server_insert_at (songs, song_pos);
931         } else {
932                 /* For each filename :*/
933                 for (tmp = songs; tmp; tmp = g_slist_next (tmp)) {
934                         /* Add it in the playlist*/
935                         ario_server_queue_add (tmp->data);
936                 }
937                 /* Commit song additions */
938                 ario_server_queue_commit ();
939         }
940 
941         /* Start playing if needed */
942         if (action == PLAYLIST_ADD_PLAY || action == PLAYLIST_REPLACE)  {
943                 ario_server_do_play_pos (end);
944         }
945 }
946 
947 void
ario_server_playlist_add_dir(const gchar * dir,const gint pos,const PlaylistAction action)948 ario_server_playlist_add_dir (const gchar *dir,
949                               const gint pos,
950                               const PlaylistAction action)
951 {
952         ARIO_LOG_FUNCTION_START;
953         GSList *tmp;
954         ArioServerFileList *files;
955         ArioServerSong *song;
956         GSList *char_songs = NULL;
957 
958         /* List files in dir */
959         files = ario_server_list_files (dir, TRUE);
960 
961         /* For each file */
962         for (tmp = files->songs; tmp; tmp = g_slist_next (tmp)) {
963                 song = tmp->data;
964                 /* Append file to list */
965                 char_songs = g_slist_append (char_songs, song->file);
966         }
967 
968         /* Append all files to playlist */
969         ario_server_playlist_add_songs (char_songs, pos, action);
970         g_slist_free (char_songs);
971         ario_server_free_file_list (files);
972 }
973 
974 void
ario_server_playlist_add_criterias(const GSList * criterias,const gint pos,const PlaylistAction action,const gint nb_entries)975 ario_server_playlist_add_criterias (const GSList *criterias,
976                                     const gint pos,
977                                     const PlaylistAction action,
978                                     const gint nb_entries)
979 {
980         ARIO_LOG_FUNCTION_START;
981         GSList *filenames = NULL, *tmp_filenames = NULL, *songs = NULL;
982         const GSList *tmp_criteria, *tmp_songs;
983         const ArioServerCriteria *criteria;
984         ArioServerSong *server_song;
985 
986         /* For each criteria :*/
987         for (tmp_criteria = criterias; tmp_criteria; tmp_criteria = g_slist_next (tmp_criteria)) {
988                 criteria = tmp_criteria->data;
989                 songs = ario_server_get_songs (criteria, TRUE);
990 
991                 /* For each song */
992                 for (tmp_songs = songs; tmp_songs; tmp_songs = g_slist_next (tmp_songs)) {
993                         /* Append song filename to list */
994                         server_song = tmp_songs->data;
995                         filenames = g_slist_append (filenames, server_song->file);
996                         server_song->file = NULL;
997                 }
998 
999                 g_slist_foreach (songs, (GFunc) ario_server_free_song, NULL);
1000                 g_slist_free (songs);
1001         }
1002 
1003         /* Need to only add a limited number of songs */
1004         if (nb_entries > 0 && filenames) {
1005                 /* Randomly get some songs in list */
1006                 tmp_filenames = ario_util_gslist_randomize (&filenames, nb_entries);
1007                 g_slist_foreach (filenames, (GFunc) g_free, NULL);
1008                 g_slist_free (filenames);
1009 
1010                 filenames = tmp_filenames;
1011         }
1012 
1013         /* Add songs to playlist */
1014         ario_server_playlist_add_songs (filenames,
1015                                         pos,
1016                                         action);
1017 
1018         g_slist_foreach (filenames, (GFunc) g_free, NULL);
1019         g_slist_free (filenames);
1020 }
1021 
1022 void
ario_server_playlist_append_songs(const GSList * songs,const PlaylistAction action)1023 ario_server_playlist_append_songs (const GSList *songs,
1024                                    const PlaylistAction action)
1025 {
1026         ARIO_LOG_FUNCTION_START;
1027         /* Add songs to playlist */
1028         ario_server_playlist_add_songs (songs, -1, action);
1029 }
1030 
1031 void
ario_server_playlist_append_server_songs(const GSList * songs,const PlaylistAction action)1032 ario_server_playlist_append_server_songs (const GSList *songs,
1033                                           const PlaylistAction action)
1034 {
1035         ARIO_LOG_FUNCTION_START;
1036         const GSList *tmp;
1037         GSList *char_songs = NULL;
1038         ArioServerSong *song;
1039 
1040         /* For each song */
1041         for (tmp = songs; tmp; tmp = g_slist_next (tmp)) {
1042                 /* Append song filename to list */
1043                 song = tmp->data;
1044                 char_songs = g_slist_append (char_songs, song->file);
1045         }
1046 
1047         /* Add songs to playlist */
1048         ario_server_playlist_add_songs (char_songs, -1, action);
1049         g_slist_free (char_songs);
1050 }
1051 
1052 void
ario_server_playlist_append_artists(const GSList * artists,const PlaylistAction action,const gint nb_entries)1053 ario_server_playlist_append_artists (const GSList *artists,
1054                                      const PlaylistAction action,
1055                                      const gint nb_entries)
1056 {
1057         ARIO_LOG_FUNCTION_START;
1058         ArioServerAtomicCriteria *atomic_criteria;
1059         ArioServerCriteria *criteria;
1060         GSList *criterias = NULL;
1061         const GSList *tmp;
1062 
1063         /* For each artist */
1064         for (tmp = artists; tmp; tmp = g_slist_next (tmp)) {
1065                 /* Create a criteria corresponding to artist */
1066                 criteria = NULL;
1067                 atomic_criteria = (ArioServerAtomicCriteria *) g_malloc0 (sizeof (ArioServerAtomicCriteria));
1068                 atomic_criteria->tag = ARIO_TAG_ARTIST;
1069                 atomic_criteria->value = g_strdup (tmp->data);
1070 
1071                 criteria = g_slist_append (criteria, atomic_criteria);
1072                 criterias = g_slist_append (criterias, criteria);
1073         }
1074 
1075         /* Add songs matching criteria to playlist */
1076         ario_server_playlist_append_criterias (criterias, action, nb_entries);
1077 
1078         g_slist_foreach (criterias, (GFunc) ario_server_criteria_free, NULL);
1079         g_slist_free (criterias);
1080 }
1081 
1082 void
ario_server_playlist_append_dir(const gchar * dir,const PlaylistAction action)1083 ario_server_playlist_append_dir (const gchar *dir,
1084                                  const PlaylistAction action)
1085 {
1086         ARIO_LOG_FUNCTION_START;
1087         /* Append all files in dir to playlist */
1088         ario_server_playlist_add_dir (dir, -1, action);
1089 }
1090 
1091 void
ario_server_playlist_append_criterias(const GSList * criterias,const PlaylistAction action,const gint nb_entries)1092 ario_server_playlist_append_criterias (const GSList *criterias,
1093                                        const PlaylistAction action,
1094                                        const gint nb_entries)
1095 {
1096         ARIO_LOG_FUNCTION_START;
1097         /* Append all songs matching criteria to playlist */
1098         ario_server_playlist_add_criterias (criterias, -1, action, nb_entries);
1099 }
1100 
1101 void
ario_server_free_song(ArioServerSong * song)1102 ario_server_free_song (ArioServerSong *song)
1103 {
1104         ARIO_LOG_FUNCTION_START;
1105         if (song) {
1106                 g_free (song->file);
1107                 g_free (song->artist);
1108                 g_free (song->title);
1109                 g_free (song->album);
1110                 g_free (song->album_artist);
1111                 g_free (song->track);
1112                 g_free (song->name);
1113                 g_free (song->date);
1114                 g_free (song->genre);
1115                 g_free (song->composer);
1116                 g_free (song->performer);
1117                 g_free (song->disc);
1118                 g_free (song->comment);
1119                 g_free (song);
1120         }
1121 }
1122 
1123 void
ario_server_free_output(ArioServerOutput * output)1124 ario_server_free_output (ArioServerOutput *output)
1125 {
1126         ARIO_LOG_FUNCTION_START;
1127         if (output) {
1128                 g_free (output->name);
1129                 g_free (output);
1130         }
1131 }
1132 
1133