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-interface.h"
21 #include <gtk/gtk.h>
22
23 #include "ario-debug.h"
24 #include "ario-util.h"
25
26 static void ario_server_interface_finalize (GObject *object);
27 static void ario_server_interface_set_property (GObject *object,
28 guint prop_id,
29 const GValue *value,
30 GParamSpec *pspec);
31 static void ario_server_interface_get_property (GObject *object,
32 guint prop_id,
33 GValue *value,
34 GParamSpec *pspec);
35
36 /* Object properties */
37 enum
38 {
39 PROP_0,
40 PROP_SONGID,
41 PROP_STATE,
42 PROP_VOLUME,
43 PROP_ELAPSED,
44 PROP_PLAYLISTID,
45 PROP_CONSUME,
46 PROP_RANDOM,
47 PROP_UPDATINGDB,
48 PROP_REPEAT
49 };
50
G_DEFINE_TYPE(ArioServerInterface,ario_server_interface,G_TYPE_OBJECT)51 G_DEFINE_TYPE (ArioServerInterface, ario_server_interface, G_TYPE_OBJECT)
52
53 /* Dummy methods for default behavior */
54 static void
55 dummy_void_void (void)
56 {
57 }
58
59 static void
dummy_void_int(const int a)60 dummy_void_int (const int a)
61 {
62 }
63
64 static void
dummy_void_int_int(const int a,const int b)65 dummy_void_int_int (const int a,
66 const int b)
67 {
68 }
69
70 static void
dummy_void_pointer(const gpointer * a)71 dummy_void_pointer (const gpointer *a)
72 {
73 }
74
75 static void
dummy_void_pointer_int(const gpointer * a,const int b)76 dummy_void_pointer_int (const gpointer *a,
77 const int b)
78 {
79 }
80
81 static int
dummy_int_void(void)82 dummy_int_void (void)
83 {
84 return 0;
85 }
86
87 static int
dummy_int_pointer(const gpointer * a)88 dummy_int_pointer (const gpointer *a)
89 {
90 return 0;
91 }
92
93 static unsigned long
dummy_ulong_void(void)94 dummy_ulong_void (void)
95 {
96 return 0;
97 }
98
99 static gpointer
dummy_pointer_void(void)100 dummy_pointer_void (void)
101 {
102 return NULL;
103 }
104
105 static gpointer
dummy_pointer_pointer(const gpointer * a)106 dummy_pointer_pointer (const gpointer *a)
107 {
108 return NULL;
109 }
110
111 static gpointer
dummy_pointer_pointer_int(const gpointer * a,const int b)112 dummy_pointer_pointer_int (const gpointer *a,
113 const int b)
114 {
115 return NULL;
116 }
117
118 static gpointer
dummy_pointer_tag_pointer(const ArioServerTag a,const gpointer * b)119 dummy_pointer_tag_pointer (const ArioServerTag a,
120 const gpointer *b)
121 {
122 return NULL;
123 }
124
125 static gpointer
dummy_pointer_int(gint64 playlist_id)126 dummy_pointer_int (gint64 playlist_id)
127 {
128 return NULL;
129 }
130
131 static void
ario_server_interface_class_init(ArioServerInterfaceClass * klass)132 ario_server_interface_class_init (ArioServerInterfaceClass *klass)
133 {
134 ARIO_LOG_FUNCTION_START;
135 GObjectClass *object_class = G_OBJECT_CLASS (klass);
136
137 /* GObject virtual methods */
138 object_class->finalize = ario_server_interface_finalize;
139 object_class->set_property = ario_server_interface_set_property;
140 object_class->get_property = ario_server_interface_get_property;
141
142 /* Default virtual methods for ArioServerInterface */
143 klass->connect = dummy_void_void;
144 klass->disconnect = dummy_void_void;
145 klass->is_connected = dummy_int_void;
146 klass->update_status = dummy_int_void;
147 klass->update_db = (void (*) (const char *)) dummy_void_pointer;
148 klass->list_tags = (GSList* (*) (const ArioServerTag, const ArioServerCriteria *)) dummy_pointer_tag_pointer;
149 klass->get_albums = (GSList* (*) (const ArioServerCriteria *)) dummy_pointer_pointer;
150 klass->get_songs = (GSList* (*) (const ArioServerCriteria *, const gboolean)) dummy_pointer_pointer_int;
151 klass->get_songs_from_playlist = (GSList* (*) (char *)) dummy_pointer_pointer;
152 klass->get_playlists = (GSList* (*) (void)) dummy_pointer_void;
153 klass->get_playlist_changes = (GSList* (*) (gint64))dummy_pointer_int;
154 klass->get_current_song_on_server = (ArioServerSong* (*) (void)) dummy_pointer_void;
155 klass->get_current_playlist_total_time = dummy_int_void;
156 klass->get_last_update = dummy_ulong_void;
157 klass->do_next = dummy_void_void;
158 klass->do_prev = dummy_void_void;
159 klass->do_play = dummy_void_void;
160 klass->do_play_pos = dummy_void_int;
161 klass->do_pause = dummy_void_void;
162 klass->do_stop = dummy_void_void;
163 klass->set_current_elapsed = dummy_void_int;
164 klass->set_current_volume = dummy_void_int;
165 klass->set_current_consume = dummy_void_int;
166 klass->set_current_random = dummy_void_int;
167 klass->set_current_repeat = dummy_void_int;
168 klass->set_crossfadetime = dummy_void_int;
169 klass->clear = dummy_void_void;
170 klass->shuffle = dummy_void_void;
171 klass->queue_commit = dummy_void_void;
172 klass->insert_at = (void (*) (const GSList *, const gint)) dummy_void_pointer_int;
173 klass->save_playlist = (int (*) (const char *)) dummy_int_pointer;
174 klass->delete_playlist = (void (*) (const char *)) dummy_void_pointer;
175 klass->get_outputs = (GSList* (*) (void)) dummy_pointer_void;
176 klass->enable_output = dummy_void_int_int;
177 klass->get_stats = (ArioServerStats* (*) (void)) dummy_pointer_void;
178 klass->get_songs_info = (GList* (*) (GSList *)) dummy_pointer_pointer;
179 klass->list_files = (ArioServerFileList* (*) (const char *, const int)) dummy_pointer_pointer_int;
180
181 /* Object properties */
182 g_object_class_install_property (object_class,
183 PROP_SONGID,
184 g_param_spec_int ("song_id",
185 "song_id",
186 "song_id",
187 -1, INT_MAX, 0,
188 G_PARAM_READWRITE));
189
190 g_object_class_install_property (object_class,
191 PROP_STATE,
192 g_param_spec_uint ("state",
193 "state",
194 "state",
195 0, 3, 0,
196 G_PARAM_READWRITE));
197
198 g_object_class_install_property (object_class,
199 PROP_VOLUME,
200 g_param_spec_int ("volume",
201 "volume",
202 "volume",
203 -1, 100, 0,
204 G_PARAM_READWRITE));
205
206 g_object_class_install_property (object_class,
207 PROP_ELAPSED,
208 g_param_spec_uint ("elapsed",
209 "elapsed",
210 "elapsed",
211 0, INT_MAX, 0,
212 G_PARAM_READWRITE));
213
214 g_object_class_install_property (object_class,
215 PROP_PLAYLISTID,
216 g_param_spec_int64 ("playlist_id",
217 "playlist_id",
218 "playlist_id",
219 -1, G_MAXINT64, 0,
220 G_PARAM_READWRITE));
221
222 g_object_class_install_property (object_class,
223 PROP_RANDOM,
224 g_param_spec_boolean ("random",
225 "random",
226 "random",
227 FALSE,
228 G_PARAM_READWRITE));
229
230 g_object_class_install_property (object_class,
231 PROP_CONSUME,
232 g_param_spec_boolean ("consume",
233 "consume",
234 "consume",
235 FALSE,
236 G_PARAM_READWRITE));
237
238 g_object_class_install_property (object_class,
239 PROP_REPEAT,
240 g_param_spec_boolean ("repeat",
241 "repeat",
242 "repeat",
243 FALSE,
244 G_PARAM_READWRITE));
245
246 g_object_class_install_property (object_class,
247 PROP_UPDATINGDB,
248 g_param_spec_uint ("updatingdb",
249 "updatingdb",
250 "updatingdb",
251 0, INT_MAX, 0,
252 G_PARAM_READWRITE));
253 }
254
255 static void
ario_server_interface_init(ArioServerInterface * server_interface)256 ario_server_interface_init (ArioServerInterface *server_interface)
257 {
258 ARIO_LOG_FUNCTION_START;
259 /* Initialization of attributes */
260 server_interface->song_id = -1;
261 server_interface->playlist_id = -1;
262 server_interface->volume = -1;
263 }
264
265 static void
ario_server_interface_finalize(GObject * object)266 ario_server_interface_finalize (GObject *object)
267 {
268 ARIO_LOG_FUNCTION_START;
269 ArioServerInterface *server_interface;
270
271 g_return_if_fail (object != NULL);
272 g_return_if_fail (IS_ARIO_SERVER_INTERFACE (object));
273
274 server_interface = ARIO_SERVER_INTERFACE (object);
275
276 /* Free current song */
277 if (server_interface->server_song)
278 ario_server_free_song (server_interface->server_song);
279
280 G_OBJECT_CLASS (ario_server_interface_parent_class)->finalize (object);
281 }
282
283 static void
ario_server_interface_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)284 ario_server_interface_set_property (GObject *object,
285 guint prop_id,
286 const GValue *value,
287 GParamSpec *pspec)
288 {
289 ARIO_LOG_FUNCTION_START;
290 ArioServerInterface *server_interface = ARIO_SERVER_INTERFACE (object);
291 int song_id;
292 gboolean song_changed = FALSE;
293
294 switch (prop_id) {
295 case PROP_SONGID:
296 song_id = g_value_get_int (value);
297 /* Detect if song has changed */
298 if (server_interface->song_id != song_id) {
299 server_interface->signals_to_emit |= SERVER_SONG_CHANGED_FLAG;
300 server_interface->song_id = song_id;
301 song_changed = TRUE;
302 }
303
304 /* Check if there is a connection */
305 if (ario_server_is_connected ()) {
306 ArioServerSong *new_song;
307 ArioServerSong *old_song = server_interface->server_song;
308 gboolean state_changed;
309 gboolean artist_changed = FALSE;
310 gboolean album_changed = FALSE;
311
312 /* Get new song on server */
313 new_song = ario_server_get_current_song_on_server ();
314
315 /* Detect is state has changed */
316 state_changed = (!old_song || !new_song);
317 if (!state_changed) {
318 /* Detect if artist has changed */
319 artist_changed = ario_util_strcmp (old_song->artist, new_song->artist) != 0;
320 if (!artist_changed)
321 album_changed = ario_util_strcmp (old_song->album, new_song->album) != 0;
322 /* Detect if song has changed */
323 if (!song_changed)
324 song_changed = ario_util_strcmp (old_song->name, new_song->name) != 0
325 || ario_util_strcmp (old_song->title, new_song->title) != 0;
326 }
327
328 /* Remember to emit album-changed signal */
329 if (state_changed || artist_changed || album_changed)
330 server_interface->signals_to_emit |= SERVER_ALBUM_CHANGED_FLAG;
331
332 /* Remember to emit song-changed signal */
333 if (song_changed)
334 server_interface->signals_to_emit |= SERVER_SONG_CHANGED_FLAG;
335
336 /* Change current song */
337 if (server_interface->server_song)
338 ario_server_free_song (server_interface->server_song);
339 server_interface->server_song = new_song;
340 } else {
341 /* Not connected: free song */
342 if (server_interface->server_song) {
343 ario_server_free_song (server_interface->server_song);
344 server_interface->server_song = NULL;
345 }
346 }
347 break;
348 case PROP_STATE:
349 /* Change value and flag signal to emit */
350 server_interface->state = g_value_get_uint (value);
351 server_interface->signals_to_emit |= SERVER_STATE_CHANGED_FLAG;
352 break;
353 case PROP_VOLUME:
354 /* Change value and flag signal to emit */
355 server_interface->volume = g_value_get_int (value);
356 server_interface->signals_to_emit |= SERVER_VOLUME_CHANGED_FLAG;
357 break;
358 case PROP_ELAPSED:
359 /* Change value and flag signal to emit */
360 server_interface->elapsed = g_value_get_uint (value);
361 server_interface->signals_to_emit |= SERVER_ELAPSED_CHANGED_FLAG;
362 break;
363 case PROP_PLAYLISTID:
364 /* Change value and flag signal to emit */
365 server_interface->playlist_id = g_value_get_int64 (value);
366 if (!ario_server_is_connected ())
367 server_interface->playlist_length = 0;
368 server_interface->signals_to_emit |= SERVER_PLAYLIST_CHANGED_FLAG;
369 break;
370 case PROP_CONSUME:
371 /* Change value and flag signal to emit */
372 server_interface->consume = g_value_get_boolean (value);
373 server_interface->signals_to_emit |= SERVER_CONSUME_CHANGED_FLAG;
374 break;
375 case PROP_RANDOM:
376 /* Change value and flag signal to emit */
377 server_interface->random = g_value_get_boolean (value);
378 server_interface->signals_to_emit |= SERVER_RANDOM_CHANGED_FLAG;
379 break;
380 case PROP_REPEAT:
381 /* Change value and flag signal to emit */
382 server_interface->repeat = g_value_get_boolean (value);
383 server_interface->signals_to_emit |= SERVER_REPEAT_CHANGED_FLAG;
384 break;
385 case PROP_UPDATINGDB:
386 /* Change value and flag signal to emit */
387 server_interface->updatingdb = g_value_get_uint (value);
388 server_interface->signals_to_emit |= SERVER_UPDATINGDB_CHANGED_FLAG;
389 break;
390 default:
391 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
392 break;
393 }
394 }
395
396 static void
ario_server_interface_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)397 ario_server_interface_get_property (GObject *object,
398 guint prop_id,
399 GValue *value,
400 GParamSpec *pspec)
401 {
402 ARIO_LOG_FUNCTION_START;
403 ArioServerInterface *server_interface = ARIO_SERVER_INTERFACE (object);
404
405 switch (prop_id) {
406 case PROP_SONGID:
407 g_value_set_int (value, server_interface->song_id);
408 break;
409 case PROP_STATE:
410 g_value_set_int (value, server_interface->state);
411 break;
412 case PROP_VOLUME:
413 g_value_set_int (value, server_interface->volume);
414 break;
415 case PROP_ELAPSED:
416 g_value_set_int (value, server_interface->elapsed);
417 break;
418 case PROP_PLAYLISTID:
419 g_value_set_int64 (value, server_interface->playlist_id);
420 break;
421 case PROP_CONSUME:
422 g_value_set_boolean (value, server_interface->consume);
423 break;
424 case PROP_RANDOM:
425 g_value_set_boolean (value, server_interface->random);
426 break;
427 case PROP_REPEAT:
428 g_value_set_boolean (value, server_interface->repeat);
429 break;
430 case PROP_UPDATINGDB:
431 g_value_set_int (value, server_interface->updatingdb);
432 break;
433 default:
434 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
435 break;
436 }
437 }
438
439 void
ario_server_interface_set_default(ArioServerInterface * server_interface)440 ario_server_interface_set_default (ArioServerInterface *server_interface)
441 {
442 ARIO_LOG_FUNCTION_START;
443 /* Set default song ID */
444 if (server_interface->song_id != 0)
445 g_object_set (G_OBJECT (server_interface), "song_id", 0, NULL);
446
447 /* Set default state */
448 if (server_interface->state != ARIO_STATE_UNKNOWN)
449 g_object_set (G_OBJECT (server_interface), "state", ARIO_STATE_UNKNOWN, NULL);
450
451 /* Set default volume */
452 if (server_interface->volume != -1)
453 g_object_set (G_OBJECT (server_interface), "volume", -1, NULL);
454
455 /* Set default elapsed time */
456 if (server_interface->elapsed != 0)
457 g_object_set (G_OBJECT (server_interface), "elapsed", 0, NULL);
458
459 /* Set default playlist ID */
460 g_object_set (G_OBJECT (server_interface), "playlist_id", (gint64) -1, NULL);
461
462 /* Set default consume value */
463 if (server_interface->consume != FALSE)
464 g_object_set (G_OBJECT (server_interface), "consume", FALSE, NULL);
465
466 /* Set default random value */
467 if (server_interface->random != FALSE)
468 g_object_set (G_OBJECT (server_interface), "random", FALSE, NULL);
469
470 /* Set default repeat value */
471 if (server_interface->repeat != FALSE)
472 g_object_set (G_OBJECT (server_interface), "repeat", FALSE, NULL);
473
474 /* Set default updatingdb value */
475 if (server_interface->updatingdb != 0)
476 g_object_set (G_OBJECT (server_interface), "updatingdb", 0, NULL);
477 }
478
479 void
ario_server_interface_emit(ArioServerInterface * server_interface,ArioServer * server)480 ario_server_interface_emit (ArioServerInterface *server_interface,
481 ArioServer *server)
482 {
483 ARIO_LOG_FUNCTION_START;
484 /* Emit signals depending of flags set in signals_to_emit */
485 if (server_interface->signals_to_emit & SERVER_SONG_CHANGED_FLAG)
486 g_signal_emit_by_name (G_OBJECT (server), "song_changed");
487 if (server_interface->signals_to_emit & SERVER_ALBUM_CHANGED_FLAG)
488 g_signal_emit_by_name (G_OBJECT (server), "album_changed");
489 if (server_interface->signals_to_emit & SERVER_STATE_CHANGED_FLAG)
490 g_signal_emit_by_name (G_OBJECT (server), "state_changed");
491 if (server_interface->signals_to_emit & SERVER_VOLUME_CHANGED_FLAG)
492 g_signal_emit_by_name (G_OBJECT (server), "volume_changed", server_interface->volume);
493 if (server_interface->signals_to_emit & SERVER_ELAPSED_CHANGED_FLAG)
494 g_signal_emit_by_name (G_OBJECT (server), "elapsed_changed", server_interface->elapsed);
495 if (server_interface->signals_to_emit & SERVER_PLAYLIST_CHANGED_FLAG)
496 g_signal_emit_by_name (G_OBJECT (server), "playlist_changed");
497 if (server_interface->signals_to_emit & SERVER_CONSUME_CHANGED_FLAG)
498 g_signal_emit_by_name (G_OBJECT (server), "consume_changed");
499 if (server_interface->signals_to_emit & SERVER_RANDOM_CHANGED_FLAG)
500 g_signal_emit_by_name (G_OBJECT (server), "random_changed");
501 if (server_interface->signals_to_emit & SERVER_REPEAT_CHANGED_FLAG)
502 g_signal_emit_by_name (G_OBJECT (server), "repeat_changed");
503 if (server_interface->signals_to_emit & SERVER_UPDATINGDB_CHANGED_FLAG)
504 g_signal_emit_by_name (G_OBJECT (server), "updatingdb_changed");
505 server_interface->signals_to_emit = 0;
506 }
507