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