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-app-helper.h>
40 #include <libgnomeui/gnome-authentication-manager.h>
44 #ifdef HAVE_GSTREAMER_0_8
45 #include <gst/gconf/gconf.h>
46 #include <gst/control/control.h>
49 #ifdef WITH_RHYTHMDB_GDA
50 #include <libgda/libgda.h>
53 #include "rb-refstring.h"
55 #include "rb-shell-player.h"
57 #include "rb-dialog.h"
58 #include "rb-file-helpers.h"
59 #include "rb-stock-icons.h"
61 #include "eel-gconf-extensions.h"
65 #include <dbus/dbus-glib.h>
66 #include "rb-shell-glue.h"
67 #include "rb-shell-player-glue.h"
68 #include "rb-playlist-manager.h"
69 #include "rb-playlist-manager-glue.h"
71 #include <dbus/dbus.h>
72 #include <dbus/dbus-glib.h>
73 #include <dbus/dbus-glib-lowlevel.h>
76 #define HAVE_LIBGNOME_GOPTION defined(GNOME_PARAM_GOPTION_CONTEXT)
78 static gboolean debug
= FALSE
;
79 static char *debug_match
= NULL
;
80 static gboolean quit
= FALSE
;
81 static gboolean no_registration
= FALSE
;
82 static gboolean no_update
= FALSE
;
83 static gboolean dry_run
= FALSE
;
84 static char *rhythmdb_file
= NULL
;
85 static char *playlists_file
= NULL
;
86 static char **remaining_args
= NULL
;
89 static gboolean
load_uri_args (const char **args
, GFunc handler
, gpointer user_data
);
90 static void dbus_load_uri (const char *filename
, DBusGProxy
*proxy
);
93 static void main_shell_weak_ref_cb (gpointer data
, GObject
*objptr
);
96 static void register_dbus_handler (DBusConnection
*connection
, RBShell
*shell
);
97 static gboolean
send_present_message (DBusConnection
*connection
, guint32 current_time
);
102 main (int argc
, char **argv
)
104 GnomeProgram
*program
= NULL
;
105 #if WITH_DBUS || WITH_OLD_DBUS
106 DBusGConnection
*session_bus
;
107 GError
*error
= NULL
;
114 GOptionContext
*context
;
115 static const GOptionEntry options
[] = {
116 { "debug", 'd', 0, G_OPTION_ARG_NONE
, &debug
, N_("Enable debug output"), NULL
},
117 { "debug-match", 'D', 0, G_OPTION_ARG_STRING
, &debug_match
, N_("Enable debug output matching a specified string"), NULL
},
118 { "no-update", 0, 0, G_OPTION_ARG_NONE
, &no_update
, N_("Do not update the library with file changes"), NULL
},
119 { "no-registration", 'n', 0, G_OPTION_ARG_NONE
, &no_registration
, N_("Do not register the shell"), NULL
},
120 { "dry-run", 0, 0, G_OPTION_ARG_NONE
, &dry_run
, N_("Don't save any data permanently (implies --no-registration)"), NULL
},
121 { "rhythmdb-file", 0, 0, G_OPTION_ARG_STRING
, &rhythmdb_file
, N_("Path for database file to use"), NULL
},
122 { "playlists-file", 0, 0, G_OPTION_ARG_STRING
, &playlists_file
, N_("Path for playlists file to use"), NULL
},
123 { "quit", 'q', 0, G_OPTION_ARG_NONE
, &quit
, N_("Quit Rhythmbox"), NULL
},
124 { G_OPTION_REMAINING
, 0, 0, G_OPTION_ARG_STRING_ARRAY
, &remaining_args
, NULL
, N_("[URI...]") },
128 rb_profile_start ("starting rhythmbox");
130 context
= g_option_context_new (NULL
);
131 g_option_context_add_main_entries (context
, options
, GETTEXT_PACKAGE
);
133 /* Disable event sounds for now by passing "--disable-sound" to libgnomeui.
134 * See: http://bugzilla.gnome.org/show_bug.cgi?id=119222 */
135 new_argv
= g_strdupv (argv
);
136 new_argv
= g_realloc (new_argv
, (argc
+2)*sizeof(char*));
137 new_argv
[argc
] = g_strdup ("--disable-sound");
138 new_argv
[argc
+1] = NULL
;
140 #ifdef HAVE_GSTREAMER_0_8
141 /* To pass options to GStreamer in 0.8, RB needs to use popt, for
142 * now, GStreamer can live without them (people can still use env
143 * vars, after all) */
144 gst_init (NULL
, NULL
);
145 #elif HAVE_GSTREAMER_0_10
146 rb_profile_start ("initializing gstreamer");
147 g_option_context_add_group (context
, gst_init_get_option_group ());
148 rb_profile_end ("initializing gstreamer");
152 rb_profile_start ("initializing gnome program");
154 #if HAVE_LIBGNOME_GOPTION
155 program
= gnome_program_init (PACKAGE
, VERSION
,
158 GNOME_PARAM_GOPTION_CONTEXT
, context
,
159 GNOME_PARAM_HUMAN_READABLE_NAME
, _("Rhythmbox"),
160 GNOME_PARAM_APP_DATADIR
, DATADIR
,
163 g_option_context_parse (context
, &argc
, &argv
, NULL
);
164 g_option_context_free (context
);
165 program
= gnome_program_init (PACKAGE
, VERSION
,
168 GNOME_PARAM_HUMAN_READABLE_NAME
, _("Rhythmbox"),
169 GNOME_PARAM_APP_DATADIR
, DATADIR
,
173 rb_profile_end ("initializing gnome program");
175 rb_profile_start ("initializing gnome auth manager");
176 gnome_authentication_manager_init ();
177 rb_profile_end ("initializing gnome auth manager");
179 g_random_set_seed (time (0));
182 /* initialize i18n */
183 bindtextdomain (GETTEXT_PACKAGE
, GNOMELOCALEDIR
);
184 bind_textdomain_codeset (GETTEXT_PACKAGE
, "UTF-8");
186 /* ask for utf-8 message text from GStreamer too,
187 * since it doesn't do that itself.
189 #ifdef HAVE_GSTREAMER_0_10
190 bind_textdomain_codeset ("gstreamer-0.10", "UTF-8");
192 bind_textdomain_codeset ("gstreamer-0.8", "UTF-8");
194 textdomain (GETTEXT_PACKAGE
);
197 #ifdef HAVE_GSTREAMER_0_8
198 gst_control_init (&argc
, &argv
);
201 if (!debug
&& debug_match
)
202 rb_debug_init_match (debug_match
);
204 rb_debug_init (debug
);
205 rb_debug ("initializing Rhythmbox %s", VERSION
);
207 /* TODO: kill this function */
212 #if WITH_DBUS || WITH_OLD_DBUS
213 rb_debug ("going to create DBus object");
215 dbus_g_thread_init ();
217 session_bus
= dbus_g_bus_get (DBUS_BUS_SESSION
, &error
);
218 if (session_bus
== NULL
) {
219 g_warning ("couldn't connect to session bus: %s", (error
) ? error
->message
: "(null)");
220 g_clear_error (&error
);
221 } else if (!no_registration
) {
222 guint request_name_reply
;
224 #ifndef DBUS_NAME_FLAG_DO_NOT_QUEUE
225 flags
= DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
;
227 flags
= DBUS_NAME_FLAG_DO_NOT_QUEUE
;
230 #ifndef WITH_OLD_DBUS
231 DBusGProxy
*bus_proxy
;
233 bus_proxy
= dbus_g_proxy_new_for_name (session_bus
,
234 "org.freedesktop.DBus",
235 "/org/freedesktop/DBus",
236 "org.freedesktop.DBus");
238 if (!dbus_g_proxy_call (bus_proxy
,
242 "org.gnome.Rhythmbox",
249 g_warning ("Failed to invoke RequestName: %s",
252 g_object_unref (bus_proxy
);
255 DBusError dbus_error
= {0,};
256 DBusConnection
*connection
;
258 connection
= dbus_g_connection_get_connection (session_bus
);
259 request_name_reply
= dbus_bus_request_name (connection
,
260 "org.gnome.Rhythmbox",
263 if (dbus_error_is_set (&dbus_error
)) {
264 g_warning ("Failed to invoke RequestName: %s",
267 dbus_error_free (&dbus_error
);
269 if (request_name_reply
== DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
270 || request_name_reply
== DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
)
272 else if (request_name_reply
== DBUS_REQUEST_NAME_REPLY_EXISTS
273 || request_name_reply
== DBUS_REQUEST_NAME_REPLY_IN_QUEUE
)
276 g_warning ("Got unhandled reply %u from RequestName",
285 rb_debug ("was asked to quit, but no instance was running");
286 gdk_notify_startup_complete ();
289 #ifdef WITH_RHYTHMDB_GDA
290 gda_init (PACKAGE
, VERSION
, argc
, argv
);
293 rb_refstring_system_init ();
295 rb_file_helpers_init ();
297 rb_debug ("Going to create a new shell");
301 rb_stock_icons_init ();
303 gtk_window_set_default_icon_name ("rhythmbox");
305 rb_shell
= rb_shell_new (argc
, argv
, no_registration
, no_update
, dry_run
, rhythmdb_file
, playlists_file
);
306 g_object_weak_ref (G_OBJECT (rb_shell
), main_shell_weak_ref_cb
, NULL
);
307 if (!no_registration
&& session_bus
!= NULL
) {
312 dbus_g_object_type_install_info (RB_TYPE_SHELL
, &dbus_glib_rb_shell_object_info
);
313 dbus_g_connection_register_g_object (session_bus
, "/org/gnome/Rhythmbox/Shell", G_OBJECT (rb_shell
));
315 /* register player object */
316 dbus_g_object_type_install_info (RB_TYPE_SHELL_PLAYER
, &dbus_glib_rb_shell_player_object_info
);
317 obj
= rb_shell_get_player (rb_shell
);
318 path
= rb_shell_get_player_path (rb_shell
);
319 dbus_g_connection_register_g_object (session_bus
, path
, obj
);
321 /* register playlist manager object */
322 dbus_g_object_type_install_info (RB_TYPE_PLAYLIST_MANAGER
, &dbus_glib_rb_playlist_manager_object_info
);
323 obj
= rb_shell_get_playlist_manager (rb_shell
);
324 path
= rb_shell_get_playlist_manager_path (rb_shell
);
325 dbus_g_connection_register_g_object (session_bus
, path
, obj
);
327 register_dbus_handler (dbus_g_connection_get_connection (session_bus
),
329 #endif /* WITH_DBUS */
331 } else if (!no_registration
&& session_bus
!= NULL
) {
333 DBusGProxy
*shell_proxy
;
335 guint32 current_time
;
336 #if GTK_MINOR_VERSION >= 8
337 current_time
= gdk_x11_display_get_user_time (gdk_display_get_default ());
339 /* FIXME - this does not work; it will return 0 since
340 * we're not in an event. When we pass this to
341 * gtk_window_present_with_time, it ignores the value
342 * since it's 0. The only alternative is to parse the
343 * startup-notification junk from the environment
346 current_time
= GDK_CURRENT_TIME
;
347 #endif /* GTK_MINOR_VERSION */
350 shell_proxy
= dbus_g_proxy_new_for_name_owner (session_bus
,
351 "org.gnome.Rhythmbox",
352 "/org/gnome/Rhythmbox/Shell",
353 "org.gnome.Rhythmbox.Shell",
356 g_warning ("Couldn't create proxy for Rhythmbox shell: %s",
360 dbus_g_proxy_call_no_reply (shell_proxy
, "quit",
363 load_uri_args ((const char **) remaining_args
, (GFunc
) dbus_load_uri
, shell_proxy
);
364 dbus_g_proxy_call_no_reply (shell_proxy
, "present",
365 G_TYPE_UINT
, current_time
,
368 g_object_unref (G_OBJECT (shell_proxy
));
371 if (!send_present_message (dbus_g_connection_get_connection (session_bus
),
373 g_warning ("Unable to send dbus message to existing rhythmbox instance");
374 #endif /* WITH_DBUS */
378 gdk_notify_startup_complete ();
381 rb_profile_start ("mainloop");
383 rb_profile_end ("mainloop");
385 rb_debug ("out of toplevel loop");
387 rb_file_helpers_shutdown ();
388 rb_stock_icons_shutdown ();
389 rb_refstring_system_shutdown ();
391 gnome_vfs_shutdown ();
394 #ifdef HAVE_GSTREAMER_0_10
398 g_strfreev (new_argv
);
400 rb_debug ("THE END");
401 rb_profile_end ("starting rhythmbox");
402 g_object_unref (program
);
404 gnome_accelerators_sync ();
411 load_uri_args (const char **args
, GFunc handler
, gpointer user_data
)
417 for (i
= 0; args
&& args
[i
]; i
++) {
420 rb_debug ("examining argument %s", args
[i
]);
422 uri
= gnome_vfs_make_uri_from_shell_arg (args
[i
]);
424 if (rb_uri_is_local (uri
) == FALSE
|| rb_uri_exists (uri
)) {
425 handler (uri
, user_data
);
435 dbus_load_uri (const char *filename
, DBusGProxy
*proxy
)
437 GError
*error
= NULL
;
438 rb_debug ("Sending loadURI for %s", filename
);
439 if (!dbus_g_proxy_call (proxy
, "loadURI", &error
,
440 G_TYPE_STRING
, filename
,
441 G_TYPE_BOOLEAN
, TRUE
,
444 g_printerr ("Failed to load %s: %s",
445 filename
, error
->message
);
450 main_shell_weak_ref_cb (gpointer data
, GObject
*objptr
)
452 rb_debug ("caught shell finalization");
457 /* old dbus support (0.31-0.34) */
460 send_present_message (DBusConnection
*connection
, guint32 current_time
)
462 DBusMessage
*message
;
465 message
= dbus_message_new_method_call ("org.gnome.Rhythmbox",
466 "/org/gnome/Rhythmbox/Shell",
467 "org.gnome.Rhythmbox.Shell",
472 if (!dbus_message_append_args (message
,
473 DBUS_TYPE_UINT32
, ¤t_time
,
474 DBUS_TYPE_INVALID
)) {
475 dbus_message_unref (message
);
479 result
= dbus_connection_send (connection
, message
, NULL
);
480 dbus_message_unref (message
);
486 unregister_dbus_handler (DBusConnection
*connection
, void *data
)
491 static DBusHandlerResult
492 handle_dbus_message (DBusConnection
*connection
, DBusMessage
*message
, void *data
)
494 RBShell
*shell
= (RBShell
*)data
;
496 rb_debug ("Handling dbus message");
497 if (dbus_message_is_method_call (message
, "org.gnome.Rhythmbox.Shell", "present")) {
498 DBusMessageIter iter
;
499 guint32 current_time
;
501 if (!dbus_message_iter_init (message
, &iter
))
502 return DBUS_HANDLER_RESULT_NEED_MEMORY
;
504 if (dbus_message_iter_get_arg_type (&iter
) != DBUS_TYPE_UINT32
)
505 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
507 dbus_message_iter_get_basic (&iter
, ¤t_time
);
509 rb_shell_present (shell
, current_time
, NULL
);
510 return DBUS_HANDLER_RESULT_HANDLED
;
512 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
517 register_dbus_handler (DBusConnection
*connection
, RBShell
*shell
)
519 DBusObjectPathVTable vt
= {
520 unregister_dbus_handler
,
522 NULL
, NULL
, NULL
, NULL
525 dbus_connection_register_object_path (connection
,
526 "/org/gnome/Rhythmbox/Shell",
529 dbus_connection_ref (connection
);
530 dbus_connection_setup_with_g_main (connection
, NULL
);