1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 
3 /***************************************************************************
4  *            audio-disc.c
5  *
6  *  dim nov 27 15:34:32 2005
7  *  Copyright  2005  Rouquier Philippe
8  *  brasero-app@wanadoo.fr
9  ***************************************************************************/
10 
11 /*
12  *  Brasero is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  Brasero is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU Library General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to:
24  * 	The Free Software Foundation, Inc.,
25  * 	51 Franklin Street, Fifth Floor
26  * 	Boston, MA  02110-1301, USA.
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #  include <config.h>
31 #endif
32 
33 #include <time.h>
34 #include <errno.h>
35 #include <string.h>
36 
37 #include <glib.h>
38 #include <glib/gi18n.h>
39 
40 #include <gdk/gdkkeysyms.h>
41 
42 #include <gtk/gtk.h>
43 
44 #include "brasero-misc.h"
45 #include "brasero-io.h"
46 #include "brasero-notify.h"
47 
48 #include "brasero-units.h"
49 
50 #include "brasero-tags.h"
51 #include "brasero-track-stream-cfg.h"
52 #include "brasero-session-cfg.h"
53 
54 #include "brasero-app.h"
55 #include "brasero-disc.h"
56 #include "brasero-audio-disc.h"
57 #include "brasero-metadata.h"
58 #include "brasero-utils.h"
59 #include "brasero-multi-song-props.h"
60 #include "brasero-song-properties.h"
61 #include "brasero-split-dialog.h"
62 #include "brasero-video-tree-model.h"
63 
64 #include "eggtreemultidnd.h"
65 
66 static BraseroDiscResult
67 brasero_audio_disc_set_session_contents (BraseroDisc *disc,
68 					 BraseroBurnSession *session);
69 
70 static BraseroDiscResult
71 brasero_audio_disc_add_uri (BraseroDisc *disc,
72 			    const char *uri);
73 static void
74 brasero_audio_disc_delete_selected (BraseroDisc *disc);
75 
76 
77 static guint
78 brasero_audio_disc_add_ui (BraseroDisc *disc,
79 			   GtkUIManager *manager,
80 			   GtkWidget *message);
81 
82 static gboolean
83 brasero_audio_disc_button_pressed_cb (GtkTreeView *tree,
84 				      GdkEventButton *event,
85 				      BraseroAudioDisc *disc);
86 static gboolean
87 brasero_audio_disc_key_released_cb (GtkTreeView *tree,
88 				    GdkEventKey *event,
89 				    BraseroAudioDisc *disc);
90 static void
91 brasero_audio_disc_display_edited_cb (GtkCellRendererText *cellrenderertext,
92 				      gchar *path_string,
93 				      gchar *text,
94 				      BraseroAudioDisc *disc);
95 static void
96 brasero_audio_disc_display_editing_started_cb (GtkCellRenderer *renderer,
97 					       GtkCellEditable *editable,
98 					       gchar *path,
99 					       BraseroAudioDisc *disc);
100 static void
101 brasero_audio_disc_display_editing_canceled_cb (GtkCellRenderer *renderer,
102 						 BraseroAudioDisc *disc);
103 
104 static void
105 brasero_audio_disc_edit_information_cb (GtkAction *action,
106 					BraseroAudioDisc *disc);
107 static void
108 brasero_audio_disc_open_activated_cb (GtkAction *action,
109 				      BraseroAudioDisc *disc);
110 static void
111 brasero_audio_disc_delete_activated_cb (GtkAction *action,
112 					BraseroDisc *disc);
113 static void
114 brasero_audio_disc_paste_activated_cb (GtkAction *action,
115 				       BraseroAudioDisc *disc);
116 static gboolean
117 brasero_audio_disc_get_selected_uri (BraseroDisc *disc,
118 				     gchar **uri);
119 static gboolean
120 brasero_audio_disc_get_boundaries (BraseroDisc *disc,
121 				   gint64 *start,
122 				   gint64 *end);
123 
124 static void
125 brasero_audio_disc_add_pause_cb (GtkAction *action, BraseroAudioDisc *disc);
126 static void
127 brasero_audio_disc_split_cb (GtkAction *action, BraseroAudioDisc *disc);
128 
129 static void
130 brasero_audio_disc_selection_changed (GtkTreeSelection *selection, BraseroAudioDisc *disc);
131 
132 struct _BraseroAudioDiscPrivate {
133 	BraseroIOJobBase *add_dir;
134 	BraseroIOJobBase *add_playlist;
135 
136 	GtkWidget *tree;
137 
138 	GtkWidget *message;
139 	GtkUIManager *manager;
140 	GtkActionGroup *disc_group;
141 
142 	GtkTreePath *selected_path;
143 
144        	GdkDragContext *drag_context;
145 
146 	/* only used at start time when loading a project */
147 	guint loading;
148 
149 	guint editing:1;
150 	guint dragging:1;
151 	guint reject_files:1;
152 };
153 
154 static GtkActionEntry entries[] = {
155 	{"ContextualMenu", NULL, N_("Menu")},
156 	{"OpenSong", GTK_STOCK_OPEN, NULL, NULL, N_("Open the selected files"),
157 	 G_CALLBACK (brasero_audio_disc_open_activated_cb)},
158 	{"EditSong", GTK_STOCK_PROPERTIES, N_("_Edit Information…"), NULL, N_("Edit the track information (start, end, author, etc.)"),
159 	 G_CALLBACK (brasero_audio_disc_edit_information_cb)},
160 	{"DeleteAudio", GTK_STOCK_REMOVE, NULL, NULL, N_("Remove the selected files from the project"),
161 	 G_CALLBACK (brasero_audio_disc_delete_activated_cb)},
162 	{"PasteAudio", NULL, N_("Paste files"), NULL, N_("Add the files stored in the clipboard"),
163 	 G_CALLBACK (brasero_audio_disc_paste_activated_cb)},
164 	{"Pause", "insert-pause", N_("I_nsert a Pause"), NULL, N_("Add a 2 second pause after the track"),
165 	 G_CALLBACK (brasero_audio_disc_add_pause_cb)},
166 	{"Split", "transform-crop-and-resize", N_("_Split Track…"), NULL, N_("Split the selected track"),
167 	 G_CALLBACK (brasero_audio_disc_split_cb)}
168 };
169 
170 static const gchar *description = {
171 	"<ui>"
172 	"<menubar name='menubar' >"
173 		"<menu action='EditMenu'>"
174 		"<placeholder name='EditPlaceholder'>"
175 			"<menuitem action='Pause'/>"
176 			"<menuitem action='Split'/>"
177 		"</placeholder>"
178 		"</menu>"
179 	"</menubar>"
180 	"<popup action='ContextMenu'>"
181 		"<menuitem action='OpenSong'/>"
182 		"<menuitem action='DeleteAudio'/>"
183 		"<separator/>"
184 		"<menuitem action='PasteAudio'/>"
185 		"<separator/>"
186 		"<menuitem action='Pause'/>"
187 		"<menuitem action='Split'/>"
188 		"<separator/>"
189 		"<menuitem action='EditSong'/>"
190 	"</popup>"
191 	"<toolbar name='Toolbar'>"
192 		"<placeholder name='DiscButtonPlaceholder'>"
193 			"<separator/>"
194 			"<toolitem action='Pause'/>"
195 			"<toolitem action='Split'/>"
196 		"</placeholder>"
197 	"</toolbar>"
198 	"</ui>"
199 };
200 
201 enum {
202 	TREE_MODEL_ROW = 150,
203 	TARGET_URIS_LIST,
204 };
205 
206 static GtkTargetEntry ntables_cd [] = {
207 	{"GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
208 	{"text/uri-list", 0, TARGET_URIS_LIST}
209 };
210 static guint nb_targets_cd = sizeof (ntables_cd) / sizeof (ntables_cd[0]);
211 
212 static GtkTargetEntry ntables_source [] = {
213 	{"GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, TREE_MODEL_ROW},
214 };
215 static guint nb_targets_source = sizeof (ntables_source) / sizeof (ntables_source[0]);
216 
217 static GObjectClass *parent_class = NULL;
218 
219 enum {
220 	PROP_NONE,
221 	PROP_REJECT_FILE,
222 };
223 
224 #define COL_KEY "column_key"
225 
226 #define BRASERO_AUDIO_DISC_CONTEXT		1000
227 
228 static void brasero_audio_disc_iface_disc_init (BraseroDiscIface *iface);
229 
230 G_DEFINE_TYPE_WITH_CODE (BraseroAudioDisc,
231 			 brasero_audio_disc,
232 			 GTK_TYPE_BOX,
233 			 G_IMPLEMENT_INTERFACE (BRASERO_TYPE_DISC,
234 					        brasero_audio_disc_iface_disc_init));
235 static gboolean
brasero_audio_disc_is_empty(BraseroDisc * disc)236 brasero_audio_disc_is_empty (BraseroDisc *disc)
237 {
238 	GtkTreeModel *model;
239 
240 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (BRASERO_AUDIO_DISC (disc)->priv->tree));
241 	if (!model)
242 		return FALSE;
243 
244 	return gtk_tree_model_iter_n_children (model, NULL) != 0;
245 }
246 
247 static void
brasero_audio_disc_iface_disc_init(BraseroDiscIface * iface)248 brasero_audio_disc_iface_disc_init (BraseroDiscIface *iface)
249 {
250 	iface->add_uri = brasero_audio_disc_add_uri;
251 	iface->delete_selected = brasero_audio_disc_delete_selected;
252 
253 	iface->is_empty = brasero_audio_disc_is_empty;
254 
255 	iface->set_session_contents = brasero_audio_disc_set_session_contents;
256 	iface->get_selected_uri = brasero_audio_disc_get_selected_uri;
257 	iface->get_boundaries = brasero_audio_disc_get_boundaries;
258 	iface->add_ui = brasero_audio_disc_add_ui;
259 }
260 
261 static void
brasero_audio_disc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)262 brasero_audio_disc_get_property (GObject * object,
263 				 guint prop_id,
264 				 GValue * value,
265 				 GParamSpec * pspec)
266 {
267 	BraseroAudioDisc *disc;
268 
269 	disc = BRASERO_AUDIO_DISC (object);
270 
271 	switch (prop_id) {
272 	case PROP_REJECT_FILE:
273 		g_value_set_boolean (value, disc->priv->reject_files);
274 		break;
275 	default:
276 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
277 		break;
278 	}
279 }
280 
281 static void
brasero_audio_disc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)282 brasero_audio_disc_set_property (GObject * object,
283 				 guint prop_id,
284 				 const GValue * value,
285 				 GParamSpec * pspec)
286 {
287 	BraseroAudioDisc *disc;
288 
289 	disc = BRASERO_AUDIO_DISC (object);
290 
291 	switch (prop_id) {
292 	case PROP_REJECT_FILE:
293 		disc->priv->reject_files = g_value_get_boolean (value);
294 		break;
295 	default:
296 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
297 		break;
298 	}
299 }
300 
301 static guint
brasero_audio_disc_add_ui(BraseroDisc * disc,GtkUIManager * manager,GtkWidget * message)302 brasero_audio_disc_add_ui (BraseroDisc *disc,
303 			   GtkUIManager *manager,
304 			   GtkWidget *message)
305 {
306 	BraseroAudioDisc *audio_disc;
307 	GError *error = NULL;
308 	GtkAction *action;
309 	guint merge_id;
310 
311 	audio_disc = BRASERO_AUDIO_DISC (disc);
312 
313 	if (audio_disc->priv->message) {
314 		g_object_unref (audio_disc->priv->message);
315 		audio_disc->priv->message = NULL;
316 	}
317 
318 	audio_disc->priv->message = g_object_ref (message);
319 
320 	if (!audio_disc->priv->disc_group) {
321 		audio_disc->priv->disc_group = gtk_action_group_new (BRASERO_DISC_ACTION "-audio");
322 		gtk_action_group_set_translation_domain (audio_disc->priv->disc_group, GETTEXT_PACKAGE);
323 		gtk_action_group_add_actions (audio_disc->priv->disc_group,
324 					      entries,
325 					      G_N_ELEMENTS (entries),
326 					      disc);
327 		gtk_ui_manager_insert_action_group (manager,
328 						    audio_disc->priv->disc_group,
329 						    0);
330 	}
331 
332 	merge_id = gtk_ui_manager_add_ui_from_string (manager,
333 						      description,
334 						      -1,
335 						      &error);
336 	if (!merge_id) {
337 		g_error_free (error);
338 		return 0;
339 	}
340 
341 	action = gtk_action_group_get_action (audio_disc->priv->disc_group, "Pause");
342 	g_object_set (action,
343 		      "short-label", _("Pause"), /* for toolbar buttons */
344 		      NULL);
345 	gtk_action_set_sensitive (action, FALSE);
346 
347 	action = gtk_action_group_get_action (audio_disc->priv->disc_group, "Split");
348 	g_object_set (action,
349 		      "short-label", _("Split"), /* for toolbar buttons */
350 		      NULL);
351 	gtk_action_set_sensitive (action, FALSE);
352 
353 	audio_disc->priv->manager = manager;
354 	g_object_ref (manager);
355 
356 	return merge_id;
357 }
358 
359 static gboolean
brasero_audio_disc_selection_function(GtkTreeSelection * selection,GtkTreeModel * model,GtkTreePath * treepath,gboolean is_selected,gpointer NULL_data)360 brasero_audio_disc_selection_function (GtkTreeSelection *selection,
361 				       GtkTreeModel *model,
362 				       GtkTreePath *treepath,
363 				       gboolean is_selected,
364 				       gpointer NULL_data)
365 {
366 /*	BraseroTrack *track;
367 
368 	track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
369 	if (track)
370 		gtk_list_store_set (GTK_LIST_STORE (model), &iter,
371 				    BRASERO_VIDEO_TREE_MODEL_EDITABLE, (is_selected == FALSE),
372 				    -1);
373 */
374 	return TRUE;
375 }
376 
377 static void
brasero_audio_disc_init(BraseroAudioDisc * obj)378 brasero_audio_disc_init (BraseroAudioDisc *obj)
379 {
380 	GtkTreeSelection *selection;
381 	GtkTreeViewColumn *column;
382 	GtkCellRenderer *renderer;
383 	GtkWidget *scroll;
384 
385 	obj->priv = g_new0 (BraseroAudioDiscPrivate, 1);
386 	gtk_box_set_spacing (GTK_BOX (obj), 0);
387 	gtk_orientable_set_orientation (GTK_ORIENTABLE (obj), GTK_ORIENTATION_VERTICAL);
388 
389 	/* Tree */
390 	obj->priv->tree = gtk_tree_view_new ();
391 	gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (obj->priv->tree), TRUE);
392 
393 	g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (obj->priv->tree)),
394 			  "changed",
395 			  G_CALLBACK (brasero_audio_disc_selection_changed),
396 			  obj);
397 
398 	/* This must be before connecting to button press event */
399 	egg_tree_multi_drag_add_drag_support (GTK_TREE_VIEW (obj->priv->tree));
400 
401 	gtk_widget_show (obj->priv->tree);
402 	g_signal_connect (G_OBJECT (obj->priv->tree),
403 			  "button-press-event",
404 			  G_CALLBACK (brasero_audio_disc_button_pressed_cb),
405 			  obj);
406 	g_signal_connect (G_OBJECT (obj->priv->tree),
407 			  "key-release-event",
408 			  G_CALLBACK (brasero_audio_disc_key_released_cb),
409 			  obj);
410 
411 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (obj->priv->tree));
412 	gtk_tree_selection_set_mode (selection,GTK_SELECTION_MULTIPLE);
413 	gtk_tree_selection_set_select_function (selection, brasero_audio_disc_selection_function, NULL, NULL);
414 	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (obj->priv->tree), TRUE);
415 
416 	/* Track num column */
417 	renderer = gtk_cell_renderer_text_new ();
418 	column = gtk_tree_view_column_new_with_attributes (_("Track"), renderer,
419 							   "text", BRASERO_VIDEO_TREE_MODEL_INDEX,
420 							   NULL);
421 	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree), column);
422 	gtk_tree_view_column_set_resizable (column, TRUE);
423 
424 	/* Other columns */
425 	column = gtk_tree_view_column_new ();
426 	gtk_tree_view_column_set_resizable (column, TRUE);
427 	gtk_tree_view_column_set_expand (column, TRUE);
428 
429 	renderer = gtk_cell_renderer_pixbuf_new ();
430 	gtk_tree_view_column_pack_start (column, renderer, FALSE);
431 	gtk_tree_view_column_add_attribute (column, renderer,
432 					    "icon-name", BRASERO_VIDEO_TREE_MODEL_ICON_NAME);
433 
434 	renderer = gtk_cell_renderer_text_new ();
435 	g_object_set_data (G_OBJECT (renderer), COL_KEY, BRASERO_TRACK_STREAM_TITLE_TAG);
436 	g_object_set (G_OBJECT (renderer),
437 		      "mode", GTK_CELL_RENDERER_MODE_EDITABLE,
438 		      "ellipsize-set", TRUE,
439 		      "ellipsize", PANGO_ELLIPSIZE_END,
440 		      NULL);
441 
442 	g_signal_connect (G_OBJECT (renderer), "edited",
443 			  G_CALLBACK (brasero_audio_disc_display_edited_cb), obj);
444 	g_signal_connect (G_OBJECT (renderer), "editing-started",
445 			  G_CALLBACK (brasero_audio_disc_display_editing_started_cb), obj);
446 	g_signal_connect (G_OBJECT (renderer), "editing-canceled",
447 			  G_CALLBACK (brasero_audio_disc_display_editing_canceled_cb), obj);
448 
449 	gtk_tree_view_column_pack_end (column, renderer, TRUE);
450 	gtk_tree_view_column_add_attribute (column, renderer,
451 					    "text", BRASERO_VIDEO_TREE_MODEL_NAME);
452 	gtk_tree_view_column_add_attribute (column, renderer,
453 					    "style", BRASERO_VIDEO_TREE_MODEL_STYLE);
454 	gtk_tree_view_column_add_attribute (column, renderer,
455 					    "weight", BRASERO_VIDEO_TREE_MODEL_WEIGHT);
456 	gtk_tree_view_column_add_attribute (column, renderer,
457 					    "editable", BRASERO_VIDEO_TREE_MODEL_EDITABLE);
458 	gtk_tree_view_column_set_title (column, _("Title"));
459 	g_object_set (G_OBJECT (column),
460 		      "spacing", 4,
461 		      NULL);
462 	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree), column);
463 	gtk_tree_view_set_expander_column (GTK_TREE_VIEW (obj->priv->tree), column);
464 
465 	renderer = gtk_cell_renderer_text_new ();
466 	g_object_set_data (G_OBJECT (renderer), COL_KEY, BRASERO_TRACK_STREAM_ARTIST_TAG);
467 	g_object_set (G_OBJECT (renderer),
468 		      /* "editable", TRUE, disable this for the time being it doesn't play well with DND and double click */
469 		      /* "mode", GTK_CELL_RENDERER_MODE_EDITABLE,*/
470 		      "ellipsize-set", TRUE,
471 		      "ellipsize", PANGO_ELLIPSIZE_END,
472 		      NULL);
473 
474 	g_signal_connect (G_OBJECT (renderer), "edited",
475 			  G_CALLBACK (brasero_audio_disc_display_edited_cb), obj);
476 	g_signal_connect (G_OBJECT (renderer), "editing-started",
477 			  G_CALLBACK (brasero_audio_disc_display_editing_started_cb), obj);
478 	g_signal_connect (G_OBJECT (renderer), "editing-canceled",
479 			  G_CALLBACK (brasero_audio_disc_display_editing_canceled_cb), obj);
480 	column = gtk_tree_view_column_new_with_attributes (_("Artist"), renderer,
481 							   "text", BRASERO_VIDEO_TREE_MODEL_ARTIST,
482 							   NULL);
483 	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree), column);
484 	gtk_tree_view_column_set_resizable (column, TRUE);
485 	gtk_tree_view_column_set_min_width (column, 200);
486 
487 	renderer = gtk_cell_renderer_text_new ();
488 	column = gtk_tree_view_column_new_with_attributes (_("Length"), renderer,
489 							   "text", BRASERO_VIDEO_TREE_MODEL_SIZE,
490 							  /* "background", BACKGROUND_COL, */
491 							   NULL);
492 	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree), column);
493 	gtk_tree_view_column_set_resizable (column, TRUE);
494 
495 	scroll = gtk_scrolled_window_new (NULL, NULL);
496 	gtk_widget_show (scroll);
497 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
498 					     GTK_SHADOW_IN);
499 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
500 					GTK_POLICY_AUTOMATIC,
501 					GTK_POLICY_AUTOMATIC);
502 	gtk_container_add (GTK_CONTAINER (scroll), obj->priv->tree);
503 
504 	gtk_box_pack_start (GTK_BOX (obj), scroll, TRUE, TRUE, 0);
505 
506 	/* dnd */
507 	gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (obj->priv->tree),
508 					      ntables_cd,
509 					      nb_targets_cd,
510 					      GDK_ACTION_COPY|
511 					      GDK_ACTION_MOVE);
512 
513 	gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (obj->priv->tree),
514 						GDK_BUTTON1_MASK,
515 						ntables_source,
516 						nb_targets_source,
517 						GDK_ACTION_COPY |
518 						GDK_ACTION_MOVE);
519 }
520 
521 static void
brasero_audio_disc_reset_real(BraseroAudioDisc * disc)522 brasero_audio_disc_reset_real (BraseroAudioDisc *disc)
523 {
524 	brasero_io_cancel_by_base (disc->priv->add_dir);
525 	brasero_io_cancel_by_base (disc->priv->add_playlist);
526 
527 	if (disc->priv->selected_path) {
528 		gtk_tree_path_free (disc->priv->selected_path);
529 		disc->priv->selected_path = NULL;
530 	}
531 
532 	if (disc->priv->message)
533 		brasero_notify_message_remove (disc->priv->message, BRASERO_AUDIO_DISC_CONTEXT);
534 }
535 
536 static void
brasero_audio_disc_finalize(GObject * object)537 brasero_audio_disc_finalize (GObject *object)
538 {
539 	BraseroAudioDisc *cobj;
540 	cobj = BRASERO_AUDIO_DISC(object);
541 
542 	brasero_audio_disc_reset_real (cobj);
543 
544 	brasero_io_job_base_free (cobj->priv->add_dir);
545 	brasero_io_job_base_free (cobj->priv->add_playlist);
546 	cobj->priv->add_dir = NULL;
547 	cobj->priv->add_playlist = NULL;
548 
549 	if (cobj->priv->message) {
550 		g_object_unref (cobj->priv->message);
551 		cobj->priv->message = NULL;
552 	}
553 
554 	if (cobj->priv->manager) {
555 		g_object_unref (cobj->priv->manager);
556 		cobj->priv->manager = NULL;
557 	}
558 
559 	g_free (cobj->priv);
560 	G_OBJECT_CLASS (parent_class)->finalize (object);
561 }
562 
563 /******************************** utility functions ****************************/
564 
565 static void
brasero_audio_disc_add_gap(BraseroAudioDisc * disc,GtkTreePath * treepath,gint64 gap)566 brasero_audio_disc_add_gap (BraseroAudioDisc *disc,
567 			    GtkTreePath *treepath,
568 			    gint64 gap)
569 {
570 	GtkTreeModel *model;
571 	BraseroTrack *track;
572 
573 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
574 	track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
575 	brasero_track_stream_set_boundaries (BRASERO_TRACK_STREAM (track),
576 					     -1,
577 					     -1,
578 					     gap);
579 }
580 
581 static void
brasero_audio_disc_short_track_dialog(BraseroAudioDisc * disc)582 brasero_audio_disc_short_track_dialog (BraseroAudioDisc *disc)
583 {
584 	brasero_app_alert (brasero_app_get_default (),
585 			   _("The track will be padded at its end."),
586 			   _("The track is shorter than 6 seconds"),
587 			   GTK_MESSAGE_WARNING);
588 }
589 
590 static BraseroDiscResult
brasero_audio_disc_add_uri_real(BraseroAudioDisc * disc,const gchar * uri,gint pos,gint64 gap_sectors,gint64 start,gint64 end,GtkTreePath ** path_return)591 brasero_audio_disc_add_uri_real (BraseroAudioDisc *disc,
592 				 const gchar *uri,
593 				 gint pos,
594 				 gint64 gap_sectors,
595 				 gint64 start,
596 				 gint64 end,
597 				 GtkTreePath **path_return)
598 {
599 	BraseroTrackStreamCfg *track;
600 	BraseroTrack *sibling = NULL;
601 	BraseroSessionCfg *session;
602 	GtkTreeModel *store;
603 
604 	g_return_val_if_fail (uri != NULL, BRASERO_DISC_ERROR_UNKNOWN);
605 
606 	if (disc->priv->reject_files)
607 		return BRASERO_DISC_NOT_READY;
608 
609 	store = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
610 	session = brasero_video_tree_model_get_session (BRASERO_VIDEO_TREE_MODEL (store));
611 
612 	track = brasero_track_stream_cfg_new ();
613 	brasero_track_stream_set_source (BRASERO_TRACK_STREAM (track), uri);
614 	brasero_track_stream_set_boundaries (BRASERO_TRACK_STREAM (track),
615 					     start,
616 					     end,
617 					     BRASERO_SECTORS_TO_DURATION (gap_sectors));
618 
619 	session = brasero_video_tree_model_get_session (BRASERO_VIDEO_TREE_MODEL (store));
620 	if (pos > 0) {
621 		GSList *tracks;
622 
623 		tracks = brasero_burn_session_get_tracks (BRASERO_BURN_SESSION (session));
624 		sibling = g_slist_nth_data (tracks, pos - 1);
625 	}
626 
627 	brasero_burn_session_add_track (BRASERO_BURN_SESSION (session), BRASERO_TRACK (track), sibling);
628 	if (path_return)
629 		*path_return = brasero_video_tree_model_track_to_path (BRASERO_VIDEO_TREE_MODEL (store), BRASERO_TRACK (track));
630 
631 	return BRASERO_DISC_OK;
632 }
633 
634 /*************** shared code for dir/playlist addition *************************/
635 static void
brasero_audio_disc_file_type_error_dialog(BraseroAudioDisc * disc,const gchar * uri)636 brasero_audio_disc_file_type_error_dialog (BraseroAudioDisc *disc,
637 					   const gchar *uri)
638 {
639 	gchar *primary;
640 	gchar *name;
641 
642     	BRASERO_GET_BASENAME_FOR_DISPLAY (uri, name);
643 	primary = g_strdup_printf (_("\"%s\" could not be handled by GStreamer."), name);
644 	brasero_app_alert (brasero_app_get_default (),
645 			   primary,
646 			   _("Make sure the appropriate codec is installed"),
647 			   GTK_MESSAGE_ERROR);
648 	g_free (primary);
649 	g_free (name);
650 }
651 
652 static gboolean
brasero_audio_disc_video_file_dialog(BraseroAudioDisc * disc,const gchar * uri)653 brasero_audio_disc_video_file_dialog (BraseroAudioDisc *disc,
654 				      const gchar *uri)
655 {
656 	GtkWidget *dialog;
657 	GtkResponseType answer;
658 	gchar *string;
659 	gchar *name;
660 
661     	BRASERO_GET_BASENAME_FOR_DISPLAY (uri, name);
662 	string = g_strdup_printf (_("Do you want to add \"%s\", which is a video file?"), name);
663 	dialog = brasero_app_dialog (brasero_app_get_default (),
664 				     string,
665 				     GTK_BUTTONS_NONE,
666 				     GTK_MESSAGE_QUESTION);
667 	g_free (string);
668 	g_free (name);
669 
670 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
671 						  _("This file is a video and therefore only the audio part can be written to the disc."));
672 
673 	gtk_dialog_add_button (GTK_DIALOG (dialog),
674 			       _("_Discard File"),
675 			       GTK_RESPONSE_CANCEL);
676 	gtk_dialog_add_button (GTK_DIALOG (dialog),
677 			       _("_Add File"),
678 			       GTK_RESPONSE_OK);
679 
680 	answer = gtk_dialog_run (GTK_DIALOG (dialog));
681 	gtk_widget_destroy (dialog);
682 
683 	return (answer != GTK_RESPONSE_OK);
684 }
685 
686 static void
brasero_audio_disc_result(GObject * obj,GError * error,const gchar * uri,GFileInfo * info,gpointer null_data)687 brasero_audio_disc_result (GObject *obj,
688 			   GError *error,
689 			   const gchar *uri,
690 			   GFileInfo *info,
691 			   gpointer null_data)
692 {
693 	BraseroAudioDisc *disc = BRASERO_AUDIO_DISC (obj);
694 
695 	if (error)
696 		return;
697 
698 	/* we silently ignore the title and any error */
699 	if (g_file_info_get_attribute_string (info, BRASERO_IO_PLAYLIST_TITLE))
700 		return;
701 
702 	if (!g_file_info_get_attribute_boolean (info, BRASERO_IO_HAS_AUDIO))
703 		return;
704 
705 	if (g_file_info_get_attribute_boolean (info, BRASERO_IO_HAS_VIDEO)
706 	&& !brasero_audio_disc_video_file_dialog (disc, uri))
707 		return;
708 
709 	brasero_audio_disc_add_uri_real (disc,
710 					 uri,
711 					 -1,
712 					 -1,
713 					 -1,
714 					 -1,
715 					 NULL);
716 }
717 
718 /*********************** directories exploration *******************************/
719 static BraseroDiscResult
brasero_audio_disc_add_directory_contents(BraseroAudioDisc * disc,const gchar * uri)720 brasero_audio_disc_add_directory_contents (BraseroAudioDisc *disc,
721 					   const gchar *uri)
722 {
723 	if (!disc->priv->add_dir)
724 		disc->priv->add_dir = brasero_io_register (G_OBJECT (disc),
725 							   brasero_audio_disc_result,
726 							   NULL,
727 							   NULL);
728 
729 	/* we have to pass a dummy value here otherwise finished is never called */
730 	brasero_io_load_directory (uri,
731 				   disc->priv->add_dir,
732 				   BRASERO_IO_INFO_MIME|
733 				   BRASERO_IO_INFO_PERM|
734 				   BRASERO_IO_INFO_METADATA|
735 				   BRASERO_IO_INFO_METADATA_MISSING_CODEC|
736 				   BRASERO_IO_INFO_RECURSIVE,
737 				   disc);
738 	return BRASERO_DISC_OK;
739 }
740 
741 static gboolean
brasero_audio_disc_add_dir(BraseroAudioDisc * disc,const gchar * uri)742 brasero_audio_disc_add_dir (BraseroAudioDisc *disc, const gchar *uri)
743 {
744 	gint answer;
745 	GtkWidget *dialog;
746 
747 	dialog = brasero_app_dialog (brasero_app_get_default (),
748 				     _("Do you want to search for audio files inside the directory?"),
749 				     GTK_BUTTONS_NONE,
750 				     GTK_MESSAGE_WARNING);
751 
752 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
753 						  "%s.",
754 						  _("Directories cannot be added to video or audio discs"));
755 
756 	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
757 				GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
758 				_("Search _Directory"), GTK_RESPONSE_OK,
759 				NULL);
760 
761 	gtk_widget_show_all (dialog);
762 	answer = gtk_dialog_run (GTK_DIALOG (dialog));
763 	gtk_widget_destroy (dialog);
764 
765 	if (answer == GTK_RESPONSE_OK)
766 		return TRUE;
767 
768 	return FALSE;
769 }
770 
771 /************************** playlist parsing ***********************************/
772 
773 #if BUILD_PLAYLIST
774 
775 static BraseroDiscResult
brasero_audio_disc_add_playlist(BraseroAudioDisc * disc,const gchar * uri)776 brasero_audio_disc_add_playlist (BraseroAudioDisc *disc,
777 				 const gchar *uri)
778 {
779 	if (!disc->priv->add_playlist)
780 		disc->priv->add_playlist = brasero_io_register (G_OBJECT (disc),
781 								brasero_audio_disc_result,
782 								NULL,
783 								NULL);
784 
785 	brasero_io_parse_playlist (uri,
786 				   disc->priv->add_playlist,
787 				   BRASERO_IO_INFO_PERM|
788 				   BRASERO_IO_INFO_MIME|
789 				   BRASERO_IO_INFO_METADATA|
790 				   BRASERO_IO_INFO_METADATA_MISSING_CODEC,
791 				   disc); /* It's necessary to have a callback_data != from NULL */
792 
793 	return BRASERO_DISC_OK;
794 }
795 
796 #endif
797 
798 /**************************** New Row ******************************************/
799 static void
brasero_audio_disc_unreadable_dialog(BraseroAudioDisc * disc,const gchar * uri,GError * error)800 brasero_audio_disc_unreadable_dialog (BraseroAudioDisc *disc,
801 				      const gchar *uri,
802 				      GError *error)
803 {
804 	gchar *primary;
805 	gchar *name;
806 	GFile *file;
807 
808 	file = g_file_new_for_uri (uri);
809 	name = g_file_get_basename (file);
810 	g_object_unref (file);
811 
812 	primary = g_strdup_printf (_("\"%s\" could not be opened."), name);
813 	brasero_app_alert (brasero_app_get_default (),
814 			   primary,
815 			   error->message,
816 			   GTK_MESSAGE_ERROR);
817 	g_free (primary);
818 	g_free (name);
819 }
820 
821 static void
brasero_audio_disc_wav_dts_response_cb(GtkButton * button,GtkResponseType response,BraseroAudioDisc * disc)822 brasero_audio_disc_wav_dts_response_cb (GtkButton *button,
823                                         GtkResponseType response,
824                                         BraseroAudioDisc *disc)
825 {
826 	BraseroSessionCfg *session;
827 	GtkTreeModel *model;
828 
829 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
830 	session = brasero_video_tree_model_get_session (BRASERO_VIDEO_TREE_MODEL (model));
831 
832 	if (response == GTK_RESPONSE_OK)
833 		brasero_burn_session_tag_add_int (BRASERO_BURN_SESSION (session),
834 		                                  BRASERO_SESSION_STREAM_AUDIO_FORMAT,
835 		                                  BRASERO_AUDIO_FORMAT_DTS);
836 }
837 
838 static void
brasero_audio_disc_wav_dts_file_dialog(BraseroAudioDisc * disc)839 brasero_audio_disc_wav_dts_file_dialog (BraseroAudioDisc *disc)
840 {
841 	GtkWidget *message;
842 	BraseroSessionCfg *session;
843 	GtkTreeModel *model;
844 
845 	if (brasero_notify_get_message_by_context_id (disc->priv->message,
846 	                                              BRASERO_AUDIO_DISC_CONTEXT))
847 		return;
848 
849 	/* Add a tag (RAW by default) so that we won't try to display this message again */
850 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
851 	session = brasero_video_tree_model_get_session (BRASERO_VIDEO_TREE_MODEL (model));
852 	brasero_burn_session_tag_add_int (BRASERO_BURN_SESSION (session),
853 	                                  BRASERO_SESSION_STREAM_AUDIO_FORMAT,
854 	                                  BRASERO_AUDIO_FORMAT_RAW);
855 
856 	message = brasero_notify_message_add (disc->priv->message,
857 					      _("Do you want to create an audio CD with DTS tracks?"),
858 					      _("Some of the selected songs are suitable for creating DTS tracks."
859 					        "\nThis type of audio CD track provides a higher quality of sound but can only be played by specific digital players."
860 					        "\nNote: if you agree, normalization will not be applied to these tracks."),
861 					      0,
862 					      BRASERO_AUDIO_DISC_CONTEXT);
863 
864 	gtk_info_bar_set_message_type (GTK_INFO_BAR (message), GTK_MESSAGE_INFO);
865 
866 	gtk_widget_set_tooltip_text (gtk_info_bar_add_button (GTK_INFO_BAR (message),
867 							    						  _("Create _Regular Tracks"),
868 							    						  GTK_RESPONSE_NO),
869 					     	     _("Click here to burn all songs as regular tracks"));
870 
871 	gtk_widget_set_tooltip_text (gtk_info_bar_add_button (GTK_INFO_BAR (message),
872 							    						  _("Create _DTS Tracks"),
873 							    						  GTK_RESPONSE_OK),
874 					     	     _("Click here to burn all suitable songs as DTS tracks"));
875 
876 	g_signal_connect (BRASERO_DISC_MESSAGE (message),
877 			  "response",
878 			  G_CALLBACK (brasero_audio_disc_wav_dts_response_cb),
879 			  disc);
880 }
881 
882 static void
brasero_audio_disc_session_changed(BraseroSessionCfg * session,BraseroAudioDisc * self)883 brasero_audio_disc_session_changed (BraseroSessionCfg *session,
884 				    BraseroAudioDisc *self)
885 {
886 	GSList *next;
887 	GSList *tracks;
888 	BraseroStatus *status;
889 	gboolean should_use_dts;
890 
891 	if (!gtk_widget_get_window (GTK_WIDGET (self)))
892 		return;
893 
894 	/* make sure all tracks have video */
895 	should_use_dts = FALSE;
896 	status = brasero_status_new ();
897 	tracks = brasero_burn_session_get_tracks (BRASERO_BURN_SESSION (session));
898 	for (; tracks; tracks = next) {
899 		BraseroStreamFormat format;
900 		BraseroTrackStream *track;
901 		BraseroBurnResult result;
902 
903 		track = tracks->data;
904 		next = tracks->next;
905 
906 		if (!BRASERO_IS_TRACK_STREAM (track))
907 			continue;
908 
909 		result = brasero_track_get_status (BRASERO_TRACK (track), status);
910 		if (result == BRASERO_BURN_ERR) {
911 			GError *error;
912 			gboolean res;
913 			gchar *uri;
914 
915 			uri = brasero_track_stream_get_source (track, TRUE);
916 
917 			/* Remove the track now otherwise on each session change we'll get the
918 			 * same message over and over again. */
919 			brasero_burn_session_remove_track (BRASERO_BURN_SESSION (session),
920 							   BRASERO_TRACK (track));
921 
922 			error = brasero_status_get_error (status);
923 			if (!error)
924 				brasero_audio_disc_file_type_error_dialog (self, uri);
925 			else if (error->code == BRASERO_BURN_ERROR_FILE_FOLDER) {
926 				res = brasero_audio_disc_add_dir (self, uri);
927 				if (res)
928 					brasero_audio_disc_add_directory_contents (self, uri);
929 			}
930 
931 #if BUILD_PLAYLIST
932 			else if (error->code == BRASERO_BURN_ERROR_FILE_PLAYLIST) {
933 				/* This is a supported playlist */
934 				brasero_audio_disc_add_playlist (self, uri);
935 			}
936 #endif
937 
938 			else if (error->code == BRASERO_BURN_ERROR_FILE_NOT_FOUND) {
939 				/* It could be a file that was deleted */
940 				brasero_audio_disc_file_type_error_dialog (self, uri);
941 			}
942 			else
943 				brasero_audio_disc_unreadable_dialog (self,
944 								      uri,
945 								      error);
946 
947 			g_error_free (error);
948 			g_free (uri);
949 			continue;
950 		}
951 
952 		if (result == BRASERO_BURN_NOT_READY || result == BRASERO_BURN_RUNNING)
953 			continue;
954 
955 		if (result != BRASERO_BURN_OK)
956 			continue;
957 
958 		format = brasero_track_stream_get_format (track);
959 		if (!BRASERO_STREAM_FORMAT_AUDIO (format)) {
960 			gchar *uri;
961 
962 			uri = brasero_track_stream_get_source (track, TRUE);
963 			brasero_audio_disc_file_type_error_dialog (self, uri);
964 			brasero_burn_session_remove_track (BRASERO_BURN_SESSION (session),
965 							   BRASERO_TRACK (track));
966 			g_free (uri);
967 			continue;
968 		}
969 
970 		if ((format & BRASERO_AUDIO_FORMAT_DTS) != 0)
971 			should_use_dts = TRUE;
972 
973 		if (BRASERO_STREAM_FORMAT_HAS_VIDEO (format)) {
974 			gboolean res;
975 			gchar *uri;
976 
977 			uri = brasero_track_stream_get_source (track, TRUE);
978 			res = brasero_audio_disc_video_file_dialog (self, uri);
979 			if (res)
980 				brasero_burn_session_remove_track (BRASERO_BURN_SESSION (session),
981 								   BRASERO_TRACK (track));
982 			g_free (uri);
983 		}
984 	}
985 	g_object_unref (status);
986 
987 	if (should_use_dts
988 	&&  brasero_burn_session_tag_lookup (BRASERO_BURN_SESSION (session), BRASERO_SESSION_STREAM_AUDIO_FORMAT, NULL) != BRASERO_BURN_OK)
989 		brasero_audio_disc_wav_dts_file_dialog (self);
990 }
991 
992 static BraseroDiscResult
brasero_audio_disc_add_uri(BraseroDisc * disc,const gchar * uri)993 brasero_audio_disc_add_uri (BraseroDisc *disc,
994 			    const gchar *uri)
995 {
996 	GtkTreePath *treepath = NULL;
997 	BraseroAudioDisc *audio_disc;
998 	BraseroDiscResult result;
999 
1000 	audio_disc = BRASERO_AUDIO_DISC (disc);
1001 	result = brasero_audio_disc_add_uri_real (audio_disc,
1002 						  uri,
1003 						  -1,
1004 						  0,
1005 						  -1,
1006 						  -1,
1007 						  &treepath);
1008 
1009 	if (treepath) {
1010 		gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (audio_disc->priv->tree),
1011 					      treepath,
1012 					      NULL,
1013 					      TRUE,
1014 					      0.5,
1015 					      0.5);
1016 		gtk_tree_path_free (treepath);
1017 	}
1018 
1019 	return result;
1020 }
1021 
1022 static void
brasero_audio_disc_remove(BraseroAudioDisc * disc,GtkTreePath * treepath)1023 brasero_audio_disc_remove (BraseroAudioDisc *disc,
1024 			   GtkTreePath *treepath)
1025 {
1026 	BraseroSessionCfg *session;
1027 	GtkTreeModel *model;
1028 	BraseroTrack *track;
1029 	GtkTreeIter iter;
1030 	gboolean is_gap;
1031 
1032 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1033 	gtk_tree_model_get_iter (model, &iter, treepath);
1034 	gtk_tree_model_get (model, &iter,
1035 			    BRASERO_VIDEO_TREE_MODEL_IS_GAP, &is_gap,
1036 			    -1);
1037 
1038 	session = brasero_video_tree_model_get_session (BRASERO_VIDEO_TREE_MODEL (model));
1039 	track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1040 
1041 	if (is_gap)
1042 		brasero_track_stream_set_boundaries (BRASERO_TRACK_STREAM (track),
1043 						     -1,
1044 						     -1,
1045 						     0);
1046 	else
1047 		brasero_burn_session_remove_track (BRASERO_BURN_SESSION (session), track);
1048 }
1049 
1050 static void
brasero_audio_disc_delete_selected(BraseroDisc * disc)1051 brasero_audio_disc_delete_selected (BraseroDisc *disc)
1052 {
1053 	GtkTreeSelection *selection;
1054 	BraseroAudioDisc *audio;
1055 	GtkTreePath *treepath;
1056 	GtkTreeModel *model;
1057 	GList *list;
1058 
1059 	audio = BRASERO_AUDIO_DISC (disc);
1060 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (audio->priv->tree));
1061 
1062 	/* we must start by the end for the treepaths to point to valid rows */
1063 	list = gtk_tree_selection_get_selected_rows (selection, &model);
1064 	list = g_list_reverse (list);
1065 	for (; list; list = g_list_remove (list, treepath)) {
1066 		treepath = list->data;
1067 		brasero_audio_disc_remove (audio, treepath);
1068 		gtk_tree_path_free (treepath);
1069 	}
1070 
1071 	/* warn that the selection changed (there are no more selected paths) */
1072 	if (audio->priv->selected_path) {
1073 		gtk_tree_path_free (audio->priv->selected_path);
1074 		audio->priv->selected_path = NULL;
1075 	}
1076 	brasero_disc_selection_changed (disc);
1077 }
1078 
1079 static BraseroDiscResult
brasero_audio_disc_set_session_contents(BraseroDisc * disc,BraseroBurnSession * session)1080 brasero_audio_disc_set_session_contents (BraseroDisc *disc,
1081 					 BraseroBurnSession *session)
1082 {
1083 	BraseroAudioDisc *audio;
1084 	GtkTreeModel *current_model;
1085 	BraseroVideoTreeModel *model;
1086 
1087 	audio = BRASERO_AUDIO_DISC (disc);
1088 
1089 	if (audio->priv->add_dir)
1090 		brasero_io_cancel_by_base (audio->priv->add_dir);
1091 
1092 	if (audio->priv->add_playlist)
1093 		brasero_io_cancel_by_base (audio->priv->add_playlist);
1094 
1095 	/* disconnect some signals */
1096 	current_model = gtk_tree_view_get_model (GTK_TREE_VIEW (audio->priv->tree));
1097 	if (current_model) {
1098 		BraseroSessionCfg *current_session;
1099 
1100 		current_session = brasero_video_tree_model_get_session (BRASERO_VIDEO_TREE_MODEL (current_model));
1101 		if (current_session)
1102 			g_signal_handlers_disconnect_by_func (current_session,
1103 							      brasero_audio_disc_session_changed,
1104 							      disc);
1105 	}
1106 
1107 	if (!session) {
1108 		gtk_tree_view_set_model (GTK_TREE_VIEW (audio->priv->tree), NULL);
1109 		return BRASERO_DISC_OK;
1110 	}
1111 
1112 	model = brasero_video_tree_model_new ();
1113 	brasero_video_tree_model_set_session (model, BRASERO_SESSION_CFG (session));
1114 	gtk_tree_view_set_model (GTK_TREE_VIEW (audio->priv->tree),
1115 				 GTK_TREE_MODEL (model));
1116 	g_object_unref (model);
1117 
1118 	g_signal_connect (session,
1119 			  "is-valid",
1120 			  G_CALLBACK (brasero_audio_disc_session_changed),
1121 			  disc);
1122 
1123 	return BRASERO_DISC_OK;
1124 }
1125 
1126 /********************************** Cell Editing *******************************/
1127 static void
brasero_audio_disc_display_edited_cb(GtkCellRendererText * renderer,gchar * path_string,gchar * text,BraseroAudioDisc * disc)1128 brasero_audio_disc_display_edited_cb (GtkCellRendererText *renderer,
1129 				      gchar *path_string,
1130 				      gchar *text,
1131 				      BraseroAudioDisc *disc)
1132 {
1133 	const gchar *tag;
1134 	GtkTreeModel *model;
1135 	BraseroTrack *track;
1136 	GtkTreePath *treepath;
1137 
1138 	tag = g_object_get_data (G_OBJECT (renderer), COL_KEY);
1139 
1140 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1141 	treepath = gtk_tree_path_new_from_string (path_string);
1142 	track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1143 	brasero_track_tag_add_string (BRASERO_TRACK (track),
1144 				      tag,
1145 				      text);
1146 	disc->priv->editing = 0;
1147 }
1148 
1149 static void
brasero_audio_disc_display_editing_started_cb(GtkCellRenderer * renderer,GtkCellEditable * editable,gchar * path,BraseroAudioDisc * disc)1150 brasero_audio_disc_display_editing_started_cb (GtkCellRenderer *renderer,
1151 					       GtkCellEditable *editable,
1152 					       gchar *path,
1153 					       BraseroAudioDisc *disc)
1154 {
1155 	disc->priv->editing = 1;
1156 }
1157 
1158 static void
brasero_audio_disc_display_editing_canceled_cb(GtkCellRenderer * renderer,BraseroAudioDisc * disc)1159 brasero_audio_disc_display_editing_canceled_cb (GtkCellRenderer *renderer,
1160 						BraseroAudioDisc *disc)
1161 {
1162 	disc->priv->editing = 0;
1163 }
1164 
1165 /********************************** Pause **************************************/
1166 static void
brasero_audio_disc_add_pause(BraseroAudioDisc * disc)1167 brasero_audio_disc_add_pause (BraseroAudioDisc *disc)
1168 {
1169 	GtkTreeSelection *selection;
1170 	GtkTreePath *treepath;
1171 	GtkTreeModel *model;
1172 	GList *references = NULL;
1173 	GList *selected;
1174 	GList *iter;
1175 
1176 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (disc->priv->tree));
1177 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1178 	selected = gtk_tree_selection_get_selected_rows (selection, &model);
1179 
1180 	/* since we are going to modify the model, we need to convert all these
1181 	 * into row references */
1182 	for (iter = selected; iter; iter = iter->next) {
1183 		GtkTreeRowReference *ref;
1184 
1185 		treepath = iter->data;
1186 		ref = gtk_tree_row_reference_new (model, treepath);
1187 		references = g_list_append (references, ref);
1188 	}
1189 
1190 	g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1191 	g_list_free (selected);
1192 
1193 	for (iter = references; iter; iter = iter->next) {
1194 		GtkTreeRowReference *ref;
1195 
1196 		ref = iter->data;
1197 		treepath = gtk_tree_row_reference_get_path (ref);
1198 		gtk_tree_row_reference_free (ref);
1199 
1200 		brasero_audio_disc_add_gap (disc, treepath, 2 * GST_SECOND);
1201 		gtk_tree_path_free (treepath);
1202 	}
1203 
1204 	g_list_free (references);
1205 }
1206 
1207 static void
brasero_audio_disc_add_pause_cb(GtkAction * action,BraseroAudioDisc * disc)1208 brasero_audio_disc_add_pause_cb (GtkAction *action,
1209 				 BraseroAudioDisc *disc)
1210 {
1211 	brasero_audio_disc_add_pause (disc);
1212 }
1213 
1214 static void
brasero_audio_disc_add_slices(BraseroAudioDisc * disc,GtkTreePath * treepath,GSList * slices)1215 brasero_audio_disc_add_slices (BraseroAudioDisc *disc,
1216 			       GtkTreePath *treepath,
1217 			       GSList *slices)
1218 {
1219 	BraseroSessionCfg *session;
1220 	BraseroStreamFormat format;
1221 	BraseroAudioSlice *slice;
1222 	BraseroTrack *track;
1223 	GtkTreeModel *model;
1224 	GSList *iter;
1225 	gchar *uri;
1226 
1227 	if (!slices)
1228 		return;
1229 
1230 	/* the first slice is used for the existing row */
1231 	slice = slices->data;
1232 
1233 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1234 	session = brasero_video_tree_model_get_session (BRASERO_VIDEO_TREE_MODEL (model));
1235 	track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1236 
1237 	brasero_track_stream_set_boundaries (BRASERO_TRACK_STREAM (track),
1238 					     slice->start,
1239 					     slice->end,
1240 					     -1);
1241 
1242 	uri = brasero_track_stream_get_source (BRASERO_TRACK_STREAM (track), TRUE);
1243 	format = brasero_track_stream_get_format (BRASERO_TRACK_STREAM (track));
1244 
1245 	for (iter = slices->next; iter; iter = iter->next) {
1246 		BraseroTrackStream *new_track;
1247 
1248 		slice = iter->data;
1249 
1250 		new_track = brasero_track_stream_new ();
1251 		brasero_track_stream_set_source (new_track, uri);
1252 		brasero_track_stream_set_format (new_track, format);
1253 		brasero_track_stream_set_boundaries (new_track,
1254 						     slice->start,
1255 						     slice->end,
1256 						     brasero_track_stream_get_gap (BRASERO_TRACK_STREAM (track)));
1257 		brasero_track_tag_copy_missing (BRASERO_TRACK (new_track),
1258 						BRASERO_TRACK (track));
1259 		brasero_burn_session_add_track (BRASERO_BURN_SESSION (session),
1260 						BRASERO_TRACK (new_track),
1261 						BRASERO_TRACK (track));
1262 	}
1263 
1264 	g_free (uri);
1265 }
1266 
1267 static void
brasero_audio_disc_split(BraseroAudioDisc * disc)1268 brasero_audio_disc_split (BraseroAudioDisc *disc)
1269 {
1270 	GtkTreeSelection *selection;
1271 	GtkTreePath *treepath;
1272 	GtkTreeModel *model;
1273 	BraseroTrack *track;
1274 
1275 	GtkResponseType response;
1276 	GtkWidget *toplevel;
1277 	GtkWidget *dialog;
1278 	GList *selected;
1279 	GSList *slices;
1280 	gchar *uri;
1281 
1282 	/* get the URIs */
1283 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (disc->priv->tree));
1284 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1285 	selected = gtk_tree_selection_get_selected_rows (selection, &model);
1286 
1287 	/* don't check g_slist_length == 0 since then the button is greyed */
1288 	if (g_list_length (selected) > 1) {
1289 		brasero_app_alert (brasero_app_get_default (),
1290 				   _("Select one song only please."),
1291 				   _("Impossible to split more than one song at a time"),
1292 				   GTK_MESSAGE_ERROR);
1293 
1294 		g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1295 		g_list_free (selected);
1296 		return;
1297 	}
1298 
1299 	treepath = selected->data;
1300 	g_list_free (selected);
1301 
1302 	/* NOTE: this is necessarily a song since otherwise button is grey */
1303 	track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1304 
1305 	dialog = brasero_split_dialog_new ();
1306 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (disc));
1307 	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
1308 	gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
1309 	gtk_window_set_position (GTK_WINDOW (toplevel), GTK_WIN_POS_CENTER_ON_PARENT);
1310 
1311 	uri = brasero_track_stream_get_source (BRASERO_TRACK_STREAM (track), TRUE);
1312 	brasero_split_dialog_set_uri (BRASERO_SPLIT_DIALOG (dialog),
1313 	                              uri,
1314 	                              brasero_track_tag_lookup_string (track, BRASERO_TRACK_STREAM_TITLE_TAG),
1315 	                              brasero_track_tag_lookup_string (track, BRASERO_TRACK_STREAM_ARTIST_TAG));
1316 	g_free (uri);
1317 
1318 	brasero_split_dialog_set_boundaries (BRASERO_SPLIT_DIALOG (dialog),
1319 					     brasero_track_stream_get_start (BRASERO_TRACK_STREAM (track)),
1320 					     brasero_track_stream_get_end (BRASERO_TRACK_STREAM (track)));
1321 
1322 	response = gtk_dialog_run (GTK_DIALOG (dialog));
1323 	if (response != GTK_RESPONSE_OK) {
1324 		gtk_widget_destroy (dialog);
1325 		gtk_tree_path_free (treepath);
1326 		return;
1327 	}
1328 
1329 	slices = brasero_split_dialog_get_slices (BRASERO_SPLIT_DIALOG (dialog));
1330 	gtk_widget_destroy (dialog);
1331 
1332 	brasero_audio_disc_add_slices (disc, treepath, slices);
1333 	g_slist_foreach (slices, (GFunc) g_free, NULL);
1334 	g_slist_free (slices);
1335 	gtk_tree_path_free (treepath);
1336 }
1337 
1338 static void
brasero_audio_disc_split_cb(GtkAction * action,BraseroAudioDisc * disc)1339 brasero_audio_disc_split_cb (GtkAction *action,
1340 			     BraseroAudioDisc *disc)
1341 {
1342 	brasero_audio_disc_split (disc);
1343 }
1344 
1345 static void
brasero_audio_disc_selection_changed(GtkTreeSelection * selection,BraseroAudioDisc * disc)1346 brasero_audio_disc_selection_changed (GtkTreeSelection *selection,
1347 				      BraseroAudioDisc *disc)
1348 {
1349 	GtkAction *action_delete;
1350 	GtkAction *action_pause;
1351 	GtkAction *action_split;
1352 	GtkAction *action_edit;
1353 	GtkAction *action_open;
1354 	guint selected_num = 0;
1355 	GtkTreeModel *model;
1356 	GList *selected;
1357 	GList *iter;
1358 
1359 	selected = gtk_tree_selection_get_selected_rows (selection, &model);
1360 
1361 	if (disc->priv->selected_path)
1362 		gtk_tree_path_free (disc->priv->selected_path);
1363 
1364 	if (selected)
1365 		disc->priv->selected_path = gtk_tree_path_copy (selected->data);
1366 	else
1367 		disc->priv->selected_path = NULL;
1368 
1369 	brasero_disc_selection_changed (BRASERO_DISC (disc));
1370 
1371 	if (!disc->priv->disc_group)
1372 		return;
1373 
1374 	action_delete = gtk_action_group_get_action (disc->priv->disc_group, "DeleteAudio");
1375 	action_open = gtk_action_group_get_action (disc->priv->disc_group, "OpenSong");
1376 	action_edit = gtk_action_group_get_action (disc->priv->disc_group, "EditSong");
1377 	action_split = gtk_action_group_get_action (disc->priv->disc_group, "Split");
1378 	action_pause = gtk_action_group_get_action (disc->priv->disc_group, "Pause");
1379 
1380 	gtk_action_set_sensitive (action_split, FALSE);
1381 	gtk_action_set_sensitive (action_pause, FALSE);
1382 	gtk_action_set_sensitive (action_edit, FALSE);
1383 	gtk_action_set_sensitive (action_open, FALSE);
1384 
1385 	if (selected)
1386 		gtk_action_set_sensitive (action_delete, TRUE);
1387 	else
1388 		gtk_action_set_sensitive (action_delete, FALSE);
1389 
1390 	for (iter = selected; iter; iter = iter->next) {
1391 		GtkTreeIter row;
1392 		GtkTreePath *treepath;
1393 
1394 		treepath = iter->data;
1395 		if (gtk_tree_model_get_iter (model, &row, treepath)) {
1396 			gboolean is_gap;
1397 
1398 			gtk_tree_model_get (model, &row,
1399 					    BRASERO_VIDEO_TREE_MODEL_IS_GAP, &is_gap,
1400 					    -1);
1401 			if (!is_gap) {
1402 				selected_num ++;
1403 
1404 				gtk_action_set_sensitive (action_open, TRUE);
1405 				gtk_action_set_sensitive (action_edit, TRUE);
1406 				gtk_action_set_sensitive (action_pause, TRUE);
1407 				if (selected_num != 1) {
1408 					gtk_action_set_sensitive (action_split, FALSE);
1409 					break;
1410 				}
1411 				else
1412 					gtk_action_set_sensitive (action_split, TRUE);
1413 			}
1414 		}
1415 	}
1416 
1417 	g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1418 	g_list_free (selected);
1419 }
1420 
1421 /********************************** Menus **************************************/
1422 static void
brasero_audio_disc_open_file(BraseroAudioDisc * disc)1423 brasero_audio_disc_open_file (BraseroAudioDisc *disc)
1424 {
1425 	char *uri;
1426 	GList *item, *list;
1427 	GSList *uris = NULL;
1428 	GtkTreeModel *model;
1429 	GtkTreePath *treepath;
1430 	GtkTreeSelection *selection;
1431 
1432 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (disc->priv->tree));
1433 	list = gtk_tree_selection_get_selected_rows (selection, &model);
1434 
1435 	for (item = list; item; item = item->next) {
1436                 BraseroTrack *track;
1437 
1438 		treepath = item->data;
1439                 track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1440 		gtk_tree_path_free (treepath);
1441 
1442 		if (!track)
1443 			continue;
1444 
1445 		uri = brasero_track_stream_get_source (BRASERO_TRACK_STREAM (track), TRUE);
1446 
1447 		if (uri)
1448 			uris = g_slist_prepend (uris, uri);
1449 	}
1450 	g_list_free (list);
1451 
1452 	brasero_utils_launch_app (GTK_WIDGET (disc), uris);
1453 	g_slist_foreach (uris, (GFunc) g_free, NULL);
1454 	g_slist_free (uris);
1455 }
1456 
1457 static gboolean
brasero_audio_disc_rename_songs(GtkTreeModel * model,GtkTreeIter * iter,GtkTreePath * treepath,const gchar * old_name,const gchar * new_name)1458 brasero_audio_disc_rename_songs (GtkTreeModel *model,
1459 				 GtkTreeIter *iter,
1460 				 GtkTreePath *treepath,
1461 				 const gchar *old_name,
1462 				 const gchar *new_name)
1463 {
1464 	BraseroTrack *track;
1465 
1466 	track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1467 	brasero_track_tag_add_string (track,
1468 				      BRASERO_TRACK_STREAM_TITLE_TAG,
1469 				      new_name);
1470 
1471 	/* Update the view */
1472 	brasero_track_changed (track);
1473 	return TRUE;
1474 }
1475 
1476 static void
brasero_audio_disc_edit_multi_song_properties(BraseroAudioDisc * disc,GList * list)1477 brasero_audio_disc_edit_multi_song_properties (BraseroAudioDisc *disc,
1478 					       GList *list)
1479 {
1480 	gint64 gap;
1481 	GList *copy;
1482 	GList *item;
1483 	GtkWidget *props;
1484 	GtkWidget *toplevel;
1485 	GtkTreeModel *model;
1486 	gchar *artist = NULL;
1487 	GtkResponseType result;
1488 	gchar *composer = NULL;
1489 	gchar *isrc = NULL;
1490 
1491 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1492 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (disc));
1493 
1494 	props = brasero_multi_song_props_new ();
1495 	gtk_window_set_transient_for (GTK_WINDOW (props),
1496 				      GTK_WINDOW (toplevel));
1497 	gtk_window_set_modal (GTK_WINDOW (props), TRUE);
1498 	gtk_window_set_position (GTK_WINDOW (props),
1499 				 GTK_WIN_POS_CENTER_ON_PARENT);
1500 
1501 	gtk_widget_show (GTK_WIDGET (props));
1502 	result = gtk_dialog_run (GTK_DIALOG (props));
1503 	gtk_widget_hide (GTK_WIDGET (props));
1504 	if (result != GTK_RESPONSE_ACCEPT) {
1505 		gtk_widget_destroy (props);
1506 		return;
1507 	}
1508 
1509 	brasero_multi_song_props_set_rename_callback (BRASERO_MULTI_SONG_PROPS (props),
1510 						      gtk_tree_view_get_selection (GTK_TREE_VIEW (disc->priv->tree)),
1511 						      BRASERO_VIDEO_TREE_MODEL_NAME,
1512 						      brasero_audio_disc_rename_songs);
1513 
1514 	brasero_multi_song_props_get_properties (BRASERO_MULTI_SONG_PROPS (props),
1515 						 &artist,
1516 						 &composer,
1517 						 &isrc,
1518 						 &gap);
1519 
1520 	/* start by the end in case we add silences since then the next
1521 	 * treepaths will be wrong */
1522 	copy = g_list_copy (list);
1523 	copy = g_list_reverse (copy);
1524 	for (item = copy; item; item = item->next) {
1525 		GtkTreePath *treepath;
1526 		BraseroTrack *track;
1527 		GtkTreeIter iter;
1528 		gboolean is_gap;
1529 
1530 		treepath = item->data;
1531                 gtk_tree_model_get_iter (model, &iter, treepath);
1532 		gtk_tree_model_get (model, &iter,
1533 				    BRASERO_VIDEO_TREE_MODEL_IS_GAP, &is_gap,
1534 				    -1);
1535 
1536 		if (is_gap)
1537 			continue;
1538 
1539                 track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1540 		if (!track)
1541 			continue;
1542 
1543 		if (artist)
1544                         brasero_track_tag_add_string (BRASERO_TRACK (track),
1545                                                       BRASERO_TRACK_STREAM_ARTIST_TAG,
1546                                                       artist);
1547 
1548 		if (composer)
1549                         brasero_track_tag_add_string (BRASERO_TRACK (track),
1550                                                       BRASERO_TRACK_STREAM_COMPOSER_TAG,
1551                                                       composer);
1552 
1553 		if (isrc)
1554                         brasero_track_tag_add_string (BRASERO_TRACK (track),
1555                                                       BRASERO_TRACK_STREAM_ISRC_TAG,
1556                                                       isrc);
1557 
1558                 if (gap > -1)
1559                         brasero_track_stream_set_boundaries (BRASERO_TRACK_STREAM (track),
1560                                                                                        -1,
1561                                                                                        -1,
1562                                                                                        gap);
1563 	}
1564 	g_list_free (copy);
1565 	g_free (artist);
1566 	g_free (composer);
1567 	g_free (isrc);
1568 
1569 	gtk_widget_destroy (props);
1570 }
1571 
1572 static void
brasero_audio_disc_edit_single_song_properties(BraseroAudioDisc * disc,GtkTreePath * treepath)1573 brasero_audio_disc_edit_single_song_properties (BraseroAudioDisc *disc,
1574 						GtkTreePath *treepath)
1575 {
1576 	gint64 gap;
1577 	gint64 end;
1578 	gint64 start;
1579 	guint track_num;
1580 	GtkWidget *props;
1581 	GtkWidget *toplevel;
1582 	GtkTreeModel *model;
1583 	BraseroTrack *track;
1584 	GtkResponseType result;
1585 	guint64 length;
1586 	gchar *title;
1587 	gchar *artist;
1588 	gchar *composer;
1589 	gchar *isrc;
1590 	GtkTreeIter iter;
1591 
1592 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1593         track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model), treepath);
1594 	if (!track)
1595 		return;
1596 
1597         /* information about the track */
1598         gtk_tree_model_get_iter (model, &iter, treepath);
1599         gtk_tree_model_get (model, &iter,
1600                             BRASERO_VIDEO_TREE_MODEL_INDEX_NUM, &track_num,
1601                             -1);
1602         brasero_track_stream_get_length (BRASERO_TRACK_STREAM (track), &length);
1603 
1604 	/* set up dialog */
1605 	props = brasero_song_props_new ();
1606 	brasero_song_props_set_properties (BRASERO_SONG_PROPS (props),
1607 					   track_num,
1608 					   brasero_track_tag_lookup_string (BRASERO_TRACK (track), BRASERO_TRACK_STREAM_ARTIST_TAG),
1609 					   brasero_track_tag_lookup_string (BRASERO_TRACK (track), BRASERO_TRACK_STREAM_TITLE_TAG),
1610 					   brasero_track_tag_lookup_string (BRASERO_TRACK (track), BRASERO_TRACK_STREAM_COMPOSER_TAG),
1611 					   brasero_track_tag_lookup_string (BRASERO_TRACK (track), BRASERO_TRACK_STREAM_ISRC_TAG),
1612 					   length,
1613 					   brasero_track_stream_get_start (BRASERO_TRACK_STREAM (track)),
1614 					   brasero_track_stream_get_end (BRASERO_TRACK_STREAM (track)),
1615 					   brasero_track_stream_get_gap (BRASERO_TRACK_STREAM (track)));
1616 
1617 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (disc));
1618 	gtk_window_set_transient_for (GTK_WINDOW (props),
1619 				      GTK_WINDOW (toplevel));
1620 	gtk_window_set_modal (GTK_WINDOW (props), TRUE);
1621 	gtk_window_set_position (GTK_WINDOW (props),
1622 				 GTK_WIN_POS_CENTER_ON_PARENT);
1623 
1624 	gtk_widget_show (GTK_WIDGET (props));
1625 	result = gtk_dialog_run (GTK_DIALOG (props));
1626 	gtk_widget_hide (GTK_WIDGET (props));
1627 	if (result != GTK_RESPONSE_ACCEPT) {
1628 		gtk_widget_destroy (props);
1629 		return;
1630 	}
1631 
1632 	brasero_song_props_get_properties (BRASERO_SONG_PROPS (props),
1633 					   &artist,
1634 					   &title,
1635 					   &composer,
1636 					   &isrc,
1637 					   &start,
1638 					   &end,
1639 					   &gap);
1640 
1641 	brasero_track_stream_set_boundaries (BRASERO_TRACK_STREAM (track),
1642                                              start,
1643                                              end,
1644                                              gap);
1645 
1646 	if (title)
1647 		brasero_track_tag_add_string (BRASERO_TRACK (track),
1648 					      BRASERO_TRACK_STREAM_TITLE_TAG,
1649 					      title);
1650 
1651 	if (artist)
1652 		brasero_track_tag_add_string (BRASERO_TRACK (track),
1653 					      BRASERO_TRACK_STREAM_ARTIST_TAG,
1654 					      artist);
1655 
1656 	if (composer)
1657 		brasero_track_tag_add_string (BRASERO_TRACK (track),
1658 					      BRASERO_TRACK_STREAM_COMPOSER_TAG,
1659 					      composer);
1660 
1661 	if (isrc)
1662 		brasero_track_tag_add_string (BRASERO_TRACK (track),
1663 					      BRASERO_TRACK_STREAM_ISRC_TAG,
1664 					      isrc);
1665 
1666 	if (end - start + BRASERO_SECTORS_TO_DURATION (gap) < BRASERO_MIN_STREAM_LENGTH)
1667 		brasero_audio_disc_short_track_dialog (disc);
1668 
1669 	g_free (title);
1670 	g_free (artist);
1671 	g_free (composer);
1672 	g_free (isrc);
1673 	gtk_widget_destroy (props);
1674 }
1675 
1676 static void
brasero_audio_disc_edit_song_properties(BraseroAudioDisc * disc,GList * list)1677 brasero_audio_disc_edit_song_properties (BraseroAudioDisc *disc,
1678 					 GList *list)
1679 {
1680 	GList *item;
1681 	gint song_num;
1682 	GtkTreeModel *model;
1683 	GList *real_list = NULL;
1684 
1685 	if (!g_list_length (list))
1686 		return;
1687 
1688 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (disc->priv->tree));
1689 
1690 	/* count the number of selected songs */
1691 	song_num = 0;
1692 	for (item = list; item; item = item->next) {
1693 		GtkTreePath *tmp;
1694 		gboolean is_gap;
1695 		GtkTreeIter iter;
1696 
1697 		tmp = item->data;
1698 
1699 		gtk_tree_model_get_iter (model, &iter, tmp);
1700 		gtk_tree_model_get (model, &iter,
1701 				    BRASERO_VIDEO_TREE_MODEL_IS_GAP, &is_gap,
1702 				    -1);
1703 
1704 		if (!is_gap) {
1705 			song_num ++;
1706 			real_list = g_list_prepend (real_list, tmp);
1707 		}
1708 	}
1709 
1710 	if (!song_num)
1711 		return;
1712 
1713 	if (song_num == 1)
1714 		brasero_audio_disc_edit_single_song_properties (disc, real_list->data);
1715 	else
1716 		brasero_audio_disc_edit_multi_song_properties (disc, real_list);
1717 
1718 	g_list_free (real_list);
1719 }
1720 
1721 static void
brasero_audio_disc_open_activated_cb(GtkAction * action,BraseroAudioDisc * disc)1722 brasero_audio_disc_open_activated_cb (GtkAction *action,
1723 				      BraseroAudioDisc *disc)
1724 {
1725 	brasero_audio_disc_open_file (disc);
1726 }
1727 
1728 static void
brasero_audio_disc_edit_information_cb(GtkAction * action,BraseroAudioDisc * disc)1729 brasero_audio_disc_edit_information_cb (GtkAction *action,
1730 					BraseroAudioDisc *disc)
1731 {
1732 	GList *list;
1733 	GtkTreeModel *model;
1734 	GtkTreeSelection *selection;
1735 
1736 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (disc->priv->tree));
1737 	list = gtk_tree_selection_get_selected_rows (selection, &model);
1738 
1739 	brasero_audio_disc_edit_song_properties (disc, list);
1740 
1741 	g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1742 	g_list_free (list);
1743 }
1744 
1745 static void
brasero_audio_disc_delete_activated_cb(GtkAction * action,BraseroDisc * disc)1746 brasero_audio_disc_delete_activated_cb (GtkAction *action,
1747 					BraseroDisc *disc)
1748 {
1749 	brasero_audio_disc_delete_selected (disc);
1750 }
1751 
1752 static void
brasero_audio_disc_clipboard_text_cb(GtkClipboard * clipboard,const gchar * text,BraseroAudioDisc * disc)1753 brasero_audio_disc_clipboard_text_cb (GtkClipboard *clipboard,
1754 				      const gchar *text,
1755 				      BraseroAudioDisc *disc)
1756 {
1757 	gchar **array;
1758 	gchar **item;
1759 
1760 	if (!text)
1761 		return;
1762 
1763 	array = g_uri_list_extract_uris (text);
1764 	item = array;
1765 	while (*item) {
1766 		if (**item != '\0') {
1767 			GFile *file;
1768 			gchar *uri;
1769 
1770 			file = g_file_new_for_commandline_arg (*item);
1771 			uri = g_file_get_uri (file);
1772 			g_object_unref (file);
1773 
1774 			brasero_audio_disc_add_uri_real (disc,
1775 							 uri,
1776 							 -1,
1777 							 0,
1778 							 -1,
1779 							 -1,
1780 							 NULL);
1781 			g_free (uri);
1782 		}
1783 
1784 		item++;
1785 	}
1786 	g_strfreev (array);
1787 }
1788 
1789 static void
brasero_audio_disc_clipboard_targets_cb(GtkClipboard * clipboard,GdkAtom * atoms,gint n_atoms,BraseroAudioDisc * disc)1790 brasero_audio_disc_clipboard_targets_cb (GtkClipboard *clipboard,
1791 					 GdkAtom *atoms,
1792 					 gint n_atoms,
1793 					 BraseroAudioDisc *disc)
1794 {
1795 	if (brasero_clipboard_selection_may_have_uri (atoms, n_atoms))
1796 		gtk_clipboard_request_text (clipboard,
1797 					    (GtkClipboardTextReceivedFunc) brasero_audio_disc_clipboard_text_cb,
1798 					    disc);
1799 }
1800 
1801 static void
brasero_audio_disc_paste_activated_cb(GtkAction * action,BraseroAudioDisc * disc)1802 brasero_audio_disc_paste_activated_cb (GtkAction *action,
1803 				       BraseroAudioDisc *disc)
1804 {
1805 	GtkClipboard *clipboard;
1806 
1807 	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1808 	gtk_clipboard_request_targets (clipboard,
1809 				       (GtkClipboardTargetsReceivedFunc) brasero_audio_disc_clipboard_targets_cb,
1810 				       disc);
1811 }
1812 
1813 static gboolean
brasero_audio_disc_button_pressed_cb(GtkTreeView * tree,GdkEventButton * event,BraseroAudioDisc * disc)1814 brasero_audio_disc_button_pressed_cb (GtkTreeView *tree,
1815 				      GdkEventButton *event,
1816 				      BraseroAudioDisc *disc)
1817 {
1818 	GtkWidgetClass *widget_class;
1819 
1820 	/* Avoid minding signals that happen out of the tree area (like in the
1821 	 * headers for example) */
1822 	if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (tree)))
1823 		return FALSE;
1824 
1825 	widget_class = GTK_WIDGET_GET_CLASS (tree);
1826 
1827 	/* Check that the click happened in the main window with rows. */
1828 	if (event->button == 3) {
1829 		GtkTreeSelection *selection;
1830 		GtkTreePath *path = NULL;
1831 		GtkWidget *widget;
1832 
1833 		gtk_tree_view_get_path_at_pos (tree,
1834 					       event->x,
1835 					       event->y,
1836 					       &path,
1837 					       NULL,
1838 					       NULL,
1839 					       NULL);
1840 
1841 		selection = gtk_tree_view_get_selection (tree);
1842 		if (!path || !gtk_tree_selection_path_is_selected (selection, path)) {
1843 			/* Don't update the selection if the right click was on one of
1844 			 * the already selected rows */
1845 			widget_class->button_press_event (GTK_WIDGET (tree), event);
1846 
1847 			if (!path) {
1848 				GtkTreeSelection *selection;
1849 
1850 				/* This is to deselect any row when selecting a
1851 				 * row that cannot be selected or in an empty
1852 				 * part */
1853 				selection = gtk_tree_view_get_selection (tree);
1854 				gtk_tree_selection_unselect_all (selection);
1855 			}
1856 		}
1857 
1858 		widget = gtk_ui_manager_get_widget (disc->priv->manager, "/ContextMenu/PasteAudio");
1859 		if (widget) {
1860 			if (gtk_clipboard_wait_is_text_available (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)))
1861 				gtk_widget_set_sensitive (widget, TRUE);
1862 			else
1863 				gtk_widget_set_sensitive (widget, FALSE);
1864 		}
1865 
1866 		widget = gtk_ui_manager_get_widget (disc->priv->manager,"/ContextMenu");
1867 		gtk_menu_popup (GTK_MENU (widget),
1868 				NULL,
1869 				NULL,
1870 				NULL,
1871 				NULL,
1872 				event->button,
1873 				event->time);
1874 		return TRUE;
1875 	}
1876 	else if (event->button == 1) {
1877 		gboolean result;
1878 		GtkTreePath *treepath = NULL;
1879 
1880 		result = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (disc->priv->tree),
1881 							event->x,
1882 							event->y,
1883 							&treepath,
1884 							NULL,
1885 							NULL,
1886 							NULL);
1887 		/* we call the default handler for the treeview before everything else
1888 		 * so it can update itself (paticularly its selection) before we have
1889 		 * a look at it */
1890 		widget_class->button_press_event (GTK_WIDGET (tree), event);
1891 
1892 		if (!treepath) {
1893 			GtkTreeSelection *selection;
1894 
1895 			/* This is to deselect any row when selecting a
1896 			 * row that cannot be selected or in an empty
1897 			 * part */
1898 			selection = gtk_tree_view_get_selection (tree);
1899 			gtk_tree_selection_unselect_all (selection);
1900 			return FALSE;
1901 		}
1902 
1903 		if (!result)
1904 			return FALSE;
1905 
1906 		if (disc->priv->selected_path)
1907 			gtk_tree_path_free (disc->priv->selected_path);
1908 
1909 		disc->priv->selected_path = treepath;
1910 		brasero_disc_selection_changed (BRASERO_DISC (disc));
1911 
1912 		if (event->type == GDK_2BUTTON_PRESS) {
1913 			GList *list;
1914 
1915 			list = g_list_prepend (NULL, treepath);
1916 			brasero_audio_disc_edit_song_properties (disc, list);
1917 			g_list_free (list);
1918 		}
1919 	}
1920 
1921 	return TRUE;
1922 }
1923 
1924 /********************************** key press event ****************************/
1925 static void
brasero_audio_disc_rename_activated(BraseroAudioDisc * disc)1926 brasero_audio_disc_rename_activated (BraseroAudioDisc *disc)
1927 {
1928 	GtkTreeSelection *selection;
1929 	GtkTreeViewColumn *column;
1930 	GtkTreePath *treepath;
1931 	GtkTreeModel *model;
1932 	GList *list;
1933 
1934 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (disc->priv->tree));
1935 	list = gtk_tree_selection_get_selected_rows (selection, &model);
1936 
1937 	for (; list; list = g_list_remove (list, treepath)) {
1938 		treepath = list->data;
1939 
1940 		gtk_widget_grab_focus (disc->priv->tree);
1941 		column = gtk_tree_view_get_column (GTK_TREE_VIEW (disc->priv->tree), 0);
1942 		gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (disc->priv->tree),
1943 					      treepath,
1944 					      NULL,
1945 					      TRUE,
1946 					      0.5,
1947 					      0.5);
1948 		gtk_tree_view_set_cursor (GTK_TREE_VIEW (disc->priv->tree),
1949 					  treepath,
1950 					  column,
1951 					  TRUE);
1952 
1953 		gtk_tree_path_free (treepath);
1954 	}
1955 }
1956 
1957 static gboolean
brasero_audio_disc_key_released_cb(GtkTreeView * tree,GdkEventKey * event,BraseroAudioDisc * disc)1958 brasero_audio_disc_key_released_cb (GtkTreeView *tree,
1959 				    GdkEventKey *event,
1960 				    BraseroAudioDisc *disc)
1961 {
1962 	if (disc->priv->editing)
1963 		return FALSE;
1964 
1965 	if (event->keyval == GDK_KEY_KP_Delete || event->keyval == GDK_KEY_Delete) {
1966 		brasero_audio_disc_delete_selected (BRASERO_DISC (disc));
1967 	}
1968 	else if (event->keyval == GDK_KEY_F2)
1969 		brasero_audio_disc_rename_activated (disc);
1970 
1971 	return FALSE;
1972 }
1973 
1974 /**********************************               ******************************/
1975 static gboolean
brasero_audio_disc_get_selected_uri(BraseroDisc * disc,gchar ** uri)1976 brasero_audio_disc_get_selected_uri (BraseroDisc *disc,
1977 				     gchar **uri)
1978 {
1979 	BraseroTrack *track;
1980 	GtkTreeModel *model;
1981 	BraseroAudioDisc *audio;
1982 
1983 	audio = BRASERO_AUDIO_DISC (disc);
1984 	if (!audio->priv->selected_path)
1985 		return FALSE;
1986 
1987 	if (!uri)
1988 		return TRUE;
1989 
1990 	/* we are asked for just one uri so return the first one */
1991 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (audio->priv->tree));
1992         track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model),
1993                                                                                        audio->priv->selected_path);
1994         if (!track) {
1995 		gtk_tree_path_free (audio->priv->selected_path);
1996 		audio->priv->selected_path = NULL;
1997 		return FALSE;
1998 	}
1999 
2000 	*uri = brasero_track_stream_get_source (BRASERO_TRACK_STREAM (track), TRUE);
2001 	return TRUE;
2002 }
2003 
2004 static gboolean
brasero_audio_disc_get_boundaries(BraseroDisc * disc,gint64 * start,gint64 * end)2005 brasero_audio_disc_get_boundaries (BraseroDisc *disc,
2006 				   gint64 *start,
2007 				   gint64 *end)
2008 {
2009 	BraseroTrack *track;
2010 	GtkTreeModel *model;
2011 	BraseroAudioDisc *audio;
2012 
2013 	audio = BRASERO_AUDIO_DISC (disc);
2014 	if (!audio->priv->selected_path)
2015 		return FALSE;
2016 
2017 	/* we are asked for just one uri so return the first one */
2018 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (audio->priv->tree));
2019         track = brasero_video_tree_model_path_to_track (BRASERO_VIDEO_TREE_MODEL (model),
2020                                                                                        audio->priv->selected_path);
2021         if (!track) {
2022 		gtk_tree_path_free (audio->priv->selected_path);
2023 		audio->priv->selected_path = NULL;
2024 		return FALSE;
2025 	}
2026 
2027         *start = brasero_track_stream_get_start (BRASERO_TRACK_STREAM (track));
2028         *end = brasero_track_stream_get_end (BRASERO_TRACK_STREAM (track));
2029 	return TRUE;
2030 }
2031 
2032 static void
brasero_audio_disc_class_init(BraseroAudioDiscClass * klass)2033 brasero_audio_disc_class_init (BraseroAudioDiscClass *klass)
2034 {
2035 	GObjectClass *object_class = G_OBJECT_CLASS(klass);
2036 
2037 	parent_class = g_type_class_peek_parent (klass);
2038 	object_class->finalize = brasero_audio_disc_finalize;
2039 	object_class->set_property = brasero_audio_disc_set_property;
2040 	object_class->get_property = brasero_audio_disc_get_property;
2041 
2042 	g_object_class_install_property (object_class,
2043 					 PROP_REJECT_FILE,
2044 					 g_param_spec_boolean
2045 					 ("reject-file",
2046 					  "Whether it accepts files",
2047 					  "Whether it accepts files",
2048 					  FALSE,
2049 					  G_PARAM_READWRITE));
2050 }
2051 
2052 GtkWidget *
brasero_audio_disc_new()2053 brasero_audio_disc_new ()
2054 {
2055 	BraseroAudioDisc *obj;
2056 
2057 	obj = BRASERO_AUDIO_DISC (g_object_new (BRASERO_TYPE_AUDIO_DISC, NULL));
2058 
2059 	return GTK_WIDGET (obj);
2060 }
2061 
2062