1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * arch-tag: The Rhythmbox main entrypoint
5 * Copyright (C) 2002 Jorn Baayen
6 * Copyright (C) 2003,2004 Colin Walters <walters@gnome.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <glib/gi18n.h>
34 #include <gdk/gdkx.h> /* For _get_user_time... */
36 #include <glade/glade-init.h>
37 #include <libgnome/gnome-program.h>
38 #include <libgnomeui/gnome-ui-init.h>
39 #include <libgnomeui/gnome-authentication-manager.h>
43 #ifdef HAVE_GSTREAMER_0_8
44 #include <gst/gconf/gconf.h>
45 #include <gst/control/control.h>
48 #ifdef WITH_RHYTHMDB_GDA
49 #include <libgda/libgda.h>
52 #include "rb-refstring.h"
54 #include "rb-shell-player.h"
56 #include "rb-dialog.h"
57 #include "rb-file-helpers.h"
58 #include "rb-stock-icons.h"
60 #include "eel-gconf-extensions.h"
64 #include <dbus/dbus-glib.h>
65 #include "rb-shell-glue.h"
66 #include "rb-shell-player-glue.h"
67 #include "rb-playlist-manager.h"
68 #include "rb-playlist-manager-glue.h"
70 #include <dbus/dbus.h>
71 #include <dbus/dbus-glib.h>
72 #include <dbus/dbus-glib-lowlevel.h>
75 #include <nautilus-burn-drive.h>
76 #ifndef NAUTILUS_BURN_CHECK_VERSION
77 #define NAUTILUS_BURN_CHECK_VERSION(a,b,c) FALSE
80 #if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
81 #include <nautilus-burn.h>
84 #define HAVE_LIBGNOME_GOPTION defined(GNOME_PARAM_GOPTION_CONTEXT)
86 static gboolean debug
= FALSE
;
87 static char *debug_match
= NULL
;
88 static gboolean quit
= FALSE
;
89 static gboolean no_registration
= FALSE
;
90 static gboolean no_update
= FALSE
;
91 static gboolean dry_run
= FALSE
;
92 static char *rhythmdb_file
= NULL
;
93 static char *playlists_file
= NULL
;
94 static char **remaining_args
= NULL
;
97 static gboolean
load_uri_args (const char **args
, GFunc handler
, gpointer user_data
);
98 static void dbus_load_uri (const char *filename
, DBusGProxy
*proxy
);
101 static void main_shell_weak_ref_cb (gpointer data
, GObject
*objptr
);
104 static void register_dbus_handler (DBusConnection
*connection
, RBShell
*shell
);
105 static gboolean
send_present_message (DBusConnection
*connection
, guint32 current_time
);
110 main (int argc
, char **argv
)
112 GnomeProgram
*program
= NULL
;
113 #if WITH_DBUS || WITH_OLD_DBUS
114 DBusGConnection
*session_bus
;
115 GError
*error
= NULL
;
122 GOptionContext
*context
;
123 static const GOptionEntry options
[] = {
124 { "debug", 'd', 0, G_OPTION_ARG_NONE
, &debug
, N_("Enable debug output"), NULL
},
125 { "debug-match", 'D', 0, G_OPTION_ARG_STRING
, &debug_match
, N_("Enable debug output matching a specified string"), NULL
},
126 { "no-update", 0, 0, G_OPTION_ARG_NONE
, &no_update
, N_("Do not update the library with file changes"), NULL
},
127 { "no-registration", 'n', 0, G_OPTION_ARG_NONE
, &no_registration
, N_("Do not register the shell"), NULL
},
128 { "dry-run", 0, 0, G_OPTION_ARG_NONE
, &dry_run
, N_("Don't save any data permanently (implies --no-registration)"), NULL
},
129 { "rhythmdb-file", 0, 0, G_OPTION_ARG_STRING
, &rhythmdb_file
, N_("Path for database file to use"), NULL
},
130 { "playlists-file", 0, 0, G_OPTION_ARG_STRING
, &playlists_file
, N_("Path for playlists file to use"), NULL
},
131 { "quit", 'q', 0, G_OPTION_ARG_NONE
, &quit
, N_("Quit Rhythmbox"), NULL
},
132 { G_OPTION_REMAINING
, 0, 0, G_OPTION_ARG_STRING_ARRAY
, &remaining_args
, NULL
, N_("[URI...]") },
136 rb_profile_start ("starting rhythmbox");
138 context
= g_option_context_new (NULL
);
139 g_option_context_add_main_entries (context
, options
, GETTEXT_PACKAGE
);
141 /* Disable event sounds for now by passing "--disable-sound" to libgnomeui.
142 * See: http://bugzilla.gnome.org/show_bug.cgi?id=119222 */
143 new_argv
= g_strdupv (argv
);
144 new_argv
= g_realloc (new_argv
, (argc
+2)*sizeof(char*));
145 new_argv
[argc
] = g_strdup ("--disable-sound");
146 new_argv
[argc
+1] = NULL
;
148 #ifdef HAVE_GSTREAMER_0_8
149 /* To pass options to GStreamer in 0.8, RB needs to use popt, for
150 * now, GStreamer can live without them (people can still use env
151 * vars, after all) */
152 gst_init (NULL
, NULL
);
153 #elif HAVE_GSTREAMER_0_10
154 rb_profile_start ("initializing gstreamer");
155 g_option_context_add_group (context
, gst_init_get_option_group ());
156 rb_profile_end ("initializing gstreamer");
160 rb_profile_start ("initializing gnome program");
162 #if HAVE_LIBGNOME_GOPTION
163 program
= gnome_program_init (PACKAGE
, VERSION
,
166 GNOME_PARAM_GOPTION_CONTEXT
, context
,
167 GNOME_PARAM_HUMAN_READABLE_NAME
, _("Rhythmbox"),
168 GNOME_PARAM_APP_DATADIR
, DATADIR
,
171 g_option_context_parse (context
, &argc
, &argv
, NULL
);
172 g_option_context_free (context
);
173 program
= gnome_program_init (PACKAGE
, VERSION
,
176 GNOME_PARAM_HUMAN_READABLE_NAME
, _("Rhythmbox"),
177 GNOME_PARAM_APP_DATADIR
, DATADIR
,
181 rb_profile_end ("initializing gnome program");
183 rb_profile_start ("initializing gnome auth manager");
184 gnome_authentication_manager_init ();
185 rb_profile_end ("initializing gnome auth manager");
187 g_random_set_seed (time (0));
190 /* initialize i18n */
191 bindtextdomain (GETTEXT_PACKAGE
, GNOMELOCALEDIR
);
192 bind_textdomain_codeset (GETTEXT_PACKAGE
, "UTF-8");
193 textdomain (GETTEXT_PACKAGE
);
196 #ifdef HAVE_GSTREAMER_0_8
197 gst_control_init (&argc
, &argv
);
200 if (!debug
&& debug_match
)
201 rb_debug_init_match (debug_match
);
203 rb_debug_init (debug
);
204 rb_debug ("initializing Rhythmbox %s", VERSION
);
206 /* TODO: kill this function */
211 #if WITH_DBUS || WITH_OLD_DBUS
212 rb_debug ("going to create DBus object");
214 dbus_g_thread_init ();
216 session_bus
= dbus_g_bus_get (DBUS_BUS_SESSION
, &error
);
217 if (session_bus
== NULL
) {
218 g_warning ("couldn't connect to session bus: %s", (error
) ? error
->message
: "(null)");
219 g_clear_error (&error
);
220 } else if (!no_registration
) {
221 guint request_name_reply
;
223 #ifndef DBUS_NAME_FLAG_DO_NOT_QUEUE
224 flags
= DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
;
226 flags
= DBUS_NAME_FLAG_DO_NOT_QUEUE
;
229 #ifndef WITH_OLD_DBUS
230 DBusGProxy
*bus_proxy
;
232 bus_proxy
= dbus_g_proxy_new_for_name (session_bus
,
233 "org.freedesktop.DBus",
234 "/org/freedesktop/DBus",
235 "org.freedesktop.DBus");
237 if (!dbus_g_proxy_call (bus_proxy
,
241 "org.gnome.Rhythmbox",
248 g_warning ("Failed to invoke RequestName: %s",
251 g_object_unref (bus_proxy
);
254 DBusError dbus_error
= {0,};
255 DBusConnection
*connection
;
257 connection
= dbus_g_connection_get_connection (session_bus
);
258 request_name_reply
= dbus_bus_request_name (connection
,
259 "org.gnome.Rhythmbox",
262 if (dbus_error_is_set (&dbus_error
)) {
263 g_warning ("Failed to invoke RequestName: %s",
266 dbus_error_free (&dbus_error
);
268 if (request_name_reply
== DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
269 || request_name_reply
== DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
)
271 else if (request_name_reply
== DBUS_REQUEST_NAME_REPLY_EXISTS
272 || request_name_reply
== DBUS_REQUEST_NAME_REPLY_IN_QUEUE
)
275 g_warning ("Got unhandled reply %u from RequestName",
284 rb_debug ("was asked to quit, but no instance was running");
285 gdk_notify_startup_complete ();
288 #ifdef WITH_RHYTHMDB_GDA
289 gda_init (PACKAGE
, VERSION
, argc
, argv
);
292 rb_refstring_system_init ();
294 rb_file_helpers_init ();
296 rb_debug ("Going to create a new shell");
300 rb_stock_icons_init ();
302 #if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
303 nautilus_burn_init ();
306 gtk_window_set_default_icon_name ("rhythmbox");
308 rb_shell
= rb_shell_new (argc
, argv
, no_registration
, no_update
, dry_run
, rhythmdb_file
, playlists_file
);
309 g_object_weak_ref (G_OBJECT (rb_shell
), main_shell_weak_ref_cb
, NULL
);
310 if (!no_registration
&& session_bus
!= NULL
) {
315 dbus_g_object_type_install_info (RB_TYPE_SHELL
, &dbus_glib_rb_shell_object_info
);
316 dbus_g_connection_register_g_object (session_bus
, "/org/gnome/Rhythmbox/Shell", G_OBJECT (rb_shell
));
318 /* register player object */
319 dbus_g_object_type_install_info (RB_TYPE_SHELL_PLAYER
, &dbus_glib_rb_shell_player_object_info
);
320 obj
= rb_shell_get_player (rb_shell
);
321 path
= rb_shell_get_player_path (rb_shell
);
322 dbus_g_connection_register_g_object (session_bus
, path
, obj
);
324 /* register playlist manager object */
325 dbus_g_object_type_install_info (RB_TYPE_PLAYLIST_MANAGER
, &dbus_glib_rb_playlist_manager_object_info
);
326 obj
= rb_shell_get_playlist_manager (rb_shell
);
327 path
= rb_shell_get_playlist_manager_path (rb_shell
);
328 dbus_g_connection_register_g_object (session_bus
, path
, obj
);
330 register_dbus_handler (dbus_g_connection_get_connection (session_bus
),
332 #endif /* WITH_DBUS */
334 } else if (!no_registration
&& session_bus
!= NULL
) {
336 DBusGProxy
*shell_proxy
;
338 guint32 current_time
;
339 #if GTK_MINOR_VERSION >= 8
340 current_time
= gdk_x11_display_get_user_time (gdk_display_get_default ());
342 /* FIXME - this does not work; it will return 0 since
343 * we're not in an event. When we pass this to
344 * gtk_window_present_with_time, it ignores the value
345 * since it's 0. The only alternative is to parse the
346 * startup-notification junk from the environment
349 current_time
= GDK_CURRENT_TIME
;
350 #endif /* GTK_MINOR_VERSION */
353 shell_proxy
= dbus_g_proxy_new_for_name_owner (session_bus
,
354 "org.gnome.Rhythmbox",
355 "/org/gnome/Rhythmbox/Shell",
356 "org.gnome.Rhythmbox.Shell",
359 g_warning ("Couldn't create proxy for Rhythmbox shell: %s",
363 dbus_g_proxy_call_no_reply (shell_proxy
, "quit",
366 load_uri_args ((const char **) remaining_args
, (GFunc
) dbus_load_uri
, shell_proxy
);
367 dbus_g_proxy_call_no_reply (shell_proxy
, "present",
368 G_TYPE_UINT
, current_time
,
371 g_object_unref (G_OBJECT (shell_proxy
));
374 if (!send_present_message (dbus_g_connection_get_connection (session_bus
),
376 g_warning ("Unable to send dbus message to existing rhythmbox instance");
377 #endif /* WITH_DBUS */
381 gdk_notify_startup_complete ();
384 rb_profile_start ("mainloop");
386 rb_profile_end ("mainloop");
388 rb_debug ("out of toplevel loop");
390 rb_file_helpers_shutdown ();
391 rb_stock_icons_shutdown ();
392 rb_refstring_system_shutdown ();
394 gnome_vfs_shutdown ();
396 #if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
397 nautilus_burn_shutdown ();
401 #ifdef HAVE_GSTREAMER_0_10
405 g_strfreev (new_argv
);
407 rb_debug ("THE END");
408 rb_profile_end ("starting rhythmbox");
409 g_object_unref (program
);
416 load_uri_args (const char **args
, GFunc handler
, gpointer user_data
)
422 for (i
= 0; args
&& args
[i
]; i
++) {
425 rb_debug ("examining argument %s", args
[i
]);
427 uri
= gnome_vfs_make_uri_from_shell_arg (args
[i
]);
429 if (rb_uri_is_local (uri
) == FALSE
|| rb_uri_exists (uri
)) {
430 handler (uri
, user_data
);
440 dbus_load_uri (const char *filename
, DBusGProxy
*proxy
)
442 GError
*error
= NULL
;
443 rb_debug ("Sending loadURI for %s", filename
);
444 if (!dbus_g_proxy_call (proxy
, "loadURI", &error
,
445 G_TYPE_STRING
, filename
,
446 G_TYPE_BOOLEAN
, TRUE
,
449 g_printerr ("Failed to load %s: %s",
450 filename
, error
->message
);
455 main_shell_weak_ref_cb (gpointer data
, GObject
*objptr
)
457 rb_debug ("caught shell finalization");
462 /* old dbus support (0.31-0.34) */
465 send_present_message (DBusConnection
*connection
, guint32 current_time
)
467 DBusMessage
*message
;
470 message
= dbus_message_new_method_call ("org.gnome.Rhythmbox",
471 "/org/gnome/Rhythmbox/Shell",
472 "org.gnome.Rhythmbox.Shell",
477 if (!dbus_message_append_args (message
,
478 DBUS_TYPE_UINT32
, ¤t_time
,
479 DBUS_TYPE_INVALID
)) {
480 dbus_message_unref (message
);
484 result
= dbus_connection_send (connection
, message
, NULL
);
485 dbus_message_unref (message
);
491 unregister_dbus_handler (DBusConnection
*connection
, void *data
)
496 static DBusHandlerResult
497 handle_dbus_message (DBusConnection
*connection
, DBusMessage
*message
, void *data
)
499 RBShell
*shell
= (RBShell
*)data
;
501 rb_debug ("Handling dbus message");
502 if (dbus_message_is_method_call (message
, "org.gnome.Rhythmbox.Shell", "present")) {
503 DBusMessageIter iter
;
504 guint32 current_time
;
506 if (!dbus_message_iter_init (message
, &iter
))
507 return DBUS_HANDLER_RESULT_NEED_MEMORY
;
509 if (dbus_message_iter_get_arg_type (&iter
) != DBUS_TYPE_UINT32
)
510 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
512 dbus_message_iter_get_basic (&iter
, ¤t_time
);
514 rb_shell_present (shell
, current_time
, NULL
);
515 return DBUS_HANDLER_RESULT_HANDLED
;
517 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
522 register_dbus_handler (DBusConnection
*connection
, RBShell
*shell
)
524 DBusObjectPathVTable vt
= {
525 unregister_dbus_handler
,
527 NULL
, NULL
, NULL
, NULL
530 dbus_connection_register_object_path (connection
,
531 "/org/gnome/Rhythmbox/Shell",
534 dbus_connection_ref (connection
);
535 dbus_connection_setup_with_g_main (connection
, NULL
);