1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * brasero
4  * Copyright (C) Philippe Rouquier 2007-2008 <bonfire-app@wanadoo.fr>
5  *
6  *  Brasero is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  * brasero is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with brasero.  If not, write to:
18  * 	The Free Software Foundation, Inc.,
19  * 	51 Franklin Street, Fifth Floor
20  * 	Boston, MA  02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26 
27 #include <glib.h>
28 #include <glib/gi18n-lib.h>
29 
30 #include <gtk/gtk.h>
31 
32 #include "brasero-misc.h"
33 #include "brasero-metadata.h"
34 
35 #include "brasero-units.h"
36 
37 #include "brasero-track.h"
38 #include "brasero-track-stream.h"
39 
40 #include "brasero-split-dialog.h"
41 #include "brasero-song-control.h"
42 #include "brasero-utils.h"
43 
44 enum {
45 	START_COL,
46 	END_COL,
47 	LENGTH_COL,
48 	START_STR_COL,
49 	END_STR_COL,
50 	LENGTH_STR_COL,
51 	COLUMN_NUM,
52 };
53 
54 typedef struct _BraseroSplitDialogPrivate BraseroSplitDialogPrivate;
55 struct _BraseroSplitDialogPrivate
56 {
57 	GtkWidget *cut;
58 
59 	GtkListStore *model;
60 
61 	GtkWidget *tree;
62 	GtkWidget *player;
63 
64 	GtkWidget *notebook;
65 	GtkWidget *combo;
66 
67 	GtkWidget *spin_parts;
68 	GtkWidget *spin_sec;
69 
70 	GtkWidget *silence_label;
71 
72 	GtkWidget *reset_button;
73 	GtkWidget *merge_button;
74 	GtkWidget *remove_button;
75 
76 	gint64 start;
77 	gint64 end;
78 
79 	BraseroMetadata *metadata;
80 };
81 
82 #define BRASERO_SPLIT_DIALOG_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_SPLIT_DIALOG, BraseroSplitDialogPrivate))
83 
84 G_DEFINE_TYPE (BraseroSplitDialog, brasero_split_dialog, GTK_TYPE_DIALOG);
85 
86 void
brasero_split_dialog_set_uri(BraseroSplitDialog * self,const gchar * uri,const gchar * title,const gchar * artist)87 brasero_split_dialog_set_uri (BraseroSplitDialog *self,
88 			      const gchar *uri,
89                               const gchar *title,
90                               const gchar *artist)
91 {
92 	BraseroSplitDialogPrivate *priv;
93 
94 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
95 	brasero_song_control_set_uri (BRASERO_SONG_CONTROL (priv->player), uri);
96 	brasero_song_control_set_info (BRASERO_SONG_CONTROL (priv->player), title, artist);
97 }
98 
99 void
brasero_split_dialog_set_boundaries(BraseroSplitDialog * self,gint64 start,gint64 end)100 brasero_split_dialog_set_boundaries (BraseroSplitDialog *self,
101 				     gint64 start,
102 				     gint64 end)
103 {
104 	BraseroSplitDialogPrivate *priv;
105 	guint64 length;
106 
107 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
108 
109 	if (BRASERO_DURATION_TO_BYTES (start) % 2352)
110 		start += BRASERO_BYTES_TO_DURATION (2352 - (BRASERO_DURATION_TO_BYTES (start) % 2352));
111 
112 	if (BRASERO_DURATION_TO_BYTES (end) % 2352)
113 		end += BRASERO_BYTES_TO_DURATION (2352 - (BRASERO_DURATION_TO_BYTES (end) % 2352));
114 
115 	if (end - start < BRASERO_MIN_STREAM_LENGTH)
116 		return;
117 
118 	priv->start = start;
119 	priv->end = end;
120 
121 	brasero_song_control_set_boundaries (BRASERO_SONG_CONTROL (priv->player),
122 	                                     priv->start,
123 	                                     priv->end);
124 
125 	/* Don't allow splitting the track in sections longer than the track
126 	 * length in seconds */
127 	length = (gdouble) brasero_song_control_get_length  (BRASERO_SONG_CONTROL (priv->player)) / 1000000000;
128 	gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->spin_sec), 1.0, length);
129 }
130 
131 GSList *
brasero_split_dialog_get_slices(BraseroSplitDialog * self)132 brasero_split_dialog_get_slices (BraseroSplitDialog *self)
133 {
134 	BraseroSplitDialogPrivate *priv;
135 	GSList *retval = NULL;
136 	GtkTreeModel *model;
137 	GtkTreeIter iter;
138 
139 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
140 
141 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
142 	if (!gtk_tree_model_get_iter_first (model, &iter))
143 		return NULL;
144 
145 	do {
146 		BraseroAudioSlice *slice;
147 
148 		slice = g_new0 (BraseroAudioSlice, 1);
149 		retval = g_slist_append (retval, slice);
150 
151 		gtk_tree_model_get (model, &iter,
152 				    START_COL, &slice->start,
153 				    END_COL, &slice->end,
154 				    -1);
155 
156 	} while (gtk_tree_model_iter_next (model, &iter));
157 
158 	return retval;
159 }
160 
161 static gboolean
brasero_split_dialog_size_error(BraseroSplitDialog * self)162 brasero_split_dialog_size_error (BraseroSplitDialog *self)
163 {
164 	GtkWidget *message;
165 	GtkResponseType answer;
166 
167 	message = gtk_message_dialog_new (GTK_WINDOW (self),
168 					  GTK_DIALOG_DESTROY_WITH_PARENT|
169 					  GTK_DIALOG_MODAL,
170 					  GTK_MESSAGE_QUESTION,
171 					  GTK_BUTTONS_NONE,
172 					  _("Do you really want to split the track?"));
173 
174 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message),
175 						  _("If you split the track, the size of the new track will be shorter than 6 seconds and will be padded."));
176 
177 	gtk_dialog_add_button (GTK_DIALOG (message),
178 			       GTK_STOCK_CANCEL,
179 			       GTK_RESPONSE_CANCEL);
180 	gtk_dialog_add_button (GTK_DIALOG (message),
181 			       _("_Split"),
182 			       GTK_RESPONSE_YES);
183 
184 	answer = gtk_dialog_run (GTK_DIALOG (message));
185 	gtk_widget_destroy (message);
186 
187 	if (answer == GTK_RESPONSE_YES)
188 		return TRUE;
189 
190 	return FALSE;
191 }
192 
193 static gboolean
brasero_split_dialog_cut(BraseroSplitDialog * self,gint64 pos,gboolean warn)194 brasero_split_dialog_cut (BraseroSplitDialog *self,
195 			  gint64 pos,
196 			  gboolean warn)
197 {
198 	BraseroSplitDialogPrivate *priv;
199 	BraseroAudioSlice slice = {0,0};
200 	GtkTreeModel *model;
201 	GtkTreeIter child;
202 	GtkTreeIter iter;
203 	gchar *length_str;
204 	gchar *start_str;
205 	gchar *end_str;
206 
207 	if (!pos)
208 		return FALSE;
209 
210 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
211 
212 	/* since pos is in nanosecond we have a small lattitude. Make sure that
213 	 * is up to the size of a sector */
214 	if (BRASERO_DURATION_TO_BYTES (pos) % 2352)
215 		pos += BRASERO_BYTES_TO_DURATION (2352 - (BRASERO_DURATION_TO_BYTES (pos) % 2352));
216 
217 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
218 	if (!gtk_tree_model_get_iter_first (model, &iter)) {
219 		gint64 end;
220 
221 		/* nothing in the tree yet */
222 		if (priv->end <= 0)
223 			end = brasero_song_control_get_length (BRASERO_SONG_CONTROL (priv->player));
224 		else
225 			end = priv->end;
226 
227 		/* check that pos > 300 sectors ( == 4 sec ) */
228 		if (warn
229 		&&  pos - priv->start < BRASERO_MIN_STREAM_LENGTH
230 		&& !brasero_split_dialog_size_error (self))
231 			return FALSE;
232 
233 		if (warn
234 		&&  end - (pos + 1) < BRASERO_MIN_STREAM_LENGTH
235 		&& !brasero_split_dialog_size_error (self))
236 			return FALSE;
237 
238 		length_str = brasero_units_get_time_string (pos - priv->start, TRUE, FALSE);
239 		start_str = brasero_units_get_time_string (priv->start, TRUE, FALSE);
240 		end_str = brasero_units_get_time_string (pos, TRUE, FALSE);
241 
242 		gtk_list_store_append (priv->model, &iter);
243 		gtk_list_store_set (priv->model, &iter,
244 				    START_COL, (gint64) priv->start,
245 				    END_COL, (gint64) pos,
246 				    LENGTH_COL, (gint64) pos - priv->start,
247 				    START_STR_COL, start_str,
248 				    END_STR_COL, end_str,
249 				    LENGTH_STR_COL, length_str,
250 				    -1);
251 		g_free (length_str);
252 		g_free (start_str);
253 		g_free (end_str);
254 
255 		pos ++;
256 		length_str = brasero_units_get_time_string (end - pos, TRUE, FALSE);
257 		start_str = brasero_units_get_time_string (pos, TRUE, FALSE);
258 		end_str = brasero_units_get_time_string (end, TRUE, FALSE);
259 
260 		gtk_list_store_append (priv->model, &iter);
261 		gtk_list_store_set (priv->model, &iter,
262 				    START_COL, pos,
263 				    END_COL, end,
264 				    LENGTH_COL, (gint64) (end - pos),
265 				    START_STR_COL, start_str,
266 				    END_STR_COL, end_str,
267 				    LENGTH_STR_COL, length_str,
268 				    -1);
269 		g_free (length_str);
270 		g_free (start_str);
271 		g_free (end_str);
272 		return TRUE;
273 	}
274 
275 	/* Try to find an already created slice encompassing the position */
276 	do {
277 		gint64 start;
278 		gint64 end;
279 
280 		gtk_tree_model_get (model, &iter,
281 				    START_COL, &start,
282 				    END_COL, &end,
283 				    -1);
284 
285 		/* NOTE: if pos == start or pos == end then nothing changes */
286 		if (pos <= start || pos >= end)
287 			continue;
288 
289 		/* check the size of the new tracks */
290 		if (warn
291 		&& (pos - start) < BRASERO_MIN_STREAM_LENGTH
292 		&& !brasero_split_dialog_size_error (self))
293 			return FALSE;
294 
295 		if (warn
296 		&& (end - (pos + 1)) < BRASERO_MIN_STREAM_LENGTH
297 		&& !brasero_split_dialog_size_error (self))
298 			return FALSE;
299 
300 		/* Found one */
301 		slice.start = start;
302 		slice.end = end;
303 		break;
304 
305 	} while (gtk_tree_model_iter_next (model, &iter));
306 
307 	/* see if we found a slice, if not create a new one starting at pos
308 	 * until the end of the song */
309 
310 	if (slice.start == 0 && slice.end == 0) {
311 		slice.start = pos;
312 
313 		/* check if we need to stop this slice at the end of the song
314 		 * or at the start of the next slice. */
315 		if (gtk_tree_model_get_iter_first (model, &iter)) {
316 			do {
317 				gint64 start;
318 				gint64 end;
319 
320 				gtk_tree_model_get (model, &iter,
321 						    START_COL, &start,
322 						    END_COL, &end,
323 						    -1);
324 
325 				if (pos >= start)
326 					continue;
327 
328 				/* Found one */
329 				slice.end = start - 1;
330 			} while (gtk_tree_model_iter_next (model, &iter));
331 		}
332 
333 		if (!slice.end)
334 			slice.end = priv->end;
335 
336 		/* check the size of the new slice */
337 		if (warn
338 		&& (slice.end - slice.start) < BRASERO_MIN_STREAM_LENGTH
339 		&& !brasero_split_dialog_size_error (self))
340 			return FALSE;
341 	}
342 	else {
343 		/* we are in the middle of an existing slice */
344 		length_str = brasero_units_get_time_string (pos - slice.start, TRUE, FALSE);
345 		end_str = brasero_units_get_time_string (pos, TRUE, FALSE);
346 
347 		gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
348 								&child,
349 								&iter);
350 
351 		gtk_list_store_set (priv->model, &child,
352 				    END_COL, (gint64) pos,
353 				    LENGTH_COL, (gint64) (pos - slice.start),
354 				    END_STR_COL, end_str,
355 				    LENGTH_STR_COL, length_str,
356 				    -1);
357 		g_free (length_str);
358 		g_free (end_str);
359 
360 		/* move the position by one */
361 		pos ++;
362 	}
363 
364 	/* create a new one */
365 	gtk_list_store_append (priv->model, &child);
366 
367 	length_str = brasero_units_get_time_string (slice.end - pos, TRUE, FALSE);
368 	start_str = brasero_units_get_time_string (pos, TRUE, FALSE);
369 	end_str = brasero_units_get_time_string (slice.end, TRUE, FALSE);
370 
371 	gtk_list_store_set (priv->model, &child,
372 			    START_COL, pos,
373 			    END_COL, slice.end,
374 			    LENGTH_COL, (gint64) (slice.end - pos),
375 			    START_STR_COL, start_str,
376 			    END_STR_COL, end_str,
377 			    LENGTH_STR_COL, length_str,
378 			    -1);
379 
380 	g_free (length_str);
381 	g_free (start_str);
382 	g_free (end_str);
383 
384 	return TRUE;
385 }
386 
387 static void
brasero_split_dialog_remove_range(BraseroSplitDialog * self,gint64 start,gint64 end,gint64 length)388 brasero_split_dialog_remove_range (BraseroSplitDialog *self,
389 				   gint64 start,
390 				   gint64 end,
391 				   gint64 length)
392 {
393 	BraseroSplitDialogPrivate *priv;
394 	GtkTreeModel *model;
395 	GtkTreeIter iter;
396 	gchar *length_str;
397 	gchar *start_str;
398 	gchar *end_str;
399 
400 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
401 
402 	/* align on 2352 byte boundary */
403 	if (BRASERO_DURATION_TO_BYTES (start) % 2352)
404 		start += BRASERO_BYTES_TO_DURATION (2352 - (BRASERO_DURATION_TO_BYTES (start) % 2352));
405 
406 	if (BRASERO_DURATION_TO_BYTES (end) % 2352) {
407 		end += BRASERO_BYTES_TO_DURATION (2352 - (BRASERO_DURATION_TO_BYTES (end) % 2352));
408 		if (end > length)
409 			end = length;
410 	}
411 
412 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
413 	if (!gtk_tree_model_get_iter_first (model, &iter)) {
414 		/* nothing in the tree yet; so create two new segments:
415 		 * - 0 => start
416 		 * - end => song end
417 		 * also make sure that the track is longer than 4 sec */
418 		if (start - priv->start < BRASERO_MIN_STREAM_LENGTH
419 		&& !brasero_split_dialog_size_error (self)) {
420 			/* that's not necessarily a good solution */
421 			start = BRASERO_MIN_STREAM_LENGTH;
422 			if (start > end)
423 				end = start;
424 		}
425 
426 		if ((length - end) < BRASERO_MIN_STREAM_LENGTH
427 		&& !brasero_split_dialog_size_error (self))
428 			end = length - BRASERO_MIN_STREAM_LENGTH;
429 
430 		length_str = brasero_units_get_time_string (start - priv->start, TRUE, FALSE);
431 		start_str = brasero_units_get_time_string (priv->start, TRUE, FALSE);
432 		end_str = brasero_units_get_time_string (start, TRUE, FALSE);
433 
434 		gtk_list_store_append (priv->model, &iter);
435 		gtk_list_store_set (priv->model, &iter,
436 				    START_COL, (gint64) priv->start,
437 				    END_COL, (gint64) start,
438 				    LENGTH_COL, (gint64) start - priv->start,
439 				    START_STR_COL, start_str,
440 				    END_STR_COL, end_str,
441 				    LENGTH_STR_COL, length_str,
442 				    -1);
443 		g_free (length_str);
444 		g_free (start_str);
445 		g_free (end_str);
446 
447 		if (end == length)
448 			return;
449 
450 		length_str = brasero_units_get_time_string (length - end, TRUE, FALSE);
451 		start_str = brasero_units_get_time_string (end, TRUE, FALSE);
452 		end_str = brasero_units_get_time_string (length, TRUE, FALSE);
453 
454 		gtk_list_store_append (priv->model, &iter);
455 		gtk_list_store_set (priv->model, &iter,
456 				    START_COL, end,
457 				    END_COL, length,
458 				    LENGTH_COL, (gint64) (length - end),
459 				    START_STR_COL, start_str,
460 				    END_STR_COL, end_str,
461 				    LENGTH_STR_COL, length_str,
462 				    -1);
463 		g_free (length_str);
464 		g_free (start_str);
465 		g_free (end_str);
466 		return;
467 	}
468 
469 	do {
470 		GtkTreeIter child;
471 		gint64 track_start;
472 		gint64 track_end;
473 
474 		gtk_tree_model_get (model, &iter,
475 				    START_COL, &track_start,
476 				    END_COL, &track_end,
477 				    -1);
478 
479 		gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
480 								&child,
481 								&iter);
482 
483 		if (start == track_start) {
484 			if (start == end)
485 				return;
486 
487 			if (end == track_end) {
488 				/* suppress it */
489 				gtk_list_store_remove (priv->model, &child);
490 				return;
491 			}
492 
493 			if (end < track_end) {
494 				/* reduce the size but make sure the remaining
495 				 * track is > 4 sec */
496 				if ((track_end - end) < BRASERO_MIN_STREAM_LENGTH
497 				&& !brasero_split_dialog_size_error (self))
498 					end = track_end - BRASERO_MIN_STREAM_LENGTH;
499 
500 				start_str = brasero_units_get_time_string (end, TRUE, FALSE);
501 				length_str = brasero_units_get_time_string (track_end - end, TRUE, FALSE);
502 				gtk_list_store_set (priv->model, &child,
503 						    START_COL, end,
504 						    START_STR_COL, start_str,
505 						    LENGTH_COL, track_end - end,
506 						    LENGTH_STR_COL, length_str,
507 						    -1);
508 				g_free (length_str);
509 				g_free (start_str);
510 			}
511 			else if (!gtk_list_store_remove (priv->model, &child))
512 				return;
513 		}
514 		else if (start > track_start) {
515 			if (start > track_end)
516 				continue;
517 
518 			/* reduce the size but make sure the remaining track is
519 			 * > 4 sec else change it */
520 			if ((start - track_start) < BRASERO_MIN_STREAM_LENGTH
521 			&& !brasero_split_dialog_size_error (self))
522 				start = track_start + BRASERO_MIN_STREAM_LENGTH;
523 
524 			start_str = brasero_units_get_time_string (start, TRUE, FALSE);
525 			length_str = brasero_units_get_time_string (start - track_start, TRUE, FALSE);
526 			gtk_list_store_set (priv->model, &child,
527 					    END_COL, start,
528 					    END_STR_COL, start_str,
529 					    LENGTH_COL, start - track_start,
530 					    LENGTH_STR_COL, length_str,
531 					    -1);
532 			g_free (length_str);
533 			g_free (start_str);
534 
535 			if (end == length)
536 				return;
537 
538 			if (end == track_end)
539 				return;
540 
541 			if (end > track_end)
542 				continue;
543 
544 			/* create a new track with the remaining time.
545 			 * make sure the remaining track is > 4 sec */
546 			if ((track_end - end) < BRASERO_MIN_STREAM_LENGTH
547 			&& !brasero_split_dialog_size_error (self))
548 				end = track_end - BRASERO_MIN_STREAM_LENGTH;
549 
550 			gtk_list_store_append (priv->model, &child);
551 
552 			length_str = brasero_units_get_time_string (track_end - end, TRUE, FALSE);
553 			start_str = brasero_units_get_time_string (end, TRUE, FALSE);
554 			end_str = brasero_units_get_time_string (track_end, TRUE, FALSE);
555 
556 			gtk_list_store_set (priv->model, &child,
557 					    START_COL, end,
558 					    END_COL, track_end,
559 					    LENGTH_COL, (gint64) (track_end - end),
560 					    START_STR_COL, start_str,
561 					    END_STR_COL, end_str,
562 					    LENGTH_STR_COL, length_str,
563 					    -1);
564 			g_free (length_str);
565 			g_free (start_str);
566 			g_free (end_str);
567 		}
568 		else if (end > track_end) {
569 			if (!gtk_list_store_remove (priv->model, &child))
570 				return;
571 		}
572 		else if (end == track_end) {
573 			gtk_list_store_remove (priv->model, &child);
574 			return;
575 		}
576 		else {
577 			if (end == length) {
578 				gtk_list_store_remove (priv->model, &child);
579 				return;
580 			}
581 
582 			/* resize (make sure about the 4s) */
583 			if ((track_end - end) < BRASERO_MIN_STREAM_LENGTH
584 			&& !brasero_split_dialog_size_error (self))
585 				end = track_end - BRASERO_MIN_STREAM_LENGTH;
586 
587 			start_str = brasero_units_get_time_string (end, TRUE, FALSE);
588 			length_str = brasero_units_get_time_string (track_end - end, TRUE, FALSE);
589 			gtk_list_store_set (priv->model, &child,
590 					    START_COL, end,
591 					    START_STR_COL, start_str,
592 					    LENGTH_COL, track_end - end,
593 					    LENGTH_STR_COL, length_str,
594 					    -1);
595 			g_free (length_str);
596 			g_free (start_str);
597 		}
598 
599 		gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (model),
600 								&iter,
601 								&child);
602 	} while (gtk_tree_model_iter_next (model, &iter));
603 }
604 
605 static void
brasero_split_dialog_no_silence_message(BraseroSplitDialog * self)606 brasero_split_dialog_no_silence_message (BraseroSplitDialog *self)
607 {
608 	brasero_utils_message_dialog (GTK_WIDGET (self),
609 				      _("The track wasn't split."),
610 				      _("No silence could be detected"),
611 				      GTK_MESSAGE_WARNING);
612 }
613 
614 static void
brasero_split_dialog_metadata_finished_cb(BraseroMetadata * metadata,GError * error,BraseroSplitDialog * self)615 brasero_split_dialog_metadata_finished_cb (BraseroMetadata *metadata,
616 					   GError *error,
617 					   BraseroSplitDialog *self)
618 {
619 	BraseroMetadataInfo info = { NULL, };
620 	BraseroSplitDialogPrivate *priv;
621 	gboolean added_silence;
622 	GSList *iter;
623 
624 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
625 
626 	gtk_widget_set_sensitive (priv->cut, TRUE);
627 
628 	g_object_unref (priv->metadata);
629 	priv->metadata = NULL;
630 
631 	if (error) {
632 		brasero_utils_message_dialog (GTK_WIDGET (self),
633 					      _("An error occurred while detecting silences."),
634 					      error->message,
635 					      GTK_MESSAGE_ERROR);
636 		return;
637 	}
638 
639 	brasero_metadata_get_result (metadata, &info, NULL);
640 	if (!info.silences) {
641 		brasero_split_dialog_no_silence_message (self);
642 		return;
643 	}
644 
645 	/* remove silences */
646 	added_silence = FALSE;
647 	for (iter = info.silences; iter; iter = iter->next) {
648 		BraseroMetadataSilence *silence;
649 
650 		silence = iter->data;
651 
652 		if (!silence)
653 			continue;
654 
655 		if (silence->start >= priv->end)
656 			continue;
657 
658 		if (silence->end <= priv->start)
659 			continue;
660 
661 		if (silence->start < priv->start)
662 			silence->start = priv->start;
663 
664 		if (silence->end > priv->end)
665 			silence->end = priv->end;
666 
667 		if (!silence->start)
668 			brasero_split_dialog_cut (self, silence->end, TRUE);
669 		else if (silence->start != silence->end)
670 			brasero_split_dialog_remove_range (self,
671 							   silence->start,
672 							   silence->end,
673 							   priv->end - priv->start);
674 		else
675 			brasero_split_dialog_cut (self, silence->end, TRUE);
676 
677 		added_silence = TRUE;
678 	}
679 
680 	if (!added_silence)
681 		brasero_split_dialog_no_silence_message (self);
682 
683 	brasero_metadata_info_clear (&info);
684 }
685 
686 static gboolean
brasero_split_dialog_clear_confirm_dialog(BraseroSplitDialog * self,const gchar * primary,const gchar * cancel_button,const gchar * ok_button)687 brasero_split_dialog_clear_confirm_dialog (BraseroSplitDialog *self,
688 					   const gchar *primary,
689 					   const gchar *cancel_button,
690 					   const gchar *ok_button)
691 {
692 	BraseroSplitDialogPrivate *priv;
693 	GtkResponseType answer;
694 	GtkTreeModel *model;
695 	GtkWidget *message;
696 
697 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
698 
699 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
700 	if (!gtk_tree_model_iter_n_children (model, NULL))
701 		return TRUE;
702 
703 	message = gtk_message_dialog_new (GTK_WINDOW (self),
704 					  GTK_DIALOG_DESTROY_WITH_PARENT|
705 					  GTK_DIALOG_MODAL,
706 					  GTK_MESSAGE_QUESTION,
707 					  GTK_BUTTONS_NONE,
708 					  "%s",
709 					  primary);
710 
711 	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message),
712 						  _("This will remove all previous results."));
713 
714 	gtk_dialog_add_button (GTK_DIALOG (message),
715 			       cancel_button,
716 			       GTK_RESPONSE_CANCEL);
717 	gtk_dialog_add_button (GTK_DIALOG (message),
718 			       ok_button,
719 			       GTK_RESPONSE_YES);
720 
721 	answer = gtk_dialog_run (GTK_DIALOG (message));
722 	gtk_widget_destroy (message);
723 
724 	if (answer != GTK_RESPONSE_YES)
725 		return FALSE;
726 
727 	return TRUE;
728 }
729 
730 static void
brasero_split_dialog_cut_clicked_cb(GtkButton * button,BraseroSplitDialog * self)731 brasero_split_dialog_cut_clicked_cb (GtkButton *button,
732 				     BraseroSplitDialog *self)
733 {
734 	BraseroSplitDialogPrivate *priv;
735 	guint page;
736 
737 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
738 
739 	page = gtk_combo_box_get_active (GTK_COMBO_BOX (priv->combo));
740 	if (page == 0) {
741 		gint64 pos;
742 
743 		/* this one is before since it doesn't wipe all slices */
744 		pos = brasero_song_control_get_pos (BRASERO_SONG_CONTROL (priv->player));
745 		brasero_split_dialog_cut (self, pos + priv->start, TRUE);
746 		return;
747 	}
748 
749 	if (!brasero_split_dialog_clear_confirm_dialog (self,
750 							_("Do you really want to carry on with automatic splitting?"),
751 							_("_Don't split"),
752 							_("_Split")))
753 		return;
754 
755 	if (page == 1) {
756 		gint64 sec;
757 		gint64 start;
758 		gint64 length;
759 
760 		sec = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->spin_sec));
761 
762 		sec *= 1000000000;
763 		if (sec < BRASERO_MIN_STREAM_LENGTH
764 		&& !brasero_split_dialog_size_error (self))
765 			return;
766 
767 		length = priv->end - priv->start;
768 
769 		gtk_list_store_clear (priv->model);
770 		for (start = sec; start < length; start += sec)
771 			brasero_split_dialog_cut (self, start, FALSE);
772 
773 		return;
774 	}
775 
776 	if (page == 2) {
777 		gint64 step;
778 		gint64 start;
779 		gint64 parts;
780 		gint64 length;
781 
782 		parts = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (priv->spin_parts));
783 
784 		length = priv->end - priv->start;
785 		step = length / parts;
786 
787 		if (step < BRASERO_MIN_STREAM_LENGTH
788 		&& !brasero_split_dialog_size_error (self))
789 			return;
790 
791 		gtk_list_store_clear (priv->model);
792 
793 		parts --;
794 		for (start = step; start < length && parts; start += step, parts --)
795 			brasero_split_dialog_cut (self, start, FALSE);
796 
797 		return;
798 	}
799 
800 	gtk_list_store_clear (priv->model);
801 
802 	priv->metadata = brasero_metadata_new ();
803 	g_signal_connect (priv->metadata,
804 			  "completed",
805 			  G_CALLBACK (brasero_split_dialog_metadata_finished_cb),
806 			  self);
807 	brasero_metadata_get_info_async (priv->metadata,
808 					 brasero_song_control_get_uri (BRASERO_SONG_CONTROL (priv->player)),
809 					 BRASERO_METADATA_FLAG_SILENCES);
810 
811 	/* stop anything from playing and grey out things */
812 	gtk_widget_set_sensitive (priv->cut, FALSE);
813 }
814 
815 static void
brasero_split_dialog_merge_clicked_cb(GtkButton * button,BraseroSplitDialog * self)816 brasero_split_dialog_merge_clicked_cb (GtkButton *button,
817 				       BraseroSplitDialog *self)
818 {
819 	BraseroSplitDialogPrivate *priv;
820 	GtkTreeSelection *selection;
821 	GtkTreeModel *model;
822 	GtkTreeIter iter;
823 
824 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
825 
826 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
827 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree));
828 	if (!gtk_tree_model_get_iter_first (model, &iter))
829 		return;
830 
831 	do {
832 		guint64 end;
833 		guint64 start;
834 		gchar *end_str;
835 		gchar *start_str;
836 		GtkTreeIter next;
837 		gchar *length_str;
838 		GtkTreeIter child;
839 
840 		if (!gtk_tree_selection_iter_is_selected (selection, &iter))
841 			continue;
842 
843 		next = iter;
844 		if (!gtk_tree_model_iter_next (model, &next))
845 			continue;
846 
847 		if (!gtk_tree_selection_iter_is_selected (selection, &next))
848 			continue;
849 
850 		gtk_tree_model_get (model, &iter,
851 				    START_COL, &start,
852 				    -1);
853 
854 		gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
855 								&child,
856 								&iter);
857 
858 		do {
859 			GtkTreeIter next_child;
860 
861 			gtk_tree_model_get (model, &next,
862 					    END_COL, &end,
863 					   -1);
864 
865 			gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
866 									&next_child,
867 									&next);
868 
869 			if (!gtk_list_store_remove (priv->model, &next_child))
870 				break;
871 
872 			gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (model),
873 									&next,
874 									&next_child);
875 
876 		} while (gtk_tree_selection_iter_is_selected (selection, &next));
877 
878 		length_str = brasero_units_get_time_string (end - start, TRUE, FALSE);
879 		start_str = brasero_units_get_time_string (start, TRUE, FALSE);
880 		end_str = brasero_units_get_time_string (end, TRUE, FALSE);
881 
882 		gtk_list_store_set (priv->model, &child,
883 				    START_COL, (gint64) start,
884 				    END_COL, (gint64) end,
885 				    LENGTH_COL, (gint64) end - start,
886 				    START_STR_COL, start_str,
887 				    END_STR_COL, end_str,
888 				    LENGTH_STR_COL, length_str,
889 				    -1);
890 		g_free (length_str);
891 		g_free (start_str);
892 		g_free (end_str);
893 
894 		gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (model),
895 								&iter,
896 								&child);
897 
898 	} while (gtk_tree_model_iter_next (model, &iter));
899 
900 	if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->model), NULL) == 1)
901 		gtk_list_store_clear (priv->model);
902 }
903 
904 static void
brasero_split_dialog_remove_clicked_cb(GtkButton * button,BraseroSplitDialog * self)905 brasero_split_dialog_remove_clicked_cb (GtkButton *button,
906 				        BraseroSplitDialog *self)
907 {
908 	BraseroSplitDialogPrivate *priv;
909 	GList *references = NULL;
910 	GtkTreeModel *model;
911 	GList *selected;
912 	GList *iter;
913 
914 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
915 
916 	selected = gtk_tree_selection_get_selected_rows (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)), &model);
917 
918 	/* since we are going to modify the tree take references */
919 	for (iter = selected; iter; iter = iter->next) {
920 		GtkTreePath *treepath;
921 		GtkTreeRowReference *reference;
922 
923 		treepath = iter->data;
924 		reference = gtk_tree_row_reference_new (model, treepath);
925 		gtk_tree_path_free (treepath);
926 
927 		references = g_list_prepend (references, reference);
928 	}
929 	g_list_free (selected);
930 
931 	for (iter = references; iter; iter = iter->next) {
932 		GtkTreeRowReference *reference;
933 		GtkTreePath *treepath;
934 		GtkTreeIter child;
935 		GtkTreeIter row;
936 
937 		reference = iter->data;
938 
939 		treepath = gtk_tree_row_reference_get_path (reference);
940 		gtk_tree_row_reference_free (reference);
941 		if (!treepath)
942 			continue;
943 
944 		if (!gtk_tree_model_get_iter (model, &row, treepath)) {
945 			gtk_tree_path_free (treepath);
946 			continue;
947 		}
948 
949 		gtk_tree_path_free (treepath);
950 
951 		gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
952 								&child,
953 								&row);
954 
955 		gtk_list_store_remove (priv->model, &child);
956 	}
957 	g_list_free (references);
958 }
959 
960 static void
brasero_split_dialog_reset_clicked_cb(GtkButton * button,BraseroSplitDialog * self)961 brasero_split_dialog_reset_clicked_cb (GtkButton *button,
962 				       BraseroSplitDialog *self)
963 {
964 	BraseroSplitDialogPrivate *priv;
965 
966 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
967 	if (!brasero_split_dialog_clear_confirm_dialog (self,
968 							_("Do you really want to empty the slices preview?"),
969 							GTK_STOCK_CANCEL,
970 							_("Re_move All")))
971 		return;
972 
973 	gtk_list_store_clear (priv->model);
974 }
975 
976 static void
brasero_split_dialog_combo_changed_cb(GtkComboBox * combo,BraseroSplitDialog * self)977 brasero_split_dialog_combo_changed_cb (GtkComboBox *combo,
978 				       BraseroSplitDialog *self)
979 {
980 	BraseroSplitDialogPrivate *priv;
981 	guint page;
982 
983 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
984 	page = gtk_combo_box_get_active (combo);
985 	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), page);
986 }
987 
988 static void
brasero_split_dialog_selection_changed_cb(GtkTreeSelection * selection,BraseroSplitDialog * self)989 brasero_split_dialog_selection_changed_cb (GtkTreeSelection *selection,
990 					   BraseroSplitDialog *self)
991 {
992 	BraseroSplitDialogPrivate *priv;
993 	GList *selected;
994 
995 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
996 
997 	selected = gtk_tree_selection_get_selected_rows (selection, NULL);
998 	if (selected) {
999 		g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1000 		g_list_free (selected);
1001 
1002 		gtk_widget_set_sensitive (priv->merge_button, TRUE);
1003 		gtk_widget_set_sensitive (priv->remove_button, TRUE);
1004 	}
1005 	else {
1006 		gtk_widget_set_sensitive (priv->merge_button, FALSE);
1007 		gtk_widget_set_sensitive (priv->remove_button, FALSE);
1008 	}
1009 }
1010 
1011 static void
brasero_split_dialog_row_inserted_cb(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,BraseroSplitDialog * self)1012 brasero_split_dialog_row_inserted_cb (GtkTreeModel *model,
1013 				      GtkTreePath *path,
1014 				      GtkTreeIter *iter,
1015 				      BraseroSplitDialog *self)
1016 {
1017 	BraseroSplitDialogPrivate *priv;
1018 
1019 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
1020 	gtk_widget_set_sensitive (priv->reset_button, TRUE);
1021 }
1022 
1023 static void
brasero_split_dialog_row_deleted_cb(GtkTreeModel * model,GtkTreePath * path,BraseroSplitDialog * self)1024 brasero_split_dialog_row_deleted_cb (GtkTreeModel *model,
1025 				     GtkTreePath *path,
1026 				     BraseroSplitDialog *self)
1027 {
1028 	BraseroSplitDialogPrivate *priv;
1029 	GtkTreeIter iter;
1030 
1031 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (self);
1032 	if (!gtk_tree_model_get_iter_first (model, &iter))
1033 		gtk_widget_set_sensitive (priv->reset_button, FALSE);
1034 }
1035 
1036 static void
brasero_split_dialog_init(BraseroSplitDialog * object)1037 brasero_split_dialog_init (BraseroSplitDialog *object)
1038 {
1039 	gchar *title;
1040 	GtkWidget *vbox;
1041 	GtkWidget *hbox;
1042 	GtkWidget *vbox2;
1043 	GtkWidget *hbox2;
1044 	GtkWidget *label;
1045 	GtkWidget *scroll;
1046 	GtkWidget *button;
1047 	GtkTreeModel *model;
1048 	GtkSizeGroup *size_group;
1049 	GtkCellRenderer *renderer;
1050 	GtkTreeViewColumn *column;
1051 	BraseroSplitDialogPrivate *priv;
1052 
1053 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (object);
1054 
1055 	gtk_window_set_title (GTK_WINDOW (object), _("Split Track"));
1056 	gtk_window_set_default_size (GTK_WINDOW (object), 500, 600);
1057 
1058 	gtk_dialog_add_button (GTK_DIALOG (object), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1059 	gtk_dialog_add_button (GTK_DIALOG (object), GTK_STOCK_OK, GTK_RESPONSE_OK);
1060 
1061 	vbox = gtk_dialog_get_content_area (GTK_DIALOG (object));
1062 	gtk_box_set_spacing (GTK_BOX (vbox), 0);
1063 
1064 	size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
1065 
1066 	/* Slicing method */
1067 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1068 	gtk_widget_show (hbox);
1069 
1070 	priv->combo = gtk_combo_box_text_new ();
1071 
1072 	label = gtk_label_new_with_mnemonic (_("M_ethod:"));
1073 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1074 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->combo);
1075 	gtk_widget_show (label);
1076 	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1077 
1078 	gtk_widget_set_tooltip_text (priv->combo, _("Method to be used to split the track"));
1079 	gtk_widget_show (priv->combo);
1080 	gtk_box_pack_start (GTK_BOX (hbox), priv->combo, TRUE, TRUE, 0);
1081 	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (priv->combo), _("Split track manually"));
1082 	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (priv->combo), _("Split track in parts with a fixed length"));
1083 	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (priv->combo), _("Split track in a fixed number of parts"));
1084 	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (priv->combo), _("Split track for each silence"));
1085 	g_signal_connect (priv->combo,
1086 			  "changed",
1087 			  G_CALLBACK (brasero_split_dialog_combo_changed_cb),
1088 			  object);
1089 
1090 	button = brasero_utils_make_button (_("_Slice"),
1091 					    NULL,
1092 					    "transform-crop-and-resize",
1093 					    GTK_ICON_SIZE_BUTTON);
1094 	gtk_widget_show (button);
1095 	gtk_size_group_add_widget (size_group, button);
1096 	gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1097 	g_signal_connect (button,
1098 			  "clicked",
1099 			  G_CALLBACK (brasero_split_dialog_cut_clicked_cb),
1100 			  object);
1101 	gtk_widget_set_tooltip_text (button, _("Add a splitting point"));
1102 	priv->cut = button;
1103 
1104 	priv->notebook = gtk_notebook_new ();
1105 	gtk_widget_show (priv->notebook);
1106 	gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
1107 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
1108 
1109 	priv->player = brasero_song_control_new ();
1110 	gtk_widget_show (priv->player);
1111 	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->player, NULL);
1112 
1113 	hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1114 	gtk_widget_show (hbox2);
1115 	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), hbox2, NULL);
1116 
1117 	/* Translators: this goes with the next (= "seconds") */
1118 	label = gtk_label_new (_("Split this track every"));
1119 	gtk_widget_show (label);
1120 	gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1121 
1122 	priv->spin_sec = gtk_spin_button_new_with_range (1.0, 1000.0, 1.0);
1123 	gtk_widget_show (priv->spin_sec);
1124 	gtk_box_pack_start (GTK_BOX (hbox2), priv->spin_sec, FALSE, FALSE, 0);
1125 
1126 	/* Translators: this goes with the previous (= "Split track every") */
1127 	label = gtk_label_new (_("seconds"));
1128 	gtk_widget_show (label);
1129 	gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1130 
1131 	hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1132 	gtk_widget_show (hbox2);
1133 	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), hbox2, NULL);
1134 
1135 	/* Translators: this goes with the next (= "parts") */
1136 	label = gtk_label_new (_("Split this track in"));
1137 	gtk_widget_show (label);
1138 	gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1139 
1140 	priv->spin_parts = gtk_spin_button_new_with_range (2.0, 1000.0, 1.0);
1141 	gtk_widget_show (priv->spin_parts);
1142 	gtk_box_pack_start (GTK_BOX (hbox2), priv->spin_parts, FALSE, FALSE, 0);
1143 
1144 	/* Translators: this goes with the previous (= "Split this track in") */
1145 	label = gtk_label_new (_("parts"));
1146 	gtk_widget_show (label);
1147 	gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1148 
1149 	priv->silence_label = gtk_label_new (NULL);
1150 	gtk_widget_show (priv->silence_label);
1151 	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->silence_label, NULL);
1152 
1153 	title = g_strdup_printf ("<b>%s</b>", _("Slicing Method"));
1154 	gtk_box_pack_start (GTK_BOX (vbox),
1155 			    brasero_utils_pack_properties (title,
1156 							   priv->notebook,
1157 							   hbox,
1158 							   NULL),
1159 			    FALSE,
1160 			    FALSE,
1161 			    0);
1162 	g_free (title);
1163 
1164 	/* slices preview */
1165 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1166 	gtk_widget_show (hbox);
1167 
1168 	priv->model = gtk_list_store_new (COLUMN_NUM,
1169 					  G_TYPE_INT64,
1170 					  G_TYPE_INT64,
1171 					  G_TYPE_INT64,
1172 					  G_TYPE_STRING,
1173 					  G_TYPE_STRING,
1174 					  G_TYPE_STRING);
1175 
1176 	g_signal_connect (priv->model,
1177 			  "row-inserted",
1178 			  G_CALLBACK (brasero_split_dialog_row_inserted_cb),
1179 			  object);
1180 	g_signal_connect (priv->model,
1181 			  "row-deleted",
1182 			  G_CALLBACK (brasero_split_dialog_row_deleted_cb),
1183 			  object);
1184 
1185 	model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (priv->model));
1186 	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1187 					      START_COL,
1188 					      GTK_SORT_ASCENDING);
1189 
1190 	scroll = gtk_scrolled_window_new (NULL, NULL);
1191 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
1192 					     GTK_SHADOW_IN);
1193 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
1194 					GTK_POLICY_AUTOMATIC,
1195 					GTK_POLICY_AUTOMATIC);
1196 	gtk_widget_show (scroll);
1197 	gtk_box_pack_start (GTK_BOX (hbox), scroll, TRUE, TRUE, 0);
1198 
1199 	priv->tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
1200 	gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (priv->tree), TRUE);
1201 	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (priv->tree), TRUE);
1202 	gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv->tree), TRUE);
1203 
1204 	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)),
1205 				     GTK_SELECTION_MULTIPLE);
1206 
1207 	gtk_widget_show (priv->tree);
1208 	gtk_container_add (GTK_CONTAINER (scroll), priv->tree);
1209 
1210 	renderer = gtk_cell_renderer_text_new ();
1211 	column = gtk_tree_view_column_new_with_attributes (_("Start"),
1212 							   renderer,
1213 							   "text", START_STR_COL,
1214 							   NULL);
1215 	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree), column);
1216 
1217 	renderer = gtk_cell_renderer_text_new ();
1218 	column = gtk_tree_view_column_new_with_attributes (_("End"),
1219 							   renderer,
1220 							   "text", END_STR_COL,
1221 							   NULL);
1222 	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree), column);
1223 
1224 	renderer = gtk_cell_renderer_text_new ();
1225 	column = gtk_tree_view_column_new_with_attributes (_("Length"),
1226 							   renderer,
1227 							   "text", LENGTH_STR_COL,
1228 							   NULL);
1229 	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree), column);
1230 
1231 	g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree)),
1232 			  "changed",
1233 			  G_CALLBACK (brasero_split_dialog_selection_changed_cb),
1234 			  object);
1235 
1236 	/* buttons */
1237 	vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1238 	gtk_widget_show (vbox2);
1239 	gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
1240 
1241 	button = brasero_utils_make_button (_("Mer_ge"),
1242 					    NULL,
1243 					    NULL,
1244 					    GTK_ICON_SIZE_BUTTON);
1245 	gtk_widget_show (button);
1246 	gtk_size_group_add_widget (size_group, button);
1247 	gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1248 	g_signal_connect (button,
1249 			  "clicked",
1250 			  G_CALLBACK (brasero_split_dialog_merge_clicked_cb),
1251 			  object);
1252 	gtk_widget_set_tooltip_text (button, _("Merge a selected slice with the next selected one"));
1253 	priv->merge_button = button;
1254 
1255 	button = brasero_utils_make_button (_("_Remove"),
1256 					    GTK_STOCK_REMOVE,
1257 					    NULL,
1258 					    GTK_ICON_SIZE_BUTTON);
1259 	gtk_widget_show (button);
1260 	gtk_size_group_add_widget (size_group, button);
1261 	gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1262 	g_signal_connect (button,
1263 			  "clicked",
1264 			  G_CALLBACK (brasero_split_dialog_remove_clicked_cb),
1265 			  object);
1266 	gtk_widget_set_tooltip_text (button, _("Remove the selected slices"));
1267 	priv->remove_button = button;
1268 
1269 	button = brasero_utils_make_button (_("Re_move All"),
1270 					    NULL,
1271 					    NULL,
1272 					    GTK_ICON_SIZE_BUTTON);
1273 	gtk_widget_show (button);
1274 	gtk_size_group_add_widget (size_group, button);
1275 	gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1276 	g_signal_connect (button,
1277 			  "clicked",
1278 			  G_CALLBACK (brasero_split_dialog_reset_clicked_cb),
1279 			  object);
1280 	gtk_widget_set_tooltip_text (button, _("Clear the slices preview"));
1281 	priv->reset_button = button;
1282 
1283 	gtk_widget_set_sensitive (priv->reset_button, FALSE);
1284 	gtk_widget_set_sensitive (priv->merge_button, FALSE);
1285 	gtk_widget_set_sensitive (priv->remove_button, FALSE);
1286 
1287 	vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1288 	gtk_widget_show (vbox2);
1289 
1290 	label = gtk_label_new_with_mnemonic (_("_List of slices that are to be created:"));
1291 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1292 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->tree);
1293 	gtk_widget_show (label);
1294 
1295 	gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
1296 	gtk_box_pack_start (GTK_BOX (vbox2), hbox, TRUE, TRUE, 0);
1297 
1298 	title = g_strdup_printf ("<b>%s</b>", _("Slices Preview"));
1299 	gtk_box_pack_start (GTK_BOX (vbox),
1300 			    brasero_utils_pack_properties (title,
1301 							   vbox2,
1302 							   NULL),
1303 			    TRUE,
1304 			    TRUE,
1305 			    0);
1306 	g_free (title);
1307 
1308 	gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo), 0);
1309 	g_object_unref (size_group);
1310 }
1311 
1312 static void
brasero_split_dialog_finalize(GObject * object)1313 brasero_split_dialog_finalize (GObject *object)
1314 {
1315 	BraseroSplitDialogPrivate *priv;
1316 
1317 	priv = BRASERO_SPLIT_DIALOG_PRIVATE (object);
1318 	if (priv->metadata) {
1319 		brasero_metadata_cancel (priv->metadata);
1320 		g_object_unref (priv->metadata);
1321 		priv->metadata = NULL;
1322 	}
1323 
1324 	G_OBJECT_CLASS (brasero_split_dialog_parent_class)->finalize (object);
1325 }
1326 
1327 static void
brasero_split_dialog_class_init(BraseroSplitDialogClass * klass)1328 brasero_split_dialog_class_init (BraseroSplitDialogClass *klass)
1329 {
1330 	GObjectClass* object_class = G_OBJECT_CLASS (klass);
1331 
1332 	g_type_class_add_private (klass, sizeof (BraseroSplitDialogPrivate));
1333 
1334 	object_class->finalize = brasero_split_dialog_finalize;
1335 }
1336 
1337 GtkWidget *
brasero_split_dialog_new(void)1338 brasero_split_dialog_new (void)
1339 {
1340 	return GTK_WIDGET (g_object_new (BRASERO_TYPE_SPLIT_DIALOG, NULL));
1341 }
1342