1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3
* Copyright (C) Philippe Rouquier 2008 <bonfire-app@wanadoo.fr>
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 of the License, or
8
* (at your option) any later version.
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 Library 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 Street, Fifth Floor Boston, MA 02110-1301, USA
25
#include <glib-object.h>
26
#include <glib/gi18n-lib.h>
27
#include <glib/gstdio.h>
31
#include <libxml/xmlerror.h>
32
#include <libxml/xmlwriter.h>
33
#include <libxml/parser.h>
34
#include <libxml/xmlstring.h>
35
#include <libxml/xmlsave.h>
37
#include "totem-plugin.h"
38
#include "totem-interface.h"
40
#define TOTEM_TYPE_DISC_RECORDER_PLUGIN (totem_disc_recorder_plugin_get_type ())
41
#define TOTEM_DISC_RECORDER_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TOTEM_TYPE_DISC_RECORDER_PLUGIN, TotemDiscRecorderPlugin))
42
#define TOTEM_DISC_RECORDER_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TOTEM_TYPE_DISC_RECORDER_PLUGIN, TotemDiscRecorderPluginClass))
43
#define TOTEM_IS_DISC_RECORDER_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TOTEM_TYPE_DISC_RECORDER_PLUGIN))
44
#define TOTEM_IS_DISC_RECORDER_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TOTEM_TYPE_DISC_RECORDER_PLUGIN))
45
#define TOTEM_DISC_RECORDER_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TOTEM_TYPE_DISC_RECORDER_PLUGIN, TotemDiscRecorderPluginClass))
47
typedef struct TotemDiscRecorderPluginPrivate TotemDiscRecorderPluginPrivate;
55
GtkActionGroup *action_group;
59
} TotemDiscRecorderPlugin;
63
TotemPluginClass parent_class;
64
} TotemDiscRecorderPluginClass;
66
G_MODULE_EXPORT GType register_totem_plugin (GTypeModule *module);
67
GType totem_disc_recorder_plugin_get_type (void) G_GNUC_CONST;
69
TOTEM_PLUGIN_REGISTER (TotemDiscRecorderPlugin, totem_disc_recorder_plugin)
71
static void totem_disc_recorder_plugin_burn (GtkAction *action,
72
TotemDiscRecorderPlugin *pi);
73
static void totem_disc_recorder_plugin_copy (GtkAction *action,
74
TotemDiscRecorderPlugin *pi);
76
static GtkActionEntry totem_disc_recorder_plugin_actions [] = {
77
{ "VideoBurnToDisc", "media-optical-video-new", N_("_Create Video Disc..."), NULL,
78
N_("Create a video DVD or a (S)VCD from the currently opened movie"),
79
G_CALLBACK (totem_disc_recorder_plugin_burn) },
80
{ "VideoDVDCopy", "media-optical-copy", N_("Copy Vide_o DVD..."), NULL,
81
N_("Copy the currently playing video DVD"),
82
G_CALLBACK (totem_disc_recorder_plugin_copy) },
83
{ "VideoVCDCopy", "media-optical-copy", N_("Copy Vide_o (S)VCD..."), NULL,
84
N_("Copy the currently playing (S)VCD"),
85
G_CALLBACK (totem_disc_recorder_plugin_copy) },
89
totem_disc_recorder_plugin_start_burning (TotemDiscRecorderPlugin *pi,
93
GtkWindow *main_window;
95
char **args, *xid_str;
99
array = g_ptr_array_new ();
100
g_ptr_array_add (array, "brasero");
102
g_ptr_array_add (array, "-c");
104
g_ptr_array_add (array, "-r");
105
g_ptr_array_add (array, (gpointer) path);
107
main_window = totem_get_main_window (pi->totem);
108
if (main_window && GTK_WIDGET (main_window)->window) {
110
xid = gdk_x11_drawable_get_xid (GDK_DRAWABLE (GTK_WIDGET (main_window)->window));
111
xid_str = g_strdup_printf ("%d", xid);
112
g_ptr_array_add (array, "-x");
113
g_ptr_array_add (array, xid_str);
118
g_ptr_array_add (array, NULL);
119
args = (char **) g_ptr_array_free (array, FALSE);
122
if (!g_spawn_async (NULL, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error)) {
124
totem_interface_error (_("The video disc could not be duplicated."),
126
totem_get_main_window (pi->totem));
128
totem_interface_error (_("The movie could not be recorded."),
130
totem_get_main_window (pi->totem));
133
g_error_free (error);
143
totem_disc_recorder_plugin_write_video_project (TotemDiscRecorderPlugin *pi,
146
xmlTextWriter *project;
147
xmlDocPtr doc = NULL;
151
char *title, *path, *uri;
154
/* get a temporary path */
155
path = g_build_filename (g_get_tmp_dir (), "brasero-tmp-project-XXXXXX", NULL);
156
fd = g_mkstemp (path);
160
*error = g_strdup (_("Unable to write a project."));
164
project = xmlNewTextWriterDoc (&doc, 0);
170
*error = g_strdup (_("Unable to write a project."));
174
xmlTextWriterSetIndent (project, 1);
175
xmlTextWriterSetIndentString (project, (xmlChar *) "\t");
177
success = xmlTextWriterStartDocument (project,
184
success = xmlTextWriterStartElement (project, (xmlChar *) "braseroproject");
188
/* write the name of the version */
189
success = xmlTextWriterWriteElement (project,
190
(xmlChar *) "version",
195
title = totem_get_short_title (pi->totem);
197
success = xmlTextWriterWriteElement (project,
206
success = xmlTextWriterStartElement (project, (xmlChar *) "track");
210
success = xmlTextWriterStartElement (project, (xmlChar *) "video");
214
uri = totem_get_current_mrl (pi->totem);
215
escaped = (unsigned char *) g_uri_escape_string (uri, NULL, FALSE);
218
success = xmlTextWriterWriteElement (project,
225
/* start of the song always 0 */
226
success = xmlTextWriterWriteElement (project,
232
success = xmlTextWriterEndElement (project); /* video */
236
success = xmlTextWriterEndElement (project); /* track */
240
success = xmlTextWriterEndElement (project); /* braseroproject */
244
xmlTextWriterEndDocument (project);
245
xmlFreeTextWriter (project);
247
save = xmlSaveToFd (fd, "UTF8", XML_SAVE_FORMAT);
248
xmlSaveDoc (save, doc);
259
xmlTextWriterEndDocument (project);
260
xmlFreeTextWriter (project);
266
*error = g_strdup (_("Unable to write a project."));
271
totem_disc_recorder_plugin_burn (GtkAction *action,
272
TotemDiscRecorderPlugin *pi)
277
path = totem_disc_recorder_plugin_write_video_project (pi, &error);
279
totem_interface_error (_("The movie could not be recorded."),
281
totem_get_main_window (pi->totem));
286
if (!totem_disc_recorder_plugin_start_burning (pi, path, FALSE))
293
totem_disc_recorder_plugin_copy (GtkAction *action,
294
TotemDiscRecorderPlugin *pi)
298
mrl = totem_get_current_mrl (pi->totem);
299
if (!g_str_has_prefix (mrl, "dvd:") && !g_str_has_prefix (mrl, "vcd:")) {
301
g_assert_not_reached ();
305
totem_disc_recorder_plugin_start_burning (pi, mrl + 6, TRUE);
309
totem_disc_recorder_file_closed (TotemObject *totem,
310
TotemDiscRecorderPlugin *pi)
314
action = gtk_action_group_get_action (pi->action_group, "VideoBurnToDisc");
315
gtk_action_set_visible (action, FALSE);
316
action = gtk_action_group_get_action (pi->action_group, "VideoDVDCopy");
317
gtk_action_set_visible (action, FALSE);
318
action = gtk_action_group_get_action (pi->action_group, "VideoVCDCopy");
319
gtk_action_set_visible (action, FALSE);
323
totem_disc_recorder_file_opened (TotemObject *totem,
325
TotemDiscRecorderPlugin *pi)
329
/* Check if that stream is supported by brasero */
330
if (g_str_has_prefix (mrl, "file:")) {
331
/* If the file is supported we can always burn, even if there
332
* aren't any burner since we can still create an image. */
333
action = gtk_action_group_get_action (pi->action_group, "VideoBurnToDisc");
334
gtk_action_set_visible (action, TRUE);
335
action = gtk_action_group_get_action (pi->action_group, "VideoDVDCopy");
336
gtk_action_set_visible (action, FALSE);
337
action = gtk_action_group_get_action (pi->action_group, "VideoVCDCopy");
338
gtk_action_set_visible (action, FALSE);
340
else if (g_str_has_prefix (mrl, "dvd:")) {
341
action = gtk_action_group_get_action (pi->action_group, "VideoBurnToDisc");
342
gtk_action_set_visible (action, FALSE);
343
action = gtk_action_group_get_action (pi->action_group, "VideoDVDCopy");
344
gtk_action_set_visible (action, TRUE);
345
action = gtk_action_group_get_action (pi->action_group, "VideoVCDCopy");
346
gtk_action_set_visible (action, FALSE);
348
else if (g_str_has_prefix (mrl, "vcd:")) {
349
action = gtk_action_group_get_action (pi->action_group, "VideoBurnToDisc");
350
gtk_action_set_visible (action, FALSE);
351
action = gtk_action_group_get_action (pi->action_group, "VideoDVDCopy");
352
gtk_action_set_visible (action, FALSE);
353
action = gtk_action_group_get_action (pi->action_group, "VideoVCDCopy");
354
gtk_action_set_visible (action, TRUE);
357
action = gtk_action_group_get_action (pi->action_group, "VideoBurnToDisc");
358
gtk_action_set_visible (action, FALSE);
359
action = gtk_action_group_get_action (pi->action_group, "VideoDVDCopy");
360
gtk_action_set_visible (action, FALSE);
361
action = gtk_action_group_get_action (pi->action_group, "VideoVCDCopy");
362
gtk_action_set_visible (action, FALSE);
367
impl_activate (TotemPlugin *plugin, TotemObject *totem, GError **error)
369
TotemDiscRecorderPlugin *pi = TOTEM_DISC_RECORDER_PLUGIN (plugin);
370
GtkUIManager *uimanager = NULL;
374
/* make sure brasero is in the path */
375
path = g_find_program_in_path ("brasero");
380
//FIXME this shouldn't be necessary
382
/* Set up to use brasero icons */
383
path = g_build_path (G_DIR_SEPARATOR_S, LIBBRASERO_MEDIA_INSTALL, "/share/brasero/icons", NULL);
384
gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), path);
390
g_signal_connect (totem,
392
G_CALLBACK (totem_disc_recorder_file_opened),
394
g_signal_connect (totem,
396
G_CALLBACK (totem_disc_recorder_file_closed),
400
pi->action_group = gtk_action_group_new ("DiscRecorderActions");
401
gtk_action_group_set_translation_domain (pi->action_group, GETTEXT_PACKAGE);
402
gtk_action_group_add_actions (pi->action_group,
403
totem_disc_recorder_plugin_actions,
404
G_N_ELEMENTS (totem_disc_recorder_plugin_actions),
407
uimanager = totem_get_ui_manager (totem);
408
gtk_ui_manager_insert_action_group (uimanager, pi->action_group, -1);
409
g_object_unref (pi->action_group);
411
pi->ui_merge_id = gtk_ui_manager_new_merge_id (uimanager);
413
gtk_ui_manager_add_ui (uimanager,
415
"/ui/tmw-menubar/movie/burn-placeholder",
418
GTK_UI_MANAGER_MENUITEM,
420
gtk_ui_manager_add_ui (uimanager,
422
"/ui/totem-main-popup/burn-placeholder",
425
GTK_UI_MANAGER_MENUITEM,
428
gtk_ui_manager_add_ui (uimanager,
430
"/ui/tmw-menubar/movie/burn-placeholder",
433
GTK_UI_MANAGER_MENUITEM,
435
gtk_ui_manager_add_ui (uimanager,
437
"/ui/totem-main-popup/burn-placeholder",
440
GTK_UI_MANAGER_MENUITEM,
443
gtk_ui_manager_add_ui (uimanager,
445
"/ui/tmw-menubar/movie/burn-placeholder",
448
GTK_UI_MANAGER_MENUITEM,
450
gtk_ui_manager_add_ui (uimanager,
452
"/ui/totem-main-popup/burn-placeholder",
455
GTK_UI_MANAGER_MENUITEM,
458
if (!totem_is_paused (totem) && !totem_is_playing (totem)) {
459
action = gtk_action_group_get_action (pi->action_group, "VideoBurnToDisc");
460
gtk_action_set_visible (action, FALSE);
461
action = gtk_action_group_get_action (pi->action_group, "VideoDVDCopy");
462
gtk_action_set_visible (action, FALSE);
463
action = gtk_action_group_get_action (pi->action_group, "VideoVCDCopy");
464
gtk_action_set_visible (action, FALSE); }
468
mrl = totem_get_current_mrl (totem);
469
totem_disc_recorder_file_opened (totem, mrl, pi);
477
impl_deactivate (TotemPlugin *plugin, TotemObject *totem)
479
TotemDiscRecorderPlugin *pi = TOTEM_DISC_RECORDER_PLUGIN (plugin);
480
GtkUIManager *uimanager = NULL;
484
g_signal_handlers_disconnect_by_func (totem, totem_disc_recorder_file_opened, plugin);
485
g_signal_handlers_disconnect_by_func (totem, totem_disc_recorder_file_closed, plugin);
487
uimanager = totem_get_ui_manager (totem);
488
gtk_ui_manager_remove_ui (uimanager, pi->ui_merge_id);
489
gtk_ui_manager_remove_action_group (uimanager, pi->action_group);
495
totem_disc_recorder_plugin_finalize (GObject *object)
497
G_OBJECT_CLASS (totem_disc_recorder_plugin_parent_class)->finalize (object);
501
totem_disc_recorder_plugin_class_init (TotemDiscRecorderPluginClass *klass)
503
GObjectClass *object_class = G_OBJECT_CLASS (klass);
504
TotemPluginClass *plugin_class = TOTEM_PLUGIN_CLASS (klass);
506
object_class->finalize = totem_disc_recorder_plugin_finalize;
508
plugin_class->activate = impl_activate;
509
plugin_class->deactivate = impl_deactivate;
513
totem_disc_recorder_plugin_init (TotemDiscRecorderPlugin *pi)