brasero r989 - in trunk: . po src src/plugins src/plugins/cdrdao src/plugins/cdrkit src/plugins/cdrtools src/plugins/dvdauthor src/plugins/libburnia src/plugins/local-track src/plugins/transcode src/plugins/vcdimager
- From: philippr svn gnome org
- To: svn-commits-list gnome org
- Subject: brasero r989 - in trunk: . po src src/plugins src/plugins/cdrdao src/plugins/cdrkit src/plugins/cdrtools src/plugins/dvdauthor src/plugins/libburnia src/plugins/local-track src/plugins/transcode src/plugins/vcdimager
- Date: Mon, 14 Jul 2008 18:07:55 +0000 (UTC)
Author: philippr
Date: Mon Jul 14 18:07:55 2008
New Revision: 989
URL: http://svn.gnome.org/viewvc/brasero?rev=989&view=rev
Log:
Added video project branch changes
Added:
trunk/src/brasero-video-disc.c
trunk/src/brasero-video-disc.h
trunk/src/brasero-video-project.c (contents, props changed)
trunk/src/brasero-video-project.h (contents, props changed)
trunk/src/brasero-video-tree-model.c (contents, props changed)
trunk/src/brasero-video-tree-model.h (contents, props changed)
trunk/src/plugins/dvdauthor/
trunk/src/plugins/dvdauthor/Makefile.am
trunk/src/plugins/dvdauthor/burn-dvdauthor.c (contents, props changed)
trunk/src/plugins/dvdauthor/burn-dvdauthor.h (contents, props changed)
trunk/src/plugins/transcode/burn-vob.c (contents, props changed)
trunk/src/plugins/transcode/burn-vob.h (contents, props changed)
trunk/src/plugins/vcdimager/
trunk/src/plugins/vcdimager/Makefile.am
trunk/src/plugins/vcdimager/burn-vcdimager.c
trunk/src/plugins/vcdimager/burn-vcdimager.h
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/po/POTFILES.in
trunk/src/Makefile.am
trunk/src/brasero-dest-selection.c
trunk/src/brasero-disc-option-dialog.c
trunk/src/brasero-disc.h
trunk/src/brasero-file-chooser.c
trunk/src/brasero-io.c
trunk/src/brasero-io.h
trunk/src/brasero-layout.c
trunk/src/brasero-layout.h
trunk/src/brasero-metadata.c
trunk/src/brasero-metadata.h
trunk/src/brasero-multi-song-props.c
trunk/src/brasero-multi-song-props.h
trunk/src/brasero-project-manager.c
trunk/src/brasero-project-manager.h
trunk/src/brasero-project-type-chooser.c
trunk/src/brasero-project-type-chooser.h
trunk/src/brasero-project.c
trunk/src/brasero-project.h
trunk/src/brasero-song-properties.c
trunk/src/brasero-time-button.c
trunk/src/brasero-time-button.h
trunk/src/burn-basics.h
trunk/src/burn-caps.c
trunk/src/burn-debug.c
trunk/src/burn-job.c
trunk/src/burn-medium.c
trunk/src/burn-plugin-private.h
trunk/src/burn-plugin.c
trunk/src/burn-process.c
trunk/src/burn-session.c
trunk/src/burn-session.h
trunk/src/burn-track.h
trunk/src/plugins/Makefile.am
trunk/src/plugins/cdrdao/burn-toc2cue.c
trunk/src/plugins/cdrkit/burn-wodim.c
trunk/src/plugins/cdrtools/burn-cdrecord.c
trunk/src/plugins/libburnia/burn-libburn.c
trunk/src/plugins/local-track/burn-local-image.c
trunk/src/plugins/transcode/Makefile.am
trunk/src/plugins/transcode/burn-transcode.c
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Mon Jul 14 18:07:55 2008
@@ -132,6 +132,16 @@
BRASERO_GIO_CFLAGS="$BRASERO_GIO_CFLAGS $CFLAGS"
BRASERO_GIO_LIBS="$BRASERO_GIO_LIBS $LDFLAGS"
+dnl ** used by brasero and one plugin
+PKG_CHECK_MODULES(BRASERO_LIBXML, \
+ libxml-2.0 >= $LIBXML2_REQUIRED)
+
+AC_SUBST(BRASERO_LIBXML_CFLAGS)
+AC_SUBST(BRASERO_LIBXML_LIBS)
+
+BRASERO_LIBXML_CFLAGS="$BRASERO_LIBXML_CFLAGS $CFLAGS"
+BRASERO_LIBXML_LIBS="$BRASERO_LIBXML_LIBS $LDFLAGS"
+
dnl ** used by brasero and all modules
PKG_CHECK_MODULES(BRASERO_BASE, \
gconf-2.0 >= $GCONF_REQUIRED \
@@ -151,7 +161,6 @@
gtk+-2.0 >= $GTK_REQUIRED \
libgnome-2.0 >= $LIBGNOME_REQUIRED \
libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED \
- libxml-2.0 >= $LIBXML2_REQUIRED \
dbus-glib-1 >= $DBUS_REQUIRED)
AC_SUBST(BRASERO_CFLAGS)
@@ -349,8 +358,10 @@
src/plugins/libburnia/Makefile
src/plugins/transcode/Makefile
src/plugins/dvdcss/Makefile
+src/plugins/dvdauthor/Makefile
src/plugins/checksum/Makefile
src/plugins/local-track/Makefile
+src/plugins/vcdimager/Makefile
po/Makefile.in
src/Makefile
])
Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in (original)
+++ trunk/po/POTFILES.in Mon Jul 14 18:07:55 2008
@@ -102,3 +102,8 @@
src/brasero-jacket-edit.c
src/brasero-multi-song-props.c
src/brasero-rename.c
+src/brasero-video-disc.c
+src/brasero-video-tree-model.c
+src/plugins/dvdauthor/burn-dvdauthor.c
+src/plugins/transcode/burn-vob.c
+src/plugins/vcdimager/burn-vcdimager.c
Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Mon Jul 14 18:07:55 2008
@@ -14,7 +14,8 @@
-DBRASERO_DATADIR=\"$(datadir)/brasero\" \
-DBRASERO_LIBDIR=\"$(libdir)\" \
$(DISABLE_DEPRECATED) \
- $(BRASERO_CFLAGS)
+ $(BRASERO_CFLAGS) \
+ $(BRASERO_LIBXML_CFLAGS)
CLEANFILES = $(RECMARSHALFILES)
@@ -259,7 +260,13 @@
brasero-notify.c \
brasero-notify.h \
burn-volume-source.c \
- burn-volume-source.h
+ burn-volume-source.h \
+ brasero-video-disc.c \
+ brasero-video-disc.h \
+ brasero-video-project.h \
+ brasero-video-project.c \
+ brasero-video-tree-model.c \
+ brasero-video-tree-model.h
if BUILD_INOTIFY
brasero_SOURCES += brasero-file-monitor.c brasero-file-monitor.h
@@ -281,7 +288,7 @@
endif
brasero_LDADD = \
- $(BRASERO_LIBS)
+ $(BRASERO_LIBS) $(BRASERO_LIBXML_LIBS)
Modified: trunk/src/brasero-dest-selection.c
==============================================================================
--- trunk/src/brasero-dest-selection.c (original)
+++ trunk/src/brasero-dest-selection.c Mon Jul 14 18:07:55 2008
@@ -326,8 +326,24 @@
return;
}
- if (source.type == BRASERO_TRACK_TYPE_AUDIO)
+ if (source.type == BRASERO_TRACK_TYPE_AUDIO) {
+ /* If that's AUDIO only without VIDEO then return */
+ if (!(source.subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|BRASERO_VIDEO_FORMAT_VCD|BRASERO_VIDEO_FORMAT_VIDEO_DVD)))
+ return;
+
+ /* Otherwise try all possible image types */
+ output->subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
+ for (; output->subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
+ output->subtype.img_format >>= 1) {
+
+ result = brasero_burn_caps_is_output_supported (priv->caps,
+ priv->session,
+ output);
+ if (result == BRASERO_BURN_OK)
+ return;
+ }
return;
+ }
if (source.type == BRASERO_TRACK_TYPE_DATA
|| source.subtype.media & (BRASERO_MEDIUM_DVD|BRASERO_MEDIUM_DVD_DL)) {
Modified: trunk/src/brasero-disc-option-dialog.c
==============================================================================
--- trunk/src/brasero-disc-option-dialog.c (original)
+++ trunk/src/brasero-disc-option-dialog.c Mon Jul 14 18:07:55 2008
@@ -70,13 +70,18 @@
GtkWidget *button;
+ GtkWidget *video_options;
+ GtkWidget *dvd_audio;
+ GtkWidget *vcd_label;
+ GtkWidget *vcd_button;
+ GtkWidget *svcd_button;
+
guint label_modified:1;
guint joliet_warning:1;
guint checksum_saved:1;
guint joliet_saved:1;
guint multi_saved:1;
- guint video_saved:1;
};
typedef struct _BraseroDiscOptionDialogPrivate BraseroDiscOptionDialogPrivate;
@@ -195,9 +200,14 @@
}
}
else if (source.type == BRASERO_TRACK_TYPE_AUDIO) {
- /* NOTE to translators: the final string must not be over
- * 32 _bytes_ */
- title_str = g_strdup_printf (_("Audio disc (%s)"), buffer);
+ if (source.subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|BRASERO_VIDEO_FORMAT_VCD|BRASERO_VIDEO_FORMAT_VIDEO_DVD))
+ /* NOTE to translators: the final string must not be over
+ * 32 _bytes_ */
+ title_str = g_strdup_printf (_("Video disc (%s)"), buffer);
+ else
+ /* NOTE to translators: the final string must not be over
+ * 32 _bytes_ */
+ title_str = g_strdup_printf (_("Audio disc (%s)"), buffer);
if (strlen (title_str) > 32) {
g_free (title_str);
@@ -394,6 +404,51 @@
}
static void
+brasero_disc_option_dialog_update_video (BraseroDiscOptionDialog *dialog)
+{
+ BraseroDiscOptionDialogPrivate *priv;
+ BraseroMedia media;
+
+ priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (dialog);
+
+ media = brasero_burn_session_get_dest_media (priv->session);
+
+ if (media & BRASERO_MEDIUM_DVD) {
+ gtk_widget_show (priv->dvd_audio);
+ gtk_widget_hide (priv->vcd_label);
+ gtk_widget_hide (priv->vcd_button);
+ gtk_widget_hide (priv->svcd_button);
+ }
+ else if (media & BRASERO_MEDIUM_CD) {
+ gtk_widget_hide (priv->dvd_audio);
+ gtk_widget_show (priv->vcd_label);
+ gtk_widget_show (priv->vcd_button);
+ gtk_widget_show (priv->svcd_button);
+ }
+ else if (media & BRASERO_MEDIUM_FILE) {
+ BraseroImageFormat format;
+
+ /* if we create a CUE file then that's a SVCD */
+ format = brasero_burn_session_get_output_format (priv->session);
+ if (format == BRASERO_IMAGE_FORMAT_NONE)
+ return;
+
+ if (format == BRASERO_IMAGE_FORMAT_CUE) {
+ gtk_widget_hide (priv->dvd_audio);
+ gtk_widget_show (priv->vcd_label);
+ gtk_widget_show (priv->vcd_button);
+ gtk_widget_show (priv->svcd_button);
+ }
+ else if (format == BRASERO_IMAGE_FORMAT_BIN) {
+ gtk_widget_show (priv->dvd_audio);
+ gtk_widget_hide (priv->vcd_label);
+ gtk_widget_hide (priv->vcd_button);
+ gtk_widget_hide (priv->svcd_button);
+ }
+ }
+}
+
+static void
brasero_disc_option_dialog_output_changed (BraseroBurnSession *session,
BraseroDiscOptionDialog *dialog)
{
@@ -404,12 +459,17 @@
/* update the multi button:
* NOTE: order is important here multi then video */
brasero_disc_option_dialog_update_multi (dialog);
+
/* update the joliet button */
brasero_disc_option_dialog_update_joliet (dialog);
/* see if we need to update the label */
if (!priv->label_modified)
brasero_disc_option_dialog_update_label (dialog);
+
+ /* for video disc see what's the output : CD or DVD */
+ if (priv->dvd_audio)
+ brasero_disc_option_dialog_update_video (dialog);
}
/**
@@ -753,7 +813,7 @@
G_CALLBACK (brasero_disc_option_dialog_multi_toggled),
dialog);
gtk_widget_set_tooltip_text (priv->multi_toggle,
- _("Allow create what is called an enhanced CD or CD+"));
+ _("Allow create what is called an enhanced CD or CD+"));
options = brasero_utils_pack_properties (_("<b>Disc options</b>"),
priv->multi_toggle,
@@ -764,6 +824,398 @@
gtk_widget_show_all (widget);
}
+static void
+brasero_disc_option_dialog_AC3 (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ BraseroDiscOptionDialogPrivate *priv;
+ BraseroAudioFormat format;
+ GValue *value = NULL;
+
+ priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (dialog);
+
+ brasero_burn_session_tag_lookup (priv->session,
+ BRASERO_DVD_AUDIO_STREAMS,
+ &value);
+
+ if (value)
+ format = g_value_get_int (value);
+ else
+ format = BRASERO_AUDIO_FORMAT_NONE;
+
+ if (gtk_toggle_button_get_active (button))
+ format |= BRASERO_AUDIO_FORMAT_AC3;
+ else
+ format &= ~BRASERO_AUDIO_FORMAT_AC3;
+
+ value = g_new0 (GValue, 1);
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, format);
+ brasero_burn_session_tag_add (priv->session,
+ BRASERO_DVD_AUDIO_STREAMS,
+ value);
+}
+
+static void
+brasero_disc_option_dialog_MP2 (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ BraseroDiscOptionDialogPrivate *priv;
+ BraseroAudioFormat format;
+ GValue *value = NULL;
+
+ priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (dialog);
+
+ brasero_burn_session_tag_lookup (priv->session,
+ BRASERO_DVD_AUDIO_STREAMS,
+ &value);
+
+ if (value)
+ format = g_value_get_int (value);
+ else
+ format = BRASERO_AUDIO_FORMAT_NONE;
+
+ if (gtk_toggle_button_get_active (button))
+ format |= BRASERO_AUDIO_FORMAT_MP2;
+ else
+ format &= ~BRASERO_AUDIO_FORMAT_MP2;
+
+ value = g_new0 (GValue, 1);
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, format);
+ brasero_burn_session_tag_add (priv->session,
+ BRASERO_DVD_AUDIO_STREAMS,
+ value);
+}
+
+static void
+brasero_disc_option_dialog_set_tag (BraseroDiscOptionDialog *dialog,
+ const gchar *tag,
+ gint contents)
+{
+ BraseroDiscOptionDialogPrivate *priv;
+ GValue *value;
+
+ priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (dialog);
+
+ value = g_new0 (GValue, 1);
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, contents);
+ brasero_burn_session_tag_add (priv->session,
+ tag,
+ value);
+}
+
+static void
+brasero_disc_option_dialog_SVCD (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ brasero_disc_option_dialog_set_tag (dialog,
+ BRASERO_VCD_TYPE,
+ BRASERO_SVCD);
+}
+
+static void
+brasero_disc_option_dialog_VCD (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ brasero_disc_option_dialog_set_tag (dialog,
+ BRASERO_VCD_TYPE,
+ BRASERO_VCD_V2);
+}
+
+static void
+brasero_disc_option_dialog_NTSC (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ brasero_disc_option_dialog_set_tag (dialog,
+ BRASERO_VIDEO_OUTPUT_FRAMERATE,
+ BRASERO_VIDEO_FRAMERATE_NTSC);
+}
+
+static void
+brasero_disc_option_dialog_PAL_SECAM (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ brasero_disc_option_dialog_set_tag (dialog,
+ BRASERO_VIDEO_OUTPUT_FRAMERATE,
+ BRASERO_VIDEO_FRAMERATE_PAL_SECAM);
+}
+
+static void
+brasero_disc_option_dialog_native_framerate (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ BraseroDiscOptionDialogPrivate *priv;
+
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (dialog);
+ brasero_burn_session_tag_remove (priv->session,
+ BRASERO_VIDEO_OUTPUT_FRAMERATE);
+}
+
+static void
+brasero_disc_option_dialog_16_9 (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ brasero_disc_option_dialog_set_tag (dialog,
+ BRASERO_VIDEO_OUTPUT_ASPECT,
+ BRASERO_VIDEO_ASPECT_16_9);
+}
+
+static void
+brasero_disc_option_dialog_4_3 (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ brasero_disc_option_dialog_set_tag (dialog,
+ BRASERO_VIDEO_OUTPUT_ASPECT,
+ BRASERO_VIDEO_ASPECT_4_3);
+}
+
+static void
+brasero_disc_option_dialog_native_aspect (GtkToggleButton *button,
+ BraseroDiscOptionDialog *dialog)
+{
+ BraseroDiscOptionDialogPrivate *priv;
+
+ if (!gtk_toggle_button_get_active (button))
+ return;
+
+ priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (dialog);
+ brasero_burn_session_tag_remove (priv->session,
+ BRASERO_VIDEO_OUTPUT_ASPECT);
+}
+
+static void
+brasero_disc_option_dialog_add_video_options (BraseroDiscOptionDialog *dialog)
+{
+ GtkWidget *label;
+ GtkWidget *table;
+ GtkWidget *widget;
+ GtkWidget *button1;
+ GtkWidget *button2;
+ GtkWidget *button3;
+ GtkWidget *options;
+ BraseroDiscOptionDialogPrivate *priv;
+
+ priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (dialog);
+
+ widget = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+ widget,
+ FALSE,
+ FALSE,
+ 6);
+
+ table = gtk_table_new (3, 4, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 8);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_widget_show (table);
+
+ label = gtk_label_new (_("Video format:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 0, 1,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ button1 = gtk_radio_button_new_with_mnemonic (NULL,
+ _("_NTSC"));
+ gtk_widget_set_tooltip_text (button1, _("Format used mostly on the North American Continent"));
+ g_signal_connect (button1,
+ "toggled",
+ G_CALLBACK (brasero_disc_option_dialog_NTSC),
+ dialog);
+ gtk_table_attach (GTK_TABLE (table),
+ button1,
+ 3, 4,
+ 0, 1,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ button2 = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (button1),
+ _("_PAL/SECAM"));
+ gtk_widget_set_tooltip_text (button2, _("Format used mostly in Europe"));
+ g_signal_connect (button2,
+ "toggled",
+ G_CALLBACK (brasero_disc_option_dialog_PAL_SECAM),
+ dialog);
+ gtk_table_attach (GTK_TABLE (table),
+ button2,
+ 2, 3,
+ 0, 1,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ button3 = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (button1),
+ _("Native _format"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button3), TRUE);
+ g_signal_connect (button3,
+ "toggled",
+ G_CALLBACK (brasero_disc_option_dialog_native_framerate),
+ dialog);
+ gtk_table_attach (GTK_TABLE (table),
+ button3,
+ 1, 2,
+ 0, 1,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ label = gtk_label_new (_("Aspect ratio:"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 1, 2,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ button1 = gtk_radio_button_new_with_mnemonic (NULL,
+ _("_4:3"));
+ g_signal_connect (button1,
+ "toggled",
+ G_CALLBACK (brasero_disc_option_dialog_4_3),
+ dialog);
+ gtk_table_attach (GTK_TABLE (table),
+ button1,
+ 3, 4,
+ 1, 2,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ button2 = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (button1),
+ _("_16:9"));
+ g_signal_connect (button2,
+ "toggled",
+ G_CALLBACK (brasero_disc_option_dialog_16_9),
+ dialog);
+ gtk_table_attach (GTK_TABLE (table),
+ button2,
+ 2, 3,
+ 1, 2,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ button3 = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (button1),
+ _("Native aspect _ratio"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button3), TRUE);
+ g_signal_connect (button3,
+ "toggled",
+ G_CALLBACK (brasero_disc_option_dialog_native_aspect),
+ dialog);
+ gtk_table_attach (GTK_TABLE (table),
+ button3,
+ 1, 2,
+ 1, 2,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ /* Video options for (S)VCD */
+ label = gtk_label_new (_("VCD type:"));
+ priv->vcd_label = label;
+
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 2, 3,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ button1 = gtk_radio_button_new_with_mnemonic_from_widget (NULL, _("Create a SVCD"));
+ priv->svcd_button = button1;
+ gtk_table_attach (GTK_TABLE (table),
+ button1,
+ 1, 2,
+ 2, 3,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ g_signal_connect (button1,
+ "clicked",
+ G_CALLBACK (brasero_disc_option_dialog_SVCD),
+ dialog);
+
+ button2 = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (button1), _("Create a VCD"));
+ priv->vcd_button = button2;
+ gtk_table_attach (GTK_TABLE (table),
+ button2,
+ 2, 3,
+ 2, 3,
+ GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+
+ g_signal_connect (button2,
+ "clicked",
+ G_CALLBACK (brasero_disc_option_dialog_VCD),
+ dialog);
+
+ options = brasero_utils_pack_properties (_("<b>Video Options</b>"),
+ table,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (widget), options, FALSE, FALSE, 0);
+
+ /* Audio options for DVDs */
+ button1 = gtk_check_button_new_with_mnemonic (_("Add _AC3 audio stream"));
+ button2 = gtk_check_button_new_with_mnemonic (_("Add _MP2 audio stream"));
+ options = brasero_utils_pack_properties (_("<b>Audio Options</b>"),
+ button1,
+ button2,
+ NULL);
+ g_signal_connect (button1,
+ "clicked",
+ G_CALLBACK (brasero_disc_option_dialog_AC3),
+ dialog);
+ g_signal_connect (button2,
+ "clicked",
+ G_CALLBACK (brasero_disc_option_dialog_MP2),
+ dialog);
+
+ gtk_box_pack_start (GTK_BOX (widget), options, FALSE, FALSE, 0);
+ priv->dvd_audio = options;
+
+ gtk_widget_show_all (widget);
+ brasero_disc_option_dialog_update_video (dialog);
+
+ priv->video_options = widget;
+}
+
void
brasero_disc_option_dialog_set_disc (BraseroDiscOptionDialog *dialog,
BraseroDisc *disc)
@@ -802,15 +1254,23 @@
brasero_burn_session_get_input_type (priv->session, &type);
if (type.type == BRASERO_TRACK_TYPE_DATA) {
- brasero_drive_selection_set_type_shown (BRASERO_DRIVE_SELECTION (priv->selection),
- BRASERO_MEDIA_TYPE_WRITABLE|
- BRASERO_MEDIA_TYPE_FILE);
+ brasero_drive_selection_set_type_shown (BRASERO_DRIVE_SELECTION (priv->selection),
+ BRASERO_MEDIA_TYPE_WRITABLE|
+ BRASERO_MEDIA_TYPE_FILE);
brasero_disc_option_dialog_add_data_options (dialog);
}
else if (type.type == BRASERO_TRACK_TYPE_AUDIO) {
- brasero_drive_selection_set_type_shown (BRASERO_DRIVE_SELECTION (priv->selection),
- BRASERO_MEDIA_TYPE_WRITABLE);
- brasero_disc_option_dialog_add_audio_options (dialog);
+ if (type.subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|BRASERO_VIDEO_FORMAT_VCD|BRASERO_VIDEO_FORMAT_VIDEO_DVD)) {
+ brasero_drive_selection_set_type_shown (BRASERO_DRIVE_SELECTION (priv->selection),
+ BRASERO_MEDIA_TYPE_WRITABLE|
+ BRASERO_MEDIA_TYPE_FILE);
+ brasero_disc_option_dialog_add_video_options (dialog);
+ }
+ else {
+ brasero_drive_selection_set_type_shown (BRASERO_DRIVE_SELECTION (priv->selection),
+ BRASERO_MEDIA_TYPE_WRITABLE);
+ brasero_disc_option_dialog_add_audio_options (dialog);
+ }
}
}
@@ -823,6 +1283,9 @@
priv = BRASERO_DISC_OPTION_DIALOG_PRIVATE (self);
gtk_widget_set_sensitive (priv->button, valid);
+
+ if (priv->video_options)
+ gtk_widget_set_sensitive (priv->video_options, valid);
}
BraseroBurnSession *
Modified: trunk/src/brasero-disc.h
==============================================================================
--- trunk/src/brasero-disc.h (original)
+++ trunk/src/brasero-disc.h Mon Jul 14 18:07:55 2008
@@ -63,8 +63,9 @@
} BraseroDiscResult;
typedef enum {
- BRASERO_DISC_TRACK_NONE,
+ BRASERO_DISC_TRACK_NONE = 0,
BRASERO_DISC_TRACK_AUDIO,
+ BRASERO_DISC_TRACK_VIDEO,
BRASERO_DISC_TRACK_DATA,
} BraseroDiscTrackType;
Modified: trunk/src/brasero-file-chooser.c
==============================================================================
--- trunk/src/brasero-file-chooser.c (original)
+++ trunk/src/brasero-file-chooser.c Mon Jul 14 18:07:55 2008
@@ -68,6 +68,7 @@
GtkFileFilter *filter_any;
GtkFileFilter *filter_audio;
+ GtkFileFilter *filter_video;
};
static GObjectClass *parent_class = NULL;
@@ -234,6 +235,8 @@
gtk_file_filter_add_mime_type (filter, "application/x-flash-video");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (obj->priv->chooser), filter);
+ obj->priv->filter_video = filter;
+
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Image files only"));
gtk_file_filter_add_mime_type (filter, "image/*");
@@ -373,6 +376,9 @@
if (type == BRASERO_LAYOUT_AUDIO)
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (self->priv->chooser),
self->priv->filter_audio);
+ else if (type == BRASERO_LAYOUT_VIDEO)
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (self->priv->chooser),
+ self->priv->filter_video);
else
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (self->priv->chooser),
self->priv->filter_any);
Modified: trunk/src/brasero-io.c
==============================================================================
--- trunk/src/brasero-io.c (original)
+++ trunk/src/brasero-io.c Mon Jul 14 18:07:55 2008
@@ -628,6 +628,9 @@
g_file_info_set_attribute_boolean (info, BRASERO_IO_HAS_VIDEO, metadata->has_video);
g_file_info_set_attribute_boolean (info, BRASERO_IO_IS_SEEKABLE, metadata->is_seekable);
+ if (metadata->snapshot)
+ g_file_info_set_attribute_object (info, BRASERO_IO_SNAPSHOT, G_OBJECT (metadata->snapshot));
+
/* FIXME: what about silences */
}
@@ -668,10 +671,24 @@
cached = node->data;
last_modified = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
if (last_modified == cached->last_modified) {
- brasero_metadata_info_copy (meta_info, cached->info);
- return TRUE;
+ if (flags & BRASERO_METADATA_FLAG_SNAPHOT) {
+ /* If there isn't any snapshot retry */
+ if (cached->info->snapshot) {
+ brasero_metadata_info_copy (meta_info, cached->info);
+ return TRUE;
+ }
+ }
+ else {
+ brasero_metadata_info_copy (meta_info, cached->info);
+ return TRUE;
+ }
}
+ /* remove it from the queue since we can't keep the same
+ * URI twice */
+ brasero_metadata_info_free (node->data);
+ g_queue_remove (priv->meta_buffer, node->data);
+
BRASERO_BURN_LOG ("Updating cache information for %s", uri);
}
@@ -796,7 +813,8 @@
cancel,
uri,
info,
- (options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0,
+ ((options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0) |
+ ((options & BRASERO_IO_INFO_METADATA_SNAPSHOT) ? BRASERO_METADATA_FLAG_SNAPHOT : 0),
&metadata);
if (result)
@@ -1151,6 +1169,7 @@
child_uri,
info,
((data->job.options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0) |
+ ((data->job.options & BRASERO_IO_INFO_METADATA_SNAPSHOT) ? BRASERO_METADATA_FLAG_SNAPHOT : 0) |
BRASERO_METADATA_FLAG_FAST,
&metadata);
@@ -1186,7 +1205,8 @@
cancel,
child_uri,
info,
- (data->job.options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0,
+ ((data->job.options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0) |
+ ((data->job.options & BRASERO_IO_INFO_METADATA_SNAPSHOT) ? BRASERO_METADATA_FLAG_SNAPHOT : 0),
&metadata);
if (result)
data->total_b += metadata.len;
@@ -1481,6 +1501,7 @@
child_uri,
info,
((data->job.options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0) |
+ ((data->job.options & BRASERO_IO_INFO_METADATA_SNAPSHOT) ? BRASERO_METADATA_FLAG_SNAPHOT : 0) |
BRASERO_METADATA_FLAG_FAST,
&metadata);
@@ -1640,7 +1661,8 @@
cancel,
child_uri,
info,
- (data->job.options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0,
+ ((data->job.options & BRASERO_IO_INFO_METADATA_MISSING_CODEC) ? BRASERO_METADATA_FLAG_MISSING : 0) |
+ ((data->job.options & BRASERO_IO_INFO_METADATA_SNAPSHOT) ? BRASERO_METADATA_FLAG_SNAPHOT : 0),
&metadata);
if (result)
@@ -1679,7 +1701,7 @@
g_object_unref (child);
}
- if (data->job.callback_data->ref < 2) {
+ if (data->job.callback_data && data->job.callback_data->ref < 2) {
/* No result was returned so we need to return a dummy one to
* clean the callback_data in the main loop. */
brasero_io_return_result (BRASERO_IO (manager),
Modified: trunk/src/brasero-io.h
==============================================================================
--- trunk/src/brasero-io.h (original)
+++ trunk/src/brasero-io.h Mon Jul 14 18:07:55 2008
@@ -59,9 +59,10 @@
BRASERO_IO_INFO_ICON = 1,
BRASERO_IO_INFO_PERM = 1 << 1,
BRASERO_IO_INFO_METADATA = 1 << 2,
- BRASERO_IO_INFO_RECURSIVE = 1 << 3,
- BRASERO_IO_INFO_CHECK_PARENT_SYMLINK = 1 << 4,
- BRASERO_IO_INFO_METADATA_MISSING_CODEC = 1 << 5,
+ BRASERO_IO_INFO_METADATA_SNAPSHOT = 1 << 3,
+ BRASERO_IO_INFO_RECURSIVE = 1 << 4,
+ BRASERO_IO_INFO_CHECK_PARENT_SYMLINK = 1 << 5,
+ BRASERO_IO_INFO_METADATA_MISSING_CODEC = 1 << 6,
BRASERO_IO_INFO_URGENT = 1 << 9,
BRASERO_IO_INFO_IDLE = 1 << 10
@@ -83,12 +84,13 @@
#define BRASERO_IO_COUNT_SIZE "count::size"
#define BRASERO_IO_COUNT_INVALID "count::invalid"
+#define BRASERO_IO_SNAPSHOT "metadata::snapshot"
+
#define BRASERO_IO_LEN "metadata::length"
#define BRASERO_IO_ISRC "metadata::isrc"
#define BRASERO_IO_TITLE "metadata::title"
#define BRASERO_IO_ARTIST "metadata::artist"
#define BRASERO_IO_ALBUM "metadata::album"
-#define BRASERO_IO_ALBUM "metadata::album"
#define BRASERO_IO_GENRE "metadata::genre"
#define BRASERO_IO_COMPOSER "metadata::composer"
#define BRASERO_IO_HAS_AUDIO "metadata::has_audio"
Modified: trunk/src/brasero-layout.c
==============================================================================
--- trunk/src/brasero-layout.c (original)
+++ trunk/src/brasero-layout.c Mon Jul 14 18:07:55 2008
@@ -138,17 +138,29 @@
"F7", N_(BRASERO_LAYOUT_NONE_TOOLTIP), G_CALLBACK (brasero_layout_empty_toggled_cb), 1 }
};
-const gchar description [] = "<ui>"
- "<menubar name='menubar' >"
- "<menu action='ViewMenu'>"
- "<placeholder name='ViewPlaceholder'>"
+const GtkRadioActionEntry radio_entries [] = {
+ { "HView", NULL, N_("_Horizontal Layout"),
+ NULL, N_("Set an horizontal layout"), 0 },
+
+ { "VView", NULL, N_("_Vertical Layout"),
+ NULL, N_("Set a vertical layout"), 1 },
+};
+
+const gchar description [] =
+ "<ui>"
+ "<menubar name='menubar' >"
+ "<menu action='ViewMenu'>"
+ "<placeholder name='ViewPlaceholder'>"
"<menuitem action='"BRASERO_LAYOUT_NONE_ID"'/>"
"<menuitem action='"BRASERO_LAYOUT_PREVIEW_ID"'/>"
"<separator/>"
- "</placeholder>"
- "</menu>"
- "</menubar>"
- "</ui>";
+ "<menuitem action='VView'/>"
+ "<menuitem action='HView'/>"
+ "<separator/>"
+ "</placeholder>"
+ "</menu>"
+ "</menubar>"
+ "</ui>";
/* GCONF keys */
#define BRASERO_KEY_DISPLAY_LAYOUT "/apps/brasero/display/layout"
@@ -158,6 +170,7 @@
#define BRASERO_KEY_DISPLAY_DIR "/apps/brasero/display/"
#define BRASERO_KEY_LAYOUT_AUDIO BRASERO_KEY_DISPLAY_DIR "audio_pane"
#define BRASERO_KEY_LAYOUT_DATA BRASERO_KEY_DISPLAY_DIR "data_pane"
+#define BRASERO_KEY_LAYOUT_VIDEO BRASERO_KEY_DISPLAY_DIR "video_pane"
static void
brasero_layout_pack_preview (BraseroLayout *layout)
@@ -560,6 +573,10 @@
&& layout->priv->ctx_type == BRASERO_LAYOUT_DATA)
return;
+ if (!strcmp (entry->key, BRASERO_KEY_LAYOUT_VIDEO)
+ && layout->priv->ctx_type == BRASERO_LAYOUT_VIDEO)
+ return;
+
value = gconf_entry_get_value (entry);
if (value->type != GCONF_VALUE_STRING)
return;
@@ -643,6 +660,25 @@
NULL,
&error);
}
+ else if (layout->priv->ctx_type == BRASERO_LAYOUT_VIDEO) {
+ gconf_client_set_string (layout->priv->client,
+ BRASERO_KEY_LAYOUT_VIDEO,
+ id,
+ &error);
+
+ if (error) {
+ g_warning ("Can't set GConf key %s. \n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+
+ layout->priv->radio_notify = gconf_client_notify_add (layout->priv->client,
+ BRASERO_KEY_LAYOUT_VIDEO,
+ brasero_layout_displayed_item_changed_cb,
+ layout,
+ NULL,
+ &error);
+ }
if (error) {
g_warning ("Can't set GConf notify on key %s. \n", error->message);
@@ -801,6 +837,10 @@
layout_id = gconf_client_get_string (layout->priv->client,
BRASERO_KEY_LAYOUT_DATA,
&error);
+ else if (type == BRASERO_LAYOUT_VIDEO)
+ layout_id = gconf_client_get_string (layout->priv->client,
+ BRASERO_KEY_LAYOUT_VIDEO,
+ &error);
if (error) {
g_warning ("Can't access GConf key %s. This is probably harmless (first launch of brasero).\n", error->message);
@@ -823,6 +863,13 @@
layout,
NULL,
&error);
+ else if (type == BRASERO_LAYOUT_VIDEO)
+ layout->priv->radio_notify = gconf_client_notify_add (layout->priv->client,
+ BRASERO_KEY_LAYOUT_VIDEO,
+ brasero_layout_displayed_item_changed_cb,
+ layout,
+ NULL,
+ &error);
if (error) {
g_warning ("Could not set notify for GConf key %s.\n", error->message);
@@ -903,47 +950,39 @@
}
static void
-brasero_layout_type_changed_cb (GConfClient *client,
- guint cxn,
- GConfEntry *entry,
- gpointer data)
+brasero_layout_change_type (BraseroLayout *layout,
+ BraseroLayoutType layout_type)
{
- GConfValue *value;
- GtkWidget *source_pane;
- GtkWidget *project_pane;
- BraseroLayoutType layout_type;
- BraseroLayout *layout = BRASERO_LAYOUT (data);
+ GtkWidget *source_pane = NULL;
+ GtkWidget *project_pane = NULL;
- value = gconf_entry_get_value (entry);
- if (value->type != GCONF_VALUE_INT)
- return;
-
- g_object_ref (layout->priv->preview_pane);
- if (layout->priv->layout_type == BRASERO_LAYOUT_BOTTOM)
- gtk_container_remove (GTK_CONTAINER (layout->priv->project), layout->priv->preview_pane);
- else
- gtk_container_remove (GTK_CONTAINER (layout->priv->main_box), layout->priv->preview_pane);
+ if (layout->priv->pane) {
+ g_object_ref (layout->priv->preview_pane);
+ if (layout->priv->layout_type == BRASERO_LAYOUT_BOTTOM)
+ gtk_container_remove (GTK_CONTAINER (layout->priv->project), layout->priv->preview_pane);
+ else
+ gtk_container_remove (GTK_CONTAINER (layout->priv->main_box), layout->priv->preview_pane);
- if (layout->priv->layout_type == BRASERO_LAYOUT_TOP
- || layout->priv->layout_type == BRASERO_LAYOUT_LEFT) {
- project_pane = gtk_paned_get_child1 (GTK_PANED (layout->priv->pane));
- source_pane = gtk_paned_get_child2 (GTK_PANED (layout->priv->pane));
- }
- else {
- source_pane = gtk_paned_get_child1 (GTK_PANED (layout->priv->pane));
- project_pane = gtk_paned_get_child2 (GTK_PANED (layout->priv->pane));
- }
+ if (layout->priv->layout_type == BRASERO_LAYOUT_TOP
+ || layout->priv->layout_type == BRASERO_LAYOUT_LEFT) {
+ project_pane = gtk_paned_get_child1 (GTK_PANED (layout->priv->pane));
+ source_pane = gtk_paned_get_child2 (GTK_PANED (layout->priv->pane));
+ }
+ else {
+ source_pane = gtk_paned_get_child1 (GTK_PANED (layout->priv->pane));
+ project_pane = gtk_paned_get_child2 (GTK_PANED (layout->priv->pane));
+ }
- g_object_ref (source_pane);
- gtk_container_remove (GTK_CONTAINER (layout->priv->pane), source_pane);
+ g_object_ref (source_pane);
+ gtk_container_remove (GTK_CONTAINER (layout->priv->pane), source_pane);
- g_object_ref (project_pane);
- gtk_container_remove (GTK_CONTAINER (layout->priv->pane), project_pane);
+ g_object_ref (project_pane);
+ gtk_container_remove (GTK_CONTAINER (layout->priv->pane), project_pane);
- gtk_widget_destroy (layout->priv->pane);
- layout->priv->pane = NULL;
+ gtk_widget_destroy (layout->priv->pane);
+ layout->priv->pane = NULL;
+ }
- layout_type = gconf_value_get_int (value);
if (layout_type > BRASERO_LAYOUT_BOTTOM
|| layout_type < BRASERO_LAYOUT_RIGHT)
layout_type = BRASERO_LAYOUT_RIGHT;
@@ -966,39 +1005,123 @@
gtk_widget_show (layout->priv->pane);
gtk_box_pack_end (GTK_BOX (layout), layout->priv->pane, TRUE, TRUE, 0);
- switch (layout_type) {
- case BRASERO_LAYOUT_TOP:
- case BRASERO_LAYOUT_LEFT:
- gtk_paned_pack2 (GTK_PANED (layout->priv->pane), source_pane, TRUE, FALSE);
- gtk_paned_pack1 (GTK_PANED (layout->priv->pane), project_pane, TRUE, FALSE);
- break;
-
- case BRASERO_LAYOUT_BOTTOM:
- case BRASERO_LAYOUT_RIGHT:
- gtk_paned_pack2 (GTK_PANED (layout->priv->pane), project_pane, TRUE, FALSE);
- gtk_paned_pack1 (GTK_PANED (layout->priv->pane), source_pane, TRUE, FALSE);
- break;
-
- default:
- break;
- }
-
g_signal_connect (layout->priv->pane,
"notify::position",
G_CALLBACK (brasero_layout_pane_moved_cb),
layout);
layout->priv->layout_type = layout_type;
- g_object_unref (project_pane);
- g_object_unref (source_pane);
- brasero_layout_pack_preview (layout);
- g_object_unref (layout->priv->preview_pane);
+ if (source_pane && project_pane) {
+ switch (layout_type) {
+ case BRASERO_LAYOUT_TOP:
+ case BRASERO_LAYOUT_LEFT:
+ gtk_paned_pack2 (GTK_PANED (layout->priv->pane), source_pane, TRUE, FALSE);
+ gtk_paned_pack1 (GTK_PANED (layout->priv->pane), project_pane, TRUE, FALSE);
+ break;
+
+ case BRASERO_LAYOUT_BOTTOM:
+ case BRASERO_LAYOUT_RIGHT:
+ gtk_paned_pack1 (GTK_PANED (layout->priv->pane), source_pane, TRUE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (layout->priv->pane), project_pane, TRUE, FALSE);
+ break;
+
+ default:
+ break;
+ }
+
+ g_object_unref (project_pane);
+ g_object_unref (source_pane);
+ }
+
+ if (layout->priv->preview_pane) {
+ brasero_layout_pack_preview (layout);
+ g_object_unref (layout->priv->preview_pane);
+ }
brasero_layout_size_reallocate (layout);
}
static void
+brasero_layout_HV_radio_button_toggled_cb (GtkRadioAction *radio,
+ GtkRadioAction *current,
+ BraseroLayout *layout);
+
+static void
+brasero_layout_type_changed_cb (GConfClient *client,
+ guint cxn,
+ GConfEntry *entry,
+ gpointer data)
+{
+ GSList *iter;
+ GSList *radios;
+ GtkAction *action;
+ GConfValue *value;
+ BraseroLayoutType layout_type;
+ BraseroLayout *layout = BRASERO_LAYOUT (data);
+
+ value = gconf_entry_get_value (entry);
+ if (value->type != GCONF_VALUE_INT)
+ return;
+
+ layout_type = gconf_value_get_int (value);
+ brasero_layout_change_type (layout, layout_type);
+
+ /* make sure our radio actions reflect the change */
+ action = gtk_action_group_get_action (layout->priv->action_group, "HView");
+
+ radios = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
+ for (iter = radios; iter; iter = iter->next)
+ g_signal_handlers_block_by_func (iter->data,
+ brasero_layout_HV_radio_button_toggled_cb,
+ layout);
+
+ gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action),
+ GTK_IS_VPANED (layout->priv->pane));
+
+ for (iter = radios; iter; iter = iter->next)
+ g_signal_handlers_unblock_by_func (iter->data,
+ brasero_layout_HV_radio_button_toggled_cb,
+ layout);
+
+ g_slist_free (radios);
+}
+
+static void
+brasero_layout_HV_radio_button_toggled_cb (GtkRadioAction *radio,
+ GtkRadioAction *current,
+ BraseroLayout *layout)
+{
+ guint layout_type;
+
+ if (gtk_radio_action_get_current_value (current))
+ layout_type = BRASERO_LAYOUT_BOTTOM;
+ else
+ layout_type = BRASERO_LAYOUT_RIGHT;
+
+ brasero_layout_change_type (layout, layout_type);
+
+ /* update the GConf key */
+ gconf_client_notify_remove (layout->priv->client,
+ layout->priv->layout_notify);
+ layout->priv->layout_notify = 0;
+
+ gconf_client_set_int (layout->priv->client,
+ BRASERO_KEY_DISPLAY_LAYOUT,
+ layout_type,
+ NULL);
+
+ /* This is to avoid a notification for change */
+ gconf_client_clear_cache (layout->priv->client);
+ layout->priv->layout_notify = gconf_client_notify_add (layout->priv->client,
+ BRASERO_KEY_DISPLAY_LAYOUT,
+ brasero_layout_type_changed_cb,
+ layout,
+ NULL,
+ NULL);
+}
+
+static void
brasero_layout_close_button_clicked_cb (GtkWidget *button,
BraseroLayout *layout)
{
@@ -1184,6 +1307,14 @@
gtk_widget_show (obj->priv->pane);
gtk_box_pack_end (GTK_BOX (obj), obj->priv->pane, TRUE, TRUE, 0);
+ /* reflect that layout in the menus */
+ gtk_action_group_add_radio_actions (obj->priv->action_group,
+ radio_entries,
+ sizeof (radio_entries) / sizeof (GtkRadioActionEntry),
+ GTK_IS_VPANED (obj->priv->pane),
+ G_CALLBACK (brasero_layout_HV_radio_button_toggled_cb),
+ obj);
+
/* remember the position */
position = gconf_client_get_int (obj->priv->client,
BRASERO_KEY_DISPLAY_POSITION,
Modified: trunk/src/brasero-layout.h
==============================================================================
--- trunk/src/brasero-layout.h (original)
+++ trunk/src/brasero-layout.h Mon Jul 14 18:07:55 2008
@@ -50,6 +50,7 @@
BRASERO_LAYOUT_NONE = 0,
BRASERO_LAYOUT_AUDIO = 1,
BRASERO_LAYOUT_DATA = 1 << 1,
+ BRASERO_LAYOUT_VIDEO = 1 << 2
} BraseroLayoutType;
typedef struct {
Modified: trunk/src/brasero-metadata.c
==============================================================================
--- trunk/src/brasero-metadata.c (original)
+++ trunk/src/brasero-metadata.c Mon Jul 14 18:07:55 2008
@@ -32,6 +32,8 @@
#include <glib/gi18n-lib.h>
#include <glib-object.h>
+#include <gdk/gdkpixbuf.h>
+
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#include <gst/pbutils/install-plugins.h>
@@ -42,6 +44,8 @@
#include "brasero-utils.h"
#include "burn-debug.h"
+#define BRASERO_METADATA_INITIAL_STATE GST_STATE_PAUSED
+
G_DEFINE_TYPE(BraseroMetadata, brasero_metadata, G_TYPE_OBJECT)
@@ -54,7 +58,11 @@
GstElement *convert;
GstElement *level;
GstElement *sink;
- GstElement *first;
+
+ GstElement *audio;
+ GstElement *video;
+
+ GstElement *snapshot;
GMainLoop *loop;
GError *error;
@@ -77,6 +85,9 @@
guint started:1;
guint moved_forward:1;
guint prev_level_mes:1;
+ guint video_linked:1;
+ guint audio_linked:1;
+ guint snapshot_started:1;
};
typedef struct BraseroMetadataPrivate BraseroMetadataPrivate;
#define BRASERO_METADATA_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), BRASERO_TYPE_METADATA, BraseroMetadataPrivate))
@@ -117,6 +128,11 @@
if (!info)
return;
+ if (info->snapshot) {
+ g_object_unref (info->snapshot);
+ info->snapshot = NULL;
+ }
+
if (info->uri)
g_free (info->uri);
@@ -225,6 +241,26 @@
}
}
+static gboolean
+brasero_metadata_completed (BraseroMetadata *self)
+{
+ BraseroMetadataPrivate *priv;
+
+ priv = BRASERO_METADATA_PRIVATE (self);
+ if ((!priv->loop || !g_main_loop_is_running (priv->loop)) && !priv->cond) {
+ /* we send a message only if we haven't got a loop (= async mode) */
+ g_object_ref (self);
+ g_signal_emit (G_OBJECT (self),
+ brasero_metadata_signals [COMPLETED_SIGNAL],
+ 0,
+ priv->error);
+ g_object_unref (self);
+ }
+
+ brasero_metadata_stop (self);
+ return TRUE;
+}
+
static gint
brasero_metadata_report_progress (BraseroMetadata *self)
{
@@ -250,6 +286,42 @@
return TRUE;
}
+static gboolean
+brasero_metadata_thumbnail (BraseroMetadata *self)
+{
+ BraseroMetadataPrivate *priv;
+ gint64 position;
+ gboolean res;
+
+ priv = BRASERO_METADATA_PRIVATE (self);
+
+ /* find the right position and move forward */
+ position = 15 * GST_SECOND;
+ while (position >= priv->info->len)
+ position -= 5 * GST_SECOND;
+
+ gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+
+ priv->snapshot_started = 1;
+ if (position < GST_SECOND)
+ position = GST_SECOND;
+
+ res = gst_element_seek_simple (priv->pipeline,
+ GST_FORMAT_TIME,
+ GST_SEEK_FLAG_FLUSH,
+ position);
+
+ BRASERO_BURN_LOG ("Seeking forward %i for %s", res, priv->info->uri);
+ if (!res)
+ return brasero_metadata_completed (self);
+
+ g_object_set (priv->snapshot,
+ "send-messages", TRUE,
+ NULL);
+
+ return TRUE;
+}
+
static void
brasero_metadata_is_seekable (BraseroMetadata *self)
{
@@ -338,26 +410,6 @@
return FALSE;
}
-static gboolean
-brasero_metadata_completed (BraseroMetadata *self)
-{
- BraseroMetadataPrivate *priv;
-
- priv = BRASERO_METADATA_PRIVATE (self);
- if ((!priv->loop || !g_main_loop_is_running (priv->loop)) && !priv->cond) {
- /* we send a message only if we haven't got a loop (= async mode) */
- g_object_ref (self);
- g_signal_emit (G_OBJECT (self),
- brasero_metadata_signals [COMPLETED_SIGNAL],
- 0,
- priv->error);
- g_object_unref (self);
- }
-
- brasero_metadata_stop (self);
- return TRUE;
-}
-
static void
foreach_tag (const GstTagList *list,
const gchar *tag,
@@ -436,6 +488,8 @@
priv = BRASERO_METADATA_PRIVATE (self);
+ BRASERO_BURN_LOG ("Metadata retrieval successfully completed for %s", priv->info->uri);
+
/* find the type of the file */
brasero_metadata_get_mime_type (self);
@@ -461,7 +515,7 @@
return brasero_metadata_completed (self);
}
- BRASERO_BURN_LOG ("found duration %lli", duration);
+ BRASERO_BURN_LOG ("found duration %lli for %s", duration, priv->info->uri);
priv->info->len = duration;
@@ -477,6 +531,12 @@
/* empty the bus of any pending message */
brasero_metadata_process_pending_tag_messages (self);
+ /* before leaving, check if we need a snapshot */
+ if (priv->snapshot
+ && priv->video_linked
+ && !priv->snapshot_started)
+ return brasero_metadata_thumbnail (self);
+
return brasero_metadata_completed (self);
}
@@ -735,10 +795,27 @@
priv = BRASERO_METADATA_PRIVATE (self);
switch (GST_MESSAGE_TYPE (msg)) {
+ case GST_MESSAGE_ASYNC_DONE:
+ BRASERO_BURN_LOG ("Async state change done for %s", priv->info->uri);
+ break;
case GST_MESSAGE_ELEMENT:
+ if (!strcmp (gst_structure_get_name (msg->structure), "preroll-pixbuf")
+ || !strcmp (gst_structure_get_name (msg->structure), "pixbuf")) {
+ const GValue *value;
+
+ value = gst_structure_get_value (msg->structure, "pixbuf");
+ priv->info->snapshot = g_value_get_object (value);
+ g_object_ref (priv->info->snapshot);
+
+ BRASERO_BURN_LOG ("Received pixbuf snapshot sink (%p) for %s", priv->info->snapshot, priv->info->uri);
+
+ /* Now we can stop */
+ brasero_metadata_completed (self);
+ return TRUE;
+ }
/* here we just want to check if that's a missing codec */
- if ((priv->flags & BRASERO_METADATA_FLAG_MISSING)
- && gst_is_missing_plugin_message (msg))
+ else if ((priv->flags & BRASERO_METADATA_FLAG_MISSING)
+ && gst_is_missing_plugin_message (msg))
priv->missing_plugins = g_slist_prepend (priv->missing_plugins, gst_message_ref (msg));
else if (!strcmp (gst_structure_get_name (msg->structure), "level")
&& gst_structure_has_field (msg->structure, "peak")) {
@@ -810,6 +887,7 @@
break;
case GST_MESSAGE_EOS:
+ BRASERO_BURN_LOG ("End of stream reached for %s", priv->info->uri);
brasero_metadata_success (self);
break;
@@ -825,6 +903,7 @@
&newstate,
NULL,
0);
+
if (result != GST_STATE_CHANGE_SUCCESS)
break;
@@ -872,6 +951,109 @@
return TRUE;
}
+static gboolean
+brasero_metadata_create_audio_pipeline (BraseroMetadata *self)
+{
+ BraseroMetadataPrivate *priv;
+ GstPad *audio_pad;
+
+ priv = BRASERO_METADATA_PRIVATE (self);
+
+ priv->audio = gst_bin_new (NULL);
+
+ /* set up the pipeline according to flags */
+ if (priv->flags & BRASERO_METADATA_FLAG_SILENCES) {
+ priv->prev_level_mes = 0;
+ gst_object_ref (priv->convert);
+ gst_object_ref (priv->level);
+ gst_object_ref (priv->sink);
+
+ gst_bin_add_many (GST_BIN (priv->audio),
+ priv->convert,
+ priv->level,
+ priv->sink,
+ NULL);
+ gst_element_link_many (priv->convert,
+ priv->level,
+ priv->sink,
+ NULL);
+ audio_pad = gst_element_get_static_pad (priv->convert, "sink");
+ }
+ else if (priv->flags & BRASERO_METADATA_FLAG_SNAPHOT) {
+ GstElement *queue;
+
+ queue = gst_element_factory_make ("queue", NULL);
+ gst_object_ref (priv->convert);
+ gst_object_ref (priv->sink);
+
+ gst_bin_add_many (GST_BIN (priv->audio),
+ queue,
+ priv->convert,
+ priv->sink,
+ NULL);
+ gst_element_link_many (queue,
+ priv->convert,
+ priv->sink,
+ NULL);
+ audio_pad = gst_element_get_static_pad (queue, "sink");
+ }
+ else {
+ gst_object_ref (priv->sink);
+ gst_bin_add (GST_BIN (priv->audio), priv->sink);
+ audio_pad = gst_element_get_static_pad (priv->sink, "sink");
+ }
+
+ gst_element_add_pad (priv->audio, gst_ghost_pad_new ("sink", audio_pad));
+ gst_object_unref (audio_pad);
+
+ gst_bin_add (GST_BIN (priv->pipeline), priv->audio);
+ BRASERO_BURN_LOG ("Adding audio pipeline for %s", priv->info->uri);
+
+ return TRUE;
+}
+
+static gboolean
+brasero_metadata_create_video_pipeline (BraseroMetadata *self)
+{
+ BraseroMetadataPrivate *priv;
+ GstElement *colorspace;
+ GstPad *video_pad;
+ GstElement *queue;
+
+ priv = BRASERO_METADATA_PRIVATE (self);
+
+ priv->video = gst_bin_new (NULL);
+
+ priv->snapshot = gst_element_factory_make ("gdkpixbufsink", NULL);
+ colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+ queue = gst_element_factory_make ("queue", NULL);
+
+ g_object_set (priv->snapshot,
+ "qos", FALSE,
+ "send-messages", FALSE,
+ "max-lateness", (gint64) - 1,
+ NULL);
+
+ gst_bin_add_many (GST_BIN (priv->video),
+ queue,
+ colorspace,
+ priv->snapshot,
+ NULL);
+ gst_element_link_many (queue,
+ colorspace,
+ priv->snapshot,
+ NULL);
+
+ video_pad = gst_element_get_static_pad (queue, "sink");
+ gst_element_add_pad (priv->video, gst_ghost_pad_new ("sink", video_pad));
+ gst_object_unref (video_pad);
+
+ gst_bin_add (GST_BIN (priv->pipeline), priv->video);
+ BRASERO_BURN_LOG ("Adding pixbuf snapshot sink for %s", priv->info->uri);
+
+ return TRUE;
+}
+
static void
brasero_metadata_new_decoded_pad_cb (GstElement *decode,
GstPad *pad,
@@ -880,6 +1062,9 @@
{
GstPad *sink;
GstCaps *caps;
+ const gchar *name;
+ gboolean has_audio;
+ gboolean has_video;
GstPadLinkReturn res;
GstStructure *structure;
BraseroMetadataPrivate *priv;
@@ -887,26 +1072,55 @@
priv = BRASERO_METADATA_PRIVATE (self);
res = GST_PAD_LINK_REFUSED;
- BRASERO_BURN_LOG ("new pad");
- sink = gst_element_get_pad (priv->first, "sink");
- if (!sink || GST_PAD_IS_LINKED (sink))
- return;
+
+ BRASERO_BURN_LOG ("New pad for %s", priv->info->uri);
/* make sure that this is audio / video */
caps = gst_pad_get_caps (pad);
structure = gst_caps_get_structure (caps, 0);
- if (structure) {
- const gchar *name;
+ if (!structure)
+ return;
+
+ name = gst_structure_get_name (structure);
+ has_audio = (g_strrstr (name, "audio") != NULL);
+ has_video = (g_strrstr (name, "video") != NULL);
+
+ priv->info->has_audio |= has_audio;
+ priv->info->has_video |= has_video;
+
+ if (has_audio && !priv->audio_linked) {
+ brasero_metadata_create_audio_pipeline (self);
+ sink = gst_element_get_static_pad (priv->audio, "sink");
+ if (sink && !GST_PAD_IS_LINKED (sink)) {
+ res = gst_pad_link (pad, sink);
+ BRASERO_BURN_LOG ("Audio stream link %i for %s", res, priv->info->uri);
+ gst_object_unref (sink);
- name = gst_structure_get_name (structure);
- priv->info->has_audio = (g_strrstr (name, "audio") != NULL);
- priv->info->has_video = (g_strrstr (name, "video") != NULL);
+ priv->audio_linked = (res == GST_PAD_LINK_OK);
+ gst_element_set_state (priv->audio, BRASERO_METADATA_INITIAL_STATE);
+ }
+ }
+
+ if (g_strrstr (name, "video/x-raw-") && !priv->video_linked) {
+ if (priv->flags & BRASERO_METADATA_FLAG_SNAPHOT) {
+ brasero_metadata_create_video_pipeline (self);
+ sink = gst_element_get_static_pad (priv->video, "sink");
+ if (!sink || GST_PAD_IS_LINKED (sink)) {
+ gst_object_unref (sink);
+ gst_caps_unref (caps);
+ return;
+ }
- if (priv->info->has_audio || priv->info->has_video)
res = gst_pad_link (pad, sink);
+ priv->video_linked = (res == GST_PAD_LINK_OK);
+ gst_object_unref (sink);
+
+ gst_element_set_state (priv->video, BRASERO_METADATA_INITIAL_STATE);
+
+ BRASERO_BURN_LOG ("Video stream link %i for %s", res, priv->info->uri);
+ }
}
- gst_object_unref (sink);
gst_caps_unref (caps);
}
@@ -940,6 +1154,7 @@
"Can't create audioconvert");
return FALSE;
}
+ gst_object_ref (priv->convert);
priv->level = gst_element_factory_make ("level", NULL);
if (!priv->level) {
@@ -948,6 +1163,7 @@
"Can't create level");
return FALSE;
}
+ gst_object_ref (priv->level);
g_object_set (priv->level,
"message", TRUE,
"interval", (guint64) BRASERO_METADATA_SILENCE_INTERVAL,
@@ -960,7 +1176,7 @@
"Can't create fake sink");
return FALSE;
}
- gst_bin_add (GST_BIN (priv->pipeline), priv->sink);
+ gst_object_ref (priv->sink);
return TRUE;
}
@@ -974,6 +1190,8 @@
priv = BRASERO_METADATA_PRIVATE (self);
+ BRASERO_BURN_LOG ("New retrieval for %s", uri);
+
brasero_metadata_info_free (priv->info);
priv->info = NULL;
@@ -996,6 +1214,17 @@
gst_bin_remove (GST_BIN (priv->pipeline), priv->source);
priv->source = NULL;
}
+
+ if (priv->audio) {
+ gst_bin_remove (GST_BIN (priv->pipeline), priv->audio);
+ priv->audio = NULL;
+ }
+
+ if (priv->video) {
+ gst_bin_remove (GST_BIN (priv->pipeline), priv->video);
+ priv->snapshot = NULL;
+ priv->video = NULL;
+ }
}
else if (!brasero_metadata_create_pipeline (self))
return FALSE;
@@ -1003,36 +1232,9 @@
if (!gst_uri_is_valid (uri))
return FALSE;
- /* set up the pipeline according to flags */
- if (priv->flags & BRASERO_METADATA_FLAG_SILENCES) {
- priv->prev_level_mes = 0;
- if (priv->first != priv->convert) {
- gst_bin_add_many (GST_BIN (priv->pipeline),
- priv->convert,
- priv->level,
- NULL);
- gst_element_link_many (priv->convert,
- priv->level,
- priv->sink,
- NULL);
-
- priv->first = priv->convert;
- }
- }
- else {
- if (priv->first == priv->convert) {
- gst_object_ref (priv->convert);
- gst_object_ref (priv->level);
-
- gst_bin_remove_many (GST_BIN (priv->pipeline),
- priv->convert,
- priv->level,
- NULL);
- }
-
- if (priv->first != priv->sink)
- priv->first = priv->sink;
- }
+ priv->video_linked = 0;
+ priv->audio_linked = 0;
+ priv->snapshot_started = 0;
/* create a necessary source */
priv->source = gst_element_make_from_uri (GST_URI_SRC,
@@ -1113,7 +1315,7 @@
}
priv->started = 1;
- gst_element_set_state (GST_ELEMENT (priv->pipeline), GST_STATE_PLAYING);
+ gst_element_set_state (GST_ELEMENT (priv->pipeline), BRASERO_METADATA_INITIAL_STATE);
g_cond_wait (priv->cond, priv->mutex);
g_mutex_unlock (priv->mutex);
@@ -1159,7 +1361,7 @@
}
priv->started = 1;
- gst_element_set_state (GST_ELEMENT (priv->pipeline), GST_STATE_PLAYING);
+ gst_element_set_state (GST_ELEMENT (priv->pipeline), BRASERO_METADATA_INITIAL_STATE);
/* run the loop until it's finished */
priv->loop = g_main_loop_new (NULL, FALSE);
@@ -1211,7 +1413,7 @@
}
priv->started = 1;
- gst_element_set_state (GST_ELEMENT (priv->pipeline), GST_STATE_PLAYING);
+ gst_element_set_state (GST_ELEMENT (priv->pipeline), BRASERO_METADATA_INITIAL_STATE);
return TRUE;
}
@@ -1252,6 +1454,11 @@
if (src->musicbrainz_id)
dest->musicbrainz_id = g_strdup (src->musicbrainz_id);
+ if (src->snapshot) {
+ dest->snapshot = src->snapshot;
+ g_object_ref (dest->snapshot);
+ }
+
for (iter = src->silences; iter; iter = iter->next) {
BraseroMetadataSilence *silence, *copy;
@@ -1336,16 +1543,34 @@
if (change == GST_STATE_CHANGE_FAILURE)
g_warning ("State change failure\n");
+ if (priv->audio) {
+ gst_bin_remove (GST_BIN (priv->pipeline), priv->audio);
+ priv->audio = NULL;
+ }
+
+ if (priv->video) {
+ gst_bin_remove (GST_BIN (priv->pipeline), priv->video);
+ priv->snapshot = NULL;
+ priv->video = NULL;
+ }
+
gst_object_unref (GST_OBJECT (priv->pipeline));
priv->pipeline = NULL;
- if (priv->first == priv->sink) {
- gst_object_unref (GST_OBJECT (priv->convert));
- priv->convert = NULL;
-
+ if (priv->level) {
gst_object_unref (GST_OBJECT (priv->level));
priv->level = NULL;
}
+
+ if (priv->sink) {
+ gst_object_unref (GST_OBJECT (priv->sink));
+ priv->sink = NULL;
+ }
+
+ if (priv->convert) {
+ gst_object_unref (GST_OBJECT (priv->convert));
+ priv->convert = NULL;
+ }
}
static void
Modified: trunk/src/brasero-metadata.h
==============================================================================
--- trunk/src/brasero-metadata.h (original)
+++ trunk/src/brasero-metadata.h Mon Jul 14 18:07:55 2008
@@ -29,6 +29,8 @@
#include <glib-object.h>
#include <gio/gio.h>
+#include <gdk/gdkpixbuf.h>
+
#include <gst/gst.h>
G_BEGIN_DECLS
@@ -37,7 +39,8 @@
BRASERO_METADATA_FLAG_NONE = 0,
BRASERO_METADATA_FLAG_FAST = 1,
BRASERO_METADATA_FLAG_SILENCES = 1 << 1,
- BRASERO_METADATA_FLAG_MISSING = 1 << 2
+ BRASERO_METADATA_FLAG_MISSING = 1 << 2,
+ BRASERO_METADATA_FLAG_SNAPHOT = 1 << 3
} BraseroMetadataFlag;
#define BRASERO_TYPE_METADATA (brasero_metadata_get_type ())
@@ -66,6 +69,8 @@
GSList *silences;
+ GdkPixbuf *snapshot;
+
guint is_seekable:1;
guint has_audio:1;
guint has_video:1;
Modified: trunk/src/brasero-multi-song-props.c
==============================================================================
--- trunk/src/brasero-multi-song-props.c (original)
+++ trunk/src/brasero-multi-song-props.c Mon Jul 14 18:07:55 2008
@@ -42,6 +42,8 @@
GtkWidget *artist;
GtkWidget *composer;
GtkWidget *isrc;
+
+ GtkWidget *gap_box;
GtkWidget *gap;
};
@@ -169,6 +171,18 @@
return FALSE;
}
+void
+brasero_multi_song_props_set_show_gap (BraseroMultiSongProps *self,
+ gboolean show)
+{
+ BraseroMultiSongPropsPrivate *priv;
+
+ priv = BRASERO_MULTI_SONG_PROPS_PRIVATE (self);
+ if (show)
+ gtk_widget_show (priv->gap_box);
+ else
+ gtk_widget_hide (priv->gap_box);
+}
static void
brasero_multi_song_props_init (BraseroMultiSongProps *object)
@@ -280,6 +294,8 @@
gtk_widget_show (box);
frame = brasero_utils_pack_properties (_("<b>Options</b>"), box, NULL);
+ priv->gap_box = frame;
+
gtk_widget_show (frame);
gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), frame, FALSE, FALSE, 0);
Modified: trunk/src/brasero-multi-song-props.h
==============================================================================
--- trunk/src/brasero-multi-song-props.h (original)
+++ trunk/src/brasero-multi-song-props.h Mon Jul 14 18:07:55 2008
@@ -56,7 +56,11 @@
brasero_multi_song_props_new (void);
void
-brasero_multi_song_props_set_rename_callback (BraseroMultiSongProps *self,
+brasero_multi_song_props_set_show_gap (BraseroMultiSongProps *props,
+ gboolean show);
+
+void
+brasero_multi_song_props_set_rename_callback (BraseroMultiSongProps *props,
GtkTreeSelection *selection,
gint column_num,
BraseroRenameCallback callback);
Modified: trunk/src/brasero-project-manager.c
==============================================================================
--- trunk/src/brasero-project-manager.c (original)
+++ trunk/src/brasero-project-manager.c Mon Jul 14 18:07:55 2008
@@ -86,6 +86,8 @@
static void
brasero_project_manager_new_data_prj_cb (GtkAction *action, BraseroProjectManager *manager);
static void
+brasero_project_manager_new_video_prj_cb (GtkAction *action, BraseroProjectManager *manager);
+static void
brasero_project_manager_new_copy_prj_cb (GtkAction *action, BraseroProjectManager *manager);
static void
brasero_project_manager_new_iso_prj_cb (GtkAction *action, BraseroProjectManager *manager);
@@ -115,6 +117,8 @@
N_("Create a new audio project"), G_CALLBACK (brasero_project_manager_new_audio_prj_cb)},
{"NewData", "media-optical-data-new", N_("New _Data Project"), NULL,
N_("Create a new data project"), G_CALLBACK (brasero_project_manager_new_data_prj_cb)},
+ {"NewVideo", "media-optical-video-new", N_("New _Video Project"), NULL,
+ N_("Create a new video project"), G_CALLBACK (brasero_project_manager_new_video_prj_cb)},
{"NewCopy", "media-optical-copy", N_("Copy _Disc..."), NULL,
N_("Copy a disc"), G_CALLBACK (brasero_project_manager_new_copy_prj_cb)},
{"NewIso", "iso-image-burn", N_("_Burn Image..."), NULL,
@@ -132,6 +136,7 @@
"<menu action='New'>"
"<menuitem action='NewAudio'/>"
"<menuitem action='NewData'/>"
+ "<menuitem action='NewVideo'/>"
"<menuitem action='NewCopy'/>"
"<menuitem action='NewIso'/>"
"</menu>"
@@ -516,7 +521,8 @@
GtkAction *action;
if ((manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO
- || manager->priv->type == BRASERO_PROJECT_TYPE_DATA)
+ || manager->priv->type == BRASERO_PROJECT_TYPE_DATA
+ || manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO)
&& !brasero_project_confirm_switch (BRASERO_PROJECT (manager->priv->project)))
return;
@@ -566,6 +572,20 @@
if (toplevel)
gtk_window_set_title (GTK_WINDOW (toplevel), _("Brasero - New Data Disc Project"));
}
+ else if (type == BRASERO_PROJECT_TYPE_VIDEO) {
+ brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_VIDEO);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (manager), 1);
+ gtk_action_set_sensitive (action, TRUE);
+
+ if (reset) {
+ /* tell the BraseroProject object that we want a data selection */
+ brasero_project_set_video (BRASERO_PROJECT (manager->priv->project), uris);
+ }
+
+ if (toplevel)
+ gtk_window_set_title (GTK_WINDOW (toplevel), _("Brasero - New Video disc project"));
+ }
else if (type == BRASERO_PROJECT_TYPE_ISO) {
brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_NONE);
brasero_project_set_none (BRASERO_PROJECT (manager->priv->project));
@@ -618,6 +638,12 @@
}
static void
+brasero_project_manager_new_video_prj_cb (GtkAction *action, BraseroProjectManager *manager)
+{
+ brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_VIDEO, NULL, NULL, TRUE);
+}
+
+static void
brasero_project_manager_new_copy_prj_cb (GtkAction *action, BraseroProjectManager *manager)
{
brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_COPY, NULL, NULL, TRUE);
@@ -650,6 +676,16 @@
}
void
+brasero_project_manager_video (BraseroProjectManager *manager, GSList *uris)
+{
+ brasero_project_manager_switch (manager,
+ BRASERO_PROJECT_TYPE_VIDEO,
+ uris,
+ NULL,
+ TRUE);
+}
+
+void
brasero_project_manager_copy (BraseroProjectManager *manager)
{
brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_COPY, NULL, NULL, TRUE);
@@ -951,7 +987,7 @@
_("Browse the file system"),
_("Display File Browser"),
GTK_STOCK_DIRECTORY,
- BRASERO_LAYOUT_AUDIO|BRASERO_LAYOUT_DATA);
+ BRASERO_LAYOUT_AUDIO|BRASERO_LAYOUT_DATA|BRASERO_LAYOUT_VIDEO);
#ifdef BUILD_PREVIEW
brasero_preview_add_source (BRASERO_PREVIEW (preview),
@@ -975,7 +1011,7 @@
_("Search files using keywords"),
_("Display Search"),
GTK_STOCK_FIND,
- BRASERO_LAYOUT_AUDIO|BRASERO_LAYOUT_DATA);
+ BRASERO_LAYOUT_AUDIO|BRASERO_LAYOUT_DATA|BRASERO_LAYOUT_VIDEO);
#ifdef BUILD_PREVIEW
brasero_preview_add_source (BRASERO_PREVIEW (preview),
Modified: trunk/src/brasero-project-manager.h
==============================================================================
--- trunk/src/brasero-project-manager.h (original)
+++ trunk/src/brasero-project-manager.h Mon Jul 14 18:07:55 2008
@@ -61,6 +61,8 @@
void
brasero_project_manager_data (BraseroProjectManager *manager, GSList *uris);
void
+brasero_project_manager_video (BraseroProjectManager *manager, GSList *uris);
+void
brasero_project_manager_copy (BraseroProjectManager *manager);
void
brasero_project_manager_iso (BraseroProjectManager *manager, const gchar *uri);
Modified: trunk/src/brasero-project-type-chooser.c
==============================================================================
--- trunk/src/brasero-project-type-chooser.c (original)
+++ trunk/src/brasero-project-type-chooser.c Mon Jul 14 18:07:55 2008
@@ -79,6 +79,11 @@
N_("Create a CD/DVD containing any type of data that can only be read on a computer"),
"media-optical-data-new",
BRASERO_PROJECT_TYPE_DATA},
+ {N_("<big>_Video project</big>"),
+ N_("Create a video DVD or a SVCD"),
+ N_("Create a video DVD or a SVCD that are readable on TV readers"),
+ "media-optical-copy",
+ BRASERO_PROJECT_TYPE_VIDEO},
{N_("<big>Disc _copy</big>"),
N_("Create 1:1 copy of a CD/DVD"),
N_("Create a 1:1 copy of an audio CD or a data CD/DVD on your hardisk or on another CD/DVD"),
Modified: trunk/src/brasero-project-type-chooser.h
==============================================================================
--- trunk/src/brasero-project-type-chooser.h (original)
+++ trunk/src/brasero-project-type-chooser.h Mon Jul 14 18:07:55 2008
@@ -31,6 +31,7 @@
#include <gtk/gtkeventbox.h>
G_BEGIN_DECLS
+
#define BRASERO_TYPE_PROJECT_TYPE_CHOOSER (brasero_project_type_chooser_get_type ())
#define BRASERO_PROJECT_TYPE_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), BRASERO_TYPE_PROJECT_TYPE_CHOOSER, BraseroProjectTypeChooser))
#define BRASERO_PROJECT_TYPE_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k),BRASERO_TYPE_PROJECT_TYPE_CHOOSER, BraseroProjectTypeChooserClass))
@@ -51,6 +52,7 @@
BRASERO_PROJECT_TYPE_ISO,
BRASERO_PROJECT_TYPE_AUDIO,
BRASERO_PROJECT_TYPE_DATA,
+ BRASERO_PROJECT_TYPE_VIDEO
} BraseroProjectType;
typedef struct {
Modified: trunk/src/brasero-project.c
==============================================================================
--- trunk/src/brasero-project.c (original)
+++ trunk/src/brasero-project.c Mon Jul 14 18:07:55 2008
@@ -71,6 +71,7 @@
#include "brasero-disc.h"
#include "brasero-data-disc.h"
#include "brasero-audio-disc.h"
+#include "brasero-video-disc.h"
#include "brasero-disc-option-dialog.h"
#include "brasero-burn-dialog.h"
#include "brasero-utils.h"
@@ -157,6 +158,7 @@
GtkWidget *discs;
GtkWidget *audio;
GtkWidget *data;
+ GtkWidget *video;
GtkWidget *message;
@@ -438,7 +440,7 @@
gtk_container_add (GTK_CONTAINER (alignment), obj->priv->burn);
gtk_box_pack_end (GTK_BOX (box), alignment, FALSE, FALSE, 0);
- /* The two panes to put into the notebook */
+ /* The three panes to put into the notebook */
obj->priv->audio = brasero_audio_disc_new ();
gtk_widget_show (obj->priv->audio);
g_signal_connect (G_OBJECT (obj->priv->audio),
@@ -474,10 +476,28 @@
G_CALLBACK (brasero_project_selection_changed_cb),
obj);
+ obj->priv->video = brasero_video_disc_new ();
+ gtk_widget_show (obj->priv->video);
+ g_signal_connect (G_OBJECT (obj->priv->video),
+ "contents-changed",
+ G_CALLBACK (brasero_project_contents_changed_cb),
+ obj);
+ g_signal_connect (G_OBJECT (obj->priv->video),
+ "size-changed",
+ G_CALLBACK (brasero_project_size_changed_cb),
+ obj);
+ g_signal_connect (G_OBJECT (obj->priv->video),
+ "selection-changed",
+ G_CALLBACK (brasero_project_selection_changed_cb),
+ obj);
+
obj->priv->discs = gtk_notebook_new ();
gtk_widget_show (obj->priv->discs);
gtk_notebook_set_show_border (GTK_NOTEBOOK (obj->priv->discs), FALSE);
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (obj->priv->discs), FALSE);
+
+ gtk_notebook_prepend_page (GTK_NOTEBOOK (obj->priv->discs),
+ obj->priv->video, NULL);
gtk_notebook_prepend_page (GTK_NOTEBOOK (obj->priv->discs),
obj->priv->data, NULL);
gtk_notebook_prepend_page (GTK_NOTEBOOK (obj->priv->discs),
@@ -1069,7 +1089,7 @@
/******************************** ******************************************/
static void
-brasero_project_switch (BraseroProject *project, gboolean audio)
+brasero_project_switch (BraseroProject *project, BraseroProjectType type)
{
GtkAction *action;
GConfClient *client;
@@ -1100,7 +1120,7 @@
gtk_ui_manager_remove_ui (project->priv->manager,
project->priv->merge_id);
- if (audio) {
+ if (type == BRASERO_PROJECT_TYPE_AUDIO) {
project->priv->current = BRASERO_DISC (project->priv->audio);
project->priv->merge_id = brasero_disc_add_ui (project->priv->current,
project->priv->manager,
@@ -1109,7 +1129,7 @@
gtk_notebook_set_current_page (GTK_NOTEBOOK (project->priv->discs), 0);
brasero_project_size_set_context (BRASERO_PROJECT_SIZE (project->priv->size_display), TRUE);
}
- else {
+ else if (type == BRASERO_PROJECT_TYPE_DATA) {
project->priv->current = BRASERO_DISC (project->priv->data);
project->priv->merge_id = brasero_disc_add_ui (project->priv->current,
project->priv->manager,
@@ -1118,6 +1138,15 @@
gtk_notebook_set_current_page (GTK_NOTEBOOK (project->priv->discs), 1);
brasero_project_size_set_context (BRASERO_PROJECT_SIZE (project->priv->size_display), FALSE);
}
+ else if (type == BRASERO_PROJECT_TYPE_VIDEO) {
+ project->priv->current = BRASERO_DISC (project->priv->video);
+ project->priv->merge_id = brasero_disc_add_ui (project->priv->current,
+ project->priv->manager,
+ project->priv->message);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (project->priv->discs), 2);
+ brasero_project_size_set_context (BRASERO_PROJECT_SIZE (project->priv->size_display), TRUE);
+ }
brasero_notify_message_remove (BRASERO_NOTIFY (project->priv->message), BRASERO_NOTIFY_CONTEXT_SIZE);
@@ -1140,7 +1169,7 @@
void
brasero_project_set_audio (BraseroProject *project, GSList *uris)
{
- brasero_project_switch (project, TRUE);
+ brasero_project_switch (project, BRASERO_PROJECT_TYPE_AUDIO);
for (; uris; uris = uris->next) {
gchar *uri;
@@ -1153,7 +1182,20 @@
void
brasero_project_set_data (BraseroProject *project, GSList *uris)
{
- brasero_project_switch (project, FALSE);
+ brasero_project_switch (project, BRASERO_PROJECT_TYPE_DATA);
+
+ for (; uris; uris = uris->next) {
+ gchar *uri;
+
+ uri = uris->data;
+ brasero_disc_add_uri (project->priv->current, uri);
+ }
+}
+
+void
+brasero_project_set_video (BraseroProject *project, GSList *uris)
+{
+ brasero_project_switch (project, BRASERO_PROJECT_TYPE_VIDEO);
for (; uris; uris = uris->next) {
gchar *uri;
@@ -1700,9 +1742,11 @@
BRASERO_GET_BASENAME_FOR_DISPLAY (uri, name);
if (type == BRASERO_PROJECT_TYPE_DATA)
title = g_strdup_printf (_("Brasero - %s (Data Disc)"), name);
- else
+ else if (type == BRASERO_PROJECT_TYPE_AUDIO)
title = g_strdup_printf (_("Brasero - %s (Audio Disc)"), name);
- g_free (name);
+ else if (type == BRASERO_PROJECT_TYPE_AUDIO)
+ title = g_strdup_printf (_("Brasero - %s (Video Disc)"), name);
+ g_free (name);
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (project));
gtk_window_set_title (GTK_WINDOW (toplevel), title);
@@ -1859,8 +1903,6 @@
BraseroDiscSong *song;
track = g_new0 (BraseroDiscTrack, 1);
- track->type = BRASERO_DISC_TRACK_AUDIO;
-
song = NULL;
while (uris) {
@@ -1964,6 +2006,8 @@
track_node->xmlChildrenNode);
if (!newtrack)
goto error;
+
+ newtrack->type = BRASERO_DISC_TRACK_AUDIO;
}
else if (!xmlStrcmp (track_node->name, (const xmlChar *) "data")) {
if (newtrack)
@@ -1975,6 +2019,18 @@
if (!newtrack)
goto error;
}
+ else if (!xmlStrcmp (track_node->name, (const xmlChar *) "video")) {
+ if (newtrack)
+ goto error;
+
+ newtrack = _read_audio_track (project,
+ track_node->xmlChildrenNode);
+
+ if (!newtrack)
+ goto error;
+
+ newtrack->type = BRASERO_DISC_TRACK_VIDEO;
+ }
else if (track_node->type == XML_ELEMENT_NODE)
goto error;
@@ -2087,19 +2143,19 @@
brasero_project_size_set_sectors (BRASERO_PROJECT_SIZE (project->priv->size_display),
0);
- if (track->type == BRASERO_DISC_TRACK_AUDIO) {
- brasero_project_switch (project, TRUE);
+ if (track->type == BRASERO_DISC_TRACK_AUDIO)
type = BRASERO_PROJECT_TYPE_AUDIO;
- }
- else if (track->type == BRASERO_DISC_TRACK_DATA) {
- brasero_project_switch (project, FALSE);
+ else if (track->type == BRASERO_DISC_TRACK_DATA)
type = BRASERO_PROJECT_TYPE_DATA;
- }
+ else if (track->type == BRASERO_DISC_TRACK_VIDEO)
+ type = BRASERO_PROJECT_TYPE_VIDEO;
else {
brasero_track_free (track);
return BRASERO_PROJECT_TYPE_INVALID;
}
+ brasero_project_switch (project, type);
+
brasero_disc_load_track (project->priv->current, track);
brasero_track_free (track);
@@ -2205,19 +2261,19 @@
if (!brasero_project_open_project_xml (project, uri, &track, FALSE))
return BRASERO_PROJECT_TYPE_INVALID;
- if (track->type == BRASERO_DISC_TRACK_AUDIO) {
- brasero_project_switch (project, TRUE);
+ if (track->type == BRASERO_DISC_TRACK_AUDIO)
type = BRASERO_PROJECT_TYPE_AUDIO;
- }
- else if (track->type == BRASERO_DISC_TRACK_DATA) {
- brasero_project_switch (project, FALSE);
+ else if (track->type == BRASERO_DISC_TRACK_DATA)
type = BRASERO_PROJECT_TYPE_DATA;
- }
+ else if (track->type == BRASERO_DISC_TRACK_VIDEO)
+ type = BRASERO_PROJECT_TYPE_VIDEO;
else {
brasero_track_free (track);
return BRASERO_PROJECT_TYPE_INVALID;
}
+ brasero_project_switch (project, type);
+
brasero_disc_load_track (project->priv->current, track);
brasero_track_free (track);
@@ -2500,7 +2556,20 @@
if (success < 0)
goto error;
}
- else
+ else if (track->type == BRASERO_DISC_TRACK_VIDEO) {
+ success = xmlTextWriterStartElement (project, (xmlChar *) "video");
+ if (success < 0)
+ goto error;
+
+ retval = _save_audio_track_xml (project, track);
+ if (!retval)
+ goto error;
+
+ success = xmlTextWriterEndElement (project); /* audio */
+ if (success < 0)
+ goto error;
+ }
+ else
retval = FALSE;
success = xmlTextWriterEndElement (project); /* track */
Modified: trunk/src/brasero-project.h
==============================================================================
--- trunk/src/brasero-project.h (original)
+++ trunk/src/brasero-project.h Mon Jul 14 18:07:55 2008
@@ -70,6 +70,8 @@
void
brasero_project_set_data (BraseroProject *project, GSList *uris);
void
+brasero_project_set_video (BraseroProject *project, GSList *uris);
+void
brasero_project_set_none (BraseroProject *project);
void
Modified: trunk/src/brasero-song-properties.c
==============================================================================
--- trunk/src/brasero-song-properties.c (original)
+++ trunk/src/brasero-song-properties.c Mon Jul 14 18:07:55 2008
@@ -57,7 +57,9 @@
GtkWidget *length;
GtkWidget *start;
GtkWidget *end;
+
GtkWidget *gap;
+ GtkWidget *gap_label;
};
static GObjectClass *parent_class = NULL;
@@ -201,6 +203,7 @@
gtk_table_attach (GTK_TABLE (table), obj->priv->end, 1, 2, 1, 2, 0, 0, 0, 0);
label = gtk_label_new (_("Pause length:\t"));
+ obj->priv->gap_label = label;
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
obj->priv->gap = gtk_spin_button_new_with_range (0.0, 100.0, 1.0);
alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
@@ -242,6 +245,21 @@
gtk_window_set_title (GTK_WINDOW (obj), _("Song Information"));
}
+static gchar *
+brasero_song_props_get_entry_value (GtkEntry *entry)
+{
+ const gchar *text;
+
+ text = gtk_entry_get_text (entry);
+ if (!text)
+ return NULL;
+
+ if (text [0] == '\0')
+ return NULL;
+
+ return g_strdup (text);
+}
+
void
brasero_song_props_get_properties (BraseroSongProps *self,
gchar **artist,
@@ -253,16 +271,20 @@
gint64 *gap)
{
if (artist)
- *artist = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->priv->artist)));
+ *artist = brasero_song_props_get_entry_value (GTK_ENTRY (self->priv->artist));
if (title)
- *title = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->priv->title)));
+ *title = brasero_song_props_get_entry_value (GTK_ENTRY (self->priv->title));
if (composer)
- *composer = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->priv->composer)));
+ *composer = brasero_song_props_get_entry_value (GTK_ENTRY (self->priv->composer));
+
if (isrc) {
const gchar *string;
- string = gtk_entry_get_text (GTK_ENTRY (self->priv->isrc));
- *isrc = (gint) g_strtod (string, NULL);
+ string = brasero_song_props_get_entry_value (GTK_ENTRY (self->priv->isrc));
+ if (string)
+ *isrc = (gint) g_strtod (string, NULL);
+ else
+ *isrc = 0;
}
if (start)
@@ -288,9 +310,19 @@
gchar *string;
gdouble secs;
- string = g_strdup_printf (_("<b>Song information for track %02i</b>"), track_num);
- gtk_label_set_markup (GTK_LABEL (self->priv->label), string);
- g_free (string);
+ if (track_num >= 0) {
+ string = g_strdup_printf (_("<b>Song information for track %02i</b>"), track_num);
+ gtk_label_set_markup (GTK_LABEL (self->priv->label), string);
+ g_free (string);
+ }
+ else {
+ brasero_time_button_set_show_frames (BRASERO_TIME_BUTTON (self->priv->start), FALSE);
+ brasero_time_button_set_show_frames (BRASERO_TIME_BUTTON (self->priv->end), FALSE);
+
+ gtk_widget_hide (self->priv->gap_label);
+ gtk_widget_hide (self->priv->label);
+ gtk_widget_hide (self->priv->gap);
+ }
if (artist)
gtk_entry_set_text (GTK_ENTRY (self->priv->artist), artist);
@@ -304,8 +336,14 @@
g_free (string);
}
- secs = gap / GST_SECOND;
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->priv->gap), secs);
+ if (gap > 0) {
+ secs = gap / GST_SECOND;
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->priv->gap), secs);
+ }
+ else {
+ gtk_widget_hide (self->priv->gap);
+ gtk_widget_hide (self->priv->gap_label);
+ }
brasero_time_button_set_max (BRASERO_TIME_BUTTON (self->priv->start), end - 1);
brasero_time_button_set_value (BRASERO_TIME_BUTTON (self->priv->start), start);
Modified: trunk/src/brasero-time-button.c
==============================================================================
--- trunk/src/brasero-time-button.c (original)
+++ trunk/src/brasero-time-button.c Mon Jul 14 18:07:55 2008
@@ -162,6 +162,20 @@
}
void
+brasero_time_button_set_show_frames (BraseroTimeButton *self,
+ gboolean show)
+{
+ BraseroTimeButtonPrivate *priv;
+
+ priv = BRASERO_TIME_BUTTON_PRIVATE (self);
+
+ if (show)
+ gtk_widget_show (priv->frame);
+ else
+ gtk_widget_hide (priv->frame);
+}
+
+void
brasero_time_button_set_max (BraseroTimeButton *self,
gint64 max)
{
Modified: trunk/src/brasero-time-button.h
==============================================================================
--- trunk/src/brasero-time-button.h (original)
+++ trunk/src/brasero-time-button.h Mon Jul 14 18:07:55 2008
@@ -59,14 +59,19 @@
brasero_time_button_new (void);
gint64
-brasero_time_button_get_value (BraseroTimeButton *self);
+brasero_time_button_get_value (BraseroTimeButton *time);
void
-brasero_time_button_set_value (BraseroTimeButton *self,
+brasero_time_button_set_value (BraseroTimeButton *time,
gint64 value);
void
-brasero_time_button_set_max (BraseroTimeButton *self,
+brasero_time_button_set_max (BraseroTimeButton *time,
gint64 max);
+
+void
+brasero_time_button_set_show_frames (BraseroTimeButton *time,
+ gboolean show);
+
G_END_DECLS
#endif /* _BRASERO_TIME_BUTTON_H_ */
Added: trunk/src/brasero-video-disc.c
==============================================================================
--- (empty file)
+++ trunk/src/brasero-video-disc.c Mon Jul 14 18:07:55 2008
@@ -0,0 +1,1480 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * brasero is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gdk/gdkkeysyms.h>
+
+#include <gtk/gtk.h>
+
+#include "eggtreemultidnd.h"
+
+#include "burn-debug.h"
+#include "brasero-disc.h"
+#include "brasero-io.h"
+#include "brasero-utils.h"
+#include "brasero-video-disc.h"
+#include "brasero-video-project.h"
+#include "brasero-video-tree-model.h"
+#include "brasero-multi-song-props.h"
+#include "brasero-song-properties.h"
+
+typedef struct _BraseroVideoDiscPrivate BraseroVideoDiscPrivate;
+struct _BraseroVideoDiscPrivate
+{
+ GtkWidget *notebook;
+ GtkWidget *tree;
+
+ GtkWidget *message;
+ GtkUIManager *manager;
+ GtkActionGroup *disc_group;
+
+ guint reject_files:1;
+ guint editing:1;
+ guint loading:1;
+};
+
+#define BRASERO_VIDEO_DISC_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_VIDEO_DISC, BraseroVideoDiscPrivate))
+
+static void
+brasero_video_disc_iface_disc_init (BraseroDiscIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (BraseroVideoDisc,
+ brasero_video_disc,
+ GTK_TYPE_VBOX,
+ G_IMPLEMENT_INTERFACE (BRASERO_TYPE_DISC,
+ brasero_video_disc_iface_disc_init));
+
+enum {
+ PROP_NONE,
+ PROP_REJECT_FILE,
+};
+
+static void
+brasero_video_disc_edit_information_cb (GtkAction *action,
+ BraseroVideoDisc *disc);
+static void
+brasero_video_disc_open_activated_cb (GtkAction *action,
+ BraseroVideoDisc *disc);
+static void
+brasero_video_disc_delete_activated_cb (GtkAction *action,
+ BraseroVideoDisc *disc);
+static void
+brasero_video_disc_paste_activated_cb (GtkAction *action,
+ BraseroVideoDisc *disc);
+
+static GtkActionEntry entries[] = {
+ {"ContextualMenu", NULL, N_("Menu")},
+ {"OpenVideo", GTK_STOCK_OPEN, NULL, NULL, N_("Open the selected video"),
+ G_CALLBACK (brasero_video_disc_open_activated_cb)},
+ {"EditVideo", GTK_STOCK_PROPERTIES, N_("_Edit Information..."), NULL, N_("Edit the video information (start, end, author, ...)"),
+ G_CALLBACK (brasero_video_disc_edit_information_cb)},
+ {"DeleteVideo", GTK_STOCK_REMOVE, NULL, NULL, N_("Remove the selected videos from the project"),
+ G_CALLBACK (brasero_video_disc_delete_activated_cb)},
+ {"PasteVideo", GTK_STOCK_PASTE, NULL, NULL, N_("Add the files stored in the clipboard"),
+ G_CALLBACK (brasero_video_disc_paste_activated_cb)},
+/* {"Split", "transform-crop-and-resize", N_("_Split Track..."), NULL, N_("Split the selected track"),
+ G_CALLBACK (brasero_video_disc_split_cb)} */
+};
+
+static const gchar *description = {
+ "<ui>"
+ "<menubar name='menubar' >"
+ "<menu action='EditMenu'>"
+/* "<placeholder name='EditPlaceholder'>"
+ "<menuitem action='Split'/>"
+ "</placeholder>"
+*/ "</menu>"
+ "</menubar>"
+ "<popup action='ContextMenu'>"
+ "<menuitem action='OpenVideo'/>"
+ "<menuitem action='DeleteVideo'/>"
+ "<separator/>"
+ "<menuitem action='PasteVideo'/>"
+/* "<separator/>"
+ "<menuitem action='Split'/>"
+*/ "<separator/>"
+ "<menuitem action='EditVideo'/>"
+ "</popup>"
+/* "<toolbar name='Toolbar'>"
+ "<placeholder name='DiscButtonPlaceholder'>"
+ "<separator/>"
+ "<toolitem action='Split'/>"
+ "</placeholder>"
+ "</toolbar>"
+*/ "</ui>"
+};
+
+enum {
+ TREE_MODEL_ROW = 150,
+ TARGET_URIS_LIST,
+};
+
+static GtkTargetEntry ntables_cd [] = {
+ {BRASERO_DND_TARGET_SELF_FILE_NODES, GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
+ {"text/uri-list", 0, TARGET_URIS_LIST}
+};
+static guint nb_targets_cd = sizeof (ntables_cd) / sizeof (ntables_cd[0]);
+
+static GtkTargetEntry ntables_source [] = {
+ {BRASERO_DND_TARGET_SELF_FILE_NODES, GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
+};
+
+static guint nb_targets_source = sizeof (ntables_source) / sizeof (ntables_source[0]);
+
+
+/**
+ * Row name edition
+ */
+
+static void
+brasero_video_disc_name_editing_started_cb (GtkCellRenderer *renderer,
+ GtkCellEditable *editable,
+ gchar *path,
+ BraseroVideoDisc *disc)
+{
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+ priv->editing = 1;
+}
+
+static void
+brasero_video_disc_name_editing_canceled_cb (GtkCellRenderer *renderer,
+ BraseroVideoDisc *disc)
+{
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+ priv->editing = 0;
+}
+
+static void
+brasero_video_disc_name_edited_cb (GtkCellRendererText *cellrenderertext,
+ gchar *path_string,
+ gchar *text,
+ BraseroVideoDisc *self)
+{
+ BraseroVideoDiscPrivate *priv;
+ BraseroVideoProject *project;
+ BraseroVideoFile *file;
+ GtkTreePath *path;
+ GtkTreeIter row;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ priv->editing = 0;
+
+ path = gtk_tree_path_new_from_string (path_string);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+
+ /* see if this is still a valid path. It can happen a user removes it
+ * while the name of the row is being edited */
+ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (project), &row, path)) {
+ gtk_tree_path_free (path);
+ return;
+ }
+
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (project), path);
+ gtk_tree_path_free (path);
+
+ brasero_video_project_rename (project, file, text);
+}
+
+static void
+brasero_video_disc_vfs_activity_changed (BraseroVideoProject *project,
+ gboolean activity,
+ BraseroVideoDisc *self)
+{
+ GdkCursor *cursor;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ if (!GTK_WIDGET (self)->window)
+ return;
+
+ if (activity) {
+ cursor = gdk_cursor_new (GDK_WATCH);
+ gdk_window_set_cursor (GTK_WIDGET (self)->window, cursor);
+ gdk_cursor_unref (cursor);
+ }
+ else
+ gdk_window_set_cursor (GTK_WIDGET (self)->window, NULL);
+}
+
+static gboolean
+brasero_video_disc_directory_dialog (BraseroVideoProject *project,
+ const gchar *uri,
+ BraseroVideoDisc *self)
+{
+ gint answer;
+ GtkWidget *dialog;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
+ GTK_DIALOG_DESTROY_WITH_PARENT |
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ _("Do you want to search for video files inside the directory?"));
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Directory Search"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Directories can't be added to video disc."));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Search directory"), GTK_RESPONSE_OK,
+ NULL);
+
+ gtk_widget_show_all (dialog);
+ answer = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ if (answer != GTK_RESPONSE_OK)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+brasero_video_disc_unreadable_uri_dialog (BraseroVideoProject *project,
+ GError *error,
+ const gchar *uri,
+ BraseroVideoDisc *self)
+{
+ GtkWidget *dialog, *toplevel;
+ gchar *name;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ if (toplevel == NULL) {
+ g_warning ("Can't open file %s : %s\n",
+ uri,
+ error->message);
+ return;
+ }
+
+ name = g_filename_display_basename (uri);
+ dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
+ GTK_DIALOG_DESTROY_WITH_PARENT|
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("File \"%s\" can't be opened."),
+ name);
+ g_free (name);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Unreadable file"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ error->message);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+static void
+brasero_video_disc_not_video_dialog (BraseroVideoProject *project,
+ const gchar *uri,
+ BraseroVideoDisc *self)
+{
+ GtkWidget *dialog, *toplevel;
+ gchar *name;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ if (toplevel == NULL) {
+ g_warning ("Content widget error : can't handle \"%s\".\n", uri);
+ return ;
+ }
+
+ BRASERO_GET_BASENAME_FOR_DISPLAY (uri, name);
+ dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
+ GTK_DIALOG_DESTROY_WITH_PARENT|
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("\"%s\" does not have a suitable type for video projects."),
+ name);
+ g_free (name);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Unhandled file"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Please only add files with video contents."));
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+static BraseroDiscResult
+brasero_video_disc_add_uri_real (BraseroVideoDisc *self,
+ const gchar *uri,
+ gint pos,
+ gint64 start,
+ gint64 end,
+ GtkTreePath **path_return)
+{
+ BraseroVideoFile *file;
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+ BraseroVideoFile *sibling = NULL;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ if (priv->reject_files)
+ return BRASERO_DISC_NOT_READY;
+
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+
+ if (pos > 0) {
+ GtkTreePath *treepath;
+
+ treepath = gtk_tree_path_new ();
+ gtk_tree_path_append_index (treepath, pos);
+ sibling = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (project), treepath);
+ gtk_tree_path_free (treepath);
+ }
+
+ file = brasero_video_project_add_uri (project,
+ uri,
+ sibling,
+ start,
+ end);
+ if (path_return && file)
+ *path_return = brasero_video_tree_model_file_to_path (BRASERO_VIDEO_TREE_MODEL (project), file);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
+
+ return BRASERO_DISC_OK;
+}
+
+static BraseroDiscResult
+brasero_video_disc_add_uri (BraseroDisc *self,
+ const gchar *uri)
+{
+ BraseroVideoDiscPrivate *priv;
+ GtkTreePath *treepath = NULL;
+ BraseroDiscResult result;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ result = brasero_video_disc_add_uri_real (BRASERO_VIDEO_DISC (self),
+ uri,
+ -1,
+ -1,
+ -1,
+ &treepath);
+
+ if (treepath) {
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->tree),
+ treepath,
+ NULL,
+ TRUE,
+ 0.5,
+ 0.5);
+ gtk_tree_path_free (treepath);
+ }
+
+ return result;
+}
+
+static void
+brasero_video_disc_delete_selected (BraseroDisc *self)
+{
+ BraseroVideoDiscPrivate *priv;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GList *selected;
+ GList *iter;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
+
+ selected = gtk_tree_selection_get_selected_rows (selection, &model);
+ selected = g_list_reverse (selected);
+ for (iter = selected; iter; iter = iter->next) {
+ BraseroVideoFile *file;
+ GtkTreePath *treepath;
+
+ treepath = iter->data;
+
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ gtk_tree_path_free (treepath);
+
+ if (!file)
+ continue;
+
+ brasero_video_project_remove_file (BRASERO_VIDEO_PROJECT (model), file);
+ }
+ g_list_free (selected);
+}
+
+static gboolean
+brasero_video_disc_get_selected_uri (BraseroDisc *self,
+ gchar **uri)
+{
+ GList *selected;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
+ selected = gtk_tree_selection_get_selected_rows (selection, &model);
+ if (!selected)
+ return FALSE;
+
+ if (uri) {
+ BraseroVideoFile *file;
+ GtkTreePath *treepath;
+
+ treepath = selected->data;
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ if (file)
+ *uri = g_strdup (file->uri);
+ else
+ *uri = NULL;
+ }
+
+ g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (selected);
+
+ return TRUE;
+}
+
+static void
+brasero_video_disc_selection_changed_cb (GtkTreeSelection *selection,
+ BraseroVideoDisc *self)
+{
+ brasero_disc_selection_changed (BRASERO_DISC (self));
+}
+
+static gboolean
+brasero_video_disc_selection_function (GtkTreeSelection *selection,
+ GtkTreeModel *model,
+ GtkTreePath *treepath,
+ gboolean path_currently_selected,
+ gpointer NULL_data)
+{
+ BraseroVideoFile *file;
+
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ if (file)
+ file->editable = !path_currently_selected;
+
+ return TRUE;
+}
+
+
+/**
+ * Callback for menu
+ */
+
+static gboolean
+brasero_video_disc_rename_songs (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreePath *treepath,
+ const gchar *old_name,
+ const gchar *new_name)
+{
+ BraseroVideoFile *file;
+
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ if (!file)
+ return FALSE;
+
+ if (file->name)
+ g_free (file->name);
+
+ file->name = g_strdup (new_name);
+ return TRUE;
+}
+
+static void
+brasero_video_disc_edit_song_properties_list (BraseroVideoDisc *self,
+ GList *list)
+{
+ GList *item;
+ gint isrc;
+ GList *copy;
+ GtkWidget *props;
+ GtkWidget *toplevel;
+ GtkTreeModel *model;
+ gchar *artist = NULL;
+ gchar *composer = NULL;
+ GtkResponseType result;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ if (!g_list_length (list))
+ return;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ props = brasero_multi_song_props_new ();
+ brasero_multi_song_props_set_show_gap (BRASERO_MULTI_SONG_PROPS (props), FALSE);
+
+ gtk_window_set_transient_for (GTK_WINDOW (props),
+ GTK_WINDOW (toplevel));
+ gtk_window_set_modal (GTK_WINDOW (props), TRUE);
+ gtk_window_set_position (GTK_WINDOW (props),
+ GTK_WIN_POS_CENTER_ON_PARENT);
+
+ gtk_widget_show (GTK_WIDGET (props));
+ result = gtk_dialog_run (GTK_DIALOG (props));
+ gtk_widget_hide (GTK_WIDGET (props));
+ if (result != GTK_RESPONSE_ACCEPT)
+ goto end;
+
+ brasero_multi_song_props_set_rename_callback (BRASERO_MULTI_SONG_PROPS (props),
+ gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)),
+ BRASERO_VIDEO_TREE_MODEL_NAME,
+ brasero_video_disc_rename_songs);
+
+ brasero_multi_song_props_get_properties (BRASERO_MULTI_SONG_PROPS (props),
+ &artist,
+ &composer,
+ &isrc,
+ NULL);
+
+ /* start by the end in case we add silences since then the next
+ * treepaths will be wrong */
+ copy = g_list_copy (list);
+ copy = g_list_reverse (copy);
+
+ for (item = copy; item; item = item->next) {
+ GtkTreePath *treepath;
+ BraseroVideoFile *file;
+
+ treepath = item->data;
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ if (!file)
+ continue;
+
+ if (artist) {
+ g_free (file->info->artist);
+ file->info->artist = g_strdup (artist);
+ }
+
+ if (composer) {
+ g_free (file->info->composer);
+ file->info->composer = g_strdup (composer);
+ }
+
+ if (isrc > 0)
+ file->info->isrc = isrc;
+ }
+
+ g_list_free (copy);
+ g_free (artist);
+ g_free (composer);
+end:
+
+ gtk_widget_destroy (props);
+}
+
+static void
+brasero_video_disc_edit_song_properties_file (BraseroVideoDisc *self,
+ BraseroVideoFile *file)
+{
+ gint64 end;
+ gint64 start;
+ GtkWidget *props;
+ GtkWidget *toplevel;
+ GtkTreeModel *model;
+ GtkResponseType result;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+
+ props = brasero_song_props_new ();
+ brasero_song_props_set_properties (BRASERO_SONG_PROPS (props),
+ -1,
+ file->info->artist,
+ file->info->title,
+ file->info->composer,
+ file->info->isrc,
+ file->end - file->start,
+ file->start,
+ file->end,
+ -1);
+
+ gtk_window_set_transient_for (GTK_WINDOW (props),
+ GTK_WINDOW (toplevel));
+ gtk_window_set_modal (GTK_WINDOW (props), TRUE);
+ gtk_window_set_position (GTK_WINDOW (props),
+ GTK_WIN_POS_CENTER_ON_PARENT);
+
+ gtk_widget_show (GTK_WIDGET (props));
+ result = gtk_dialog_run (GTK_DIALOG (props));
+ gtk_widget_hide (GTK_WIDGET (props));
+ if (result != GTK_RESPONSE_ACCEPT)
+ goto end;
+
+ brasero_song_info_free (file->info);
+ file->info = g_new0 (BraseroSongInfo, 1);
+
+ brasero_song_props_get_properties (BRASERO_SONG_PROPS (props),
+ &file->info->artist,
+ &file->info->title,
+ &file->info->composer,
+ &file->info->isrc,
+ &start,
+ &end,
+ NULL);
+
+ brasero_video_project_resize_file (BRASERO_VIDEO_PROJECT (model), file, start, end);
+
+end:
+
+ gtk_widget_destroy (props);
+}
+static void
+brasero_video_disc_edit_information_cb (GtkAction *action,
+ BraseroVideoDisc *self)
+{
+ GList *list;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
+ list = gtk_tree_selection_get_selected_rows (selection, &model);
+
+ if (!list)
+ return;
+
+ if (g_list_length (list) == 1) {
+ BraseroVideoFile *file;
+ GtkTreePath *treepath;
+
+ treepath = list->data;
+
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ if (file)
+ brasero_video_disc_edit_song_properties_file (self, file);
+ }
+ else
+ brasero_video_disc_edit_song_properties_list (self, list);
+
+ g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (list);
+}
+
+static void
+brasero_video_disc_open_file (BraseroVideoDisc *self)
+{
+ GList *item, *list;
+ GSList *uris = NULL;
+ GtkTreeModel *model;
+ GtkTreePath *treepath;
+ GtkTreeSelection *selection;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
+ list = gtk_tree_selection_get_selected_rows (selection, &model);
+
+ for (item = list; item; item = item->next) {
+ BraseroVideoFile *file;
+
+ treepath = item->data;
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ gtk_tree_path_free (treepath);
+
+ if (!file)
+ continue;
+
+ if (file->uri)
+ uris = g_slist_prepend (uris, file->uri);
+ }
+ g_list_free (list);
+
+ brasero_utils_launch_app (GTK_WIDGET (self), uris);
+ g_slist_free (uris);
+}
+
+static void
+brasero_video_disc_open_activated_cb (GtkAction *action,
+ BraseroVideoDisc *self)
+{
+ brasero_video_disc_open_file (self);
+}
+
+static void
+brasero_video_disc_clipboard_text_cb (GtkClipboard *clipboard,
+ const gchar *text,
+ BraseroVideoDisc *self)
+{
+ gchar **array;
+ gchar **item;
+
+ array = g_strsplit_set (text, "\n\r", 0);
+ item = array;
+ while (*item) {
+ if (**item != '\0') {
+ GFile *file;
+ gchar *uri;
+
+ file = g_file_new_for_commandline_arg (*item);
+ uri = g_file_get_uri (file);
+ g_object_unref (file);
+
+ brasero_video_disc_add_uri_real (self,
+ uri,
+ -1,
+ -1,
+ -1,
+ NULL);
+ g_free (uri);
+ }
+
+ item++;
+ }
+}
+
+static void
+brasero_video_disc_clipboard_targets_cb (GtkClipboard *clipboard,
+ GdkAtom *atoms,
+ gint n_atoms,
+ BraseroVideoDisc *self)
+{
+ GdkAtom *iter;
+ gchar *target;
+
+ iter = atoms;
+ while (n_atoms) {
+ target = gdk_atom_name (*iter);
+
+ if (!strcmp (target, "x-special/gnome-copied-files")
+ || !strcmp (target, "UTF8_STRING")) {
+ gtk_clipboard_request_text (clipboard,
+ (GtkClipboardTextReceivedFunc) brasero_video_disc_clipboard_text_cb,
+ self);
+ g_free (target);
+ return;
+ }
+
+ g_free (target);
+ iter++;
+ n_atoms--;
+ }
+}
+
+static void
+brasero_video_disc_paste_activated_cb (GtkAction *action,
+ BraseroVideoDisc *self)
+{
+ GtkClipboard *clipboard;
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_request_targets (clipboard,
+ (GtkClipboardTargetsReceivedFunc) brasero_video_disc_clipboard_targets_cb,
+ self);
+}
+
+static void
+brasero_video_disc_delete_activated_cb (GtkAction *action,
+ BraseroVideoDisc *self)
+{
+ brasero_video_disc_delete_selected (BRASERO_DISC (self));
+}
+
+static gboolean
+brasero_video_disc_button_pressed_cb (GtkTreeView *tree,
+ GdkEventButton *event,
+ BraseroVideoDisc *self)
+{
+ GtkWidgetClass *widget_class;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ widget_class = GTK_WIDGET_GET_CLASS (tree);
+
+ if (event->button == 3) {
+ GtkTreeSelection *selection;
+ GtkTreePath *path = NULL;
+ GtkWidget *widget;
+
+ gtk_tree_view_get_path_at_pos (tree,
+ event->x,
+ event->y,
+ &path,
+ NULL,
+ NULL,
+ NULL);
+
+ selection = gtk_tree_view_get_selection (tree);
+
+ /* Don't update the selection if the right click was on one of
+ * the already selected rows */
+ if (!path || !gtk_tree_selection_path_is_selected (selection, path))
+ widget_class->button_press_event (GTK_WIDGET (tree), event);
+
+ widget = gtk_ui_manager_get_widget (priv->manager, "/ContextMenu/PasteAudio");
+ if (widget) {
+ if (gtk_clipboard_wait_is_text_available (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)))
+ gtk_widget_set_sensitive (widget, TRUE);
+ else
+ gtk_widget_set_sensitive (widget, FALSE);
+ }
+
+ widget = gtk_ui_manager_get_widget (priv->manager,"/ContextMenu");
+ gtk_menu_popup (GTK_MENU (widget),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ event->button,
+ event->time);
+ return TRUE;
+ }
+ else if (event->button == 1) {
+ gboolean result;
+ GtkTreePath *treepath = NULL;
+
+ result = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree),
+ event->x,
+ event->y,
+ &treepath,
+ NULL,
+ NULL,
+ NULL);
+
+ /* we call the default handler for the treeview before everything else
+ * so it can update itself (paticularly its selection) before we have
+ * a look at it */
+ widget_class->button_press_event (GTK_WIDGET (tree), event);
+
+ if (!treepath) {
+ GtkTreeSelection *selection;
+
+ /* This is to deselect any row when selecting a
+ * row that cannot be selected or in an empty
+ * part */
+ selection = gtk_tree_view_get_selection (tree);
+ gtk_tree_selection_unselect_all (selection);
+ return FALSE;
+ }
+
+ if (!result)
+ return FALSE;
+
+ brasero_disc_selection_changed (BRASERO_DISC (self));
+ if (event->type == GDK_2BUTTON_PRESS) {
+ BraseroVideoFile *file;
+ GtkTreeModel *model;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (model), treepath);
+ if (file)
+ brasero_video_disc_edit_song_properties_file (self, file);
+ }
+ }
+
+ return TRUE;
+}
+
+static guint
+brasero_video_disc_add_ui (BraseroDisc *disc,
+ GtkUIManager *manager,
+ GtkWidget *message)
+{
+ BraseroVideoDiscPrivate *priv;
+ GError *error = NULL;
+ guint merge_id;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+
+ if (priv->message) {
+ g_object_unref (priv->message);
+ priv->message = NULL;
+ }
+
+ priv->message = message;
+ g_object_ref (message);
+
+ if (!priv->disc_group) {
+ priv->disc_group = gtk_action_group_new (BRASERO_DISC_ACTION);
+ gtk_action_group_set_translation_domain (priv->disc_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (priv->disc_group,
+ entries,
+ G_N_ELEMENTS (entries),
+ disc);
+/* gtk_action_group_add_toggle_actions (priv->disc_group,
+ toggle_entries,
+ G_N_ELEMENTS (toggle_entries),
+ disc); */
+ gtk_ui_manager_insert_action_group (manager,
+ priv->disc_group,
+ 0);
+ }
+
+ merge_id = gtk_ui_manager_add_ui_from_string (manager,
+ description,
+ -1,
+ &error);
+ if (!merge_id) {
+ BRASERO_BURN_LOG ("Adding ui elements failed: %s", error->message);
+ g_error_free (error);
+ return 0;
+ }
+
+ priv->manager = manager;
+ g_object_ref (manager);
+ return merge_id;
+}
+
+static void
+brasero_video_disc_rename_activated (BraseroVideoDisc *self)
+{
+ BraseroVideoDiscPrivate *priv;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+ GtkTreePath *treepath;
+ GtkTreeModel *model;
+ GList *list;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
+ list = gtk_tree_selection_get_selected_rows (selection, &model);
+
+ for (; list; list = g_list_remove (list, treepath)) {
+ treepath = list->data;
+
+ gtk_widget_grab_focus (priv->tree);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->tree), 0);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->tree),
+ treepath,
+ NULL,
+ TRUE,
+ 0.5,
+ 0.5);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->tree),
+ treepath,
+ column,
+ TRUE);
+
+ gtk_tree_path_free (treepath);
+ }
+}
+
+static gboolean
+brasero_video_disc_key_released_cb (GtkTreeView *tree,
+ GdkEventKey *event,
+ BraseroVideoDisc *self)
+{
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ if (priv->editing)
+ return FALSE;
+
+ if (event->keyval == GDK_KP_Delete || event->keyval == GDK_Delete) {
+ brasero_video_disc_delete_selected (BRASERO_DISC (self));
+ }
+ else if (event->keyval == GDK_F2)
+ brasero_video_disc_rename_activated (self);
+
+ return FALSE;
+}
+
+static void
+brasero_video_disc_row_deleted_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ BraseroVideoDisc *self)
+{
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ brasero_disc_contents_changed (BRASERO_DISC (self),
+ brasero_video_project_get_file_num (BRASERO_VIDEO_PROJECT (model)));
+}
+
+static void
+brasero_video_disc_row_inserted_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ BraseroVideoDisc *self)
+{
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ brasero_disc_contents_changed (BRASERO_DISC (self),
+ brasero_video_project_get_file_num (BRASERO_VIDEO_PROJECT (model)));
+}
+
+static void
+brasero_video_disc_row_changed_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ BraseroVideoDisc *self)
+{
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ brasero_disc_contents_changed (BRASERO_DISC (self),
+ brasero_video_project_get_file_num (BRASERO_VIDEO_PROJECT (model)));
+}
+
+static void
+brasero_video_disc_size_changed_cb (BraseroVideoProject *project,
+ BraseroVideoDisc *self)
+{
+ brasero_disc_size_changed (BRASERO_DISC (self), brasero_video_project_get_size (project));
+}
+
+static void
+brasero_video_disc_init (BraseroVideoDisc *object)
+{
+ BraseroVideoDiscPrivate *priv;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkTreeModel *model;
+ GtkWidget *mainbox;
+ GtkWidget *scroll;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (object);
+
+ /* the information displayed about how to use this tree */
+ priv->notebook = brasero_disc_get_use_info_notebook ();
+ gtk_widget_show (priv->notebook);
+ gtk_box_pack_start (GTK_BOX (object), priv->notebook, TRUE, TRUE, 0);
+
+ mainbox = gtk_vbox_new (FALSE, 12);
+ gtk_widget_show (mainbox);
+ gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), mainbox, NULL);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0);
+
+ /* Tree */
+ model = GTK_TREE_MODEL (brasero_video_tree_model_new ());
+
+ g_signal_connect (G_OBJECT (model),
+ "row-deleted",
+ G_CALLBACK (brasero_video_disc_row_deleted_cb),
+ object);
+ g_signal_connect (G_OBJECT (model),
+ "row-inserted",
+ G_CALLBACK (brasero_video_disc_row_inserted_cb),
+ object);
+ g_signal_connect (G_OBJECT (model),
+ "row-changed",
+ G_CALLBACK (brasero_video_disc_row_changed_cb),
+ object);
+
+ g_signal_connect (G_OBJECT (model),
+ "size-changed",
+ G_CALLBACK (brasero_video_disc_size_changed_cb),
+ object);
+ g_signal_connect (G_OBJECT (model),
+ "not-video-uri",
+ G_CALLBACK (brasero_video_disc_not_video_dialog),
+ object);
+ g_signal_connect (G_OBJECT (model),
+ "directory-uri",
+ G_CALLBACK (brasero_video_disc_directory_dialog),
+ object);
+ g_signal_connect (G_OBJECT (model),
+ "unreadable-uri",
+ G_CALLBACK (brasero_video_disc_unreadable_uri_dialog),
+ object);
+ g_signal_connect (G_OBJECT (model),
+ "vfs-activity",
+ G_CALLBACK (brasero_video_disc_vfs_activity_changed),
+ object);
+
+ priv->tree = gtk_tree_view_new_with_model (model);
+ egg_tree_multi_drag_add_drag_support (GTK_TREE_VIEW (priv->tree));
+ g_object_unref (G_OBJECT (model));
+ gtk_widget_show (priv->tree);
+
+ g_signal_connect (priv->tree,
+ "button-press-event",
+ G_CALLBACK (brasero_video_disc_button_pressed_cb),
+ object);
+ g_signal_connect (priv->tree,
+ "key-release-event",
+ G_CALLBACK (brasero_video_disc_key_released_cb),
+ object);
+
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (priv->tree), TRUE);
+ gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv->tree), TRUE);
+
+ /* columns */
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_min_width (column, 200);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "pixbuf", BRASERO_VIDEO_TREE_MODEL_MIME_ICON);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_signal_connect (G_OBJECT (renderer), "edited",
+ G_CALLBACK (brasero_video_disc_name_edited_cb), object);
+ g_signal_connect (G_OBJECT (renderer), "editing-started",
+ G_CALLBACK (brasero_video_disc_name_editing_started_cb), object);
+ g_signal_connect (G_OBJECT (renderer), "editing-canceled",
+ G_CALLBACK (brasero_video_disc_name_editing_canceled_cb), object);
+
+ g_object_set (G_OBJECT (renderer),
+ "mode", GTK_CELL_RENDERER_MODE_EDITABLE,
+ "ellipsize-set", TRUE,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+
+ gtk_tree_view_column_pack_end (column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "markup", BRASERO_VIDEO_TREE_MODEL_NAME);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "editable", BRASERO_VIDEO_TREE_MODEL_EDITABLE);
+ gtk_tree_view_column_set_title (column, _("Title"));
+ g_object_set (G_OBJECT (column),
+ "expand", TRUE,
+ "spacing", 4,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree),
+ column);
+
+ gtk_tree_view_set_expander_column (GTK_TREE_VIEW (priv->tree),
+ column);
+
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "text", BRASERO_VIDEO_TREE_MODEL_SIZE);
+ gtk_tree_view_column_set_title (column, _("Size"));
+
+ gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree), column);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_expand (column, FALSE);
+
+ /* selection */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+ g_signal_connect (selection,
+ "changed",
+ G_CALLBACK (brasero_video_disc_selection_changed_cb),
+ object);
+ gtk_tree_selection_set_select_function (selection,
+ brasero_video_disc_selection_function,
+ NULL,
+ NULL);
+
+ /* scroll */
+ scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scroll);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_container_add (GTK_CONTAINER (scroll), priv->tree);
+ gtk_box_pack_start (GTK_BOX (mainbox), scroll, TRUE, TRUE, 0);
+
+ /* dnd */
+ gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW
+ (priv->tree),
+ ntables_cd, nb_targets_cd,
+ GDK_ACTION_COPY |
+ GDK_ACTION_MOVE);
+
+ gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->tree),
+ GDK_BUTTON1_MASK,
+ ntables_source,
+ nb_targets_source,
+ GDK_ACTION_MOVE);
+}
+
+static void
+brasero_video_disc_reset_real (BraseroVideoDisc *self)
+{
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ brasero_video_project_reset (project);
+ brasero_video_disc_vfs_activity_changed (project, FALSE, self);
+}
+
+static void
+brasero_video_disc_clear (BraseroDisc *disc)
+{
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+
+ brasero_video_disc_reset_real (BRASERO_VIDEO_DISC (disc));
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0);
+ brasero_disc_size_changed (disc, 0);
+}
+
+static void
+brasero_video_disc_reset (BraseroDisc *disc)
+{
+ brasero_video_disc_reset_real (BRASERO_VIDEO_DISC (disc));
+}
+
+static void
+brasero_video_disc_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (brasero_video_disc_parent_class)->finalize (object);
+}
+
+static void
+brasero_video_disc_get_property (GObject * object,
+ guint prop_id,
+ GValue * value,
+ GParamSpec * pspec)
+{
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_REJECT_FILE:
+ g_value_set_boolean (value, priv->reject_files);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+brasero_video_disc_set_property (GObject * object,
+ guint prop_id,
+ const GValue * value,
+ GParamSpec * pspec)
+{
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_REJECT_FILE:
+ priv->reject_files = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static BraseroDiscResult
+brasero_video_disc_get_status (BraseroDisc *self)
+{
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ return brasero_video_project_get_status (project);
+}
+
+BraseroDiscResult
+brasero_video_disc_set_session_param (BraseroDisc *self,
+ BraseroBurnSession *session)
+{
+ BraseroTrackType type;
+
+ type.type = BRASERO_TRACK_TYPE_AUDIO;
+ type.subtype.audio_format = BRASERO_AUDIO_FORMAT_UNDEFINED|BRASERO_VIDEO_FORMAT_UNDEFINED;
+ brasero_burn_session_set_input_type (session, &type);
+ return BRASERO_BURN_OK;
+}
+
+BraseroDiscResult
+brasero_video_disc_set_session_contents (BraseroDisc *self,
+ BraseroBurnSession *session)
+{
+ GSList *tracks, *iter;
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ tracks = brasero_video_project_get_contents (project);
+
+ if (!tracks)
+ return BRASERO_DISC_ERROR_EMPTY_SELECTION;
+
+ for (iter = tracks; iter; iter = iter->next) {
+ BraseroTrack *track;
+
+ track = iter->data;
+ brasero_burn_session_add_track (session, track);
+
+ /* It's good practice to unref the track afterwards as we don't
+ * need it anymore. BraseroBurnSession refs it. */
+ brasero_track_unref (track);
+
+ }
+ g_slist_free (tracks);
+ return BRASERO_DISC_OK;
+}
+
+static BraseroDiscResult
+brasero_video_disc_get_track (BraseroDisc *disc,
+ BraseroDiscTrack *disc_track)
+{
+ GSList *iter;
+ GSList *tracks;
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ disc_track->type = BRASERO_DISC_TRACK_VIDEO;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ tracks = brasero_video_project_get_contents (project);
+
+ for (iter = tracks; iter; iter = iter->next) {
+ BraseroDiscSong *song;
+ BraseroTrack *track;
+
+ track = iter->data;
+
+ song = g_new0 (BraseroDiscSong, 1);
+ song->uri = brasero_track_get_audio_source (track, TRUE);;
+ song->start = brasero_track_get_audio_start (track);
+ song->end = brasero_track_get_audio_end (track);
+ song->info = brasero_song_info_copy (brasero_track_get_audio_info (track));
+ disc_track->contents.tracks = g_slist_append (disc_track->contents.tracks, song);
+ }
+
+ g_slist_foreach (tracks, (GFunc) brasero_track_unref, NULL);
+ g_slist_free (tracks);
+
+ return BRASERO_DISC_OK;
+}
+
+static BraseroDiscResult
+brasero_video_disc_load_track (BraseroDisc *disc,
+ BraseroDiscTrack *track)
+{
+ GSList *iter;
+ BraseroVideoProject *project;
+ BraseroVideoDiscPrivate *priv;
+
+ g_return_val_if_fail (track->type == BRASERO_DISC_TRACK_VIDEO, FALSE);
+
+ if (track->contents.tracks == NULL)
+ return BRASERO_DISC_ERROR_EMPTY_SELECTION;
+
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
+ priv->loading = g_slist_length (track->contents.tracks);
+
+ for (iter = track->contents.tracks; iter; iter = iter->next) {
+ BraseroDiscSong *song;
+
+ song = iter->data;
+
+ brasero_video_project_add_uri (BRASERO_VIDEO_PROJECT (project),
+ song->uri,
+ NULL,
+ song->start,
+ song->end);
+ }
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
+
+ return BRASERO_DISC_OK;
+}
+
+static void
+brasero_video_disc_iface_disc_init (BraseroDiscIface *iface)
+{
+ iface->add_uri = brasero_video_disc_add_uri;
+ iface->delete_selected = brasero_video_disc_delete_selected;
+ iface->clear = brasero_video_disc_clear;
+ iface->reset = brasero_video_disc_reset;
+
+ iface->get_status = brasero_video_disc_get_status;
+ iface->set_session_param = brasero_video_disc_set_session_param;
+ iface->set_session_contents = brasero_video_disc_set_session_contents;
+
+ iface->get_track = brasero_video_disc_get_track;
+ iface->load_track = brasero_video_disc_load_track;
+
+ iface->get_selected_uri = brasero_video_disc_get_selected_uri;
+ iface->add_ui = brasero_video_disc_add_ui;
+}
+
+static void
+brasero_video_disc_class_init (BraseroVideoDiscClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (BraseroVideoDiscPrivate));
+
+ object_class->finalize = brasero_video_disc_finalize;
+ object_class->set_property = brasero_video_disc_set_property;
+ object_class->get_property = brasero_video_disc_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_REJECT_FILE,
+ g_param_spec_boolean
+ ("reject-file",
+ "Whether it accepts files",
+ "Whether it accepts files",
+ FALSE,
+ G_PARAM_READWRITE));
+}
+
+GtkWidget *
+brasero_video_disc_new (void)
+{
+ return g_object_new (BRASERO_TYPE_VIDEO_DISC, NULL);
+}
+
Added: trunk/src/brasero-video-disc.h
==============================================================================
--- (empty file)
+++ trunk/src/brasero-video-disc.h Mon Jul 14 18:07:55 2008
@@ -0,0 +1,56 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * brasero is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _BRASERO_VIDEO_DISC_H_
+#define _BRASERO_VIDEO_DISC_H_
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BRASERO_TYPE_VIDEO_DISC (brasero_video_disc_get_type ())
+#define BRASERO_VIDEO_DISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_VIDEO_DISC, BraseroVideoDisc))
+#define BRASERO_VIDEO_DISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_VIDEO_DISC, BraseroVideoDiscClass))
+#define BRASERO_IS_VIDEO_DISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_VIDEO_DISC))
+#define BRASERO_IS_VIDEO_DISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_VIDEO_DISC))
+#define BRASERO_VIDEO_DISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_VIDEO_DISC, BraseroVideoDiscClass))
+
+typedef struct _BraseroVideoDiscClass BraseroVideoDiscClass;
+typedef struct _BraseroVideoDisc BraseroVideoDisc;
+
+struct _BraseroVideoDiscClass
+{
+ GtkVBoxClass parent_class;
+};
+
+struct _BraseroVideoDisc
+{
+ GtkVBox parent_instance;
+};
+
+GType brasero_video_disc_get_type (void) G_GNUC_CONST;
+
+GtkWidget *
+brasero_video_disc_new (void);
+
+G_END_DECLS
+
+#endif /* _BRASERO_VIDEO_DISC_H_ */
Added: trunk/src/brasero-video-project.c
==============================================================================
--- (empty file)
+++ trunk/src/brasero-video-project.c Mon Jul 14 18:07:55 2008
@@ -0,0 +1,1154 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * brasero is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include "brasero-video-project.h"
+#include "brasero-file-monitor.h"
+#include "brasero-io.h"
+#include "brasero-marshal.h"
+
+typedef struct _BraseroVideoProjectPrivate BraseroVideoProjectPrivate;
+struct _BraseroVideoProjectPrivate
+{
+ guint ref_count;
+ GHashTable *references;
+
+ BraseroIO *io;
+ BraseroIOJobBase *load_uri;
+ BraseroIOJobBase *load_dir;
+
+ BraseroVideoFile *first;
+
+ guint loading;
+};
+
+#define BRASERO_VIDEO_PROJECT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_VIDEO_PROJECT, BraseroVideoProjectPrivate))
+
+#ifdef BUILD_INOTIFY
+
+#include "brasero-file-monitor.h"
+
+G_DEFINE_TYPE (BraseroVideoProject, brasero_video_project, BRASERO_TYPE_FILE_MONITOR);
+
+#else
+
+G_DEFINE_TYPE (BraseroVideoProject, brasero_video_project, G_TYPE_OBJECT);
+
+#endif
+
+enum {
+ PROJECT_LOADED_SIGNAL,
+ SIZE_CHANGED_SIGNAL,
+ DIRECTORY_URI_SIGNAL,
+ UNREADABLE_SIGNAL,
+ NOT_VIDEO_SIGNAL,
+ ACTIVITY_SIGNAL,
+ LAST_SIGNAL
+};
+
+static guint brasero_video_project_signals [LAST_SIGNAL] = {0};
+
+/**
+ * Used to send signals with a default answer
+ */
+
+static gboolean
+brasero_video_project_file_signal (BraseroVideoProject *self,
+ guint signal,
+ const gchar *name)
+{
+ GValue instance_and_params [2];
+ GValue return_value;
+ GValue *params;
+
+ /* object which signalled */
+ instance_and_params->g_type = 0;
+ g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (self));
+ g_value_set_instance (instance_and_params, self);
+
+ /* arguments of signal (name) */
+ params = instance_and_params + 1;
+ params->g_type = 0;
+ g_value_init (params, G_TYPE_STRING);
+ g_value_set_string (params, name);
+
+ /* default to FALSE */
+ return_value.g_type = 0;
+ g_value_init (&return_value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&return_value, FALSE);
+
+ g_signal_emitv (instance_and_params,
+ brasero_video_project_signals [signal],
+ 0,
+ &return_value);
+
+ g_value_unset (instance_and_params);
+ g_value_unset (params);
+
+ return g_value_get_boolean (&return_value);
+}
+
+/**
+ * Manages the references to a node
+ */
+
+guint
+brasero_video_project_reference_new (BraseroVideoProject *self,
+ BraseroVideoFile *node)
+{
+ BraseroVideoProjectPrivate *priv;
+ guint retval;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ if (!priv->references)
+ priv->references = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ retval = priv->ref_count;
+ while (g_hash_table_lookup (priv->references, GINT_TO_POINTER (retval))) {
+ retval ++;
+
+ if (retval == G_MAXINT)
+ retval = 1;
+
+ /* this means there is no more room for reference */
+ if (retval == priv->ref_count)
+ return 0;
+ }
+
+ g_hash_table_insert (priv->references,
+ GINT_TO_POINTER (retval),
+ node);
+ priv->ref_count = retval + 1;
+ if (priv->ref_count == G_MAXINT)
+ priv->ref_count = 1;
+
+ return retval;
+}
+
+void
+brasero_video_project_reference_free (BraseroVideoProject *self,
+ guint reference)
+{
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ g_hash_table_remove (priv->references, GINT_TO_POINTER (reference));
+}
+
+BraseroVideoFile *
+brasero_video_project_reference_get (BraseroVideoProject *self,
+ guint reference)
+{
+ BraseroVideoProjectPrivate *priv;
+
+ /* if it was invalidated then the node returned is NULL */
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ return g_hash_table_lookup (priv->references, GINT_TO_POINTER (reference));
+}
+
+static gboolean
+brasero_video_project_reference_remove_children_cb (gpointer key,
+ gpointer data,
+ gpointer callback_data)
+{
+ BraseroVideoFile *node = data;
+ BraseroVideoFile *removable = callback_data;
+
+ if (node == removable)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+brasero_video_project_reference_invalidate (BraseroVideoProject *self,
+ BraseroVideoFile *node)
+{
+ BraseroVideoProjectPrivate *priv;
+
+ /* used internally to invalidate reference whose node was removed */
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ g_hash_table_foreach_remove (priv->references,
+ (GHRFunc) brasero_video_project_reference_remove_children_cb,
+ node);
+}
+
+/**
+ * Move functions
+ */
+
+void
+brasero_video_project_rename (BraseroVideoProject *self,
+ BraseroVideoFile *file,
+ const gchar *name)
+{
+ gchar *tmp;
+ BraseroVideoProjectClass *klass;
+
+ tmp = file->name;
+ file->name = g_strdup (name);
+ g_free (tmp);
+
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (self);
+ if (klass->node_changed)
+ klass->node_changed (self, file);
+}
+
+void
+brasero_video_project_move (BraseroVideoProject *self,
+ BraseroVideoFile *file,
+ BraseroVideoFile *next_file)
+{
+ BraseroVideoFile *prev, *next;
+ BraseroVideoProjectClass *klass;
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ if (!file)
+ return;
+
+ if (file == next_file)
+ return;
+
+ /* unlink it */
+ prev = file->prev;
+ next = file->next;
+
+ if (next)
+ next->prev = prev;
+
+ if (prev)
+ prev->next = next;
+ else
+ priv->first = next;
+
+ /* tell the model */
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (self);
+ if (klass->node_removed)
+ klass->node_removed (self, file);
+
+ /* relink it */
+ if (next_file) {
+ file->next = next_file;
+ file->prev = next_file->prev;
+ next_file->prev = file;
+
+ if (file->prev)
+ file->prev->next = file;
+ else
+ priv->first = file;
+ }
+ else if (priv->first) {
+ BraseroVideoFile *last;
+
+ /* Put it at the end */
+ last = priv->first;
+ while (last->next) last = last->next;
+
+ file->next = NULL;
+ file->prev = last;
+ last->next = file;
+ }
+ else {
+ priv->first = file;
+ file->next = NULL;
+ file->prev = NULL;
+ }
+
+ /* tell the model */
+ if (klass->node_added)
+ klass->node_added (self, file);
+}
+
+/**
+ * Remove functions
+ */
+
+void
+brasero_video_file_free (BraseroVideoFile *file)
+{
+ if (file->uri)
+ g_free (file->uri);
+
+ if (file->snapshot)
+ g_object_unref (file->snapshot);
+
+ if (file->info)
+ brasero_song_info_free (file->info);
+
+ g_free (file);
+}
+
+static gboolean
+brasero_video_project_foreach_monitor_cancel_cb (gpointer data,
+ gpointer user_data)
+{
+ BraseroVideoFile *node = data;
+ BraseroVideoFile *file = user_data;
+
+ if (node == file)
+ return TRUE;
+
+ return FALSE;
+}
+
+void
+brasero_video_project_remove_file (BraseroVideoProject *self,
+ BraseroVideoFile *file)
+{
+ BraseroVideoFile *prev, *next;
+ BraseroVideoProjectClass *klass;
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ if (!file)
+ return;
+
+ /* Unlink it */
+ prev = file->prev;
+ next = file->next;
+
+ if (next)
+ next->prev = prev;
+
+ if (prev)
+ prev->next = next;
+ else
+ priv->first = next;
+
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (self);
+ if (klass->node_removed)
+ klass->node_removed (self, file);
+
+ brasero_video_project_reference_invalidate (self, file);
+
+#ifdef BUILD_INOTIFY
+
+ /* Stop monitoring */
+ if (file->is_monitored)
+ brasero_file_monitor_foreach_cancel (BRASERO_FILE_MONITOR (self),
+ brasero_video_project_foreach_monitor_cancel_cb,
+ file);
+
+#endif
+
+ /* Free data */
+ brasero_video_file_free (file);
+
+ g_signal_emit (self,
+ brasero_video_project_signals [SIZE_CHANGED_SIGNAL],
+ 0);
+}
+
+void
+brasero_video_project_reset (BraseroVideoProject *self)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoProjectClass *klass;
+ BraseroVideoFile *iter, *next;
+ guint num_nodes = 0;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ /* cancel all VFS operations */
+ if (priv->io) {
+ brasero_io_cancel_by_base (priv->io, priv->load_uri);
+ brasero_io_cancel_by_base (priv->io, priv->load_dir);
+
+ g_free (priv->load_uri);
+ priv->load_uri = NULL;
+
+ g_free (priv->load_dir);
+ priv->load_dir = NULL;
+ }
+
+ /* destroy all references */
+ if (priv->references) {
+ g_hash_table_destroy (priv->references);
+ priv->references = g_hash_table_new (g_direct_hash, g_direct_equal);
+ }
+
+#ifdef BUILD_INOTIFY
+
+ brasero_file_monitor_reset (BRASERO_FILE_MONITOR (self));
+
+#endif
+
+ /* empty tree */
+ for (iter = priv->first; iter; iter = next) {
+ next = iter->next;
+ brasero_video_project_remove_file (self, iter);
+ }
+ priv->first = NULL;
+
+ priv->loading = 0;
+
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (self);
+ if (klass->reset)
+ klass->reset (self, num_nodes);
+}
+
+/**
+ * Add functions
+ */
+
+static BraseroVideoFile *
+brasero_video_project_add_video_file (BraseroVideoProject *self,
+ const gchar *uri,
+ BraseroVideoFile *sibling,
+ guint64 start,
+ guint64 end)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoFile *file;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ /* create new file and insert it */
+ file = g_new0 (BraseroVideoFile, 1);
+ file->uri = g_strdup (uri);
+
+ if (start > -1)
+ file->start = start;
+
+ if (end > -1)
+ file->end = end;
+
+ if (sibling) {
+ file->next = sibling;
+ file->prev = sibling->prev;
+
+ if (sibling->prev)
+ sibling->prev->next = file;
+ else
+ priv->first = file;
+
+ sibling->prev = file;
+ }
+ else if (priv->first) {
+ BraseroVideoFile *last;
+
+ /* Put it at the end */
+ last = priv->first;
+ while (last->next) last = last->next;
+
+ file->prev = last;
+ file->next = NULL;
+ last->next = file;
+ }
+ else {
+ priv->first = file;
+ file->next = NULL;
+ file->prev = NULL;
+ }
+
+ return file;
+}
+
+static void
+brasero_video_project_set_file_information (BraseroVideoProject *self,
+ BraseroVideoFile *file,
+ GFileInfo *info)
+{
+ guint64 len;
+ GdkPixbuf *snapshot;
+ BraseroSongInfo *song;
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ /* For reloading files no need to go further, we just want to check that
+ * they are still readable and still holds video. */
+ if (file->is_reloading) {
+ file->is_reloading = FALSE;
+ return;
+ }
+
+ file->is_loading = FALSE;
+
+ if (g_file_info_get_is_symlink (info)) {
+ gchar *sym_uri;
+
+ sym_uri = g_strconcat ("file://", g_file_info_get_symlink_target (info), NULL);
+ g_free (file->uri);
+
+ file->uri = sym_uri;
+ }
+
+ /* Set the snapshot */
+ snapshot = GDK_PIXBUF (g_file_info_get_attribute_object (info, BRASERO_IO_SNAPSHOT));
+ if (snapshot) {
+ GdkPixbuf *scaled;
+
+ scaled = gdk_pixbuf_scale_simple (snapshot,
+ 96 * gdk_pixbuf_get_width (snapshot) / gdk_pixbuf_get_height (snapshot),
+ 96,
+ GDK_INTERP_BILINEAR);
+ file->snapshot = scaled;
+ }
+
+ /* size */
+ len = g_file_info_get_attribute_uint64 (info, BRASERO_IO_LEN);
+ if (file->end > len)
+ file->end = len;
+ else if (file->end <= 0)
+ file->end = len;
+
+ /* Get the song info */
+ song = g_new0 (BraseroSongInfo, 1);
+ song->title = g_strdup (g_file_info_get_attribute_string (info, BRASERO_IO_TITLE));
+ song->artist = g_strdup (g_file_info_get_attribute_string (info, BRASERO_IO_ARTIST));
+ song->composer = g_strdup (g_file_info_get_attribute_string (info, BRASERO_IO_COMPOSER));
+ song->isrc = g_file_info_get_attribute_int32 (info, BRASERO_IO_ISRC);
+ file->info = song;
+
+#ifdef BUILD_INOTIFY
+
+ /* Start monitoring */
+ file->is_monitored = TRUE;
+ brasero_file_monitor_single_file (BRASERO_FILE_MONITOR (self),
+ file->uri,
+ file);
+
+#endif
+}
+
+static void
+brasero_video_project_vfs_operation_finished (GObject *object,
+ gboolean cancelled,
+ gpointer null_data)
+{
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (object);
+
+ priv->loading --;
+ g_signal_emit (object,
+ brasero_video_project_signals [ACTIVITY_SIGNAL],
+ 0,
+ priv->loading > 0);
+}
+
+static void
+brasero_video_project_add_directory_contents_result (GObject *obj,
+ GError *error,
+ const gchar *uri,
+ GFileInfo *info,
+ gpointer user_data)
+{
+ BraseroVideoFile *file;
+ BraseroVideoFile *sibling;
+ BraseroVideoProjectClass *klass;
+ guint ref = GPOINTER_TO_INT (user_data);
+
+ /* Check the return status for this file */
+ if (error)
+ return;
+
+ if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR
+ || !g_file_info_get_attribute_boolean (info, BRASERO_IO_HAS_VIDEO))
+ return;
+
+ sibling = brasero_video_project_reference_get (BRASERO_VIDEO_PROJECT (obj), ref);
+
+ /* Add a video file and set all information */
+ file = brasero_video_project_add_video_file (BRASERO_VIDEO_PROJECT (obj),
+ uri,
+ sibling,
+ -1,
+ -1);
+
+ brasero_video_project_set_file_information (BRASERO_VIDEO_PROJECT (obj),
+ file,
+ info);
+
+ /* Tell model we added a node */
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (obj);
+ if (klass->node_added)
+ klass->node_added (BRASERO_VIDEO_PROJECT (obj), file);
+
+ /* update size */
+ g_signal_emit (BRASERO_VIDEO_PROJECT (obj),
+ brasero_video_project_signals [SIZE_CHANGED_SIGNAL],
+ 0,
+ error,
+ uri);
+}
+
+static void
+brasero_video_project_add_directory_contents (BraseroVideoProject *self,
+ const gchar *uri,
+ BraseroVideoFile *sibling)
+{
+ BraseroVideoProjectPrivate *priv;
+ guint ref;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ if (!priv->io)
+ priv->io = brasero_io_get_default ();
+
+ if (!priv->load_dir)
+ priv->load_dir = brasero_io_register (G_OBJECT (self),
+ brasero_video_project_add_directory_contents_result,
+ brasero_video_project_vfs_operation_finished,
+ NULL);
+
+ priv->loading ++;
+ g_signal_emit (self,
+ brasero_video_project_signals [ACTIVITY_SIGNAL],
+ 0,
+ priv->loading != 0);
+
+ ref = brasero_video_project_reference_new (self, sibling);
+
+ brasero_io_load_directory (priv->io,
+ uri,
+ priv->load_dir,
+ BRASERO_IO_INFO_MIME|
+ BRASERO_IO_INFO_PERM|
+ BRASERO_IO_INFO_METADATA|
+ BRASERO_IO_INFO_METADATA_MISSING_CODEC|
+ BRASERO_IO_INFO_RECURSIVE|
+ BRASERO_IO_INFO_METADATA_SNAPSHOT,
+ GINT_TO_POINTER (ref));
+}
+
+static void
+brasero_video_project_result_cb (GObject *obj,
+ GError *error,
+ const gchar *uri,
+ GFileInfo *info,
+ gpointer user_data)
+{
+ BraseroVideoFile *file;
+ BraseroVideoProject *self;
+ BraseroVideoProjectClass *klass;
+ BraseroVideoProjectPrivate *priv;
+ guint ref = GPOINTER_TO_INT (user_data);
+
+ self = BRASERO_VIDEO_PROJECT (obj);
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (obj);
+
+ /* Get the reference for the node */
+ file = brasero_video_project_reference_get (self, ref);
+ if (!file)
+ return;
+
+ /* Check the return status for this file */
+ if (error) {
+ g_signal_emit (self,
+ brasero_video_project_signals [UNREADABLE_SIGNAL],
+ 0,
+ error,
+ uri);
+
+ brasero_video_project_remove_file (self, file);
+ return;
+ }
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
+ gboolean result;
+
+ /* Ask the user */
+ result = brasero_video_project_file_signal (self,
+ DIRECTORY_URI_SIGNAL,
+ uri);
+
+ /* NOTE: we need to pass a sibling here even if that the file
+ * that's going to be deleted just after. */
+ if (result)
+ brasero_video_project_add_directory_contents (self,
+ uri,
+ file->next?file->next:file);
+
+ /* remove the file */
+ brasero_video_project_remove_file (self, file);
+ return;
+ }
+
+ if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR
+ || !g_file_info_get_attribute_boolean (info, BRASERO_IO_HAS_VIDEO)) {
+ g_signal_emit (self,
+ brasero_video_project_signals [NOT_VIDEO_SIGNAL],
+ 0,
+ error,
+ uri);
+
+ brasero_video_project_remove_file (self, file);
+ return;
+ }
+
+ brasero_video_project_set_file_information (BRASERO_VIDEO_PROJECT (obj),
+ file,
+ info);
+
+ /* Tell upper object that the node status and information changed */
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (self);
+ if (klass->node_changed)
+ klass->node_changed (self, file);
+
+ /* update size */
+ g_signal_emit (self,
+ brasero_video_project_signals [SIZE_CHANGED_SIGNAL],
+ 0);
+}
+
+BraseroVideoFile *
+brasero_video_project_add_uri (BraseroVideoProject *self,
+ const gchar *uri,
+ BraseroVideoFile *sibling,
+ gint64 start,
+ gint64 end)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoProjectClass *klass;
+ BraseroVideoFile *file;
+ guint ref;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ /* create new file and insert it */
+ file = g_new0 (BraseroVideoFile, 1);
+ file->uri = g_strdup (uri);
+
+ if (start > -1)
+ file->start = start;
+
+ if (end > -1)
+ file->end = end;
+
+ if (sibling) {
+ file->next = sibling;
+ file->prev = sibling->prev;
+
+ if (sibling->prev)
+ sibling->prev->next = file;
+ else
+ priv->first = file;
+
+ sibling->prev = file;
+ }
+ else if (priv->first) {
+ BraseroVideoFile *last;
+
+ /* Put it at the end */
+ last = priv->first;
+ while (last->next) last = last->next;
+
+ file->prev = last;
+ file->next = NULL;
+ last->next = file;
+ }
+ else {
+ priv->first = file;
+ file->next = NULL;
+ file->prev = NULL;
+ }
+
+ /* Tell model we added a node */
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (self);
+ if (klass->node_added)
+ klass->node_added (self, file);
+
+ /* get info async for the file */
+ if (!priv->io)
+ priv->io = brasero_io_get_default ();
+
+ if (!priv->load_uri)
+ priv->load_uri = brasero_io_register (G_OBJECT (self),
+ brasero_video_project_result_cb,
+ brasero_video_project_vfs_operation_finished,
+ NULL);
+
+ file->is_loading = 1;
+ priv->loading ++;
+
+ ref = brasero_video_project_reference_new (self, file);
+ brasero_io_get_file_info (priv->io,
+ uri,
+ priv->load_uri,
+ BRASERO_IO_INFO_PERM|
+ BRASERO_IO_INFO_MIME|
+ BRASERO_IO_INFO_URGENT|
+ BRASERO_IO_INFO_METADATA|
+ BRASERO_IO_INFO_METADATA_MISSING_CODEC|
+ BRASERO_IO_INFO_METADATA_SNAPSHOT,
+ GINT_TO_POINTER (ref));
+
+ g_signal_emit (self,
+ brasero_video_project_signals [ACTIVITY_SIGNAL],
+ 0,
+ (priv->loading > 0));
+
+ return file;
+}
+
+void
+brasero_video_project_resize_file (BraseroVideoProject *self,
+ BraseroVideoFile *file,
+ gint64 start,
+ gint64 end)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoProjectClass *klass;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ file->start = start;
+ file->end = end;
+
+ klass = BRASERO_VIDEO_PROJECT_GET_CLASS (self);
+ if (klass->node_changed)
+ klass->node_changed (self, file);
+
+ /* update size */
+ g_signal_emit (self,
+ brasero_video_project_signals [SIZE_CHANGED_SIGNAL],
+ 0);
+}
+
+guint64
+brasero_video_project_get_size (BraseroVideoProject *self)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoFile *iter;
+ guint size = 0;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ /* FIXME: duration to sectors is not correct here, that's not audio... */
+ for (iter = priv->first; iter; iter = iter->next)
+ size += BRASERO_DURATION_TO_SECTORS (iter->end - iter->start);
+
+ return size;
+}
+
+guint
+brasero_video_project_get_file_num (BraseroVideoProject *self)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoFile *item;
+ guint num = 0;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ for (item = priv->first; item; item = item->next)
+ num ++;
+
+ return num;
+}
+
+BraseroVideoFile *
+brasero_video_project_get_nth_item (BraseroVideoProject *self,
+ guint nth)
+{
+ BraseroVideoFile *item;
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ if (!nth)
+ return priv->first;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ for (item = priv->first; item; item = item->next) {
+ if (nth <= 0)
+ return item;
+
+ nth --;
+ }
+
+ return NULL;
+}
+
+guint
+brasero_video_project_get_item_index (BraseroVideoProject *self,
+ BraseroVideoFile *file)
+{
+ guint nth = 0;
+ BraseroVideoFile *item;
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ for (item = priv->first; item; item = item->next) {
+ if (item == file)
+ return nth;
+
+ nth ++;
+ }
+
+ return nth;
+}
+
+BraseroDiscResult
+brasero_video_project_get_status (BraseroVideoProject *self)
+{
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+
+ if (priv->loading)
+ return BRASERO_DISC_LOADING;
+
+ if (!priv->first)
+ return BRASERO_DISC_ERROR_EMPTY_SELECTION;
+
+ return BRASERO_DISC_OK;
+}
+
+GSList *
+brasero_video_project_get_contents (BraseroVideoProject *self)
+{
+ GSList *tracks = NULL;
+ BraseroVideoFile *file;
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (self);
+ if (!priv->first)
+ return NULL;
+
+ for (file = priv->first; file; file = file->next) {
+ BraseroSongInfo *info = NULL;
+ BraseroTrack *track;
+
+ if (file->info)
+ info = brasero_song_info_copy (file->info);
+ else
+ info = NULL;
+
+ track = brasero_track_new (BRASERO_TRACK_TYPE_AUDIO);
+ brasero_track_set_audio_source (track,
+ file->uri,
+ BRASERO_AUDIO_FORMAT_UNDEFINED|
+ BRASERO_VIDEO_FORMAT_UNDEFINED);
+
+ brasero_track_set_audio_boundaries (track, file->start, file->end, -1);
+ brasero_track_set_audio_info (track, info);
+ tracks = g_slist_prepend (tracks, track);
+ }
+
+ return tracks;
+}
+
+static void
+brasero_video_project_init (BraseroVideoProject *object)
+{
+ BraseroVideoProjectPrivate *priv;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (object);
+ priv->ref_count = 1;
+}
+
+static void
+brasero_video_project_finalize (GObject *object)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoFile *iter, *next;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (object);
+
+ for (iter = priv->first; iter; iter = next) {
+ next = iter->next;
+ g_free (iter->uri);
+ brasero_song_info_free (iter->info);
+ g_free (iter);
+ }
+
+ if (priv->references) {
+ g_hash_table_destroy (priv->references);
+ priv->references = NULL;
+ }
+
+ G_OBJECT_CLASS (brasero_video_project_parent_class)->finalize (object);
+}
+/**
+ * Callbacks for inotify backend
+ */
+
+#ifdef BUILD_INOTIFY
+
+static void
+brasero_video_project_file_renamed (BraseroFileMonitor *monitor,
+ BraseroFileMonitorType type,
+ gpointer callback_data,
+ const gchar *old_name,
+ const gchar *new_name)
+{
+ brasero_video_project_rename (BRASERO_VIDEO_PROJECT (monitor),
+ callback_data,
+ new_name);
+}
+
+static void
+brasero_video_project_file_removed (BraseroFileMonitor *monitor,
+ BraseroFileMonitorType type,
+ gpointer callback_data,
+ const gchar *name)
+{
+ brasero_video_project_remove_file (BRASERO_VIDEO_PROJECT (monitor),
+ callback_data);
+}
+
+static void
+brasero_video_project_file_modified (BraseroFileMonitor *monitor,
+ gpointer callback_data,
+ const gchar *name)
+{
+ BraseroVideoProjectPrivate *priv;
+ BraseroVideoFile *file;
+ guint ref;
+
+ priv = BRASERO_VIDEO_PROJECT_PRIVATE (monitor);
+
+ /* priv->load_uri has already been initialized otherwise the tree would
+ * be empty. But who knows... */
+ if (!priv->io || !priv->load_uri)
+ return;
+
+ file = callback_data;
+ file->is_reloading = TRUE;
+
+ ref = brasero_video_project_reference_new (BRASERO_VIDEO_PROJECT (monitor), file);
+ brasero_io_get_file_info (priv->io,
+ file->uri,
+ priv->load_uri,
+ BRASERO_IO_INFO_PERM|
+ BRASERO_IO_INFO_MIME|
+ BRASERO_IO_INFO_URGENT|
+ BRASERO_IO_INFO_METADATA|
+ BRASERO_IO_INFO_METADATA_MISSING_CODEC|
+ BRASERO_IO_INFO_METADATA_SNAPSHOT,
+ GINT_TO_POINTER (ref));
+}
+
+static void
+brasero_video_project_file_moved (BraseroFileMonitor *monitor,
+ BraseroFileMonitorType type,
+ gpointer callback_src,
+ const gchar *name_src,
+ gpointer callback_dest,
+ const gchar *name_dest)
+{
+ /* This is a file removed since we won't monitor all folders to get its
+ * new path */
+ /* FIXME: what about files moved to one of the URI in the list ? */
+ brasero_video_project_remove_file (BRASERO_VIDEO_PROJECT (monitor),
+ callback_src);
+}
+
+#endif
+
+static void
+brasero_video_project_class_init (BraseroVideoProjectClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (BraseroVideoProjectPrivate));
+
+ object_class->finalize = brasero_video_project_finalize;
+
+ brasero_video_project_signals [SIZE_CHANGED_SIGNAL] =
+ g_signal_new ("size_changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0,
+ G_TYPE_NONE);
+
+ brasero_video_project_signals [PROJECT_LOADED_SIGNAL] =
+ g_signal_new ("project-loaded",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
+
+ brasero_video_project_signals [UNREADABLE_SIGNAL] =
+ g_signal_new ("unreadable_uri",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ brasero_marshal_VOID__POINTER_STRING,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_POINTER,
+ G_TYPE_STRING);
+
+ brasero_video_project_signals [NOT_VIDEO_SIGNAL] =
+ g_signal_new ("not_video_uri",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+ brasero_video_project_signals [DIRECTORY_URI_SIGNAL] =
+ g_signal_new ("directory_uri",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
+ 0,
+ NULL, NULL,
+ brasero_marshal_BOOLEAN__STRING,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_STRING);
+
+ brasero_video_project_signals [ACTIVITY_SIGNAL] =
+ g_signal_new ("vfs_activity",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST|G_SIGNAL_NO_RECURSE,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+
+#ifdef BUILD_INOTIFY
+
+ BraseroFileMonitorClass *monitor_class = BRASERO_FILE_MONITOR_CLASS (klass);
+
+ /* NOTE: file_added is not needed here since there aren't any directory */
+ monitor_class->file_moved = brasero_video_project_file_moved;
+ monitor_class->file_removed = brasero_video_project_file_removed;
+ monitor_class->file_renamed = brasero_video_project_file_renamed;
+ monitor_class->file_modified = brasero_video_project_file_modified;
+
+#endif
+}
Added: trunk/src/brasero-video-project.h
==============================================================================
--- (empty file)
+++ trunk/src/brasero-video-project.h Mon Jul 14 18:07:55 2008
@@ -0,0 +1,176 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * brasero is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef _BRASERO_VIDEO_PROJECT_H_
+#define _BRASERO_VIDEO_PROJECT_H_
+
+#include <glib-object.h>
+#include <gdk/gdk.h>
+
+#ifdef BUILD_INOTIFY
+
+#include "brasero-file-monitor.h"
+
+#endif
+
+#include "burn-track.h"
+#include "brasero-disc.h"
+
+G_BEGIN_DECLS
+
+#define BRASERO_TYPE_VIDEO_PROJECT (brasero_video_project_get_type ())
+#define BRASERO_VIDEO_PROJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_VIDEO_PROJECT, BraseroVideoProject))
+#define BRASERO_VIDEO_PROJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_VIDEO_PROJECT, BraseroVideoProjectClass))
+#define BRASERO_IS_VIDEO_PROJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_VIDEO_PROJECT))
+#define BRASERO_IS_VIDEO_PROJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_VIDEO_PROJECT))
+#define BRASERO_VIDEO_PROJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_VIDEO_PROJECT, BraseroVideoProjectClass))
+
+typedef struct _BraseroVideoProjectClass BraseroVideoProjectClass;
+typedef struct _BraseroVideoProject BraseroVideoProject;
+
+typedef struct _BraseroVideoFile BraseroVideoFile;
+struct _BraseroVideoFile {
+ BraseroVideoFile *prev;
+ BraseroVideoFile *next;
+
+ gchar *name;
+ gchar *uri;
+
+ BraseroSongInfo *info;
+
+ guint64 start;
+ guint64 end;
+
+ GdkPixbuf *snapshot;
+
+ guint editable:1;
+ guint is_loading:1;
+ guint is_reloading:1;
+ guint is_monitored:1;
+};
+
+struct _BraseroVideoProjectClass
+{
+#ifdef BUILD_INOTIFY
+ BraseroFileMonitorClass parent_class;
+#else
+ GObjectClass parent_class;
+#endif
+
+ /* virtual functions */
+
+ /**
+ * num_nodes is the number of nodes that were at the root of the
+ * project.
+ */
+ void (*reset) (BraseroVideoProject *project,
+ guint num_nodes);
+
+ /* NOTE: node_added is also called when there is a moved node;
+ * in this case a node_removed is first called and then the
+ * following function is called (mostly to match GtkTreeModel
+ * API). To detect such a case look at uri which will then be
+ * set to NULL.
+ * NULL uri can also happen when it's a created directory.
+ * if return value is FALSE, node was invalidated during call */
+ gboolean (*node_added) (BraseroVideoProject *project,
+ BraseroVideoFile *node);
+
+ /* This is more an unparent signal. It shouldn't be assumed that the
+ * node was destroyed or not destroyed. Like the above function, it is
+ * also called when a node is moved. */
+ void (*node_removed) (BraseroVideoProject *project,
+ BraseroVideoFile *node);
+
+ void (*node_changed) (BraseroVideoProject *project,
+ BraseroVideoFile *node);
+
+ /* NOTE: there is no node reordered as this list order cannot be changed */
+};
+
+struct _BraseroVideoProject
+{
+#ifdef BUILD_INOTIFY
+ BraseroFileMonitor parent_instance;
+#else
+ GObject parent_instance;
+#endif
+};
+
+GType brasero_video_project_get_type (void) G_GNUC_CONST;
+
+void
+brasero_video_file_free (BraseroVideoFile *file);
+
+guint64
+brasero_video_project_get_size (BraseroVideoProject *project);
+
+guint
+brasero_video_project_get_file_num (BraseroVideoProject *project);
+
+void
+brasero_video_project_reset (BraseroVideoProject *project);
+
+void
+brasero_video_project_move (BraseroVideoProject *project,
+ BraseroVideoFile *file,
+ BraseroVideoFile *next);
+
+void
+brasero_video_project_rename (BraseroVideoProject *project,
+ BraseroVideoFile *file,
+ const gchar *name);
+
+void
+brasero_video_project_remove_file (BraseroVideoProject *project,
+ BraseroVideoFile *file);
+
+BraseroVideoFile *
+brasero_video_project_add_uri (BraseroVideoProject *project,
+ const gchar *uri,
+ BraseroVideoFile *sibling,
+ gint64 start,
+ gint64 end);
+
+void
+brasero_video_project_resize_file (BraseroVideoProject *project,
+ BraseroVideoFile *file,
+ gint64 start,
+ gint64 end);
+
+BraseroDiscResult
+brasero_video_project_get_status (BraseroVideoProject *project);
+
+GSList *
+brasero_video_project_get_contents (BraseroVideoProject *project);
+
+BraseroVideoFile *
+brasero_video_project_get_nth_item (BraseroVideoProject *project,
+ guint nth);
+guint
+brasero_video_project_get_item_index (BraseroVideoProject *project,
+ BraseroVideoFile *file);
+
+G_END_DECLS
+
+#endif /* _BRASERO_VIDEO_PROJECT_H_ */
Added: trunk/src/brasero-video-tree-model.c
==============================================================================
--- (empty file)
+++ trunk/src/brasero-video-tree-model.c Mon Jul 14 18:07:55 2008
@@ -0,0 +1,727 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2007 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software.
+ *
+ * You may redistribute it and/or modify it under the terms of the
+ * GNU General Public License, as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * brasero is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with brasero. If not, write to:
+ * The Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gtk/gtktreemodel.h>
+#include <gtk/gtktreednd.h>
+#include <gtk/gtkicontheme.h>
+
+#include "burn-basics.h"
+#include "brasero-utils.h"
+#include "brasero-video-project.h"
+#include "brasero-video-tree-model.h"
+
+#include "eggtreemultidnd.h"
+
+typedef struct _BraseroVideoTreeModelPrivate BraseroVideoTreeModelPrivate;
+struct _BraseroVideoTreeModelPrivate
+{
+ guint stamp;
+ GtkIconTheme *theme;
+};
+
+#define BRASERO_VIDEO_TREE_MODEL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_VIDEO_TREE_MODEL, BraseroVideoTreeModelPrivate))
+
+static void
+brasero_video_tree_model_multi_drag_source_iface_init (gpointer g_iface, gpointer data);
+static void
+brasero_video_tree_model_drag_source_iface_init (gpointer g_iface, gpointer data);
+static void
+brasero_video_tree_model_drag_dest_iface_init (gpointer g_iface, gpointer data);
+static void
+brasero_video_tree_model_iface_init (gpointer g_iface, gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE (BraseroVideoTreeModel,
+ brasero_video_tree_model,
+ BRASERO_TYPE_VIDEO_PROJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+ brasero_video_tree_model_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
+ brasero_video_tree_model_drag_dest_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
+ brasero_video_tree_model_drag_source_iface_init)
+ G_IMPLEMENT_INTERFACE (EGG_TYPE_TREE_MULTI_DRAG_SOURCE,
+ brasero_video_tree_model_multi_drag_source_iface_init));
+
+
+/**
+ * This is mainly a list so the following functions are not implemented.
+ * But we may need them for AUDIO models when we display GAPs
+ */
+static gboolean
+brasero_video_tree_model_iter_parent (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+static gboolean
+brasero_video_tree_model_iter_nth_child (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ gint n)
+{
+ return FALSE;
+}
+
+static gint
+brasero_video_tree_model_iter_n_children (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ return 0;
+}
+
+static gboolean
+brasero_video_tree_model_iter_has_child (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ return FALSE;
+}
+
+static gboolean
+brasero_video_tree_model_iter_children (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ return FALSE;
+}
+
+static void
+brasero_video_tree_model_get_value (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gint column,
+ GValue *value)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ BraseroVideoTreeModel *self;
+ BraseroVideoFile *file;
+ GdkPixbuf *pixbuf;
+ gchar *text;
+
+ self = BRASERO_VIDEO_TREE_MODEL (model);
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (model);
+
+ /* make sure that iter comes from us */
+ g_return_if_fail (priv->stamp == iter->stamp);
+ g_return_if_fail (iter->user_data != NULL);
+
+ file = iter->user_data;
+
+ switch (column) {
+ case BRASERO_VIDEO_TREE_MODEL_NAME:
+ g_value_init (value, G_TYPE_STRING);
+
+ if (file->name)
+ g_value_set_string (value, file->name);
+ else if (file->info && file->info->title)
+ g_value_set_string (value, file->info->title);
+ else {
+ gchar *name;
+ gchar *path;
+ gchar *unescaped;
+
+ unescaped = g_uri_unescape_string (file->uri, NULL);
+ path = g_filename_from_uri (unescaped, NULL, NULL);
+ g_free (unescaped);
+
+ name = g_path_get_basename (path);
+ g_free (path);
+
+ g_value_set_string (value, name);
+ g_free (name);
+ }
+
+ return;
+
+ case BRASERO_VIDEO_TREE_MODEL_MIME_ICON:
+ g_value_init (value, GDK_TYPE_PIXBUF);
+
+ if (file->snapshot) {
+ pixbuf = file->snapshot;
+ g_object_ref (file->snapshot);
+ }
+ else if (file->is_loading) {
+ pixbuf = gtk_icon_theme_load_icon (priv->theme,
+ "image-loading",
+ 96,
+ 0,
+ NULL);
+ }
+ else {
+ pixbuf = gtk_icon_theme_load_icon (priv->theme,
+ "image-missing",
+ 96,
+ 0,
+ NULL);
+ }
+
+ g_value_set_object (value, pixbuf);
+ g_object_unref (pixbuf);
+
+ return;
+
+ case BRASERO_VIDEO_TREE_MODEL_SIZE:
+ g_value_init (value, G_TYPE_STRING);
+
+ if (!file->is_loading) {
+ text = brasero_utils_get_time_string (file->end - file->start, TRUE, FALSE);
+ g_value_set_string (value, text);
+ g_free (text);
+ }
+ else
+ g_value_set_string (value, _("loading"));
+
+ return;
+
+ case BRASERO_VIDEO_TREE_MODEL_EDITABLE:
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, file->editable);
+
+ return;
+
+ default:
+ return;
+ }
+
+ return;
+}
+
+GtkTreePath *
+brasero_video_tree_model_file_to_path (BraseroVideoTreeModel *self,
+ BraseroVideoFile *file)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ GtkTreePath *path;
+ guint nth;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (self);
+
+ path = gtk_tree_path_new ();
+ nth = brasero_video_project_get_item_index (BRASERO_VIDEO_PROJECT (self), file);
+ gtk_tree_path_prepend_index (path, nth);
+
+ return path;
+}
+
+static GtkTreePath *
+brasero_video_tree_model_get_path (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ BraseroVideoFile *file;
+ GtkTreePath *path;
+ guint nth;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (model);
+
+ /* make sure that iter comes from us */
+ g_return_val_if_fail (priv->stamp == iter->stamp, NULL);
+ g_return_val_if_fail (iter->user_data != NULL, NULL);
+
+ file = iter->user_data;
+
+ /* NOTE: there is only one single file without a name: root */
+ path = gtk_tree_path_new ();
+ nth = brasero_video_project_get_item_index (BRASERO_VIDEO_PROJECT (model), file);
+ gtk_tree_path_prepend_index (path, nth);
+
+ return path;
+}
+
+BraseroVideoFile *
+brasero_video_tree_model_path_to_file (BraseroVideoTreeModel *self,
+ GtkTreePath *path)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ const gint *indices;
+ guint depth;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (self);
+
+ indices = gtk_tree_path_get_indices (path);
+ depth = gtk_tree_path_get_depth (path);
+
+ /* NOTE: it can happen that paths are depth 2 when there is DND but then
+ * only the first index is relevant. */
+ if (depth > 2)
+ return NULL;
+
+ return brasero_video_project_get_nth_item (BRASERO_VIDEO_PROJECT (self), indices [0]);
+}
+
+static gboolean
+brasero_video_tree_model_get_iter (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ BraseroVideoFile *file;
+ const gint *indices;
+ guint depth;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (model);
+
+ depth = gtk_tree_path_get_depth (path);
+ if (depth > 2)
+ return FALSE;
+
+ indices = gtk_tree_path_get_indices (path);
+ file = brasero_video_project_get_nth_item (BRASERO_VIDEO_PROJECT (model),
+ indices [0]);
+ if (!file)
+ return FALSE;
+
+ iter->user_data = file;
+ iter->stamp = priv->stamp;
+
+ return TRUE;
+}
+
+static gboolean
+brasero_video_tree_model_iter_next (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ BraseroVideoFile *file;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (model);
+
+ /* make sure that iter comes from us */
+ g_return_val_if_fail (priv->stamp == iter->stamp, FALSE);
+ g_return_val_if_fail (iter->user_data != NULL, FALSE);
+
+ file = iter->user_data;
+ if (!file || !file->next)
+ return FALSE;
+
+ iter->user_data = file->next;
+ return TRUE;
+}
+
+static GType
+brasero_video_tree_model_get_column_type (GtkTreeModel *model,
+ gint index)
+{
+ switch (index) {
+ case BRASERO_VIDEO_TREE_MODEL_NAME:
+ return G_TYPE_STRING;
+
+ case BRASERO_VIDEO_TREE_MODEL_MIME_ICON:
+ return GDK_TYPE_PIXBUF;
+
+ case BRASERO_VIDEO_TREE_MODEL_SIZE:
+ return G_TYPE_STRING;
+
+ case BRASERO_VIDEO_TREE_MODEL_EDITABLE:
+ return G_TYPE_BOOLEAN;
+
+ default:
+ break;
+ }
+
+ return G_TYPE_INVALID;
+}
+
+static gint
+brasero_video_tree_model_get_n_columns (GtkTreeModel *model)
+{
+ return BRASERO_VIDEO_TREE_MODEL_COL_NUM;
+}
+
+static GtkTreeModelFlags
+brasero_video_tree_model_get_flags (GtkTreeModel *model)
+{
+ return GTK_TREE_MODEL_LIST_ONLY;
+}
+
+static gboolean
+brasero_video_tree_model_multi_row_draggable (EggTreeMultiDragSource *drag_source,
+ GList *path_list)
+{
+ /* All rows are draggable so return TRUE */
+ return TRUE;
+}
+
+static gboolean
+brasero_video_tree_model_multi_drag_data_get (EggTreeMultiDragSource *drag_source,
+ GList *path_list,
+ GtkSelectionData *selection_data)
+{
+ if (selection_data->target == gdk_atom_intern (BRASERO_DND_TARGET_SELF_FILE_NODES, TRUE)) {
+ BraseroDNDVideoContext context;
+
+ context.model = GTK_TREE_MODEL (drag_source);
+ context.references = path_list;
+
+ gtk_selection_data_set (selection_data,
+ gdk_atom_intern_static_string (BRASERO_DND_TARGET_SELF_FILE_NODES),
+ 8,
+ (void *) &context,
+ sizeof (context));
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+brasero_video_tree_model_multi_drag_data_delete (EggTreeMultiDragSource *drag_source,
+ GList *path_list)
+{
+ /* NOTE: it's not the data in the selection_data here that should be
+ * deleted but rather the rows selected when there is a move. FALSE
+ * here means that we didn't delete anything. */
+ /* return TRUE to stop other handlers */
+ return TRUE;
+}
+
+static gboolean
+brasero_video_tree_model_drag_data_received (GtkTreeDragDest *drag_dest,
+ GtkTreePath *dest_path,
+ GtkSelectionData *selection_data)
+{
+ BraseroVideoFile *file;
+ BraseroVideoFile *sibling;
+ BraseroVideoTreeModel *self;
+
+ self = BRASERO_VIDEO_TREE_MODEL (drag_dest);
+
+ /* The new row(s) must be before dest_path but after our sibling */
+ sibling = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (drag_dest), dest_path);
+
+ /* Received data: see where it comes from:
+ * - from us, then that's a simple move
+ * - from another widget then it's going to be URIS and we add
+ * them to VideoProject */
+ if (selection_data->target == gdk_atom_intern (BRASERO_DND_TARGET_SELF_FILE_NODES, TRUE)) {
+ BraseroDNDVideoContext *context;
+ GList *iter;
+
+ context = (BraseroDNDVideoContext *) selection_data->data;
+ if (context->model != GTK_TREE_MODEL (drag_dest))
+ return TRUE;
+
+ /* That's us: move the row and its children. */
+ for (iter = context->references; iter; iter = iter->next) {
+ GtkTreeRowReference *reference;
+ GtkTreePath *treepath;
+
+ reference = iter->data;
+ treepath = gtk_tree_row_reference_get_path (reference);
+
+ file = brasero_video_tree_model_path_to_file (BRASERO_VIDEO_TREE_MODEL (drag_dest), treepath);
+ gtk_tree_path_free (treepath);
+
+ brasero_video_project_move (BRASERO_VIDEO_PROJECT (self), file, sibling);
+ }
+ }
+ else if (selection_data->target == gdk_atom_intern ("text/uri-list", TRUE)) {
+ gint i;
+ gchar **uris;
+ gboolean success = FALSE;
+
+ /* NOTE: there can be many URIs at the same time. One
+ * success is enough to return TRUE. */
+ success = FALSE;
+ uris = gtk_selection_data_get_uris (selection_data);
+ if (!uris)
+ return TRUE;
+
+ for (i = 0; uris [i]; i ++) {
+ /* Add the URIs to the project */
+ brasero_video_project_add_uri (BRASERO_VIDEO_PROJECT (self),
+ uris [i],
+ sibling,
+ -1,
+ -1);
+ }
+ g_strfreev (uris);
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+brasero_video_tree_model_row_drop_possible (GtkTreeDragDest *drag_dest,
+ GtkTreePath *dest_path,
+ GtkSelectionData *selection_data)
+{
+ /* It's always possible */
+ return TRUE;
+}
+
+static gboolean
+brasero_video_tree_model_drag_data_delete (GtkTreeDragSource *source,
+ GtkTreePath *treepath)
+{
+ return TRUE;
+}
+
+static void
+brasero_video_tree_model_clear (BraseroVideoTreeModel *self,
+ guint num_files)
+{
+ GtkTreePath *treepath;
+ BraseroVideoTreeModelPrivate *priv;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (self);
+
+ /* NOTE: no need to move to the next row since previous one was deleted */
+ treepath = gtk_tree_path_new_first ();
+ while (num_files > 0) {
+ num_files --;
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (self), treepath);
+ }
+ gtk_tree_path_free (treepath);
+}
+
+static void
+brasero_video_tree_model_reset (BraseroVideoProject *project,
+ guint num_files)
+{
+ brasero_video_tree_model_clear (BRASERO_VIDEO_TREE_MODEL (project), num_files);
+
+ /* chain up this function except if we invalidated the file */
+ if (BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->reset)
+ BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->reset (project, num_files);
+}
+
+static gboolean
+brasero_video_tree_model_file_added (BraseroVideoProject *project,
+ BraseroVideoFile *file)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (project);
+
+ iter.stamp = priv->stamp;
+ iter.user_data = file;
+
+ path = brasero_video_tree_model_file_to_path (BRASERO_VIDEO_TREE_MODEL (project), file);
+
+ /* if the file is reloading (because of a file system change or because
+ * it was a file that was a tmp folder) then no need to signal an added
+ * signal but a changed one */
+ if (file->is_reloading) {
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (project),
+ path,
+ &iter);
+ gtk_tree_path_free (path);
+ goto end;
+ }
+
+ /* Add the row itself */
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (project),
+ path,
+ &iter);
+ gtk_tree_path_free (path);
+
+end:
+ /* chain up this function */
+ if (BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->node_added)
+ return BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->node_added (project,
+ file);
+
+ return TRUE;
+}
+
+static void
+brasero_video_tree_model_file_removed (BraseroVideoProject *project,
+ BraseroVideoFile *file)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ BraseroVideoFile *next;
+ GtkTreePath *path;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (project);
+
+ /* remove the file. */
+ next = file->next;
+ path = brasero_video_tree_model_file_to_path (BRASERO_VIDEO_TREE_MODEL (project), next);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (project), path);
+ gtk_tree_path_free (path);
+
+ /* chain up this function */
+ if (BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->node_removed)
+ BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->node_removed (project,
+ file);
+}
+
+static void
+brasero_video_tree_model_file_changed (BraseroVideoProject *project,
+ BraseroVideoFile *file)
+{
+ BraseroVideoTreeModelPrivate *priv;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (project);
+
+ /* Get the iter for the file */
+ iter.stamp = priv->stamp;
+ iter.user_data = file;
+
+ path = brasero_video_tree_model_file_to_path (BRASERO_VIDEO_TREE_MODEL (project), file);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (project),
+ path,
+ &iter);
+ gtk_tree_path_free (path);
+
+ /* chain up this function */
+ if (BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->node_changed)
+ BRASERO_VIDEO_PROJECT_CLASS (brasero_video_tree_model_parent_class)->node_changed (project, file);
+}
+
+static void
+brasero_video_tree_model_init (BraseroVideoTreeModel *object)
+{
+ BraseroVideoTreeModelPrivate *priv;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (object);
+
+ priv->theme = gtk_icon_theme_get_default ();
+
+ do {
+ priv->stamp = g_random_int ();
+ } while (!priv->stamp);
+}
+
+static void
+brasero_video_tree_model_finalize (GObject *object)
+{
+ BraseroVideoTreeModelPrivate *priv;
+
+ priv = BRASERO_VIDEO_TREE_MODEL_PRIVATE (object);
+
+ if (priv->theme) {
+ g_object_unref (priv->theme);
+ priv->theme = NULL;
+ }
+
+ G_OBJECT_CLASS (brasero_video_tree_model_parent_class)->finalize (object);
+}
+
+static void
+brasero_video_tree_model_iface_init (gpointer g_iface, gpointer data)
+{
+ GtkTreeModelIface *iface = g_iface;
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ initialized = TRUE;
+
+ iface->get_flags = brasero_video_tree_model_get_flags;
+ iface->get_n_columns = brasero_video_tree_model_get_n_columns;
+ iface->get_column_type = brasero_video_tree_model_get_column_type;
+ iface->get_iter = brasero_video_tree_model_get_iter;
+ iface->get_path = brasero_video_tree_model_get_path;
+ iface->get_value = brasero_video_tree_model_get_value;
+ iface->iter_next = brasero_video_tree_model_iter_next;
+ iface->iter_children = brasero_video_tree_model_iter_children;
+ iface->iter_has_child = brasero_video_tree_model_iter_has_child;
+ iface->iter_n_children = brasero_video_tree_model_iter_n_children;
+ iface->iter_nth_child = brasero_video_tree_model_iter_nth_child;
+ iface->iter_parent = brasero_video_tree_model_iter_parent;
+}
+
+static void
+brasero_video_tree_model_multi_drag_source_iface_init (gpointer g_iface, gpointer data)
+{
+ EggTreeMultiDragSourceIface *iface = g_iface;
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ initialized = TRUE;
+
+ iface->row_draggable = brasero_video_tree_model_multi_row_draggable;
+ iface->drag_data_get = brasero_video_tree_model_multi_drag_data_get;
+ iface->drag_data_delete = brasero_video_tree_model_multi_drag_data_delete;
+}
+
+static void
+brasero_video_tree_model_drag_source_iface_init (gpointer g_iface, gpointer data)
+{
+ GtkTreeDragSourceIface *iface = g_iface;
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ initialized = TRUE;
+
+ iface->drag_data_delete = brasero_video_tree_model_drag_data_delete;
+}
+
+static void
+brasero_video_tree_model_drag_dest_iface_init (gpointer g_iface, gpointer data)
+{
+ GtkTreeDragDestIface *iface = g_iface;
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ initialized = TRUE;
+
+ iface->drag_data_received = brasero_video_tree_model_drag_data_received;
+ iface->row_drop_possible = brasero_video_tree_model_row_drop_possible;
+}
+
+static void
+brasero_video_tree_model_class_init (BraseroVideoTreeModelClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ BraseroVideoProjectClass *video_class = BRASERO_VIDEO_PROJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (BraseroVideoTreeModelPrivate));
+
+ object_class->finalize = brasero_video_tree_model_finalize;
+
+ video_class->reset = brasero_video_tree_model_reset;
+ video_class->node_added = brasero_video_tree_model_file_added;
+ video_class->node_removed = brasero_video_tree_model_file_removed;
+ video_class->node_changed = brasero_video_tree_model_file_changed;
+}
+
+BraseroVideoTreeModel *
+brasero_video_tree_model_new (void)
+{
+ return g_object_new (BRASERO_TYPE_VIDEO_TREE_MODEL, NULL);
+}
Added: trunk/src/brasero-video-tree-model.h
==============================================================================
--- (empty file)
+++ trunk/src/brasero-video-tree-model.h Mon Jul 14 18:07:55 2008
@@ -0,0 +1,83 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2007 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software.
+ *
+ * You may redistribute it and/or modify it under the terms of the
+ * GNU General Public License, as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * brasero is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with brasero. If not, write to:
+ * The Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _BRASERO_VIDEO_TREE_MODEL_H_
+#define _BRASERO_VIDEO_TREE_MODEL_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* This DND target when moving nodes inside ourselves */
+#define BRASERO_DND_TARGET_SELF_FILE_NODES "GTK_TREE_MODEL_ROW"
+
+struct _BraseroDNDVideoContext {
+ GtkTreeModel *model;
+ GList *references;
+};
+typedef struct _BraseroDNDVideoContext BraseroDNDVideoContext;
+
+typedef enum {
+ BRASERO_VIDEO_TREE_MODEL_NAME = 0,
+ BRASERO_VIDEO_TREE_MODEL_MIME_ICON,
+ BRASERO_VIDEO_TREE_MODEL_SIZE,
+ BRASERO_VIDEO_TREE_MODEL_EDITABLE,
+ BRASERO_VIDEO_TREE_MODEL_COL_NUM
+} BraseroVideoProjectColumn;
+
+#define BRASERO_TYPE_VIDEO_TREE_MODEL (brasero_video_tree_model_get_type ())
+#define BRASERO_VIDEO_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_VIDEO_TREE_MODEL, BraseroVideoTreeModel))
+#define BRASERO_VIDEO_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_VIDEO_TREE_MODEL, BraseroVideoTreeModelClass))
+#define BRASERO_IS_VIDEO_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_VIDEO_TREE_MODEL))
+#define BRASERO_IS_VIDEO_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_VIDEO_TREE_MODEL))
+#define BRASERO_VIDEO_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_VIDEO_TREE_MODEL, BraseroVideoTreeModelClass))
+
+typedef struct _BraseroVideoTreeModelClass BraseroVideoTreeModelClass;
+typedef struct _BraseroVideoTreeModel BraseroVideoTreeModel;
+
+struct _BraseroVideoTreeModelClass
+{
+ BraseroVideoProjectClass parent_class;
+};
+
+struct _BraseroVideoTreeModel
+{
+ BraseroVideoProject parent_instance;
+};
+
+GType brasero_video_tree_model_get_type (void) G_GNUC_CONST;
+
+BraseroVideoTreeModel *
+brasero_video_tree_model_new (void);
+
+BraseroVideoFile *
+brasero_video_tree_model_path_to_file (BraseroVideoTreeModel *self,
+ GtkTreePath *path);
+GtkTreePath *
+brasero_video_tree_model_file_to_path (BraseroVideoTreeModel *self,
+ BraseroVideoFile *file);
+
+G_END_DECLS
+
+#endif /* _BRASERO_VIDEO_TREE_MODEL_H_ */
Modified: trunk/src/burn-basics.h
==============================================================================
--- trunk/src/burn-basics.h (original)
+++ trunk/src/burn-basics.h Mon Jul 14 18:07:55 2008
@@ -155,7 +155,7 @@
BRASERO_BURN_FLAG_LAST
} BraseroBurnFlag;
-#define BRASERO_BURN_FLAG_ALL 0x7FFF
+#define BRASERO_BURN_FLAG_ALL 0xFFFF
#define BRASERO_PLUGIN_KEY "/apps/brasero/config/plugins"
@@ -180,6 +180,47 @@
void
brasero_burn_library_shutdown (void);
+/**
+ * Some defined and usable tags for a session
+ */
+
+/**
+ * Define the audio streams for a DVD
+ */
+#define BRASERO_DVD_AUDIO_STREAMS "DVD-audio-format"
+
+/**
+ * Define the format: whether VCD or SVCD
+ */
+enum {
+ BRASERO_VCD_NONE,
+ BRASERO_VCD_V1,
+ BRASERO_VCD_V2,
+ BRASERO_SVCD
+};
+#define BRASERO_VCD_TYPE "VCD-format"
+
+/**
+ * This is the video format that should be used.
+ */
+enum {
+ BRASERO_VIDEO_FRAMERATE_NATIVE,
+ BRASERO_VIDEO_FRAMERATE_NTSC,
+ BRASERO_VIDEO_FRAMERATE_PAL_SECAM
+};
+#define BRASERO_VIDEO_OUTPUT_FRAMERATE "video-framerate"
+
+/**
+ * Aspect ratio
+ */
+enum {
+ BRASERO_VIDEO_ASPECT_NATIVE,
+ BRASERO_VIDEO_ASPECT_4_3,
+ BRASERO_VIDEO_ASPECT_16_9
+};
+#define BRASERO_VIDEO_OUTPUT_ASPECT "video-aspect"
+
+
G_END_DECLS
#endif /* _BURN_BASICS_H */
Modified: trunk/src/burn-caps.c
==============================================================================
--- trunk/src/burn-caps.c (original)
+++ trunk/src/burn-caps.c Mon Jul 14 18:07:55 2008
@@ -801,6 +801,29 @@
return FALSE;
}
+static gboolean
+brasero_caps_link_check_media_restrictions (BraseroCapsLink *link,
+ BraseroMedia media)
+{
+ GSList *iter;
+
+ /* Go through all plugins: at least one must support record flags */
+ for (iter = link->plugins; iter; iter = iter->next) {
+ gboolean result;
+ BraseroPlugin *plugin;
+
+ plugin = iter->data;
+ if (!brasero_plugin_get_active (plugin))
+ continue;
+
+ result = brasero_plugin_check_media_restrictions (plugin, media);
+ if (result)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static BraseroPlugin *
brasero_caps_link_find_plugin (BraseroCapsLink *link,
gint group_id,
@@ -844,6 +867,8 @@
if (!result)
continue;
}
+ else if (!brasero_plugin_check_media_restrictions (plugin, media))
+ continue;
if (group_id > 0 && candidate) {
/* the candidate must be in the favourite group as much as possible */
@@ -1700,8 +1725,11 @@
/* first see if that's the perfect fit:
* - it must have the same caps (type + subtype)
* - it must have the proper IO */
- if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA
- && !brasero_caps_link_check_data_flags (link, session_flags, media))
+ if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
+ if (!brasero_caps_link_check_data_flags (link, session_flags, media))
+ continue;
+ }
+ else if (!brasero_caps_link_check_media_restrictions (link, media))
continue;
if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
@@ -2178,6 +2206,8 @@
if ((tmp & data_supported) != tmp)
continue;
}
+ else if (!brasero_caps_link_check_media_restrictions (link, media))
+ continue;
/* see if that's the perfect fit */
if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
@@ -2208,7 +2238,6 @@
flags,
supported,
compulsory);
-
if (io_flags == BRASERO_PLUGIN_IO_NONE)
continue;
@@ -2910,6 +2939,8 @@
BraseroCaps *caps;
BraseroAudioFormat common;
BraseroPluginIOFlag common_io;
+ BraseroAudioFormat common_audio;
+ BraseroAudioFormat common_video;
caps = iter->data;
@@ -2927,11 +2958,21 @@
continue;
}
- /* search caps strictly encompassed or encompassing our format */
- common = caps->type.subtype.audio_format & format;
- if (common == BRASERO_AUDIO_FORMAT_NONE)
+ /* Search caps strictly encompassed or encompassing our format
+ * NOTE: make sure that if there is a VIDEO stream in one of
+ * them, the other does have a VIDEO stream too. */
+ common_audio = BRASERO_AUDIO_CAPS_AUDIO (caps->type.subtype.audio_format) &
+ BRASERO_AUDIO_CAPS_AUDIO (format);
+ if (common_audio == BRASERO_AUDIO_FORMAT_NONE)
continue;
+ common_video = BRASERO_AUDIO_CAPS_VIDEO (caps->type.subtype.audio_format) &
+ BRASERO_AUDIO_CAPS_VIDEO (format);
+ if (common_video == BRASERO_AUDIO_FORMAT_NONE)
+ continue;
+
+ common = common_audio|common_video;
+
/* encompassed caps just add it to retval */
if (caps->type.subtype.audio_format == common)
retval = g_slist_prepend (retval, caps);
@@ -3523,7 +3564,8 @@
caps = iter->data;
if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE
- && caps->type.type != BRASERO_TRACK_TYPE_AUDIO)
+ && caps->type.type != BRASERO_TRACK_TYPE_AUDIO
+ && caps->type.type != BRASERO_TRACK_TYPE_DATA)
continue;
destination = caps->type.type;
Modified: trunk/src/burn-debug.c
==============================================================================
--- trunk/src/burn-debug.c (original)
+++ trunk/src/burn-debug.c Mon Jul 14 18:07:55 2008
@@ -268,10 +268,31 @@
strcat (buffer, "RAW ");
if (format & BRASERO_AUDIO_FORMAT_UNDEFINED)
- strcat (buffer, "UNDEFINED ");
+ strcat (buffer, "AUDIO UNDEFINED ");
if (format & BRASERO_AUDIO_FORMAT_4_CHANNEL)
strcat (buffer, "4 CHANNELS ");
+
+ if (format & BRASERO_AUDIO_FORMAT_MP2)
+ strcat (buffer, "MP2 ");
+
+ if (format & BRASERO_AUDIO_FORMAT_AC3)
+ strcat (buffer, "AC3 ");
+
+ if (format & BRASERO_AUDIO_FORMAT_44100)
+ strcat (buffer, "44100 ");
+
+ if (format & BRASERO_AUDIO_FORMAT_48000)
+ strcat (buffer, "48000 ");
+
+ if (format & BRASERO_VIDEO_FORMAT_UNDEFINED)
+ strcat (buffer, "VIDEO UNDEFINED ");
+
+ if (format & BRASERO_VIDEO_FORMAT_VCD)
+ strcat (buffer, "VCD ");
+
+ if (format & BRASERO_VIDEO_FORMAT_VCD)
+ strcat (buffer, "Video DVD ");
}
void
Modified: trunk/src/burn-job.c
==============================================================================
--- trunk/src/burn-job.c (original)
+++ trunk/src/burn-job.c Mon Jul 14 18:07:55 2008
@@ -617,8 +617,7 @@
}
}
else
- BRASERO_JOB_LOG (self, "linked to %s",
- G_OBJECT_TYPE_NAME (priv->linked));
+ BRASERO_JOB_LOG (self, "linked to %s", G_OBJECT_TYPE_NAME (priv->linked));
if (!brasero_job_is_first_active (self)) {
int fd [2];
@@ -1657,8 +1656,7 @@
{
BraseroJobPrivate *priv;
- BRASERO_JOB_DEBUG (self);
-
+ BRASERO_JOB_LOG (self, "Called brasero_job_set_progress (%lf)", progress);
priv = BRASERO_JOB_PRIVATE (self);
if (priv->next)
return BRASERO_BURN_ERR;
Modified: trunk/src/burn-medium.c
==============================================================================
--- trunk/src/burn-medium.c (original)
+++ trunk/src/burn-medium.c Mon Jul 14 18:07:55 2008
@@ -873,6 +873,7 @@
g_free (data);
return BRASERO_BURN_OK;
}
+
/**
* Functions to get information about disc contents
*/
Modified: trunk/src/burn-plugin-private.h
==============================================================================
--- trunk/src/burn-plugin-private.h (original)
+++ trunk/src/burn-plugin-private.h Mon Jul 14 18:07:55 2008
@@ -91,6 +91,9 @@
brasero_plugin_check_record_flags (BraseroPlugin *plugin,
BraseroMedia media,
BraseroBurnFlag current);
+gboolean
+brasero_plugin_check_media_restrictions (BraseroPlugin *plugin,
+ BraseroMedia media);
gboolean
brasero_plugin_get_image_flags (BraseroPlugin *plugin,
Modified: trunk/src/burn-plugin.c
==============================================================================
--- trunk/src/burn-plugin.c (original)
+++ trunk/src/burn-plugin.c Mon Jul 14 18:07:55 2008
@@ -605,6 +605,7 @@
BraseroPluginPrivate *priv;
priv = BRASERO_PLUGIN_PRIVATE (self);
+
current &= BRASERO_PLUGIN_IMAGE_FLAG_MASK;
/* If there is no flag that's no use checking anything. If there is no
@@ -623,6 +624,21 @@
}
gboolean
+brasero_plugin_check_media_restrictions (BraseroPlugin *self,
+ BraseroMedia media)
+{
+ BraseroPluginPrivate *priv;
+
+ priv = BRASERO_PLUGIN_PRIVATE (self);
+
+ /* no restrictions */
+ if (!priv->flags)
+ return TRUE;
+
+ return (brasero_plugin_get_flags (priv->flags, media) != NULL);
+}
+
+gboolean
brasero_plugin_get_record_flags (BraseroPlugin *self,
BraseroMedia media,
BraseroBurnFlag current,
Modified: trunk/src/burn-process.c
==============================================================================
--- trunk/src/burn-process.c (original)
+++ trunk/src/burn-process.c Mon Jul 14 18:07:55 2008
@@ -285,11 +285,13 @@
g_free (uri);
}
- brasero_job_add_track (BRASERO_JOB (self), track);
+ if (track) {
+ brasero_job_add_track (BRASERO_JOB (self), track);
- /* It's good practice to unref the track afterwards as we don't need it
- * anymore. BraseroTaskCtx refs it. */
- brasero_track_unref (track);
+ /* It's good practice to unref the track afterwards as we don't
+ * need it anymore. BraseroTaskCtx refs it. */
+ brasero_track_unref (track);
+ }
klass->post (BRASERO_JOB (self));
return BRASERO_BURN_OK;
Modified: trunk/src/burn-session.c
==============================================================================
--- trunk/src/burn-session.c (original)
+++ trunk/src/burn-session.c Mon Jul 14 18:07:55 2008
@@ -1095,6 +1095,22 @@
}
BraseroBurnResult
+brasero_burn_session_tag_remove (BraseroBurnSession *self,
+ const gchar *tag)
+{
+ BraseroBurnSessionPrivate *priv;
+
+ g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
+
+ priv = BRASERO_BURN_SESSION_PRIVATE (self);
+ if (!priv->tags)
+ return BRASERO_BURN_ERR;
+
+ g_hash_table_remove (priv->tags, tag);
+ return BRASERO_BURN_OK;
+}
+
+BraseroBurnResult
brasero_burn_session_tag_add (BraseroBurnSession *self,
const gchar *tag,
GValue *value)
Modified: trunk/src/burn-session.h
==============================================================================
--- trunk/src/burn-session.h (original)
+++ trunk/src/burn-session.h Mon Jul 14 18:07:55 2008
@@ -104,6 +104,11 @@
brasero_burn_session_tag_add (BraseroBurnSession *session,
const gchar *tag,
GValue *value);
+
+BraseroBurnResult
+brasero_burn_session_tag_remove (BraseroBurnSession *session,
+ const gchar *tag);
+
/**
*
*/
Modified: trunk/src/burn-track.h
==============================================================================
--- trunk/src/burn-track.h (original)
+++ trunk/src/burn-track.h Mon Jul 14 18:07:55 2008
@@ -63,9 +63,19 @@
BRASERO_AUDIO_FORMAT_NONE = 0,
BRASERO_AUDIO_FORMAT_UNDEFINED = 1,
BRASERO_AUDIO_FORMAT_4_CHANNEL = 1 << 1,
- BRASERO_AUDIO_FORMAT_RAW = 1 << 2
+ BRASERO_AUDIO_FORMAT_RAW = 1 << 2,
+ BRASERO_AUDIO_FORMAT_AC3 = 1 << 3,
+ BRASERO_AUDIO_FORMAT_MP2 = 1 << 4,
+ BRASERO_AUDIO_FORMAT_44100 = 1 << 5,
+ BRASERO_AUDIO_FORMAT_48000 = 1 << 6,
+ BRASERO_VIDEO_FORMAT_UNDEFINED = 1 << 7,
+ BRASERO_VIDEO_FORMAT_VCD = 1 << 8,
+ BRASERO_VIDEO_FORMAT_VIDEO_DVD = 1 << 9
} BraseroAudioFormat;
+#define BRASERO_AUDIO_CAPS_AUDIO(caps_FORMAT) ((caps_FORMAT) & 0x007F)
+#define BRASERO_AUDIO_CAPS_VIDEO(caps_FORMAT) ((caps_FORMAT) & 0x0180)
+
typedef enum {
BRASERO_CHECKSUM_NONE = 0,
BRASERO_CHECKSUM_MD5 = 1,
Modified: trunk/src/plugins/Makefile.am
==============================================================================
--- trunk/src/plugins/Makefile.am (original)
+++ trunk/src/plugins/Makefile.am Mon Jul 14 18:07:55 2008
@@ -1,4 +1,4 @@
-SUBDIRS = cdrdao transcode dvdcss growisofs checksum local-track
+SUBDIRS = cdrdao transcode dvdcss growisofs checksum local-track dvdauthor vcdimager
if BUILD_LIBBURNIA
SUBDIRS += libburnia
Modified: trunk/src/plugins/cdrdao/burn-toc2cue.c
==============================================================================
--- trunk/src/plugins/cdrdao/burn-toc2cue.c (original)
+++ trunk/src/plugins/cdrdao/burn-toc2cue.c Mon Jul 14 18:07:55 2008
@@ -263,7 +263,7 @@
priv->output = NULL;
}
- return BRASERO_BURN_OK;
+ return brasero_job_finished_session (job);
}
static void
Modified: trunk/src/plugins/cdrkit/burn-wodim.c
==============================================================================
--- trunk/src/plugins/cdrkit/burn-wodim.c (original)
+++ trunk/src/plugins/cdrkit/burn-wodim.c Mon Jul 14 18:07:55 2008
@@ -1087,7 +1087,8 @@
input = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_PIPE|
BRASERO_PLUGIN_IO_ACCEPT_FILE,
- BRASERO_AUDIO_FORMAT_RAW);
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100);
brasero_plugin_link_caps (plugin, output, input);
g_slist_free (output);
Modified: trunk/src/plugins/cdrtools/burn-cdrecord.c
==============================================================================
--- trunk/src/plugins/cdrtools/burn-cdrecord.c (original)
+++ trunk/src/plugins/cdrtools/burn-cdrecord.c Mon Jul 14 18:07:55 2008
@@ -1082,7 +1082,8 @@
input = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_PIPE|
BRASERO_PLUGIN_IO_ACCEPT_FILE,
- BRASERO_AUDIO_FORMAT_RAW);
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100);
brasero_plugin_link_caps (plugin, output, input);
g_slist_free (output);
Added: trunk/src/plugins/dvdauthor/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/plugins/dvdauthor/Makefile.am Mon Jul 14 18:07:55 2008
@@ -0,0 +1,24 @@
+DISABLE_DEPRECATED = -DG_DISABLE_DEPRECATED
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/src \
+ -DBRASERO_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+ -DBRASERO_PREFIX=\"$(prefix)\" \
+ -DBRASERO_SYSCONFDIR=\"$(sysconfdir)\" \
+ -DBRASERO_DATADIR=\"$(datadir)/brasero\" \
+ -DBRASERO_LIBDIR=\"$(libdir)\" \
+ $(DISABLE_DEPRECATED) \
+ $(BRASERO_BASE_CFLAGS) \
+ $(BRASERO_LIBXML_CFLAGS)
+
+AM_CFLAGS = -g
+
+dvdauthordir = $(libdir)/brasero/plugins
+dvdauthor_LTLIBRARIES = libbrasero-dvdauthor.la
+
+libbrasero_dvdauthor_la_SOURCES = burn-dvdauthor.c burn-dvdauthor.h
+libbrasero_dvdauthor_la_LIBADD = $(BRASERO_BASE_LIBS) $(BRASERO_LIBXML_LIBS)
+libbrasero_dvdauthor_la_LDFLAGS = -module -avoid-version
+
Added: trunk/src/plugins/dvdauthor/burn-dvdauthor.c
==============================================================================
--- (empty file)
+++ trunk/src/plugins/dvdauthor/burn-dvdauthor.c Mon Jul 14 18:07:55 2008
@@ -0,0 +1,404 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * burn-dvdauthor.c
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * burn-dvdauthor.c is free software.
+ *
+ * You may redistribute it and/or modify it under the terms of the
+ * GNU General Public License, as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * burn-dvdauthor.c is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with burn-dvdauthor.c. If not, write to:
+ * The Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <gmodule.h>
+
+#include <libxml/xmlerror.h>
+#include <libxml/xmlwriter.h>
+#include <libxml/parser.h>
+#include <libxml/xmlstring.h>
+#include <libxml/uri.h>
+
+#include "burn-basics.h"
+#include "burn-plugin.h"
+#include "burn-job.h"
+#include "burn-process.h"
+#include "burn-dvdauthor.h"
+
+BRASERO_PLUGIN_BOILERPLATE (BraseroDvdAuthor, brasero_dvd_author, BRASERO_TYPE_PROCESS, BraseroProcess);
+
+typedef struct _BraseroDvdAuthorPrivate BraseroDvdAuthorPrivate;
+struct _BraseroDvdAuthorPrivate
+{
+ gchar *output;
+};
+
+#define BRASERO_DVD_AUTHOR_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DVD_AUTHOR, BraseroDvdAuthorPrivate))
+
+static BraseroProcessClass *parent_class = NULL;
+
+static BraseroBurnResult
+brasero_dvd_author_add_track (BraseroJob *job)
+{
+ gchar *path;
+ BraseroTrack *track;
+ GSList *grafts = NULL;
+ BraseroGraftPt *graft;
+ BraseroDvdAuthorPrivate *priv;
+
+ priv = BRASERO_DVD_AUTHOR_PRIVATE (job);
+
+ /* create the track */
+ track = brasero_track_new (BRASERO_TRACK_TYPE_DATA);
+
+ /* audio */
+ graft = g_new (BraseroGraftPt, 1);
+ path = g_build_path (G_DIR_SEPARATOR_S,
+ priv->output,
+ "AUDIO_TS",
+ NULL);
+ graft->uri = g_filename_to_uri (path, NULL, NULL);
+ g_free (path);
+
+ graft->path = g_strdup ("/AUDIO_TS");
+ grafts = g_slist_prepend (grafts, graft);
+
+ BRASERO_JOB_LOG (job, "Adding graft point for %s", graft->uri);
+
+ /* video */
+ graft = g_new (BraseroGraftPt, 1);
+ path = g_build_path (G_DIR_SEPARATOR_S,
+ priv->output,
+ "VIDEO_TS",
+ NULL);
+ graft->uri = g_filename_to_uri (path, NULL, NULL);
+ g_free (path);
+
+ graft->path = g_strdup ("/VIDEO_TS");
+ grafts = g_slist_prepend (grafts, graft);
+
+ BRASERO_JOB_LOG (job, "Adding graft point for %s", graft->uri);
+
+ brasero_track_add_data_fs (track,
+ BRASERO_IMAGE_FS_ISO|
+ BRASERO_IMAGE_FS_UDF|
+ BRASERO_IMAGE_FS_VIDEO);
+ brasero_track_set_data_source (track,
+ grafts,
+ NULL);
+ brasero_job_add_track (job, track);
+ brasero_track_unref (track);
+
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_dvd_author_read_stdout (BraseroProcess *process,
+ const gchar *line)
+{
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_dvd_author_read_stderr (BraseroProcess *process,
+ const gchar *line)
+{
+ if (!strstr (line, ""))
+ return BRASERO_BURN_OK;
+
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_dvd_author_generate_xml_file (BraseroProcess *process,
+ const gchar *path,
+ GError **error)
+{
+ BraseroDvdAuthorPrivate *priv;
+ BraseroBurnResult result;
+ GSList *tracks = NULL;
+ xmlTextWriter *xml;
+ gint success;
+ GSList *iter;
+
+ BRASERO_JOB_LOG (process, "Creating DVD layout xml file(%s)", path);
+
+ xml = xmlNewTextWriterFilename (path, 0);
+ if (!xml)
+ return BRASERO_BURN_ERR;
+
+ priv = BRASERO_DVD_AUTHOR_PRIVATE (process);
+
+ xmlTextWriterSetIndent (xml, 1);
+ xmlTextWriterSetIndentString (xml, (xmlChar *) "\t");
+
+ success = xmlTextWriterStartDocument (xml,
+ NULL,
+ "UTF8",
+ NULL);
+ if (success < 0)
+ goto error;
+
+ result = brasero_job_get_tmp_dir (BRASERO_JOB (process),
+ &priv->output,
+ error);
+ if (result != BRASERO_BURN_OK)
+ return result;
+
+ /* let's start */
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "dvdauthor");
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "dest",
+ (xmlChar *) priv->output);
+ if (success < 0)
+ goto error;
+
+ /* This is needed to finalize */
+ success = xmlTextWriterWriteElement (xml, (xmlChar *) "vmgm", (xmlChar *) "");
+ if (success < 0)
+ goto error;
+
+ /* the tracks */
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "titleset");
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "titles");
+ if (success < 0)
+ goto error;
+
+ /* get all tracks */
+ brasero_job_get_tracks (BRASERO_JOB (process), &tracks);
+ for (iter = tracks; iter; iter = iter->next) {
+ BraseroTrack *track;
+ gchar *video;
+
+ track = iter->data;
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "pgc");
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "vob");
+ if (success < 0)
+ goto error;
+
+ video = brasero_track_get_audio_source (track, FALSE);
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "file",
+ (xmlChar *) video);
+ g_free (video);
+
+ if (success < 0)
+ goto error;
+
+ /* vob */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* pgc */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+ }
+
+ /* titles */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* titleset */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* close dvdauthor */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ xmlTextWriterEndDocument (xml);
+ xmlFreeTextWriter (xml);
+
+ return BRASERO_BURN_OK;
+
+error:
+
+ BRASERO_JOB_LOG (process, "Error");
+
+ /* close everything */
+ xmlTextWriterEndDocument (xml);
+ xmlFreeTextWriter (xml);
+
+ /* FIXME: get the error */
+
+ return BRASERO_BURN_ERR;
+}
+
+static BraseroBurnResult
+brasero_dvd_author_set_argv (BraseroProcess *process,
+ GPtrArray *argv,
+ GError **error)
+{
+ BraseroDvdAuthorPrivate *priv;
+ BraseroBurnResult result;
+ BraseroJobAction action;
+ gchar *output;
+
+ priv = BRASERO_DVD_AUTHOR_PRIVATE (process);
+
+ brasero_job_get_action (BRASERO_JOB (process), &action);
+ if (action != BRASERO_JOB_ACTION_IMAGE)
+ BRASERO_JOB_NOT_SUPPORTED (process);
+
+ g_ptr_array_add (argv, g_strdup ("dvdauthor"));
+
+ /* get all arguments to write XML file */
+ result = brasero_job_get_tmp_file (BRASERO_JOB (process),
+ NULL,
+ &output,
+ error);
+ if (result != BRASERO_BURN_OK)
+ return result;
+
+ g_ptr_array_add (argv, g_strdup ("-x"));
+ g_ptr_array_add (argv, output);
+
+ result = brasero_dvd_author_generate_xml_file (process, output, error);
+ if (result != BRASERO_BURN_OK)
+ return result;
+
+ brasero_job_set_current_action (BRASERO_JOB (process),
+ BRASERO_BURN_ACTION_CREATING_IMAGE,
+ _("Creating file layout"),
+ FALSE);
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_dvd_author_post (BraseroJob *job)
+{
+ BraseroDvdAuthorPrivate *priv;
+
+ priv = BRASERO_DVD_AUTHOR_PRIVATE (job);
+
+ brasero_dvd_author_add_track (job);
+
+ if (priv->output) {
+ g_free (priv->output);
+ priv->output = NULL;
+ }
+
+ return brasero_job_finished_session (job);
+}
+
+static void
+brasero_dvd_author_init (BraseroDvdAuthor *object)
+{}
+
+static void
+brasero_dvd_author_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+brasero_dvd_author_class_init (BraseroDvdAuthorClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ BraseroProcessClass* process_class = BRASERO_PROCESS_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (BraseroDvdAuthorPrivate));
+
+ object_class->finalize = brasero_dvd_author_finalize;
+
+ process_class->stdout_func = brasero_dvd_author_read_stdout;
+ process_class->stderr_func = brasero_dvd_author_read_stderr;
+ process_class->set_argv = brasero_dvd_author_set_argv;
+ process_class->post = brasero_dvd_author_post;
+}
+
+static BraseroBurnResult
+brasero_dvd_author_export_caps (BraseroPlugin *plugin, gchar **error)
+{
+ BraseroBurnResult result;
+ GSList *output;
+ GSList *input;
+
+ /* NOTE: it seems that cdrecord can burn cue files on the fly */
+ brasero_plugin_define (plugin,
+ "dvdauthor",
+ _("use dvdauthor to convert a set of files to burn to Video DVDs"),
+ "Philippe Rouquier",
+ 1);
+
+ /* First see if this plugin can be used */
+ result = brasero_process_check_path ("dvdauthor", error);
+ if (result != BRASERO_BURN_OK)
+ return result;
+
+ input = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
+ BRASERO_AUDIO_FORMAT_AC3|
+ BRASERO_AUDIO_FORMAT_MP2|
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100|
+ BRASERO_AUDIO_FORMAT_48000|
+ BRASERO_VIDEO_FORMAT_VIDEO_DVD);
+ output = brasero_caps_data_new (BRASERO_IMAGE_FS_ISO|
+ BRASERO_IMAGE_FS_UDF|
+ BRASERO_IMAGE_FS_VIDEO);
+
+ brasero_plugin_link_caps (plugin, output, input);
+ g_slist_free (output);
+ g_slist_free (input);
+
+ /* we only support DVDs */
+ brasero_plugin_set_flags (plugin,
+ BRASERO_MEDIUM_FILE|
+ BRASERO_MEDIUM_DVDR|
+ BRASERO_MEDIUM_DVDR_PLUS|
+ BRASERO_MEDIUM_DVD_DL|
+ BRASERO_MEDIUM_BLANK|
+ BRASERO_MEDIUM_APPENDABLE|
+ BRASERO_MEDIUM_HAS_DATA,
+ BRASERO_BURN_FLAG_NONE,
+ BRASERO_BURN_FLAG_NONE);
+
+ brasero_plugin_set_flags (plugin,
+ BRASERO_MEDIUM_DVDRW|
+ BRASERO_MEDIUM_DVDRW_PLUS|
+ BRASERO_MEDIUM_DVDRW_RESTRICTED|
+ BRASERO_MEDIUM_DVD_DL|
+ BRASERO_MEDIUM_BLANK|
+ BRASERO_MEDIUM_CLOSED|
+ BRASERO_MEDIUM_APPENDABLE|
+ BRASERO_MEDIUM_HAS_DATA,
+ BRASERO_BURN_FLAG_NONE,
+ BRASERO_BURN_FLAG_NONE);
+
+ return BRASERO_BURN_OK;
+}
Added: trunk/src/plugins/dvdauthor/burn-dvdauthor.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/dvdauthor/burn-dvdauthor.h Mon Jul 14 18:07:55 2008
@@ -0,0 +1,41 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * burn-dvdauthor.c
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * burn-dvdauthor.c is free software.
+ *
+ * You may redistribute it and/or modify it under the terms of the
+ * GNU General Public License, as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * burn-dvdauthor.c is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with burn-dvdauthor.c. If not, write to:
+ * The Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _BRASERO_DVD_AUTHOR_H_
+#define _BRASERO_DVD_AUTHOR_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define BRASERO_TYPE_DVD_AUTHOR (brasero_dvd_author_get_type ())
+#define BRASERO_DVD_AUTHOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_DVD_AUTHOR, BraseroDvdAuthor))
+#define BRASERO_DVD_AUTHOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_DVD_AUTHOR, BraseroDvdAuthorClass))
+#define BRASERO_IS_DVD_AUTHOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_DVD_AUTHOR))
+#define BRASERO_IS_DVD_AUTHOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_DVD_AUTHOR))
+#define BRASERO_DVD_AUTHOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_DVD_AUTHOR, BraseroDvdAuthorClass))
+
+G_END_DECLS
+
+#endif /* _BRASERO_DVD_AUTHOR_H_ */
Modified: trunk/src/plugins/libburnia/burn-libburn.c
==============================================================================
--- trunk/src/plugins/libburnia/burn-libburn.c (original)
+++ trunk/src/plugins/libburnia/burn-libburn.c Mon Jul 14 18:07:55 2008
@@ -883,7 +883,8 @@
/* audio support for CDs only */
input = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_PIPE|
BRASERO_PLUGIN_IO_ACCEPT_FILE,
- BRASERO_AUDIO_FORMAT_RAW);
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100);
output = brasero_caps_disc_new (media_cd);
brasero_plugin_link_caps (plugin, output, input);
Modified: trunk/src/plugins/local-track/burn-local-image.c
==============================================================================
--- trunk/src/plugins/local-track/burn-local-image.c (original)
+++ trunk/src/plugins/local-track/burn-local-image.c Mon Jul 14 18:07:55 2008
@@ -965,7 +965,14 @@
caps = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
BRASERO_AUDIO_FORMAT_UNDEFINED|
BRASERO_AUDIO_FORMAT_4_CHANNEL|
- BRASERO_AUDIO_FORMAT_RAW);
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_VIDEO_FORMAT_UNDEFINED|
+ BRASERO_VIDEO_FORMAT_VCD|
+ BRASERO_VIDEO_FORMAT_VIDEO_DVD|
+ BRASERO_AUDIO_FORMAT_AC3|
+ BRASERO_AUDIO_FORMAT_MP2|
+ BRASERO_AUDIO_FORMAT_44100|
+ BRASERO_AUDIO_FORMAT_48000);
brasero_plugin_process_caps (plugin, caps);
g_slist_free (caps);
Modified: trunk/src/plugins/transcode/Makefile.am
==============================================================================
--- trunk/src/plugins/transcode/Makefile.am (original)
+++ trunk/src/plugins/transcode/Makefile.am Mon Jul 14 18:07:55 2008
@@ -28,3 +28,10 @@
libbrasero_normalize_la_SOURCES = burn-normalize.c burn-normalize.h
libbrasero_normalize_la_LIBADD = $(BRASERO_BASE_LIBS) $(BRASERO_GSTREAMER_CFLAGS)
libbrasero_normalize_la_LDFLAGS = -module -avoid-version
+
+vobdir = $(libdir)/brasero/plugins
+vob_LTLIBRARIES = libbrasero-vob.la
+
+libbrasero_vob_la_SOURCES = burn-vob.c burn-vob.h
+libbrasero_vob_la_LIBADD = $(BRASERO_BASE_LIBS) $(BRASERO_GSTREAMER_CFLAGS)
+libbrasero_vob_la_LDFLAGS = -module -avoid-version
Modified: trunk/src/plugins/transcode/burn-transcode.c
==============================================================================
--- trunk/src/plugins/transcode/burn-transcode.c (original)
+++ trunk/src/plugins/transcode/burn-transcode.c Mon Jul 14 18:07:55 2008
@@ -243,11 +243,11 @@
|| brasero_track_tag_lookup (track, BRASERO_TRACK_GAIN_VALUE, NULL) == BRASERO_BURN_OK) {
BRASERO_JOB_LOG (transcode, "Found audio levels tags");
volume = gst_element_factory_make ("rgvolume", NULL);
- g_object_set (volume,
- "album-mode", FALSE,
- NULL);
-
- if (!volume)
+ if (volume)
+ g_object_set (volume,
+ "album-mode", FALSE,
+ NULL);
+ else
BRASERO_JOB_LOG (transcode, "rgvolume object couldn't be created");
}
@@ -585,7 +585,10 @@
}
dest = brasero_track_new (BRASERO_TRACK_TYPE_AUDIO);
- brasero_track_set_audio_source (dest, path_dest, BRASERO_AUDIO_FORMAT_RAW);
+ brasero_track_set_audio_source (dest,
+ path_dest,
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100);
/* NOTE: there is no gap and start = 0 since these tracks are the result
* of the transformation of previous ones */
@@ -860,7 +863,10 @@
brasero_job_get_output_type (BRASERO_JOB (transcode), &type);
track = brasero_track_new (BRASERO_TRACK_TYPE_AUDIO);
- brasero_track_set_audio_source (track, output, BRASERO_AUDIO_FORMAT_RAW);
+ brasero_track_set_audio_source (track,
+ output,
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100);
brasero_track_set_audio_boundaries (track, 0, length, 0);
brasero_track_set_audio_info (track, info);
@@ -1011,7 +1017,7 @@
output = NULL;
brasero_job_get_audio_output (BRASERO_JOB (transcode), &output);
- fd = open (output, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU | S_IRWXG | S_IROTH);
+ fd = open (output, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU | S_IRGRP | S_IROTH);
g_free (output);
if (fd == -1) {
@@ -1438,7 +1444,8 @@
output = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE|
BRASERO_PLUGIN_IO_ACCEPT_PIPE,
- BRASERO_AUDIO_FORMAT_RAW);
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100);
input = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
BRASERO_AUDIO_FORMAT_UNDEFINED);
Added: trunk/src/plugins/transcode/burn-vob.c
==============================================================================
--- (empty file)
+++ trunk/src/plugins/transcode/burn-vob.c Mon Jul 14 18:07:55 2008
@@ -0,0 +1,1084 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero-vob.c
+ * Copyright (C) Rouquier Philippe 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero-vob.c is free software.
+ *
+ * You may redistribute it and/or modify it under the terms of the
+ * GNU General Public License, as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * brasero-vob.c is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with brasero-vob.c. If not, write to:
+ * The Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+
+#include <gst/gst.h>
+
+#include "burn-basics.h"
+#include "burn-job.h"
+#include "burn-plugin.h"
+#include "burn-vob.h"
+
+BRASERO_PLUGIN_BOILERPLATE (BraseroVob, brasero_vob, BRASERO_TYPE_JOB, BraseroJob);
+
+typedef struct _BraseroVobPrivate BraseroVobPrivate;
+struct _BraseroVobPrivate
+{
+ GstElement *pipeline;
+
+ GstElement *audio;
+ GstElement *video;
+
+ BraseroAudioFormat format;
+
+ guint svcd:1;
+ guint is_video_dvd:1;
+};
+
+#define BRASERO_VOB_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_VOB, BraseroVobPrivate))
+
+static GObjectClass *parent_class = NULL;
+
+
+static void
+brasero_vob_stop_pipeline (BraseroVob *vob)
+{
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+ if (!priv->pipeline)
+ return;
+
+ gst_element_set_state (priv->pipeline, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (priv->pipeline));
+ priv->pipeline = NULL;
+}
+
+static BraseroBurnResult
+brasero_vob_stop (BraseroJob *job,
+ GError **error)
+{
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (job);
+
+ brasero_vob_stop_pipeline (BRASERO_VOB (job));
+ return BRASERO_BURN_OK;
+}
+
+static void
+brasero_vob_finished (BraseroVob *vob)
+{
+ BraseroVobPrivate *priv;
+ BraseroTrackType type;
+ gchar *output = NULL;
+ BraseroTrack *track;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ memset (&type, 0, sizeof (BraseroTrackType));
+ brasero_job_get_output_type (BRASERO_JOB (vob), &type);
+ brasero_job_get_audio_output (BRASERO_JOB (vob), &output);
+
+ track = brasero_track_new (BRASERO_TRACK_TYPE_AUDIO);
+ brasero_track_set_audio_source (track,
+ output,
+ type.subtype.audio_format);
+
+ brasero_job_add_track (BRASERO_JOB (vob), track);
+ brasero_track_unref (track);
+ g_free (output);
+
+ brasero_job_finished_track (BRASERO_JOB (vob));
+}
+
+static gboolean
+brasero_vob_bus_messages (GstBus *bus,
+ GstMessage *msg,
+ BraseroVob *vob)
+{
+ BraseroVobPrivate *priv;
+ GError *error = NULL;
+ gchar *debug;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+ switch (GST_MESSAGE_TYPE (msg)) {
+ case GST_MESSAGE_TAG:
+ return TRUE;
+
+ case GST_MESSAGE_ERROR:
+ gst_message_parse_error (msg, &error, &debug);
+ BRASERO_JOB_LOG (vob, debug);
+ g_free (debug);
+
+ brasero_job_error (BRASERO_JOB (vob), error);
+ return FALSE;
+
+ case GST_MESSAGE_EOS:
+ BRASERO_JOB_LOG (vob, "Transcoding finished");
+
+ /* add a new track and terminate */
+ brasero_vob_finished (vob);
+ return FALSE;
+
+ case GST_MESSAGE_STATE_CHANGED:
+ break;
+
+ default:
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+static void
+brasero_vob_new_decoded_pad_cb (GstElement *decode,
+ GstPad *pad,
+ gboolean arg2,
+ BraseroVob *vob)
+{
+ GstPad *sink;
+ GstCaps *caps;
+ GstStructure *structure;
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ /* make sure we only have audio */
+ caps = gst_pad_get_caps (pad);
+ if (!caps)
+ return;
+
+ structure = gst_caps_get_structure (caps, 0);
+ if (structure) {
+ if (g_strrstr (gst_structure_get_name (structure), "video")) {
+ sink = gst_element_get_pad (priv->video, "sink");
+ gst_pad_link (pad, sink);
+ gst_object_unref (sink);
+
+ gst_element_set_state (priv->video, GST_STATE_PLAYING);
+ }
+
+ if (g_strrstr (gst_structure_get_name (structure), "audio")) {
+ sink = gst_element_get_pad (priv->audio, "sink");
+ gst_pad_link (pad, sink);
+ gst_object_unref (sink);
+
+ gst_element_set_state (priv->audio, GST_STATE_PLAYING);
+ }
+ }
+
+ gst_caps_unref (caps);
+}
+
+static gboolean
+brasero_vob_link_audio (BraseroVob *vob,
+ GstElement *start,
+ GstElement *end,
+ GstElement *tee,
+ GstElement *muxer)
+{
+ GstPad *srcpad;
+ GstPad *sinkpad;
+ GstPadLinkReturn res;
+
+ srcpad = gst_element_get_request_pad (tee, "src%d");
+ sinkpad = gst_element_get_static_pad (start, "sink");
+ res = gst_pad_link (srcpad, sinkpad);
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ BRASERO_JOB_LOG (vob, "Linked audio bin to tee == %d", res);
+ if (res != GST_PAD_LINK_OK)
+ return FALSE;
+
+ sinkpad = gst_element_get_request_pad (muxer, "audio_%d");
+ srcpad = gst_element_get_static_pad (end, "src");
+ res = gst_pad_link (srcpad, sinkpad);
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ BRASERO_JOB_LOG (vob, "Linked audio bin to muxer == %d", res);
+ if (res != GST_PAD_LINK_OK)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+brasero_vob_build_audio_pcm (BraseroVob *vob,
+ GstElement *tee,
+ GstElement *muxer,
+ GError **error)
+{
+ GstElement *queue;
+ GstElement *convert;
+ GstElement *resample;
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ /* queue */
+ queue = gst_element_factory_make ("queue", NULL);
+ if (queue == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("queue element can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), queue);
+ g_object_set (queue,
+ "max-size-bytes", 0,
+ "max-size-buffers", 0,
+ "max-size-time", (gint64) 0,
+ NULL);
+
+ /* audioresample */
+ resample = gst_element_factory_make ("audioresample", NULL);
+ if (resample == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("audioresample can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), resample);
+
+ /* audioconvert */
+ convert = gst_element_factory_make ("audioconvert", NULL);
+ if (convert == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("audioconvert can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), convert);
+
+ gst_element_link_many (queue, resample, convert, NULL);
+ brasero_vob_link_audio (vob, queue, convert, tee, muxer);
+
+ return TRUE;
+
+error:
+
+ return FALSE;
+}
+
+static gboolean
+brasero_vob_build_audio_mp2 (BraseroVob *vob,
+ GstElement *tee,
+ GstElement *muxer,
+ GError **error)
+{
+ GstElement *queue;
+ GstElement *queue1;
+ GstElement *encode;
+ GstElement *convert;
+ GstElement *resample;
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ /* queue */
+ queue = gst_element_factory_make ("queue", NULL);
+ if (queue == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("queue element can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), queue);
+ g_object_set (queue,
+ "max-size-bytes", 0,
+ "max-size-buffers", 0,
+ "max-size-time", (gint64) 0,
+ NULL);
+
+ /* audioconvert */
+ convert = gst_element_factory_make ("audioconvert", NULL);
+ if (convert == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("audioconvert can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), convert);
+
+ /* audioresample */
+ resample = gst_element_factory_make ("audioresample", NULL);
+ if (resample == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("audioresample can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), resample);
+
+ encode = gst_element_factory_make ("ffenc_mp2", NULL);
+ if (encode == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("ffenc_mp2 can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), encode);
+
+ /* another queue */
+ queue1 = gst_element_factory_make ("queue", NULL);
+ if (queue1 == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("queue1 element can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), queue1);
+ g_object_set (queue1,
+ "max-size-bytes", 0,
+ "max-size-buffers", 0,
+ "max-size-time", (gint64) 0,
+ NULL);
+
+ if (!priv->is_video_dvd) {
+ GstElement *filter;
+ GstCaps *filtercaps;
+
+ /* This is for (S)VCD which need to have audio at 44100 khz */
+
+ /* create a filter */
+ filter = gst_element_factory_make ("capsfilter", NULL);
+ if (filter == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("filter can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), filter);
+
+ BRASERO_JOB_LOG (vob, "Setting rate to 44100");
+
+ filtercaps = gst_caps_new_full (gst_structure_new ("audio/x-raw-int",
+ "channels", G_TYPE_INT, 2,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16,
+ "endianness", G_TYPE_INT, 1234,
+ "rate", G_TYPE_INT, 44100,
+ "signed", G_TYPE_BOOLEAN, TRUE,
+ NULL),
+ NULL);
+
+ g_object_set (GST_OBJECT (filter), "caps", filtercaps, NULL);
+ gst_caps_unref (filtercaps);
+
+ gst_element_link_many (queue, convert, resample, filter, encode, queue1, NULL);
+ }
+ else
+ gst_element_link_many (queue, convert, resample, encode, queue1, NULL);
+
+ brasero_vob_link_audio (vob, queue, queue1, tee, muxer);
+ return TRUE;
+
+error:
+
+ return FALSE;
+}
+
+static gboolean
+brasero_vob_build_audio_ac3 (BraseroVob *vob,
+ GstElement *tee,
+ GstElement *muxer,
+ GError **error)
+{
+ GstElement *queue;
+ GstElement *encode;
+ GstElement *convert;
+ GstElement *resample;
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ /* queue */
+ queue = gst_element_factory_make ("queue", NULL);
+ if (queue == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("queue element can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), queue);
+ g_object_set (queue,
+ "max-size-bytes", 0,
+ "max-size-buffers", 0,
+ "max-size-time", (gint64) 0,
+ NULL);
+
+ /* audioconvert */
+ convert = gst_element_factory_make ("audioconvert", NULL);
+ if (convert == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("audioconvert can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), convert);
+
+ /* audioresample */
+ resample = gst_element_factory_make ("audioresample", NULL);
+ if (resample == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("audioresample can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), resample);
+
+ encode = gst_element_factory_make ("ffenc_ac3", NULL);
+ if (encode == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("ffenc_ac3 can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), encode);
+
+ gst_element_link_many (queue, convert, resample, encode, NULL);
+ brasero_vob_link_audio (vob, queue, encode, tee, muxer);
+
+ return TRUE;
+
+error:
+
+ return FALSE;
+}
+
+static GstElement *
+brasero_vob_build_audio_bins (BraseroVob *vob,
+ GstElement *muxer,
+ GError **error)
+{
+ GValue *value;
+ GstElement *tee;
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ /* queue */
+ tee = gst_element_factory_make ("tee", NULL);
+ if (tee == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("tee element can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), tee);
+
+ if (priv->is_video_dvd) {
+ /* Get output format */
+ value = NULL;
+ brasero_job_tag_lookup (BRASERO_JOB (vob),
+ BRASERO_DVD_AUDIO_STREAMS,
+ &value);
+
+ if (value)
+ priv->format = g_value_get_int (value);
+
+ if (priv->format == BRASERO_AUDIO_FORMAT_NONE)
+ priv->format = BRASERO_AUDIO_FORMAT_RAW;
+
+ if (priv->format & BRASERO_AUDIO_FORMAT_RAW) {
+ /* PCM : on demand */
+ BRASERO_JOB_LOG (vob, "Adding PCM audio stream");
+ if (!brasero_vob_build_audio_pcm (vob, tee, muxer, error))
+ goto error;
+ }
+
+ if (priv->format & BRASERO_AUDIO_FORMAT_AC3) {
+ /* AC3 : on demand */
+ BRASERO_JOB_LOG (vob, "Adding AC3 audio stream");
+ if (!brasero_vob_build_audio_ac3 (vob, tee, muxer, error))
+ goto error;
+ }
+
+ if (priv->format & BRASERO_AUDIO_FORMAT_MP2) {
+ /* MP2 : on demand */
+ BRASERO_JOB_LOG (vob, "Adding MP2 audio stream");
+ if (!brasero_vob_build_audio_mp2 (vob, tee, muxer, error))
+ goto error;
+ }
+ }
+ else if (!brasero_vob_build_audio_mp2 (vob, tee, muxer, error))
+ goto error;
+
+ return tee;
+
+error:
+ return NULL;
+}
+
+static GstElement *
+brasero_vob_build_video_bin (BraseroVob *vob,
+ GstElement *muxer,
+ GError **error)
+{
+ GValue *value;
+ GstPad *srcpad;
+ GstPad *sinkpad;
+ GstElement *scale;
+ GstElement *queue;
+ GstElement *filter;
+ GstElement *encode;
+ GstPadLinkReturn res;
+ GstElement *framerate;
+ GstElement *colorspace;
+ BraseroVobPrivate *priv;
+ BraseroBurnResult result;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ queue = gst_element_factory_make ("queue", NULL);
+ if (queue == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("queue element can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), queue);
+ g_object_set (queue,
+ "max-size-bytes", 0,
+ "max-size-buffers", 0,
+ "max-size-time", (gint64) 0,
+ NULL);
+
+ /* framerate and video type control */
+ framerate = gst_element_factory_make ("videorate", NULL);
+ if (framerate == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("framerate can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), framerate);
+ g_object_set (framerate,
+ "silent", TRUE,
+ NULL);
+
+ /* size scaling */
+ scale = gst_element_factory_make ("videoscale", NULL);
+ if (scale == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("scale can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), scale);
+
+ /* create a filter */
+ filter = gst_element_factory_make ("capsfilter", NULL);
+ if (filter == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("filter can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), filter);
+
+ colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+ if (colorspace == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("ffmpegcolorspace can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), colorspace);
+
+ encode = gst_element_factory_make ("mpeg2enc", NULL);
+ if (encode == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("mpeg2enc can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (priv->pipeline), encode);
+
+ if (priv->is_video_dvd)
+ g_object_set (encode,
+ "format", 8,
+ NULL);
+ /* NOTE: there is another option to improve compatibility with vcdimager
+ * but that would mean be sure that it's the next. */
+ else if (priv->svcd)
+ g_object_set (encode,
+ "format", 4,
+ NULL);
+ else
+ g_object_set (encode,
+ "format", 1,
+ NULL);
+
+ /* settings */
+ value = NULL;
+ result = brasero_job_tag_lookup (BRASERO_JOB (vob),
+ BRASERO_VIDEO_OUTPUT_FRAMERATE,
+ &value);
+
+ if (result == BRASERO_BURN_OK && value) {
+ gint rate;
+ GstCaps *filtercaps = NULL;
+
+ rate = g_value_get_int (value);
+
+ if (rate == BRASERO_VIDEO_FRAMERATE_NTSC) {
+ g_object_set (encode,
+ "norm", 110,
+ "framerate", 4,
+ NULL);
+
+ if (priv->is_video_dvd)
+ filtercaps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
+ "framerate", GST_TYPE_FRACTION, 30000, 1001,
+ "width", G_TYPE_INT, 720,
+ "height", G_TYPE_INT, 480,
+ NULL),
+ gst_structure_new ("video/x-raw-rgb",
+ "framerate", GST_TYPE_FRACTION, 30000, 1001,
+ "width", G_TYPE_INT, 720,
+ "height", G_TYPE_INT, 480,
+ NULL),
+ NULL);
+ else if (priv->svcd)
+ filtercaps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
+ "framerate", GST_TYPE_FRACTION, 30000, 1001,
+ "width", G_TYPE_INT, 480,
+ "height", G_TYPE_INT, 480,
+ NULL),
+ gst_structure_new ("video/x-raw-rgb",
+ "framerate", GST_TYPE_FRACTION, 30000, 1001,
+ "width", G_TYPE_INT, 480,
+ "height", G_TYPE_INT, 480,
+ NULL),
+ NULL);
+ else
+ filtercaps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
+ "framerate", GST_TYPE_FRACTION, 30000, 1001,
+ "width", G_TYPE_INT, 352,
+ "height", G_TYPE_INT, 240,
+ NULL),
+ gst_structure_new ("video/x-raw-rgb",
+ "framerate", GST_TYPE_FRACTION, 30000, 1001,
+ "width", G_TYPE_INT, 352,
+ "height", G_TYPE_INT, 240,
+ NULL),
+ NULL);
+ }
+ else if (rate == BRASERO_VIDEO_FRAMERATE_PAL_SECAM) {
+ g_object_set (encode,
+ "norm", 112,
+ "framerate", 3,
+ NULL);
+
+ if (priv->is_video_dvd)
+ filtercaps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "width", G_TYPE_INT, 720,
+ "height", G_TYPE_INT, 576,
+ NULL),
+ gst_structure_new ("video/x-raw-rgb",
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "width", G_TYPE_INT, 720,
+ "height", G_TYPE_INT, 576,
+ NULL),
+ NULL);
+ else if (priv->svcd)
+ filtercaps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "width", G_TYPE_INT, 480,
+ "height", G_TYPE_INT, 576,
+ NULL),
+ gst_structure_new ("video/x-raw-rgb",
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "width", G_TYPE_INT, 480,
+ "height", G_TYPE_INT, 576,
+ NULL),
+ NULL);
+ else
+ filtercaps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "width", G_TYPE_INT, 352,
+ "height", G_TYPE_INT, 288,
+ NULL),
+ gst_structure_new ("video/x-raw-rgb",
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "width", G_TYPE_INT, 352,
+ "height", G_TYPE_INT, 288,
+ NULL),
+ NULL);
+ }
+
+ if (filtercaps) {
+ g_object_set (GST_OBJECT (filter), "caps", filtercaps, NULL);
+ gst_caps_unref (filtercaps);
+ }
+ }
+
+ value = NULL;
+ result = brasero_job_tag_lookup (BRASERO_JOB (vob),
+ BRASERO_VIDEO_OUTPUT_ASPECT,
+ &value);
+ if (result == BRASERO_BURN_OK && value) {
+ gint aspect;
+
+ aspect = g_value_get_int (value);
+ if (aspect == BRASERO_VIDEO_ASPECT_4_3) {
+ g_object_set (encode,
+ "aspect", 2,
+ NULL);
+ }
+ else if (aspect == BRASERO_VIDEO_ASPECT_16_9) {
+ g_object_set (encode,
+ "aspect", 3,
+ NULL);
+ }
+ }
+
+ gst_element_link_many (queue, framerate, scale, colorspace, filter, encode, NULL);
+
+ srcpad = gst_element_get_static_pad (encode, "src");
+ sinkpad = gst_element_get_request_pad (muxer, "video_%d");
+ res = gst_pad_link (srcpad, sinkpad);
+ BRASERO_JOB_LOG (vob, "Linked video bin to muxer == %d", res)
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ return queue;
+
+error:
+
+ return NULL;
+}
+
+static gboolean
+brasero_vob_build_pipeline (BraseroVob *vob,
+ GError **error)
+{
+ gchar *uri;
+ GstBus *bus;
+ gchar *output;
+ GstElement *sink;
+ GstElement *muxer;
+ GstElement *source;
+ GstElement *decode;
+ BraseroTrack *track;
+ GstElement *pipeline;
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (vob);
+
+ BRASERO_JOB_LOG (vob, "Creating new pipeline");
+
+ pipeline = gst_pipeline_new (NULL);
+ priv->pipeline = pipeline;
+
+ /* source */
+ brasero_job_get_current_track (BRASERO_JOB (vob), &track);
+ uri = brasero_track_get_audio_source (track, TRUE);
+ source = gst_element_make_from_uri (GST_URI_SRC, uri, NULL);
+ if (source == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("source can't be created"));
+ return FALSE;
+ }
+ gst_bin_add (GST_BIN (pipeline), source);
+ g_object_set (source,
+ "typefind", FALSE,
+ NULL);
+
+ /* decode */
+ decode = gst_element_factory_make ("decodebin", NULL);
+ if (decode == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("decode can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (pipeline), decode);
+ gst_element_link_many (source, decode, NULL);
+
+ /* muxer: "mplex" */
+ muxer = gst_element_factory_make ("mplex", NULL);
+ if (muxer == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("mplex can't be created"));
+ goto error;
+ }
+ gst_bin_add (GST_BIN (pipeline), muxer);
+
+ if (priv->is_video_dvd)
+ g_object_set (muxer,
+ "format", 8,
+ NULL);
+ else if (priv->svcd)
+ g_object_set (muxer,
+ "format", 4,
+ NULL);
+ else
+ g_object_set (muxer,
+ "format", 1,
+ NULL);
+
+ /* create sink */
+ output = NULL;
+ brasero_job_get_audio_output (BRASERO_JOB (vob), &output);
+ sink = gst_element_factory_make ("filesink", NULL);
+ if (sink == NULL) {
+ g_set_error (error,
+ BRASERO_BURN_ERROR,
+ BRASERO_BURN_ERROR_GENERAL,
+ _("sink can't be created"));
+ return FALSE;
+ }
+ g_object_set (sink,
+ "location", output,
+ NULL);
+
+ gst_bin_add (GST_BIN (pipeline), sink);
+ gst_element_link (muxer, sink);
+
+ /* video encoding */
+ priv->video = brasero_vob_build_video_bin (vob, muxer, error);
+ if (!priv->video)
+ goto error;
+
+ /* audio encoding */
+ priv->audio = brasero_vob_build_audio_bins (vob, muxer, error);
+ if (!priv->audio)
+ goto error;
+
+ /* to be able to link everything */
+ g_signal_connect (G_OBJECT (decode),
+ "new-decoded-pad",
+ G_CALLBACK (brasero_vob_new_decoded_pad_cb),
+ vob);
+
+ /* connect to the bus */
+ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+ gst_bus_add_watch (bus,
+ (GstBusFunc) brasero_vob_bus_messages,
+ vob);
+ gst_object_unref (bus);
+
+ return TRUE;
+
+error:
+
+ if (error && (*error))
+ BRASERO_JOB_LOG (vob,
+ "can't create object : %s \n",
+ (*error)->message);
+
+ gst_object_unref (GST_OBJECT (pipeline));
+ return FALSE;
+}
+
+static BraseroBurnResult
+brasero_vob_start (BraseroJob *job,
+ GError **error)
+{
+ BraseroVobPrivate *priv;
+ BraseroJobAction action;
+ BraseroTrackType output;
+
+ brasero_job_get_action (job, &action);
+ if (action != BRASERO_JOB_ACTION_IMAGE)
+ return BRASERO_BURN_NOT_SUPPORTED;
+
+ priv = BRASERO_VOB_PRIVATE (job);
+
+ /* get destination medium type */
+ memset (&output, 0, sizeof (BraseroTrackType));
+ brasero_job_get_output_type (job, &output);
+ if (output.subtype.audio_format & BRASERO_VIDEO_FORMAT_VCD) {
+ GValue *value = NULL;
+
+ priv->is_video_dvd = FALSE;
+ brasero_job_tag_lookup (job,
+ BRASERO_VCD_TYPE,
+ &value);
+ if (value)
+ priv->svcd = (g_value_get_int (value) == BRASERO_SVCD);
+ }
+ else
+ priv->is_video_dvd = TRUE;
+
+ BRASERO_JOB_LOG (job,
+ "Got output type (is DVD %i, is SVCD %i",
+ priv->is_video_dvd,
+ priv->svcd);
+
+ if (!brasero_vob_build_pipeline (BRASERO_VOB (job), error))
+ return BRASERO_BURN_ERR;
+
+ /* ready to go */
+ brasero_job_set_current_action (job,
+ BRASERO_BURN_ACTION_ANALYSING,
+ _("Converting video file to MPEG2"),
+ FALSE);
+ gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
+
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_vob_clock_tick (BraseroJob *job)
+{
+ gint64 position = 0.0;
+ gint64 duration = 0.0;
+ BraseroVobPrivate *priv;
+ GstFormat format = GST_FORMAT_TIME;
+
+ priv = BRASERO_VOB_PRIVATE (job);
+
+ gst_element_query_duration (priv->pipeline, &format, &duration);
+ gst_element_query_position (priv->pipeline, &format, &position);
+
+ if (duration > 0.0) {
+ gdouble progress;
+
+ progress = (gdouble) position / (gdouble) duration;
+ brasero_job_set_progress (job, progress);
+ }
+
+ return BRASERO_BURN_OK;
+}
+
+static void
+brasero_vob_init (BraseroVob *object)
+{}
+
+static void
+brasero_vob_finalize (GObject *object)
+{
+ BraseroVobPrivate *priv;
+
+ priv = BRASERO_VOB_PRIVATE (object);
+
+ if (priv->pipeline) {
+ gst_object_unref (priv->pipeline);
+ priv->pipeline = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+brasero_vob_class_init (BraseroVobClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ BraseroJobClass* job_class = BRASERO_JOB_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (BraseroVobPrivate));
+
+ object_class->finalize = brasero_vob_finalize;
+
+ job_class->start = brasero_vob_start;
+ job_class->clock_tick = brasero_vob_clock_tick;
+ job_class->stop = brasero_vob_stop;
+}
+
+static BraseroBurnResult
+brasero_vob_export_caps (BraseroPlugin *plugin, gchar **error)
+{
+ GSList *input;
+ GSList *output;
+ GstElement *element;
+
+ /* Let's see if we've got the plugins we need */
+ element = gst_element_factory_make ("ffenc_mpeg2video", NULL);
+ if (!element)
+ return BRASERO_BURN_ERR;
+
+ element = gst_element_factory_make ("ffenc_ac3", NULL);
+ if (!element)
+ return BRASERO_BURN_ERR;
+
+ element = gst_element_factory_make ("ffenc_mp2", NULL);
+ if (!element)
+ return BRASERO_BURN_ERR;
+
+ element = gst_element_factory_make ("mplex", NULL);
+ if (!element)
+ return BRASERO_BURN_ERR;
+
+ gst_object_unref (element);
+
+ brasero_plugin_define (plugin,
+ "transcode2vob",
+ _("Vob allows to transcode any video file to a format suitable for video DVDs"),
+ "Philippe Rouquier",
+ 0);
+
+ input = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
+ BRASERO_AUDIO_FORMAT_UNDEFINED|
+ BRASERO_VIDEO_FORMAT_UNDEFINED);
+ output = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
+ BRASERO_AUDIO_FORMAT_MP2|
+ BRASERO_AUDIO_FORMAT_44100|
+ BRASERO_VIDEO_FORMAT_VCD);
+ brasero_plugin_link_caps (plugin, output, input);
+ g_slist_free (output);
+
+ output = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
+ BRASERO_AUDIO_FORMAT_AC3|
+ BRASERO_AUDIO_FORMAT_MP2|
+ BRASERO_AUDIO_FORMAT_RAW|
+ BRASERO_AUDIO_FORMAT_44100|
+ BRASERO_AUDIO_FORMAT_48000|
+ BRASERO_VIDEO_FORMAT_VIDEO_DVD);
+ brasero_plugin_link_caps (plugin, output, input);
+ g_slist_free (output);
+ g_slist_free (input);
+
+ return BRASERO_BURN_OK;
+}
Added: trunk/src/plugins/transcode/burn-vob.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/transcode/burn-vob.h Mon Jul 14 18:07:55 2008
@@ -0,0 +1,41 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero-vob.c
+ * Copyright (C) Rouquier Philippe 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero-vob.c is free software.
+ *
+ * You may redistribute it and/or modify it under the terms of the
+ * GNU General Public License, as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * brasero-vob.c is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with brasero-vob.c. If not, write to:
+ * The Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _BRASERO_VOB_H_
+#define _BRASERO_VOB_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define BRASERO_TYPE_VOB (brasero_vob_get_type ())
+#define BRASERO_VOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_VOB, BraseroVob))
+#define BRASERO_VOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_VOB, BraseroVobClass))
+#define BRASERO_IS_VOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_VOB))
+#define BRASERO_IS_VOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_VOB))
+#define BRASERO_VOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_VOB, BraseroVobClass))
+
+G_END_DECLS
+
+#endif /* _BRASERO_VOB_H_ */
Added: trunk/src/plugins/vcdimager/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/src/plugins/vcdimager/Makefile.am Mon Jul 14 18:07:55 2008
@@ -0,0 +1,24 @@
+DISABLE_DEPRECATED = -DG_DISABLE_DEPRECATED
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/src \
+ -DBRASERO_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+ -DBRASERO_PREFIX=\"$(prefix)\" \
+ -DBRASERO_SYSCONFDIR=\"$(sysconfdir)\" \
+ -DBRASERO_DATADIR=\"$(datadir)/brasero\" \
+ -DBRASERO_LIBDIR=\"$(libdir)\" \
+ $(DISABLE_DEPRECATED) \
+ $(BRASERO_BASE_CFLAGS) \
+ $(BRASERO_LIBXML_CFLAGS)
+
+AM_CFLAGS = -g
+
+vcdimagerdir = $(libdir)/brasero/plugins
+vcdimager_LTLIBRARIES = libbrasero-vcdimager.la
+
+libbrasero_vcdimager_la_SOURCES = burn-vcdimager.c burn-vcdimager.h
+libbrasero_vcdimager_la_LIBADD = $(BRASERO_BASE_LIBS) $(BRASERO_LIBXML_LIBS)
+libbrasero_vcdimager_la_LDFLAGS = -module -avoid-version
+
Added: trunk/src/plugins/vcdimager/burn-vcdimager.c
==============================================================================
--- (empty file)
+++ trunk/src/plugins/vcdimager/burn-vcdimager.c Mon Jul 14 18:07:55 2008
@@ -0,0 +1,482 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * brasero is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <gmodule.h>
+
+#include <libxml/xmlerror.h>
+#include <libxml/xmlwriter.h>
+#include <libxml/parser.h>
+#include <libxml/xmlstring.h>
+#include <libxml/uri.h>
+
+#include "burn-basics.h"
+#include "burn-plugin.h"
+#include "burn-job.h"
+#include "burn-process.h"
+#include "burn-vcdimager.h"
+
+BRASERO_PLUGIN_BOILERPLATE (BraseroVcdImager, brasero_vcd_imager, BRASERO_TYPE_PROCESS, BraseroProcess);
+
+typedef struct _BraseroVcdImagerPrivate BraseroVcdImagerPrivate;
+struct _BraseroVcdImagerPrivate
+{
+ guint svcd:1;
+};
+
+#define BRASERO_VCD_IMAGER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_VCD_IMAGER, BraseroVcdImagerPrivate))
+
+static BraseroProcessClass *parent_class = NULL;
+
+static BraseroBurnResult
+brasero_vcd_imager_read_stdout (BraseroProcess *process,
+ const gchar *line)
+{
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_vcd_imager_read_stderr (BraseroProcess *process,
+ const gchar *line)
+{
+ if (!strstr (line, ""))
+ return BRASERO_BURN_OK;
+
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_vcd_imager_generate_xml_file (BraseroProcess *process,
+ const gchar *path,
+ GError **error)
+{
+ BraseroVcdImagerPrivate *priv;
+ GSList *tracks = NULL;
+ xmlTextWriter *xml;
+ gchar buffer [64];
+ gint success;
+ GSList *iter;
+ gchar *name;
+ gint i;
+
+ BRASERO_JOB_LOG (process, "Creating DVD layout xml file(%s)", path);
+
+ xml = xmlNewTextWriterFilename (path, 0);
+ if (!xml)
+ return BRASERO_BURN_ERR;
+
+ priv = BRASERO_VCD_IMAGER_PRIVATE (process);
+
+ xmlTextWriterSetIndent (xml, 1);
+ xmlTextWriterSetIndentString (xml, (xmlChar *) "\t");
+
+ success = xmlTextWriterStartDocument (xml,
+ NULL,
+ "UTF8",
+ NULL);
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterWriteDTD (xml,
+ (xmlChar *) "videocd",
+ (xmlChar *) "-//GNU//DTD VideoCD//EN",
+ (xmlChar *) "http://www.gnu.org/software/vcdimager/videocd.dtd",
+ (xmlChar *) NULL);
+ if (success < 0)
+ goto error;
+
+ /* let's start */
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "videocd");
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "xmlns",
+ (xmlChar *) "http://www.gnu.org/software/vcdimager/1.0/");
+ if (success < 0)
+ goto error;
+
+ if (priv->svcd)
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "class",
+ (xmlChar *) "svcd");
+ else
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "class",
+ (xmlChar *) "vcd");
+
+ if (success < 0)
+ goto error;
+
+ if (priv->svcd)
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "version",
+ (xmlChar *) "1.0");
+ else
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "version",
+ (xmlChar *) "2.0");
+ if (success < 0)
+ goto error;
+
+ /* info part */
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "info");
+ if (success < 0)
+ goto error;
+
+ /* name of the volume */
+ name = NULL;
+ brasero_job_get_audio_title (BRASERO_JOB (process), &name);
+ success = xmlTextWriterWriteElement (xml,
+ (xmlChar *) "album-id",
+ (xmlChar *) name);
+ g_free (name);
+ if (success < 0)
+ goto error;
+
+ /* number of CDs */
+ success = xmlTextWriterWriteElement (xml,
+ (xmlChar *) "volume-count",
+ (xmlChar *) "1");
+ if (success < 0)
+ goto error;
+
+ /* CD number */
+ success = xmlTextWriterWriteElement (xml,
+ (xmlChar *) "volume-number",
+ (xmlChar *) "1");
+ if (success < 0)
+ goto error;
+
+ /* close info part */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* Primary Volume descriptor */
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "pvd");
+ if (success < 0)
+ goto error;
+
+ name = NULL;
+ brasero_job_get_audio_title (BRASERO_JOB (process), &name);
+ success = xmlTextWriterWriteElement (xml,
+ (xmlChar *) "volume-id",
+ (xmlChar *) name);
+ g_free (name);
+ if (success < 0)
+ goto error;
+
+ /* Makes it CD-i compatible */
+ success = xmlTextWriterWriteElement (xml,
+ (xmlChar *) "system-id",
+ (xmlChar *) "CD-RTOS CD-BRIDGE");
+ if (success < 0)
+ goto error;
+
+ /* Close Primary Volume descriptor */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* the tracks */
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "sequence-items");
+ if (success < 0)
+ goto error;
+
+ /* get all tracks */
+ brasero_job_get_tracks (BRASERO_JOB (process), &tracks);
+ for (i = 0, iter = tracks; iter; iter = iter->next, i++) {
+ BraseroTrack *track;
+ gchar *video;
+
+ track = iter->data;
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "sequence-item");
+ if (success < 0)
+ goto error;
+
+ video = brasero_track_get_audio_source (track, FALSE);
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "src",
+ (xmlChar *) video);
+ g_free (video);
+
+ if (success < 0)
+ goto error;
+
+ sprintf (buffer, "track-%i", i);
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "id",
+ (xmlChar *) buffer);
+ if (success < 0)
+ goto error;
+
+ /* close sequence-item */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+ }
+
+ /* sequence-items */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* the navigation */
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "pbc");
+ if (success < 0)
+ goto error;
+
+ /* get all tracks */
+ brasero_job_get_tracks (BRASERO_JOB (process), &tracks);
+ for (i = 0, iter = tracks; iter; iter = iter->next, i++) {
+ BraseroTrack *track;
+
+ track = iter->data;
+
+ sprintf (buffer, "playlist-%i", i);
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "playlist");
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "id",
+ (xmlChar *) buffer);
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterWriteElement (xml,
+ (xmlChar *) "wait",
+ (xmlChar *) "0");
+ if (success < 0)
+ goto error;
+
+ success = xmlTextWriterStartElement (xml, (xmlChar *) "play-item");
+ if (success < 0)
+ goto error;
+
+ sprintf (buffer, "track-%i", i);
+ success = xmlTextWriterWriteAttribute (xml,
+ (xmlChar *) "ref",
+ (xmlChar *) buffer);
+ if (success < 0)
+ goto error;
+
+ /* play-item */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* playlist */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+ }
+
+ /* pbc */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ /* close videocd */
+ success = xmlTextWriterEndElement (xml);
+ if (success < 0)
+ goto error;
+
+ xmlTextWriterEndDocument (xml);
+ xmlFreeTextWriter (xml);
+
+ return BRASERO_BURN_OK;
+
+error:
+
+ BRASERO_JOB_LOG (process, "Error");
+
+ /* close everything */
+ xmlTextWriterEndDocument (xml);
+ xmlFreeTextWriter (xml);
+
+ /* FIXME: get the error */
+
+ return BRASERO_BURN_ERR;
+}
+
+static BraseroBurnResult
+brasero_vcd_imager_set_argv (BraseroProcess *process,
+ GPtrArray *argv,
+ GError **error)
+{
+ BraseroVcdImagerPrivate *priv;
+ BraseroBurnResult result;
+ BraseroJobAction action;
+ BraseroMedia medium;
+ gchar *output;
+ gchar *image;
+ gchar *toc;
+
+ priv = BRASERO_VCD_IMAGER_PRIVATE (process);
+
+ brasero_job_get_action (BRASERO_JOB (process), &action);
+ if (action != BRASERO_JOB_ACTION_IMAGE)
+ BRASERO_JOB_NOT_SUPPORTED (process);
+
+ g_ptr_array_add (argv, g_strdup ("vcdxbuild"));
+
+ g_ptr_array_add (argv, g_strdup ("--progress"));
+ g_ptr_array_add (argv, g_strdup ("-v"));
+
+ /* specifies output */
+ image = toc = NULL;
+ brasero_job_get_image_output (BRASERO_JOB (process),
+ &image,
+ &toc);
+
+ g_ptr_array_add (argv, g_strdup ("-c"));
+ g_ptr_array_add (argv, toc);
+ g_ptr_array_add (argv, g_strdup ("-b"));
+ g_ptr_array_add (argv, image);
+
+ /* get temporary file to write XML */
+ result = brasero_job_get_tmp_file (BRASERO_JOB (process),
+ NULL,
+ &output,
+ error);
+ if (result != BRASERO_BURN_OK)
+ return result;
+
+ g_ptr_array_add (argv, output);
+
+ brasero_job_get_media (BRASERO_JOB (process), &medium);
+ if (medium & BRASERO_MEDIUM_CD) {
+ GValue *value = NULL;
+
+ brasero_job_tag_lookup (BRASERO_JOB (process),
+ BRASERO_VCD_TYPE,
+ &value);
+ if (value)
+ priv->svcd = (g_value_get_int (value) == BRASERO_SVCD);
+ }
+
+ result = brasero_vcd_imager_generate_xml_file (process, output, error);
+ if (result != BRASERO_BURN_OK)
+ return result;
+
+ brasero_job_set_current_action (BRASERO_JOB (process),
+ BRASERO_BURN_ACTION_CREATING_IMAGE,
+ _("Creating file layout"),
+ FALSE);
+ return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_vcd_imager_post (BraseroJob *job)
+{
+ BraseroVcdImagerPrivate *priv;
+
+ priv = BRASERO_VCD_IMAGER_PRIVATE (job);
+ return brasero_job_finished_session (job);
+}
+
+static void
+brasero_vcd_imager_init (BraseroVcdImager *object)
+{}
+
+static void
+brasero_vcd_imager_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+brasero_vcd_imager_class_init (BraseroVcdImagerClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ BraseroProcessClass* process_class = BRASERO_PROCESS_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (BraseroVcdImagerPrivate));
+
+ object_class->finalize = brasero_vcd_imager_finalize;
+ process_class->stdout_func = brasero_vcd_imager_read_stdout;
+ process_class->stderr_func = brasero_vcd_imager_read_stderr;
+ process_class->set_argv = brasero_vcd_imager_set_argv;
+ process_class->post = brasero_vcd_imager_post;
+}
+
+static BraseroBurnResult
+brasero_vcd_imager_export_caps (BraseroPlugin *plugin, gchar **error)
+{
+ BraseroBurnResult result;
+ GSList *output;
+ GSList *input;
+
+ /* NOTE: it seems that cdrecord can burn cue files on the fly */
+ brasero_plugin_define (plugin,
+ "vcdimager",
+ _("use vcdimager to convert a set of files to burn to SVCDs"),
+ "Philippe Rouquier",
+ 1);
+
+ /* First see if this plugin can be used */
+ result = brasero_process_check_path ("vcdimager", error);
+ if (result != BRASERO_BURN_OK)
+ return result;
+
+ input = brasero_caps_audio_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
+ BRASERO_AUDIO_FORMAT_MP2|
+ BRASERO_AUDIO_FORMAT_44100|
+ BRASERO_VIDEO_FORMAT_VCD);
+ output = brasero_caps_image_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
+ BRASERO_IMAGE_FORMAT_CUE);
+
+ brasero_plugin_link_caps (plugin, output, input);
+ g_slist_free (output);
+ g_slist_free (input);
+
+ /* we only support CDs they must be blank */
+ brasero_plugin_set_flags (plugin,
+ BRASERO_MEDIUM_CDRW|
+ BRASERO_MEDIUM_BLANK|
+ BRASERO_MEDIUM_CLOSED|
+ BRASERO_MEDIUM_APPENDABLE|
+ BRASERO_MEDIUM_HAS_DATA|
+ BRASERO_MEDIUM_HAS_AUDIO,
+ BRASERO_BURN_FLAG_NONE,
+ BRASERO_BURN_FLAG_NONE);
+
+ brasero_plugin_set_flags (plugin,
+ BRASERO_MEDIUM_FILE|
+ BRASERO_MEDIUM_CDR|
+ BRASERO_MEDIUM_BLANK|
+ BRASERO_MEDIUM_APPENDABLE|
+ BRASERO_MEDIUM_HAS_DATA|
+ BRASERO_MEDIUM_HAS_AUDIO,
+ BRASERO_BURN_FLAG_NONE,
+ BRASERO_BURN_FLAG_NONE);
+ return BRASERO_BURN_OK;
+}
+
Added: trunk/src/plugins/vcdimager/burn-vcdimager.h
==============================================================================
--- (empty file)
+++ trunk/src/plugins/vcdimager/burn-vcdimager.h Mon Jul 14 18:07:55 2008
@@ -0,0 +1,36 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * brasero
+ * Copyright (C) Philippe Rouquier 2008 <bonfire-app wanadoo fr>
+ *
+ * brasero is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * brasero is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _BRASERO_VCD_IMAGER_H_
+#define _BRASERO_VCD_IMAGER_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define BRASERO_TYPE_VCD_IMAGER (brasero_vcd_imager_get_type ())
+#define BRASERO_VCD_IMAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_VCD_IMAGER, BraseroVcdImager))
+#define BRASERO_VCD_IMAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_VCD_IMAGER, BraseroVcdImagerClass))
+#define BRASERO_IS_VCD_IMAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_VCD_IMAGER))
+#define BRASERO_IS_VCD_IMAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_VCD_IMAGER))
+#define BRASERO_VCD_IMAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_VCD_IMAGER, BraseroVcdImagerClass))
+
+G_END_DECLS
+
+#endif /* _BRASERO_VCD_IMAGER_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]