1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 #define __EXTENSIONS__
24 #include <string.h> /* For strlen */
25 #include <glib/gi18n-lib.h>
29 #include <glib-object.h>
31 #include "rb-plugin.h"
34 #include "rb-source.h"
35 #include "rb-playlist-source.h"
36 #include "rb-dialog.h"
37 #include "rb-file-helpers.h"
39 #include "rb-recorder.h"
40 #include "rb-playlist-source-recorder.h"
42 #include <nautilus-burn-drive.h>
43 #ifndef NAUTILUS_BURN_CHECK_VERSION
44 #define NAUTILUS_BURN_CHECK_VERSION(a,b,c) FALSE
47 #if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
48 #include <nautilus-burn.h>
51 #define RB_TYPE_CD_RECORDER_PLUGIN (rb_cd_recorder_plugin_get_type ())
52 #define RB_CD_RECORDER_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_CD_RECORDER_PLUGIN, RBCdRecorderPlugin))
53 #define RB_CD_RECORDER_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_CD_RECORDER_PLUGIN, RBCdRecorderPluginClass))
54 #define RB_IS_CD_RECORDER_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_CD_RECORDER_PLUGIN))
55 #define RB_IS_CD_RECORDER_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_CD_RECORDER_PLUGIN))
56 #define RB_CD_RECORDER_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_CD_RECORDER_PLUGIN, RBCdRecorderPluginClass))
63 GtkActionGroup
*action_group
;
66 RBSource
*selected_source
;
72 RBPluginClass parent_class
;
73 } RBCdRecorderPluginClass
;
75 G_MODULE_EXPORT GType
register_rb_plugin (GTypeModule
*module
);
76 GType
rb_cd_recorder_plugin_get_type (void) G_GNUC_CONST
;
78 static void rb_cd_recorder_plugin_init (RBCdRecorderPlugin
*plugin
);
79 static void rb_cd_recorder_plugin_finalize (GObject
*object
);
80 static void impl_activate (RBPlugin
*plugin
, RBShell
*shell
);
81 static void impl_deactivate (RBPlugin
*plugin
, RBShell
*shell
);
82 static void cmd_burn_source (GtkAction
*action
,
83 RBCdRecorderPlugin
*pi
);
85 static GtkActionEntry rb_cd_recorder_plugin_actions
[] = {
86 { "MusicPlaylistBurnPlaylist", GTK_STOCK_CDROM
, N_("_Create Audio CD..."), NULL
,
87 N_("Create an audio CD from playlist"),
88 G_CALLBACK (cmd_burn_source
) }
91 RB_PLUGIN_REGISTER(RBCdRecorderPlugin
, rb_cd_recorder_plugin
)
94 rb_cd_recorder_plugin_class_init (RBCdRecorderPluginClass
*klass
)
96 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
97 RBPluginClass
*plugin_class
= RB_PLUGIN_CLASS (klass
);
99 object_class
->finalize
= rb_cd_recorder_plugin_finalize
;
101 plugin_class
->activate
= impl_activate
;
102 plugin_class
->deactivate
= impl_deactivate
;
106 rb_cd_recorder_plugin_init (RBCdRecorderPlugin
*plugin
)
108 rb_debug ("RBCdRecorderPlugin initializing");
110 #if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
111 nautilus_burn_init ();
116 rb_cd_recorder_plugin_finalize (GObject
*object
)
119 RBCdRecorderPlugin *plugin = RB_CD_RECORDER_PLUGIN (object);
121 rb_debug ("RBCdRecorderPlugin finalizing");
123 #if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
124 nautilus_burn_shutdown ();
127 G_OBJECT_CLASS (rb_cd_recorder_plugin_parent_class
)->finalize (object
);
131 burn_source_iter_func (GtkTreeModel
*model
,
138 RhythmDBEntry
*entry
;
140 gtk_tree_model_get (model
, iter
, 0, &entry
, -1);
142 *uri
= rhythmdb_entry_dup_string (entry
, RHYTHMDB_PROP_LOCATION
);
143 *title
= rhythmdb_entry_dup_string (entry
, RHYTHMDB_PROP_TITLE
);
144 *artist
= rhythmdb_entry_dup_string (entry
, RHYTHMDB_PROP_ARTIST
);
145 *duration
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_DURATION
);
151 source_burn (RBSource
*source
)
161 g_object_get (G_OBJECT (source
), "query-model", &model
, NULL
);
163 /* don't burn if the source is empty */
164 if (gtk_tree_model_iter_n_children (model
, NULL
) == 0) {
165 g_object_unref (model
);
169 rb_debug ("burning source");
171 g_object_get (source
, "name", &name
, "shell", &shell
, NULL
);
173 parent
= gtk_widget_get_toplevel (GTK_WIDGET (source
));
174 recorder
= rb_playlist_source_recorder_new (parent
,
177 g_object_unref (shell
);
181 res
= rb_playlist_source_recorder_add_from_model (RB_PLAYLIST_SOURCE_RECORDER (recorder
),
183 burn_source_iter_func
,
185 g_object_unref (model
);
188 rb_error_dialog (GTK_WINDOW (parent
),
189 _("Unable to create audio CD"),
190 "%s", error
->message
);
191 g_error_free (error
);
193 gtk_widget_destroy (recorder
);
198 g_signal_connect (recorder
,
200 G_CALLBACK (gtk_widget_destroy
),
203 gtk_widget_show (recorder
);
207 cmd_burn_source (GtkAction
*action
,
208 RBCdRecorderPlugin
*pi
)
210 if (pi
->selected_source
!= NULL
) {
211 source_burn (pi
->selected_source
);
216 playlist_entries_changed (GtkTreeModel
*model
,
217 RhythmDBEntry
*entry
,
218 RBCdRecorderPlugin
*pi
)
223 num_tracks
= gtk_tree_model_iter_n_children (model
, NULL
);
225 action
= gtk_action_group_get_action (pi
->action_group
, "MusicPlaylistBurnPlaylist");
226 gtk_action_set_sensitive (action
, (num_tracks
> 0));
230 playlist_row_inserted_cb (GtkTreeModel
*model
,
233 RBCdRecorderPlugin
*pi
)
235 RhythmDBEntry
*entry
= rhythmdb_query_model_iter_to_entry (RHYTHMDB_QUERY_MODEL (model
), iter
);
237 playlist_entries_changed (model
, entry
, pi
);
239 rhythmdb_entry_unref (entry
);
243 update_source (RBCdRecorderPlugin
*pi
,
247 gboolean playlist_active
;
248 RBSource
*selected_source
;
250 if (pi
->selected_source
!= NULL
) {
251 RhythmDBQueryModel
*model
;
253 g_object_get (G_OBJECT (pi
->selected_source
), "query-model", &model
, NULL
);
254 g_signal_handlers_disconnect_by_func (model
, playlist_row_inserted_cb
, pi
);
255 g_signal_handlers_disconnect_by_func (model
, playlist_entries_changed
, pi
);
256 g_object_unref (model
);
259 g_object_get (G_OBJECT (shell
), "selected-source", &selected_source
, NULL
);
261 /* for now restrict to playlist sources */
262 playlist_active
= RB_IS_PLAYLIST_SOURCE (selected_source
);
264 action
= gtk_action_group_get_action (pi
->action_group
,
265 "MusicPlaylistBurnPlaylist");
267 if (pi
->enabled
&& playlist_active
&& rb_recorder_enabled ()) {
268 RhythmDBQueryModel
*model
;
270 g_object_get (G_OBJECT (selected_source
), "query-model", &model
, NULL
);
271 /* monitor for changes, to enable/disable the burn menu item */
272 g_signal_connect_object (G_OBJECT (model
),
274 G_CALLBACK (playlist_row_inserted_cb
),
276 g_signal_connect_object (G_OBJECT (model
),
278 G_CALLBACK (playlist_entries_changed
),
281 playlist_entries_changed (GTK_TREE_MODEL (model
), NULL
, pi
);
282 g_object_unref (model
);
283 gtk_action_set_visible (action
, TRUE
);
285 gtk_action_set_visible (action
, FALSE
);
289 if (pi
->selected_source
!= NULL
) {
290 g_object_unref (pi
->selected_source
);
292 pi
->selected_source
= selected_source
;
296 shell_selected_source_notify_cb (RBShell
*shell
,
298 RBCdRecorderPlugin
*pi
)
300 rb_debug ("RBCdRecorderPlugin selected source changed");
302 update_source (pi
, shell
);
305 static const char *ui_paths
[] = {
306 "/MenuBar/MusicMenu/PlaylistMenu/MusicPlaylistPlaylistMenuPluginPlaceholder",
307 "/ToolBar/ToolBarPluginPlaceholder",
308 "/PlaylistSourcePopup/PlaylistSourcePopupPluginPlaceholder",
309 "/AutoPlaylistSourcePopup/AutoPlaylistSourcePopupPluginPlaceholder",
310 "/QueueSourcePopup/QueueSourcePopupPluginPlaceholder",
314 impl_activate (RBPlugin
*plugin
,
317 RBCdRecorderPlugin
*pi
= RB_CD_RECORDER_PLUGIN (plugin
);
318 GtkUIManager
*uimanager
= NULL
;
323 rb_debug ("RBCdRecorderPlugin activating");
327 g_object_get (G_OBJECT (shell
),
328 "ui-manager", &uimanager
,
331 g_signal_connect_object (G_OBJECT (shell
),
332 "notify::selected-source",
333 G_CALLBACK (shell_selected_source_notify_cb
),
337 pi
->action_group
= gtk_action_group_new ("CdRecorderActions");
338 gtk_action_group_set_translation_domain (pi
->action_group
,
340 gtk_action_group_add_actions (pi
->action_group
,
341 rb_cd_recorder_plugin_actions
, G_N_ELEMENTS (rb_cd_recorder_plugin_actions
),
343 gtk_ui_manager_insert_action_group (uimanager
, pi
->action_group
, 0);
346 pi
->ui_merge_id
= gtk_ui_manager_new_merge_id (uimanager
);
347 for (i
= 0; i
< G_N_ELEMENTS (ui_paths
); i
++) {
348 gtk_ui_manager_add_ui (uimanager
,
351 "MusicPlaylistBurnPlaylistMenu",
352 "MusicPlaylistBurnPlaylist",
357 update_source (pi
, shell
);
361 impl_deactivate (RBPlugin
*plugin
,
364 RBCdRecorderPlugin
*pi
= RB_CD_RECORDER_PLUGIN (plugin
);
365 GtkUIManager
*uimanager
= NULL
;
369 rb_debug ("RBCdRecorderPlugin deactivating");
371 update_source (pi
, shell
);
373 if (pi
->selected_source
) {
374 pi
->selected_source
= NULL
;
377 g_signal_handlers_disconnect_by_func (shell
, shell_selected_source_notify_cb
, pi
);
379 g_object_get (G_OBJECT (shell
),
380 "ui-manager", &uimanager
,
383 gtk_ui_manager_remove_ui (uimanager
, pi
->ui_merge_id
);
384 gtk_ui_manager_remove_action_group (uimanager
, pi
->action_group
);
386 g_object_unref (G_OBJECT (uimanager
));