brasero r923 - in branches/video: . src
- From: philippr svn gnome org
- To: svn-commits-list gnome org
- Subject: brasero r923 - in branches/video: . src
- Date: Fri, 27 Jun 2008 13:29:10 +0000 (UTC)
Author: philippr
Date: Fri Jun 27 13:29:09 2008
New Revision: 923
URL: http://svn.gnome.org/viewvc/brasero?rev=923&view=rev
Log:
Modify the display widget for video project and split it between view and model
Added features to this widget:
- rename (not very useful ATM)
- directory search for video files
- DND
- projects support
* src/Makefile.am:
* src/brasero-disc.h:
* src/brasero-io.c (brasero_io_load_directory_thread):
* src/brasero-marshal.list:
* src/brasero-project.c (brasero_project_set_uri),
(_read_audio_track), (_get_tracks), (brasero_project_open_project),
(brasero_project_load_session), (brasero_project_save_project_xml):
* src/brasero-video-disc.c
(brasero_video_disc_name_editing_started_cb),
(brasero_video_disc_name_editing_canceled_cb),
(brasero_video_disc_name_edited_cb),
(brasero_video_disc_vfs_activity_changed),
(brasero_video_disc_directory_dialog),
(brasero_video_disc_unreadable_uri_dialog),
(brasero_video_disc_not_video_dialog),
(brasero_video_disc_add_uri_real),
(brasero_video_disc_delete_selected),
(brasero_video_disc_get_selected_uri),
(brasero_video_disc_selection_function),
(brasero_video_disc_row_deleted_cb),
(brasero_video_disc_row_inserted_cb),
(brasero_video_disc_row_changed_cb),
(brasero_video_disc_size_changed_cb), (brasero_video_disc_init),
(brasero_video_disc_reset_real), (brasero_video_disc_clear),
(brasero_video_disc_reset), (brasero_video_disc_finalize),
(brasero_video_disc_get_status),
(brasero_video_disc_set_session_param),
(brasero_video_disc_set_session_contents),
(brasero_video_disc_get_track), (brasero_video_disc_load_track),
(brasero_video_disc_iface_disc_init):
* src/brasero-video-project.c (brasero_video_project_file_signal),
(brasero_video_project_reference_new),
(brasero_video_project_reference_free),
(brasero_video_project_reference_get),
(brasero_video_project_reference_remove_children_cb),
(brasero_video_project_reference_invalidate),
(brasero_video_project_rename), (brasero_video_project_move),
(brasero_video_file_free),
(brasero_video_project_foreach_monitor_cancel_cb),
(brasero_video_project_remove_file), (brasero_video_project_reset),
(brasero_video_project_add_video_file),
(brasero_video_project_set_file_information),
(brasero_video_project_vfs_operation_finished),
(brasero_video_project_add_directory_contents_result),
(brasero_video_project_add_directory_contents),
(brasero_video_project_result_cb), (brasero_video_project_add_uri),
(brasero_video_project_get_size),
(brasero_video_project_get_file_num),
(brasero_video_project_get_nth_item),
(brasero_video_project_get_item_index),
(brasero_video_project_get_status),
(brasero_video_project_get_contents), (brasero_video_project_init),
(brasero_video_project_finalize),
(brasero_video_project_file_renamed),
(brasero_video_project_file_moved),
(brasero_video_project_file_removed),
(brasero_video_project_file_modified),
(brasero_video_project_class_init):
* src/brasero-video-project.h:
* src/brasero-video-tree-model.c
(brasero_video_tree_model_iter_parent),
(brasero_video_tree_model_iter_nth_child),
(brasero_video_tree_model_iter_n_children),
(brasero_video_tree_model_iter_has_child),
(brasero_video_tree_model_iter_children),
(brasero_video_tree_model_get_value),
(brasero_video_tree_model_file_to_path),
(brasero_video_tree_model_get_path),
(brasero_video_tree_model_path_to_file),
(brasero_video_tree_model_get_iter),
(brasero_video_tree_model_iter_next),
(brasero_video_tree_model_get_column_type),
(brasero_video_tree_model_get_n_columns),
(brasero_video_tree_model_get_flags),
(brasero_video_tree_model_multi_row_draggable),
(brasero_video_tree_model_multi_drag_data_get),
(brasero_video_tree_model_multi_drag_data_delete),
(brasero_video_tree_model_drag_data_received),
(brasero_video_tree_model_row_drop_possible),
(brasero_video_tree_model_drag_data_delete),
(brasero_video_tree_model_clear), (brasero_video_tree_model_reset),
(brasero_video_tree_model_file_added),
(brasero_video_tree_model_file_removed),
(brasero_video_tree_model_file_changed),
(brasero_video_tree_model_init),
(brasero_video_tree_model_finalize),
(brasero_video_tree_model_iface_init),
(brasero_video_tree_model_multi_drag_source_iface_init),
(brasero_video_tree_model_drag_source_iface_init),
(brasero_video_tree_model_drag_dest_iface_init),
(brasero_video_tree_model_class_init),
(brasero_video_tree_model_new):
* src/brasero-video-tree-model.h:
Added:
branches/video/src/brasero-video-project.c (contents, props changed)
branches/video/src/brasero-video-project.h (contents, props changed)
branches/video/src/brasero-video-tree-model.c (contents, props changed)
branches/video/src/brasero-video-tree-model.h (contents, props changed)
Modified:
branches/video/ChangeLog
branches/video/src/Makefile.am
branches/video/src/brasero-disc.h
branches/video/src/brasero-io.c
branches/video/src/brasero-marshal.list
branches/video/src/brasero-project.c
branches/video/src/brasero-video-disc.c
Modified: branches/video/src/Makefile.am
==============================================================================
--- branches/video/src/Makefile.am (original)
+++ branches/video/src/Makefile.am Fri Jun 27 13:29:09 2008
@@ -262,7 +262,11 @@
burn-volume-source.c \
burn-volume-source.h \
brasero-video-disc.c \
- brasero-video-disc.h
+ 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
Modified: branches/video/src/brasero-disc.h
==============================================================================
--- branches/video/src/brasero-disc.h (original)
+++ branches/video/src/brasero-disc.h Fri Jun 27 13:29:09 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: branches/video/src/brasero-io.c
==============================================================================
--- branches/video/src/brasero-io.c (original)
+++ branches/video/src/brasero-io.c Fri Jun 27 13:29:09 2008
@@ -1634,7 +1634,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: branches/video/src/brasero-marshal.list
==============================================================================
--- branches/video/src/brasero-marshal.list (original)
+++ branches/video/src/brasero-marshal.list Fri Jun 27 13:29:09 2008
@@ -7,6 +7,7 @@
VOID:DOUBLE,STRING
VOID:INT64
VOID:INT,STRING
+VOID:POINTER,STRING
VOID:DOUBLE,DOUBLE,LONG
INT:OBJECT,INT,INT
BOOLEAN:STRING
Modified: branches/video/src/brasero-project.c
==============================================================================
--- branches/video/src/brasero-project.c (original)
+++ branches/video/src/brasero-project.c Fri Jun 27 13:29:09 2008
@@ -1742,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);
@@ -1901,8 +1903,6 @@
BraseroDiscSong *song;
track = g_new0 (BraseroDiscTrack, 1);
- track->type = BRASERO_DISC_TRACK_AUDIO;
-
song = NULL;
while (uris) {
@@ -2006,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)
@@ -2017,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;
@@ -2129,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);
@@ -2247,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);
@@ -2542,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: branches/video/src/brasero-video-disc.c
==============================================================================
--- branches/video/src/brasero-video-disc.c (original)
+++ branches/video/src/brasero-video-disc.c Fri Jun 27 13:29:09 2008
@@ -28,10 +28,14 @@
#include <gtk/gtk.h>
+#include "eggtreemultidnd.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"
typedef struct _BraseroVideoDiscPrivate BraseroVideoDiscPrivate;
struct _BraseroVideoDiscPrivate
@@ -43,14 +47,8 @@
GtkUIManager *manager;
GtkActionGroup *disc_group;
- BraseroIO *io;
- BraseroIOJobBase *add_uri;
-
- gint64 sectors;
-
- guint activity;
-
guint reject_files:1;
+ guint editing:1;
guint loading:1;
};
@@ -66,66 +64,150 @@
brasero_video_disc_iface_disc_init));
enum {
- NAME_COL,
- URI_COL,
- ICON_COL,
- SIZE_COL,
- START_COL,
- END_COL,
- EDITABLE_COL,
- NUM_COL
+ PROP_NONE,
+ PROP_REJECT_FILE,
};
enum {
- PROP_NONE,
- PROP_REJECT_FILE,
+ 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_increase_activity_counter (BraseroVideoDisc *self)
+brasero_video_disc_name_editing_started_cb (GtkCellRenderer *renderer,
+ GtkCellEditable *editable,
+ gchar *path,
+ BraseroVideoDisc *disc)
{
- GdkCursor *cursor;
BraseroVideoDiscPrivate *priv;
- priv = BRASERO_VIDEO_DISC_PRIVATE (self);
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+ priv->editing = 1;
+}
- if (priv->activity == 0 && GTK_WIDGET (self)->window) {
- cursor = gdk_cursor_new (GDK_WATCH);
- gdk_window_set_cursor (GTK_WIDGET (self)->window, cursor);
- gdk_cursor_unref (cursor);
- }
+static void
+brasero_video_disc_name_editing_canceled_cb (GtkCellRenderer *renderer,
+ BraseroVideoDisc *disc)
+{
+ BraseroVideoDiscPrivate *priv;
- priv->activity++;
+ priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
+ priv->editing = 0;
}
static void
-brasero_video_disc_decrease_activity_counter (BraseroVideoDisc *self)
+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);
- if (priv->activity == 1 && GTK_WIDGET (self)->window)
- gdk_window_set_cursor (GTK_WIDGET (self)->window, NULL);
+ 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);
- priv->activity--;
+ brasero_video_project_rename (project, file, text);
}
static void
-brasero_video_disc_io_operation_finished (GObject *object,
- gboolean cancelled,
- gpointer null_data)
+brasero_video_disc_vfs_activity_changed (BraseroVideoProject *project,
+ gboolean activity,
+ BraseroVideoDisc *self)
{
- BraseroVideoDisc *self = BRASERO_VIDEO_DISC (object);
+ GdkCursor *cursor;
+ BraseroVideoDiscPrivate *priv;
- brasero_video_disc_decrease_activity_counter (self);
+ 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_dialog (BraseroVideoDisc *self,
- const gchar *uri,
- GError *error)
+brasero_video_disc_unreadable_uri_dialog (BraseroVideoProject *project,
+ GError *error,
+ const gchar *uri,
+ BraseroVideoDisc *self)
{
GtkWidget *dialog, *toplevel;
gchar *name;
@@ -158,8 +240,9 @@
}
static void
-brasero_video_disc_file_not_video_dialog (BraseroVideoDisc *self,
- const gchar *uri)
+brasero_video_disc_not_video_dialog (BraseroVideoProject *project,
+ const gchar *uri,
+ BraseroVideoDisc *self)
{
GtkWidget *dialog, *toplevel;
gchar *name;
@@ -189,94 +272,6 @@
gtk_widget_destroy (dialog);
}
-static void
-brasero_video_disc_new_row_cb (GObject *obj,
- GError *error,
- const gchar *uri,
- GFileInfo *info,
- gpointer user_data)
-{
- gint64 len;
- gchar *size_str;
- GtkTreeIter iter;
- const gchar *title;
- GdkPixbuf *snapshot;
- GtkTreeModel *model;
- GtkTreePath *treepath;
- GtkTreeRowReference *ref = user_data;
- BraseroVideoDisc *self = BRASERO_VIDEO_DISC (obj);
- BraseroVideoDiscPrivate *priv = BRASERO_VIDEO_DISC_PRIVATE (self);
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
- treepath = gtk_tree_row_reference_get_path (ref);
- gtk_tree_row_reference_free (ref);
- if (!treepath)
- return;
-
- gtk_tree_model_get_iter (model, &iter, treepath);
- gtk_tree_path_free (treepath);
-
- if (error) {
- brasero_video_disc_unreadable_dialog (self, uri, error);
- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
- return;
- }
-
- if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
-// brasero_video_disc_add_dir (self, uri);
- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
- return;
- }
-
- if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR
- || !g_file_info_get_attribute_boolean (info, BRASERO_IO_HAS_VIDEO)) {
- brasero_video_disc_file_not_video_dialog (self, uri);
- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
- return;
- }
-
- if (g_file_info_get_is_symlink (info)) {
- uri = g_strconcat ("file://", g_file_info_get_symlink_target (info), NULL);
- gtk_list_store_set (GTK_LIST_STORE (model), &iter,
- URI_COL, uri, -1);
- }
-
- /* 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);
- gtk_list_store_set (GTK_LIST_STORE (model), &iter,
- ICON_COL, scaled,
- -1);
- g_object_unref (scaled);
- }
-
- /* */
- len = g_file_info_get_attribute_uint64 (info, BRASERO_IO_LEN);
- size_str = brasero_utils_get_time_string (len, TRUE, FALSE);
- gtk_list_store_set (GTK_LIST_STORE (model), &iter,
- END_COL, len,
- SIZE_COL, size_str,
- -1);
- g_free (size_str);
-
- /* */
- title = g_file_info_get_attribute_string (info, BRASERO_IO_TITLE);
- if (title)
- gtk_list_store_set (GTK_LIST_STORE (model), &iter,
- NAME_COL, title,
- -1);
-
- /* FIXME: duration to sectors is not correct here, that's not audio... */
- priv->sectors += BRASERO_DURATION_TO_SECTORS (len);
- brasero_disc_size_changed (BRASERO_DISC (self), priv->sectors);
-}
-
static BraseroDiscResult
brasero_video_disc_add_uri_real (BraseroVideoDisc *self,
const gchar *uri,
@@ -285,91 +280,35 @@
gint64 end,
GtkTreePath **path_return)
{
+ BraseroVideoFile *file;
+ BraseroVideoProject *project;
BraseroVideoDiscPrivate *priv;
- GtkTreeRowReference *ref;
- GtkTreePath *treepath;
- GtkTreeModel *store;
- GtkTreeIter iter;
- gchar *markup;
- gchar *name;
-
- g_return_val_if_fail (uri != NULL, BRASERO_DISC_ERROR_UNKNOWN);
+ BraseroVideoFile *sibling = NULL;
priv = BRASERO_VIDEO_DISC_PRIVATE (self);
if (priv->reject_files)
return BRASERO_DISC_NOT_READY;
- gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
-
- store = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
- if (pos > -1)
- gtk_list_store_insert (GTK_LIST_STORE (store), &iter, pos);
- else
- gtk_list_store_append (GTK_LIST_STORE (store), &iter);
+ project = BRASERO_VIDEO_PROJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree)));
- BRASERO_GET_BASENAME_FOR_DISPLAY (uri, name);
- markup = g_markup_escape_text (name, -1);
- g_free (name);
+ if (pos > 0) {
+ GtkTreePath *treepath;
- gtk_list_store_set (GTK_LIST_STORE (store), &iter,
- NAME_COL, markup,
- URI_COL, uri,
- -1);
- g_free (markup);
-
- /* set size message */
- start = start > 0 ? start:0;
- if (end > 0 && end > start) {
- gchar *string;
- gint64 length;
-
- /* update global size */
- length = BRASERO_AUDIO_TRACK_LENGTH (start, end);
- priv->sectors += BRASERO_DURATION_TO_SECTORS (length);
- brasero_disc_size_changed (BRASERO_DISC (self), priv->sectors);
-
- string = brasero_utils_get_time_string (length, TRUE, FALSE);
- gtk_list_store_set (GTK_LIST_STORE (store), &iter,
- START_COL, start,
- END_COL, end,
- SIZE_COL, string,
- -1);
- g_free (string);
+ 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);
}
- else
- gtk_list_store_set (GTK_LIST_STORE (store), &iter,
- SIZE_COL, _("loading"),
- -1);
-
- /* Now load */
- treepath = gtk_tree_model_get_path (store, &iter);
- ref = gtk_tree_row_reference_new (store, treepath);
- if (path_return)
- *path_return = treepath;
- else
- 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);
- /* get info async for the file */
- if (!priv->io)
- priv->io = brasero_io_get_default ();
-
- if (!priv->add_uri)
- priv->add_uri = brasero_io_register (G_OBJECT (self),
- brasero_video_disc_new_row_cb,
- brasero_video_disc_io_operation_finished,
- NULL);
-
- brasero_video_disc_increase_activity_counter (self);
- brasero_io_get_file_info (priv->io,
- uri,
- priv->add_uri,
- BRASERO_IO_INFO_PERM|
- BRASERO_IO_INFO_MIME|
- BRASERO_IO_INFO_METADATA|
- BRASERO_IO_INFO_METADATA_MISSING_CODEC|
- BRASERO_IO_INFO_METADATA_SNAPSHOT,
- ref);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 1);
return BRASERO_DISC_OK;
}
@@ -419,26 +358,20 @@
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;
- GtkTreeIter tree_iter;
- gint64 start;
- gint64 end;
treepath = iter->data;
- gtk_tree_model_get_iter (model, &tree_iter, treepath);
- gtk_tree_model_get (model, &tree_iter,
- START_COL, &start,
- END_COL, &end,
- -1);
- priv->sectors -= BRASERO_DURATION_TO_SECTORS (end - start);
-
- gtk_list_store_remove (GTK_LIST_STORE (model), &tree_iter);
+ 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);
-
- brasero_disc_size_changed (BRASERO_DISC (self), priv->sectors);
}
static gboolean
@@ -458,14 +391,15 @@
return FALSE;
if (uri) {
- GtkTreeIter iter;
+ BraseroVideoFile *file;
GtkTreePath *treepath;
treepath = selected->data;
- gtk_tree_model_get_iter (model, &iter, treepath);
- gtk_tree_model_get (model, &iter,
- URI_COL, uri,
- -1);
+ 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);
@@ -481,6 +415,22 @@
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;
+}
+
static guint
brasero_video_disc_add_ui (BraseroDisc *disc,
GtkUIManager *manager,
@@ -544,8 +494,13 @@
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),
- gtk_tree_model_iter_n_children (model, NULL));
+ brasero_video_project_get_file_num (BRASERO_VIDEO_PROJECT (model)));
}
static void
@@ -554,8 +509,13 @@
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),
- gtk_tree_model_iter_n_children (model, NULL));
+ brasero_video_project_get_file_num (BRASERO_VIDEO_PROJECT (model)));
}
static void
@@ -564,8 +524,20 @@
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),
- gtk_tree_model_iter_n_children (model, NULL));
+ 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
@@ -592,14 +564,8 @@
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0);
/* Tree */
- model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COL,
- G_TYPE_STRING,
- G_TYPE_STRING,
- GDK_TYPE_PIXBUF,
- G_TYPE_STRING,
- G_TYPE_INT64,
- G_TYPE_INT64,
- G_TYPE_BOOLEAN));
+ 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),
@@ -613,7 +579,29 @@
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);
@@ -628,9 +616,16 @@
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_add_attribute (column, renderer,
- "pixbuf", ICON_COL);
+ "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,
@@ -639,9 +634,9 @@
gtk_tree_view_column_pack_end (column, renderer, TRUE);
gtk_tree_view_column_add_attribute (column, renderer,
- "markup", NAME_COL);
+ "markup", BRASERO_VIDEO_TREE_MODEL_NAME);
gtk_tree_view_column_add_attribute (column, renderer,
- "editable", EDITABLE_COL);
+ "editable", BRASERO_VIDEO_TREE_MODEL_EDITABLE);
gtk_tree_view_column_set_title (column, _("Title"));
g_object_set (G_OBJECT (column),
"expand", TRUE,
@@ -659,13 +654,12 @@
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_add_attribute (column, renderer,
- "text", SIZE_COL);
+ "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);
- gtk_tree_view_column_set_sort_column_id (column, NAME_COL);
/* selection */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
@@ -674,6 +668,10 @@
"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);
@@ -685,37 +683,42 @@
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);
-
- if (priv->io)
- brasero_io_cancel_by_base (priv->io, priv->add_uri);
-
- priv->sectors = 0;
-
- priv->activity = 1;
- brasero_video_disc_decrease_activity_counter (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;
- GtkTreeModel *model;
priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
brasero_video_disc_reset_real (BRASERO_VIDEO_DISC (disc));
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
- gtk_list_store_clear (GTK_LIST_STORE (model));
-
gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), 0);
brasero_disc_size_changed (disc, 0);
}
@@ -723,27 +726,12 @@
static void
brasero_video_disc_reset (BraseroDisc *disc)
{
- brasero_video_disc_clear (disc);
+ brasero_video_disc_reset_real (BRASERO_VIDEO_DISC (disc));
}
static void
brasero_video_disc_finalize (GObject *object)
{
- BraseroVideoDiscPrivate *priv;
-
- priv = BRASERO_VIDEO_DISC_PRIVATE (object);
-
- brasero_video_disc_reset_real (BRASERO_VIDEO_DISC (object));
-
- if (priv->io) {
- brasero_io_cancel_by_base (priv->io, priv->add_uri);
- g_free (priv->add_uri);
- priv->add_uri = NULL;
-
- g_object_unref (priv->io);
- priv->io = NULL;
- }
-
G_OBJECT_CLASS (brasero_video_disc_parent_class)->finalize (object);
}
@@ -788,28 +776,18 @@
}
static BraseroDiscResult
-brasero_video_disc_get_status (BraseroDisc *disc)
+brasero_video_disc_get_status (BraseroDisc *self)
{
- GtkTreeModel *model;
+ BraseroVideoProject *project;
BraseroVideoDiscPrivate *priv;
- priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
-
- if (priv->loading)
- return BRASERO_DISC_LOADING;
-
- if (priv->activity)
- return BRASERO_DISC_NOT_READY;
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
- if (!gtk_tree_model_iter_n_children (model, NULL))
- return BRASERO_DISC_ERROR_EMPTY_SELECTION;
-
- return BRASERO_DISC_OK;
+ 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);
}
-static BraseroDiscResult
-brasero_video_disc_set_session_param (BraseroDisc *disc,
+BraseroDiscResult
+brasero_video_disc_set_session_param (BraseroDisc *self,
BraseroBurnSession *session)
{
BraseroTrackType type;
@@ -820,53 +798,100 @@
return BRASERO_BURN_OK;
}
-static BraseroDiscResult
-brasero_video_disc_set_session_contents (BraseroDisc *disc,
+BraseroDiscResult
+brasero_video_disc_set_session_contents (BraseroDisc *self,
BraseroBurnSession *session)
{
- GtkTreeIter iter;
- GtkTreeModel *model;
- BraseroTrack *track;
+ GSList *tracks, *iter;
+ BraseroVideoProject *project;
BraseroVideoDiscPrivate *priv;
- priv = BRASERO_VIDEO_DISC_PRIVATE (disc);
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
- if (!gtk_tree_model_get_iter_first (model, &iter))
+ 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;
- track = NULL;
- do {
- gchar *uri;
- gint64 end;
- gint64 start;
- gchar *title;
- BraseroSongInfo *info;
-
- gtk_tree_model_get (model, &iter,
- URI_COL, &uri,
- NAME_COL, &title,
- START_COL, &start,
- END_COL, &end,
- -1);
-
- info = g_new0 (BraseroSongInfo, 1);
- info->title = title;
-
- track = brasero_track_new (BRASERO_TRACK_TYPE_AUDIO);
- brasero_track_set_audio_source (track,
- uri,
- BRASERO_AUDIO_FORMAT_UNDEFINED|
- BRASERO_VIDEO_FORMAT_UNDEFINED);
+ for (iter = tracks; iter; iter = iter->next) {
+ BraseroTrack *track;
- brasero_track_set_audio_boundaries (track, start, end, -1);
- brasero_track_set_audio_info (track, info);
+ 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);
- } while (gtk_tree_model_iter_next (model, &iter));
+ }
+ 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;
}
@@ -883,10 +908,9 @@
iface->set_session_param = brasero_video_disc_set_session_param;
iface->set_session_contents = brasero_video_disc_set_session_contents;
-/*
- iface->get_track = brasero_data_disc_get_track;
- iface->load_track = brasero_data_disc_load_track;
-*/
+ 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;
}
Added: branches/video/src/brasero-video-project.c
==============================================================================
--- (empty file)
+++ branches/video/src/brasero-video-project.c Fri Jun 27 13:29:09 2008
@@ -0,0 +1,1129 @@
+/* -*- 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,
+ error,
+ uri);
+}
+
+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_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;
+}
+
+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_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 */
+ brasero_video_project_remove_file (BRASERO_VIDEO_PROJECT (monitor),
+ callback_src);
+}
+
+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_METADATA|
+ BRASERO_IO_INFO_METADATA_MISSING_CODEC|
+ BRASERO_IO_INFO_METADATA_SNAPSHOT,
+ GINT_TO_POINTER (ref));
+}
+
+#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: branches/video/src/brasero-video-project.h
==============================================================================
--- (empty file)
+++ branches/video/src/brasero-video-project.h Fri Jun 27 13:29:09 2008
@@ -0,0 +1,170 @@
+/* -*- 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);
+
+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: branches/video/src/brasero-video-tree-model.c
==============================================================================
--- (empty file)
+++ branches/video/src/brasero-video-tree-model.c Fri Jun 27 13:29:09 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: branches/video/src/brasero-video-tree-model.h
==============================================================================
--- (empty file)
+++ branches/video/src/brasero-video-tree-model.h Fri Jun 27 13:29:09 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_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]