Location | Tool | Test ID | Function | Issue |
---|---|---|---|---|
rb-daap-plugin.c:341:2 | clang-analyzer | Value stored to 'h2' is never read |
1 /*
2 * rb-daap-plugin.c
3 *
4 * Copyright (C) 2006 James Livingston <doclivingston@gmail.com>
5 * Copyright (C) 2008 Alban Crequy <alban.crequy@collabora.co.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * The Rhythmbox authors hereby grant permission for non-GPL compatible
13 * GStreamer plugins to be used and distributed together with GStreamer
14 * and Rhythmbox. This permission is above and beyond the permissions granted
15 * by the GPL license by which Rhythmbox is covered. If you modify this code
16 * you may extend this exception to your version of the code, but you are not
17 * obligated to do so. If you do not wish to do so, delete this exception
18 * statement from your version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <string.h>
35 #include <glib.h>
36 #include <glib/gi18n-lib.h>
37 #include <gmodule.h>
38 #include <gtk/gtk.h>
39 #include <gio/gio.h>
40
41 #include <libsoup/soup.h>
42
43 #include <libpeas-gtk/peas-gtk.h>
44
45 #include "rb-plugin-macros.h"
46 #include "rb-daap-plugin.h"
47 #include "rb-debug.h"
48 #include "rb-shell.h"
49 #include "rb-dialog.h"
50 #include "rb-file-helpers.h"
51 #include "rb-builder-helpers.h"
52 #include "rb-uri-dialog.h"
53 #include "rb-display-page-group.h"
54
55 #include "rb-daap-container-record.h"
56 #include "rb-daap-record-factory.h"
57 #include "rb-daap-record.h"
58 #include "rb-daap-source.h"
59 #include "rb-daap-sharing.h"
60 #include "rb-daap-src.h"
61 #include "rb-dacp-pairing-page.h"
62 #include "rb-dacp-player.h"
63 #include "rb-dmap-container-db-adapter.h"
64 #include "rb-rhythmdb-dmap-db-adapter.h"
65 #include "rb-rhythmdb-query-model-dmap-db-adapter.h"
66
67 #include <libdmapsharing/dmap.h>
68
69 #define DAAP_DBUS_PATH "/org/gnome/Rhythmbox3/DAAP"
70 #define DAAP_DBUS_IFACE "org.gnome.Rhythmbox3.DAAP"
71
72 static const char *rb_daap_dbus_iface =
73 "<node>"
74 " <interface name='org.gnome.Rhythmbox3.DAAP'>"
75 " <method name='AddDAAPSource'>"
76 " <arg type='s' name='service_name'/>"
77 " <arg type='s' name='host'/>"
78 " <arg type='u' name='port'/>"
79 " </method>"
80 " <method name='RemoveDAAPSource'>"
81 " <arg type='s' name='service_name'/>"
82 " </method>"
83 " </interface>"
84 "</node>";
85
86 struct _RBDaapPlugin
87 {
88 PeasExtensionBase parent;
89
90 GtkBuilder *builder;
91 GtkWidget *preferences;
92 gboolean sharing;
93 gboolean shutdown;
94
95 GtkActionGroup *daap_action_group;
96 guint daap_ui_merge_id;
97
98 DMAPMdnsBrowser *mdns_browser;
99
100 DACPShare *dacp_share;
101
102 GHashTable *source_lookup;
103
104 GSettings *settings;
105 GSettings *dacp_settings;
106
107 GdkPixbuf *daap_share_pixbuf;
108 GdkPixbuf *daap_share_locked_pixbuf;
109
110 GDBusConnection *bus;
111 guint dbus_intf_id;
112 };
113
114 struct _RBDaapPluginClass
115 {
116 PeasExtensionBaseClass parent;
117 };
118
119
120 G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
121
122 static void rb_daap_plugin_init (RBDaapPlugin *plugin);
123
124 static void rb_daap_plugin_cmd_disconnect (GtkAction *action, RBSource *source);
125 static void rb_daap_plugin_cmd_connect (GtkAction *action, RBDaapPlugin *plugin);
126
127 static void create_pixbufs (RBDaapPlugin *plugin);
128 static void start_browsing (RBDaapPlugin *plugin);
129 static void stop_browsing (RBDaapPlugin *plugin);
130 static void settings_changed_cb (GSettings *settings,
131 const char *key,
132 RBDaapPlugin *plugin);
133 static void dacp_settings_changed_cb (GSettings *settings,
134 const char *key,
135 RBDaapPlugin *plugin);
136 static void libdmapsharing_debug (const char *domain,
137 GLogLevelFlags level,
138 const char *message,
139 gpointer data);
140
141 static void register_daap_dbus_iface (RBDaapPlugin *plugin);
142 static void unregister_daap_dbus_iface (RBDaapPlugin *plugin);
143
144 static void peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface);
145
146 RB_DEFINE_PLUGIN(RB_TYPE_DAAP_PLUGIN,
147 RBDaapPlugin,
148 rb_daap_plugin,
149 (G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_GTK_TYPE_CONFIGURABLE,
150 peas_gtk_configurable_iface_init)))
151
152 static GtkActionEntry rb_daap_plugin_actions [] =
153 {
154 { "MusicNewDAAPShare", GTK_STOCK_CONNECT, N_("Connect to _DAAP share..."), NULL,
155 N_("Connect to a new DAAP share"),
156 G_CALLBACK (rb_daap_plugin_cmd_connect) },
157 };
158
159 static GtkActionEntry rb_daap_source_actions[] =
160 {
161 { "DaapSourceDisconnect", GTK_STOCK_DISCONNECT, N_("_Disconnect"), NULL,
162 N_("Disconnect from DAAP share"),
163 G_CALLBACK (rb_daap_plugin_cmd_disconnect) },
164 };
165
166 static void
167 rb_daap_plugin_init (RBDaapPlugin *plugin)
168 {
169 GSettings *daap_settings;
170
171 rb_debug ("RBDaapPlugin initialising");
172 rb_daap_src_set_plugin (G_OBJECT (plugin));
173
174 plugin->settings = g_settings_new ("org.gnome.rhythmbox.sharing");
175
176 daap_settings = g_settings_new ("org.gnome.rhythmbox.plugins.daap");
177 plugin->dacp_settings = g_settings_get_child (daap_settings, "dacp");
178 g_object_unref (daap_settings);
179 }
180
181 static void
182 impl_activate (PeasActivatable *bplugin)
183 {
184 RBDaapPlugin *plugin = RB_DAAP_PLUGIN (bplugin);
185 gboolean no_registration;
186 GtkUIManager *uimanager = NULL;
187 char *uifile;
188 RBShell *shell;
189
190 plugin->shutdown = FALSE;
191
192 g_log_set_handler ("libdmapsharing",
193 G_LOG_LEVEL_MASK,
194 libdmapsharing_debug,
195 NULL);
196
197 g_object_get (plugin, "object", &shell, NULL);
198
199 g_signal_connect_object (plugin->settings, "changed", G_CALLBACK (settings_changed_cb), plugin, 0);
200
201 g_signal_connect_object (plugin->dacp_settings, "changed", G_CALLBACK (dacp_settings_changed_cb), plugin, 0);
202
203 if (g_settings_get_boolean (plugin->settings, "enable-browsing")) {
204 start_browsing (plugin);
205 }
206
207 create_pixbufs (plugin);
208
209 g_object_get (shell, "ui-manager", &uimanager, NULL);
210
211 /* add actions */
212 plugin->daap_action_group = gtk_action_group_new ("DaapActions");
213 gtk_action_group_set_translation_domain (plugin->daap_action_group,
214 GETTEXT_PACKAGE);
215 gtk_action_group_add_actions (plugin->daap_action_group,
216 rb_daap_plugin_actions, G_N_ELEMENTS (rb_daap_plugin_actions),
217 plugin);
218 _rb_action_group_add_display_page_actions (plugin->daap_action_group,
219 G_OBJECT (shell),
220 rb_daap_source_actions,
221 G_N_ELEMENTS (rb_daap_source_actions));
222 gtk_ui_manager_insert_action_group (uimanager, plugin->daap_action_group, 0);
223
224 /* add UI */
225 uifile = rb_find_plugin_data_file (G_OBJECT (plugin), "daap-ui.xml");
226 if (uifile != NULL) {
227 plugin->daap_ui_merge_id = gtk_ui_manager_add_ui_from_file (uimanager, uifile, NULL);
228 g_free (uifile);
229 }
230
231 g_object_unref (uimanager);
232
233 /*
234 * Don't use daap when the no-registration flag is set.
235 * This flag is only used to run multiple instances at the same time, and
236 * sharing from two instances would be silly
237 */
238 g_object_get (shell, "no-registration", &no_registration, NULL);
239 plugin->sharing = !no_registration;
240 if (plugin->sharing)
241 rb_daap_sharing_init (shell);
242
243 plugin->dacp_share = rb_daap_create_dacp_share (G_OBJECT (plugin));
244 if (g_settings_get_boolean (plugin->dacp_settings, "enable-remote")) {
245 dacp_share_start_lookup (plugin->dacp_share);
246 }
247
248 register_daap_dbus_iface (plugin);
249
250 g_object_unref (shell);
251 }
252
253 static void
254 impl_deactivate (PeasActivatable *bplugin)
255 {
256 RBDaapPlugin *plugin = RB_DAAP_PLUGIN (bplugin);
257 GtkUIManager *uimanager = NULL;
258 RBShell *shell;
259
260 rb_debug ("Shutting down DAAP plugin");
261
262 g_object_get (plugin, "object", &shell, NULL);
263
264 unregister_daap_dbus_iface (plugin);
265 plugin->shutdown = TRUE;
266
267 if (plugin->sharing)
268 rb_daap_sharing_shutdown (shell);
269
270 if (plugin->mdns_browser) {
271 stop_browsing (plugin);
272 }
273
274 if (plugin->settings) {
275 g_object_unref (plugin->settings);
276 plugin->settings = NULL;
277 }
278
279 g_object_unref (plugin->dacp_share);
280
281 g_object_get (shell, "ui-manager", &uimanager, NULL);
282
283 gtk_ui_manager_remove_ui (uimanager, plugin->daap_ui_merge_id);
284 gtk_ui_manager_remove_action_group (uimanager, plugin->daap_action_group);
285
286 g_object_unref (uimanager);
287
288 if (plugin->daap_share_pixbuf != NULL) {
289 g_object_unref (plugin->daap_share_pixbuf);
290 plugin->daap_share_pixbuf = NULL;
291 }
292
293 if (plugin->daap_share_locked_pixbuf != NULL) {
294 g_object_unref (plugin->daap_share_locked_pixbuf);
295 plugin->daap_share_locked_pixbuf = NULL;
296 }
297
298 if (plugin->preferences) {
299 gtk_widget_destroy (plugin->preferences);
300 plugin->preferences = NULL;
301 }
302
303 if (plugin->builder) {
304 g_object_unref (plugin->builder);
305 plugin->builder = NULL;
306 }
307
308 if (plugin->bus) {
309 g_object_unref (plugin->bus);
310 plugin->bus = NULL;
311 }
312
313 g_object_unref (shell);
314 }
315
316 /* DAAP share icons */
317
318 static GdkPixbuf *
319 composite_icons (const GdkPixbuf *src1,
320 const GdkPixbuf *src2)
321 {
322 GdkPixbuf *dest;
323 GdkPixbuf *scaled;
324 gint w1, w2, h1, h2;
325 gint dest_x, dest_y;
326 gboolean do_scale;
327
328 if (! src1) {
329 return NULL;
330 }
331
332 dest = gdk_pixbuf_copy (src1);
333
334 if (! src2) {
335 return dest;
336 }
337
338 w1 = gdk_pixbuf_get_width (src1);
339 h1 = gdk_pixbuf_get_height (src1);
340 w2 = gdk_pixbuf_get_width (src2);
341 h2 = gdk_pixbuf_get_height (src2);
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
342
343 do_scale = ((float)w1 * 0.8) < w2;
344
345 /* scale the emblem down if it will obscure the entire bottom image */
346 if (do_scale) {
347 scaled = gdk_pixbuf_scale_simple (src2, w1 / 2, h1 / 2, GDK_INTERP_BILINEAR);
348 } else {
349 scaled = (GdkPixbuf *)src2;
350 }
351
352 w2 = gdk_pixbuf_get_width (scaled);
353 h2 = gdk_pixbuf_get_height (scaled);
354
355 dest_x = w1 - w2;
356 dest_y = h1 - h2;
357
358 gdk_pixbuf_composite (scaled, dest,
359 dest_x, dest_y,
360 w2, h2,
361 dest_x, dest_y,
362 1.0, 1.0,
363 GDK_INTERP_BILINEAR, 0xFF);
364
365 if (do_scale) {
366 g_object_unref (scaled);
367 }
368
369 return dest;
370 }
371
372 static void
373 create_pixbufs (RBDaapPlugin *plugin)
374 {
375 GdkPixbuf *emblem;
376 GtkIconTheme *theme;
377 gint size;
378
379 theme = gtk_icon_theme_get_default ();
380
381 gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);
382 plugin->daap_share_pixbuf =
383 gtk_icon_theme_load_icon (theme, "gnome-fs-network", size, 0, NULL);
384
385 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &size, NULL);
386 emblem = gtk_icon_theme_load_icon (theme, "stock_lock", size, 0, NULL);
387
388 plugin->daap_share_locked_pixbuf = composite_icons (plugin->daap_share_pixbuf, emblem);
389
390 if (emblem != NULL) {
391 g_object_unref (emblem);
392 }
393 }
394
395 GdkPixbuf *
396 rb_daap_plugin_get_icon (RBDaapPlugin *plugin,
397 gboolean password_protected,
398 gboolean connected)
399 {
400 GdkPixbuf *icon;
401
402 g_return_val_if_fail (plugin->daap_share_pixbuf != NULL, NULL);
403 g_return_val_if_fail (plugin->daap_share_locked_pixbuf != NULL, NULL);
404
405 if (password_protected == FALSE) {
406 icon = g_object_ref (plugin->daap_share_pixbuf);
407 } else if (connected) {
408 icon = g_object_ref (plugin->daap_share_pixbuf);
409 } else {
410 icon = g_object_ref (plugin->daap_share_locked_pixbuf);
411 }
412
413 return icon;
414 }
415
416 /* mDNS browsing */
417
418 static RBSource *
419 find_source_by_service_name (RBDaapPlugin *plugin,
420 const char *service_name)
421 {
422 RBSource *source;
423
424 source = g_hash_table_lookup (plugin->source_lookup, service_name);
425
426 return source;
427 }
428
429 static void
430 mdns_service_added (DMAPMdnsBrowser *browser,
431 DMAPMdnsBrowserService *service,
432 RBDaapPlugin *plugin)
433 {
434 RBSource *source;
435 RBShell *shell;
436
437 rb_debug ("New service: %s name=%s host=%s port=%u password=%d",
438 service->service_name,
439 service->name,
440 service->host,
441 service->port,
442 service->password_protected);
443
444 GDK_THREADS_ENTER ();
445
446 source = find_source_by_service_name (plugin, service->service_name);
447
448 if (source == NULL) {
449 g_object_get (plugin, "object", &shell, NULL);
450
451 source = rb_daap_source_new (shell,
452 G_OBJECT (plugin),
453 service->service_name,
454 service->name,
455 service->host,
456 service->port,
457 service->password_protected);
458 g_hash_table_insert (plugin->source_lookup, g_strdup (service->service_name), source);
459 rb_shell_append_display_page (shell,
460 RB_DISPLAY_PAGE (source),
461 RB_DISPLAY_PAGE_GROUP_SHARED);
462
463 g_object_unref (shell);
464 } else {
465 g_object_set (source,
466 "name", service->name,
467 "host", service->host,
468 "port", service->port,
469 "password-protected", service->password_protected,
470 NULL);
471 }
472
473 GDK_THREADS_LEAVE ();
474 }
475
476 static void
477 mdns_service_removed (DMAPMdnsBrowser *browser,
478 const char *service_name,
479 RBDaapPlugin *plugin)
480 {
481 RBSource *source;
482
483 GDK_THREADS_ENTER ();
484
485 source = find_source_by_service_name (plugin, service_name);
486
487 rb_debug ("DAAP source '%s' went away", service_name);
488 if (source != NULL) {
489 g_hash_table_remove (plugin->source_lookup, service_name);
490 }
491
492 GDK_THREADS_LEAVE ();
493 }
494
495 static void
496 remove_source (RBSource *source)
497 {
498 char *service_name;
499
500 g_object_get (source, "service-name", &service_name, NULL);
501 rb_debug ("Removing DAAP source: %s", service_name);
502
503 rb_daap_source_disconnect (RB_DAAP_SOURCE (source));
504 rb_display_page_delete_thyself (RB_DISPLAY_PAGE (source));
505
506 g_free (service_name);
507 }
508
509 static void
510 start_browsing (RBDaapPlugin *plugin)
511 {
512 GError *error;
513
514 if (plugin->mdns_browser != NULL) {
515 return;
516 }
517
518 plugin->mdns_browser = dmap_mdns_browser_new (DMAP_MDNS_BROWSER_SERVICE_TYPE_DAAP);
519 if (plugin->mdns_browser == NULL) {
520 g_warning ("Unable to start mDNS browsing");
521 return;
522 }
523
524 g_signal_connect_object (plugin->mdns_browser,
525 "service-added",
526 G_CALLBACK (mdns_service_added),
527 plugin,
528 0);
529 g_signal_connect_object (plugin->mdns_browser,
530 "service-removed",
531 G_CALLBACK (mdns_service_removed),
532 plugin,
533 0);
534
535 error = NULL;
536 dmap_mdns_browser_start (plugin->mdns_browser, &error);
537 if (error != NULL) {
538 g_warning ("Unable to start mDNS browsing: %s", error->message);
539 g_error_free (error);
540 }
541
542 plugin->source_lookup = g_hash_table_new_full ((GHashFunc)g_str_hash,
543 (GEqualFunc)g_str_equal,
544 (GDestroyNotify)g_free,
545 (GDestroyNotify)remove_source);
546 }
547
548 static void
549 stop_browsing (RBDaapPlugin *plugin)
550 {
551 GError *error;
552
553 if (plugin->mdns_browser == NULL) {
554 return;
555 }
556
557 rb_debug ("Destroying DAAP source lookup");
558
559 g_hash_table_destroy (plugin->source_lookup);
560 plugin->source_lookup = NULL;
561
562 g_signal_handlers_disconnect_by_func (plugin->mdns_browser, mdns_service_added, plugin);
563 g_signal_handlers_disconnect_by_func (plugin->mdns_browser, mdns_service_removed, plugin);
564
565 error = NULL;
566 dmap_mdns_browser_stop (plugin->mdns_browser, &error);
567 if (error != NULL) {
568 g_warning ("Unable to stop mDNS browsing: %s", error->message);
569 g_error_free (error);
570 }
571
572 g_object_unref (plugin->mdns_browser);
573 plugin->mdns_browser = NULL;
574 }
575
576 static void
577 dacp_settings_changed_cb (GSettings *settings, const char *key, RBDaapPlugin *plugin)
578 {
579 if (g_strcmp0 (key, "enable-remote") == 0) {
580 if (g_settings_get_boolean (settings, key)) {
581 dacp_share_start_lookup (plugin->dacp_share);
582 } else {
583 dacp_share_stop_lookup (plugin->dacp_share);
584 }
585 }
586 }
587
588 static void
589 settings_changed_cb (GSettings *settings, const char *key, RBDaapPlugin *plugin)
590 {
591 if (g_strcmp0 (key, "enable-browsing") == 0) {
592 if (g_settings_get_boolean (settings, key)) {
593 start_browsing (plugin);
594 } else {
595 stop_browsing (plugin);
596 }
597 } else if (g_strcmp0 (key, "enable-sharing") == 0) {
598 GtkToggleButton *password_check;
599 GtkWidget *password_entry;
600 gboolean enabled = g_settings_get_boolean (settings, key);
601
602 password_check = GTK_TOGGLE_BUTTON (gtk_builder_get_object (plugin->builder, "daap_password_check"));
603 password_entry = GTK_WIDGET (gtk_builder_get_object (plugin->builder, "daap_password_entry"));
604
605 gtk_widget_set_sensitive (password_entry, enabled && gtk_toggle_button_get_active (password_check));
606 gtk_widget_set_sensitive (GTK_WIDGET (password_check), enabled);
607 }
608 }
609
610 static void
611 libdmapsharing_debug (const char *domain,
612 GLogLevelFlags level,
613 const char *message,
614 gpointer data)
615 {
616 if ((level & G_LOG_LEVEL_DEBUG) != 0) {
617 rb_debug ("%s", message);
618 } else {
619 g_log_default_handler (domain, level, message, data);
620 }
621 }
622
623 /* daap share connect/disconnect commands */
624
625 static void
626 rb_daap_plugin_cmd_disconnect (GtkAction *action, RBSource *source)
627 {
628 if (!RB_IS_DAAP_SOURCE (source)) {
629 g_warning ("got non-Daap source for Daap action");
630 return;
631 }
632
633 rb_daap_source_disconnect (RB_DAAP_SOURCE (source));
634 }
635
636 static void
637 new_daap_share_location_added_cb (RBURIDialog *dialog,
638 const char *location,
639 RBDaapPlugin *plugin)
640 {
641 char *host;
642 char *p;
643 int port = 3689;
644 DMAPMdnsBrowserService service;
645
646 host = g_strdup (location);
647 p = strrchr (host, ':');
648 if (p != NULL) {
649 port = strtoul (p+1, NULL, 10);
650 *p = '\0';
651 }
652
653 rb_debug ("adding manually specified DAAP share at %s", location);
654 service.name = (char *) location;
655 service.host = (char *) host;
656 service.service_name = service.name;
657 service.port = port;
658 service.password_protected = FALSE;
659 mdns_service_added (NULL,
660 &service,
661 plugin);
662
663 g_free (host);
664
665 }
666
667 static void
668 new_daap_share_response_cb (GtkDialog *dialog, int response, gpointer meh)
669 {
670 gtk_widget_destroy (GTK_WIDGET (dialog));
671 }
672
673 static void
674 rb_daap_plugin_cmd_connect (GtkAction *action,
675 RBDaapPlugin *plugin)
676 {
677 GtkWidget *dialog;
678
679 dialog = rb_uri_dialog_new (_("New DAAP share"), _("Host:port of DAAP share:"));
680 g_signal_connect_object (dialog, "location-added",
681 G_CALLBACK (new_daap_share_location_added_cb),
682 plugin, 0);
683 gtk_widget_show_all (dialog);
684 g_signal_connect (dialog, "response", G_CALLBACK (new_daap_share_response_cb), NULL);
685 }
686
687
688 /* daap:// URI -> RBDAAPSource mapping */
689
690 static gboolean
691 source_host_find (const char *key,
692 RBDAAPSource *source,
693 const char *host)
694 {
695 char *source_host;
696 gboolean result;
697
698 if (source == NULL || host == NULL) {
699 return FALSE;
700 }
701
702 g_object_get (source, "host", &source_host, NULL);
703
704 result = (strcmp (host, source_host) == 0);
705 g_free (source_host);
706
707 return result;
708 }
709
710 RBDAAPSource *
711 rb_daap_plugin_find_source_for_uri (RBDaapPlugin *plugin, const char *uri)
712 {
713 char *ip;
714 char *s;
715 RBDAAPSource *source = NULL;
716
717 if (uri == NULL) {
718 return NULL;
719 }
720
721 ip = strdup (uri + 7); /* daap:// */
722 s = strchr (ip, ':');
723 *s = '\0';
724
725 source = (RBDAAPSource *)g_hash_table_find (plugin->source_lookup, (GHRFunc)source_host_find, ip);
726
727 g_free (ip);
728
729 return source;
730 }
731
732 gboolean
733 rb_daap_plugin_shutdown (RBDaapPlugin *plugin)
734 {
735 return plugin->shutdown;
736 }
737
738 /* preferences dialog */
739
740 /* should move this to a separate class really */
741
742 static void
743 forget_remotes_button_toggled_cb (GtkToggleButton *button,
744 RBDaapPlugin *plugin)
745 {
746 g_settings_reset (plugin->dacp_settings, "known-remotes");
747 }
748
749 static gboolean
750 share_name_entry_focus_out_event_cb (GtkEntry *entry,
751 GdkEventFocus *event,
752 RBDaapPlugin *plugin)
753 {
754 gboolean changed;
755 const char *name;
756 char *old_name;
757
758 name = gtk_entry_get_text (entry);
759 old_name = g_settings_get_string (plugin->settings, "share-name");
760
761 if (name == NULL && old_name == NULL) {
762 changed = FALSE;
763 } else if (name == NULL || old_name == NULL) {
764 changed = TRUE;
765 } else if (strcmp (name, old_name) != 0) {
766 changed = TRUE;
767 } else {
768 changed = FALSE;
769 }
770
771 if (changed) {
772 g_settings_set_string (plugin->settings, "share-name", name);
773 }
774
775 g_free (old_name);
776
777 return FALSE;
778 }
779
780 static gboolean
781 share_password_entry_focus_out_event_cb (GtkEntry *entry,
782 GdkEventFocus *event,
783 RBDaapPlugin *plugin)
784 {
785 gboolean changed;
786 const char *pw;
787 char *old_pw;
788
789 pw = gtk_entry_get_text (entry);
790 old_pw = g_settings_get_string (plugin->settings, "share-password");
791
792 if (pw == NULL && old_pw == NULL) {
793 changed = FALSE;
794 } else if (pw == NULL || old_pw == NULL) {
795 changed = TRUE;
796 } else if (strcmp (pw, old_pw) != 0) {
797 changed = TRUE;
798 } else {
799 changed = FALSE;
800 }
801
802 if (changed) {
803 g_settings_set_string (plugin->settings, "share-password", pw);
804 }
805
806 g_free (old_pw);
807
808 return FALSE;
809 }
810
811 static void
812 update_config_widget (RBDaapPlugin *plugin)
813 {
814 GtkWidget *check;
815 GtkWidget *remote_check;
816 GtkWidget *name_entry;
817 GtkWidget *password_entry;
818 GtkWidget *password_check;
819 GtkWidget *forget_remotes_button;
820 char *name;
821 char *password;
822
823 check = GTK_WIDGET (gtk_builder_get_object (plugin->builder, "daap_enable_check"));
824 remote_check = GTK_WIDGET (gtk_builder_get_object (plugin->builder, "dacp_enable_check"));
825 password_check = GTK_WIDGET (gtk_builder_get_object (plugin->builder, "daap_password_check"));
826 name_entry = GTK_WIDGET (gtk_builder_get_object (plugin->builder, "daap_name_entry"));
827 password_entry = GTK_WIDGET (gtk_builder_get_object (plugin->builder, "daap_password_entry"));
828 forget_remotes_button = GTK_WIDGET (gtk_builder_get_object (plugin->builder, "forget_remotes_button"));
829
830 g_settings_bind (plugin->settings, "enable-sharing", check, "active", G_SETTINGS_BIND_DEFAULT);
831 g_settings_bind (plugin->dacp_settings, "enable-remote", remote_check, "active", G_SETTINGS_BIND_DEFAULT);
832
833 /*g_signal_connect (check, "toggled", G_CALLBACK (share_check_button_toggled_cb), plugin->builder);*/
834
835 /* probably needs rethinking to deal with remotes.. */
836 g_settings_bind (plugin->settings, "require-password", password_check, "active", G_SETTINGS_BIND_DEFAULT);
837 g_settings_bind (plugin->settings, "require-password", password_entry, "sensitive", G_SETTINGS_BIND_NO_SENSITIVITY);
838
839 g_signal_connect_object (forget_remotes_button, "clicked", G_CALLBACK (forget_remotes_button_toggled_cb), plugin, 0);
840
841 name = g_settings_get_string (plugin->settings, "share-name");
842 if (name == NULL || name[0] == '\0') {
843 g_free (name);
844 name = rb_daap_sharing_default_share_name ();
845 }
846 if (name != NULL) {
847 gtk_entry_set_text (GTK_ENTRY (name_entry), name);
848 g_free (name);
849 }
850 g_signal_connect (name_entry,
851 "focus-out-event",
852 G_CALLBACK (share_name_entry_focus_out_event_cb),
853 plugin);
854
855 password = g_settings_get_string (plugin->settings, "share-password");
856 if (password != NULL) {
857 gtk_entry_set_text (GTK_ENTRY (password_entry), password);
858 g_free (password);
859 }
860 g_signal_connect (password_entry,
861 "focus-out-event",
862 G_CALLBACK (share_password_entry_focus_out_event_cb),
863 plugin);
864
865 /*gtk_widget_set_sensitive (password_entry, require_password);*/
866 }
867
868 static GtkWidget *
869 impl_create_configure_widget (PeasGtkConfigurable *bplugin)
870 {
871 char *builder_file;
872 RBDaapPlugin *plugin = RB_DAAP_PLUGIN (bplugin);
873
874 builder_file = rb_find_plugin_data_file (G_OBJECT (plugin), "daap-prefs.ui");
875 if (builder_file == NULL) {
876 return NULL;
877 }
878
879 plugin->builder = rb_builder_load (builder_file, NULL);
880 g_free (builder_file);
881
882 update_config_widget (plugin);
883 return GTK_WIDGET (gtk_builder_get_object (plugin->builder, "daap_vbox"));
884 }
885
886 static void
887 peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface)
888 {
889 iface->create_configure_widget = impl_create_configure_widget;
890 }
891
892 /* DAAP DBus interface */
893
894 static void
895 daap_dbus_method_call (GDBusConnection *connection,
896 const char *sender,
897 const char *object_path,
898 const char *interface_name,
899 const char *method_name,
900 GVariant *parameters,
901 GDBusMethodInvocation *invocation,
902 RBDaapPlugin *plugin)
903 {
904 if (plugin->shutdown) {
905 rb_debug ("ignoring %s call", method_name);
906 return;
907 }
908
909 if (g_strcmp0 (method_name, "AddDAAPSource") == 0) {
910 DMAPMdnsBrowserService service = {0,};
911 g_variant_get (parameters, "(&s&su)", &service.name, &service.host, &service.port);
912 service.password_protected = FALSE;
913 service.service_name = service.name;
914
915 rb_debug ("adding DAAP source %s (%s:%d)", service.name, service.host, service.port);
916 mdns_service_added (NULL, &service, plugin);
917
918 g_dbus_method_invocation_return_value (invocation, NULL);
919
920 } else if (g_strcmp0 (method_name, "RemoveDAAPSource") == 0) {
921 const char *service_name;
922
923 g_variant_get (parameters, "(&s)", &service_name);
924 rb_debug ("removing DAAP source %s", service_name);
925 mdns_service_removed (plugin->mdns_browser, service_name, plugin);
926
927 g_dbus_method_invocation_return_value (invocation, NULL);
928 }
929 }
930
931 static const GDBusInterfaceVTable daap_dbus_vtable = {
932 (GDBusInterfaceMethodCallFunc) daap_dbus_method_call,
933 NULL,
934 NULL
935 };
936
937 static void
938 register_daap_dbus_iface (RBDaapPlugin *plugin)
939 {
940 GError *error = NULL;
941 GDBusNodeInfo *node_info;
942 GDBusInterfaceInfo *iface_info;
943
944 if (plugin->dbus_intf_id != 0) {
945 rb_debug ("DAAP DBus interface already registered");
946 return;
947 }
948
949 if (plugin->bus == NULL) {
950 plugin->bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
951 if (plugin->bus == NULL) {
952 rb_debug ("Unable to register DAAP DBus interface: %s", error->message);
953 g_clear_error (&error);
954 return;
955 }
956 }
957
958 node_info = g_dbus_node_info_new_for_xml (rb_daap_dbus_iface, &error);
959 if (error != NULL) {
960 rb_debug ("Unable to parse DAAP DBus spec: %s", error->message);
961 g_clear_error (&error);
962 return;
963 }
964
965 iface_info = g_dbus_node_info_lookup_interface (node_info, DAAP_DBUS_IFACE);
966 plugin->dbus_intf_id =
967 g_dbus_connection_register_object (plugin->bus,
968 DAAP_DBUS_PATH,
969 iface_info,
970 &daap_dbus_vtable,
971 g_object_ref (plugin),
972 g_object_unref,
973 &error);
974 if (error != NULL) {
975 rb_debug ("Unable to register DAAP DBus interface: %s", error->message);
976 g_clear_error (&error);
977 }
978
979 g_dbus_node_info_unref (node_info);
980 }
981
982 static void
983 unregister_daap_dbus_iface (RBDaapPlugin *plugin)
984 {
985 if (plugin->dbus_intf_id == 0) {
986 rb_debug ("DAAP DBus interface not registered");
987 return;
988 }
989
990 if (plugin->bus == NULL) {
991 rb_debug ("no bus connection");
992 return;
993 }
994
995 g_dbus_connection_unregister_object (plugin->bus, plugin->dbus_intf_id);
996 plugin->dbus_intf_id = 0;
997 }
998
999 G_MODULE_EXPORT void
1000 peas_register_types (PeasObjectModule *module)
1001 {
1002 rb_daap_plugin_register_type (G_TYPE_MODULE (module));
1003 _rb_daap_container_record_register_type (G_TYPE_MODULE (module));
1004 _rb_daap_record_factory_register_type (G_TYPE_MODULE (module));
1005 _rb_daap_record_register_type (G_TYPE_MODULE (module));
1006 _rb_daap_source_register_type (G_TYPE_MODULE (module));
1007 _rb_dacp_pairing_page_register_type (G_TYPE_MODULE (module));
1008 _rb_dacp_player_register_type (G_TYPE_MODULE (module));
1009 _rb_dmap_container_db_adapter_register_type (G_TYPE_MODULE (module));
1010 _rb_rhythmdb_dmap_db_adapter_register_type (G_TYPE_MODULE (module));
1011 _rb_rhythmdb_query_model_dmap_db_adapter_register_type (G_TYPE_MODULE (module));
1012
1013 peas_object_module_register_extension_type (module,
1014 PEAS_TYPE_ACTIVATABLE,
1015 RB_TYPE_DAAP_PLUGIN);
1016 peas_object_module_register_extension_type (module,
1017 PEAS_GTK_TYPE_CONFIGURABLE,
1018 RB_TYPE_DAAP_PLUGIN);
1019 }