hythmbox-2.98/plugins/daap/rb-daap-plugin.c

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);
Value stored to 'h2' is never read
(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 }