1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008-2011 <stebbins@stebbins>
6 * callbacks.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
15 #include <gdk/gdkkeysyms.h>
16 #include <glib/gstdio.h>
20 #include "hb-backend.h"
22 #include "callbacks.h"
27 queue_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
30 GtkTreeIter iter, piter;
32 g_debug("queue_list_selection_changed_cb ()");
33 // A queue entry is made up of a parent and multiple
34 // children that are visible when expanded. When and entry
35 // is selected, I want the parent to be selected.
36 // This is purely cosmetic.
37 if (gtk_tree_selection_get_selected(selection, &store, &iter))
39 GtkWidget *widget = GHB_WIDGET (ud->builder, "queue_edit");
40 gtk_widget_set_sensitive (widget, TRUE);
41 if (gtk_tree_model_iter_parent (store, &piter, &iter))
44 GtkTreeView *treeview;
46 gtk_tree_selection_select_iter (selection, &piter);
47 path = gtk_tree_model_get_path (store, &piter);
48 treeview = gtk_tree_selection_get_tree_view (selection);
49 // Make the parent visible in scroll window if it is not.
50 gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0, 0);
51 gtk_tree_path_free(path);
56 GtkWidget *widget = GHB_WIDGET (ud->builder, "queue_edit");
57 gtk_widget_set_sensitive (widget, FALSE);
62 add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter)
64 GtkTreeView *treeview;
70 gchar *dest, *preset, *vol_name, *basename;
71 const gchar *vcodec, *container;
72 gchar *fps, *vcodec_abbr;
73 gint title, start_point, end_point, width, height;
74 gint source_width, source_height;
75 gboolean pass2 = FALSE, keep_aspect, vqtype, turbo;
78 gchar *escape, *escape2;
80 g_debug("update_queue_list ()");
81 if (settings == NULL) return;
82 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
83 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
85 tweaks = ghb_settings_get_boolean(settings, "allow_tweaks");
86 title = ghb_settings_get_int(settings, "titlenum");
87 start_point = ghb_settings_get_int(settings, "start_point");
88 end_point = ghb_settings_get_int(settings, "end_point");
89 vol_name = ghb_settings_get_string(settings, "volume_label");
90 dest = ghb_settings_get_string(settings, "destination");
91 basename = g_path_get_basename(dest);
92 escape = g_markup_escape_text(basename, -1);
93 escape2 = g_markup_escape_text(vol_name, -1);
95 vqtype = ghb_settings_get_boolean(settings, "vquality_type_constant");
97 pass2 = ghb_settings_get_boolean(settings, "VideoTwoPass");
98 const gchar *points = "Chapters";
99 if (ghb_settings_combo_int(settings, "PtoPType") == 0)
101 else if (ghb_settings_combo_int(settings, "PtoPType") == 1)
103 else if (ghb_settings_combo_int(settings, "PtoPType") == 2)
105 info = g_strdup_printf
107 "<big><b>%s</b></big> "
108 "<small>(Title %d, %s %d through %d, %d Video %s)"
110 escape2, title, points, start_point, end_point,
111 pass2 ? 2:1, pass2 ? "Passes":"Pass", escape
120 gtk_tree_store_append(store, &iter, NULL);
122 gtk_tree_store_set(store, &iter, 1, info, 2, "hb-queue-delete", -1);
124 status = ghb_settings_get_int(settings, "job_status");
127 case GHB_QUEUE_PENDING:
128 gtk_tree_store_set(store, &iter, 0, "hb-queue-job", -1);
130 case GHB_QUEUE_CANCELED:
131 gtk_tree_store_set(store, &iter, 0, "hb-canceled", -1);
133 case GHB_QUEUE_RUNNING:
134 gtk_tree_store_set(store, &iter, 0, "hb-working0", -1);
137 gtk_tree_store_set(store, &iter, 0, "hb-complete", -1);
140 gtk_tree_store_set(store, &iter, 0, "hb-queue-job", -1);
144 GString *str = g_string_new("");
146 gboolean preset_modified;
150 container = ghb_settings_combo_option(settings, "FileFormat");
151 mux = ghb_settings_combo_int(settings, "FileFormat");
152 preset_modified = ghb_settings_get_boolean(settings, "preset_modified");
153 path = ghb_settings_get_value(settings, "preset");
154 preset = ghb_preset_path_string(path);
155 markers = ghb_settings_get_boolean(settings, "ChapterMarkers");
158 g_string_append_printf(str,
159 "<b>Modified Preset Based On:</b> <small>%s</small>\n",
162 g_string_append_printf(str,
163 "<b>Preset:</b> <small>%s</small>\n",
168 g_string_append_printf(str,
169 "<b>Format:</b> <small>%s Container, Chapter Markers</small>\n",
174 g_string_append_printf(str,
175 "<b>Format:</b> <small>%s Container</small>\n", container);
177 if (mux == HB_MUX_MP4)
179 gboolean ipod, http, large;
181 ipod = ghb_settings_get_boolean(settings, "Mp4iPodCompatible");
182 http = ghb_settings_get_boolean(settings, "Mp4HttpOptimize");
183 large = ghb_settings_get_boolean(settings, "Mp4LargeFile");
184 if (http || ipod || large)
186 g_string_append_printf(str, "<b>MP4 Options:</b><small>");
188 g_string_append_printf(str, " - iPod 5G Support");
190 g_string_append_printf(str, " - Web Optimized");
192 g_string_append_printf(str, " - Large File Size (>4GB)");
193 g_string_append_printf(str, "</small>\n");
196 escape = g_markup_escape_text(dest, -1);
197 g_string_append_printf(str,
198 "<b>Destination:</b> <small>%s</small>\n", escape);
200 width = ghb_settings_get_int(settings, "scale_width");
201 height = ghb_settings_get_int(settings, "scale_height");
202 pic_par = ghb_settings_combo_int(settings, "PicturePAR");
203 keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio");
212 aspect_desc = "(Aspect Preserved)";
216 aspect_desc = "(Aspect Lost)";
222 aspect_desc = "(Strict Anamorphic)";
227 aspect_desc = "(Loose Anamorphic)";
232 aspect_desc = "(Custom Anamorphic)";
237 aspect_desc = "(Unknown)";
240 vqtype = ghb_settings_get_boolean(settings, "vquality_type_constant");
242 gchar *vq_desc = "Error";
243 gchar *vq_units = "";
248 vqtype = ghb_settings_get_boolean(settings, "vquality_type_target");
252 vqvalue = ghb_settings_get_int(settings, "VideoAvgBitrate");
253 vq_desc = "Bitrate:";
259 vqvalue = ghb_settings_get_int(settings, "VideoTargetSize");
260 vq_desc = "Target Size:";
263 vqstr = g_strdup_printf("%d", (gint)vqvalue);
268 vqvalue = ghb_settings_get_double(settings, "VideoQualitySlider");
269 vq_desc = "Constant Quality:";
270 vqstr = g_strdup_printf("%d", (gint)vqvalue);
273 fps = ghb_settings_get_string(settings, "VideoFramerate");
274 if (strcmp("source", fps) == 0)
277 if (ghb_settings_combo_int(settings, "PictureDetelecine"))
278 fps = g_strdup("Same As Source (vfr detelecine)");
280 fps = g_strdup("Same As Source (variable)");
285 tmp = g_strdup_printf("%s (constant frame rate)", fps);
289 vcodec = ghb_settings_combo_option(settings, "VideoEncoder");
290 vcodec_abbr = ghb_settings_get_string(settings, "VideoEncoder");
291 source_width = ghb_settings_get_int(settings, "source_width");
292 source_height = ghb_settings_get_int(settings, "source_height");
293 g_string_append_printf(str,
294 "<b>Picture:</b> Source: <small>%d x %d, Output %d x %d %s</small>\n",
295 source_width, source_height, width, height, aspect_desc);
298 gboolean decomb_deint;
299 gboolean filters = FALSE;
301 decomb_deint = ghb_settings_get_boolean(settings, "PictureDecombDeinterlace");
302 decomb = ghb_settings_combo_int(settings, "PictureDecomb");
303 g_string_append_printf(str, "<b>Filters:</b><small>");
304 detel = ghb_settings_combo_int(settings, "PictureDetelecine");
307 g_string_append_printf(str, " - Detelecine");
311 cust = ghb_settings_get_string(settings, "PictureDetelecineCustom");
312 g_string_append_printf(str, ": %s", cust);
317 if (decomb_deint && decomb)
319 g_string_append_printf(str, " - Decomb");
323 cust = ghb_settings_get_string(settings, "PictureDecombCustom");
324 g_string_append_printf(str, ": %s", cust);
329 else if (!decomb_deint)
331 gint deint = ghb_settings_combo_int(settings, "PictureDeinterlace");
336 gchar *cust = ghb_settings_get_string(settings,
337 "PictureDeinterlaceCustom");
338 g_string_append_printf(str, " - Deinterlace: %s", cust);
343 const gchar *opt = ghb_settings_combo_option(settings,
344 "PictureDeinterlace");
345 g_string_append_printf(str, " - Deinterlace: %s", opt);
350 gint denoise = ghb_settings_combo_int(settings, "PictureDenoise");
355 gchar *cust = ghb_settings_get_string(settings,
356 "PictureDenoiseCustom");
357 g_string_append_printf(str, " - Denoise: %s", cust);
362 const gchar *opt = ghb_settings_combo_option(settings,
364 g_string_append_printf(str, " - Denoise: %s", opt);
368 gint deblock = ghb_settings_get_int(settings, "PictureDeblock");
371 g_string_append_printf(str, " - Deblock (%d)", deblock);
374 if (ghb_settings_get_boolean(settings, "VideoGrayScale"))
376 g_string_append_printf(str, " - Grayscale");
380 g_string_append_printf(str, " None");
381 g_string_append_printf(str, "</small>\n");
383 g_string_append_printf(str,
384 "<b>Video:</b> <small>%s, Framerate: %s, %s %s%s</small>\n",
385 vcodec, fps, vq_desc, vqstr, vq_units);
387 turbo = ghb_settings_get_boolean(settings, "VideoTurboTwoPass");
390 g_string_append_printf(str, "<b>Turbo:</b> <small>On</small>\n");
392 if (strcmp(vcodec_abbr, "x264") == 0)
394 gchar *x264opts = ghb_build_x264opts_string(settings);
395 g_string_append_printf(str,
396 "<b>x264 Options:</b> <small>%s</small>\n", x264opts);
401 const GValue *audio_list;
403 audio_list = ghb_settings_get_value(settings, "audio_list");
404 count = ghb_array_len(audio_list);
405 for (ii = 0; ii < count; ii++)
407 gchar *bitrate, *samplerate, *track;
408 const gchar *acodec, *mix;
412 asettings = ghb_array_get_nth(audio_list, ii);
414 acodec = ghb_settings_combo_option(asettings, "AudioEncoderActual");
415 bitrate = ghb_settings_get_string(asettings, "AudioBitrate");
416 sr = ghb_settings_get_double(asettings, "AudioSamplerate");
417 samplerate = ghb_settings_get_string(asettings, "AudioSamplerate");
420 samplerate = g_strdup("Same As Source");
424 samplerate = g_strdup_printf("%.4g", sr);
426 track = ghb_settings_get_string(asettings, "AudioTrackDescription");
427 mix = ghb_settings_combo_option(asettings, "AudioMixdown");
429 g_string_append_printf(str, "<b>Audio:</b>");
431 g_string_append_printf(str, "<b>Audio:</b>\n");
433 g_string_append_printf(str, "\t");
435 g_string_append_printf(str,
436 "<small> %s, Encoder: %s, Mixdown: %s, SampleRate: %s, Bitrate: %s</small>\n",
437 track, acodec, mix, samplerate, bitrate);
444 const GValue *sub_list;
446 sub_list = ghb_settings_get_value(settings, "subtitle_list");
447 count = ghb_array_len(sub_list);
448 for (ii = 0; ii < count; ii++)
452 gboolean force, burn, def;
455 settings = ghb_array_get_nth(sub_list, ii);
456 track = ghb_settings_get_string(settings, "SubtitleTrackDescription");
457 source = ghb_settings_get_int(settings, "SubtitleSource");
458 force = ghb_settings_get_boolean(settings, "SubtitleForced");
459 burn = ghb_settings_get_boolean(settings, "SubtitleBurned");
460 def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack");
462 g_string_append_printf(str, "<b>Subtitle:</b>");
464 g_string_append_printf(str, "<b>Subtitles:</b>\n");
466 g_string_append_printf(str, "\t");
468 if (source != SRTSUB)
470 g_string_append_printf(str,
471 "<small> %s%s%s%s</small>",
473 force ? " (Force)":"",
475 def ? " (Default)":""
481 gchar *filename, *basename, *code;
483 offset = ghb_settings_get_int(settings, "SrtOffset");
484 filename = ghb_settings_get_string(settings, "SrtFile");
485 basename = g_path_get_basename(filename);
486 code = ghb_settings_get_string(settings, "SrtCodeset");
487 g_string_append_printf(str,
488 "<small> %s (%s), %s, Offset (ms) %d%s</small>",
489 track, code, basename, offset,
490 def ? " (Default)":""
497 g_string_append_printf(str, "\n");
501 info = g_string_free(str, FALSE);
502 gtk_tree_store_append(store, &citer, &iter);
503 gtk_tree_store_set(store, &citer, 1, info, -1);
513 audio_list_refresh(signal_user_data_t *ud)
515 GtkTreeView *treeview;
520 const GValue *audio_list;
522 g_debug("ghb_audio_list_refresh ()");
523 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list"));
524 store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
525 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
529 const gchar *track, *codec, *br, *sr, *mix;
535 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
536 if (row >= ghb_array_len(audio_list))
538 asettings = ghb_array_get_nth(audio_list, row);
540 track = ghb_settings_combo_option(asettings, "AudioTrack");
541 itrack = ghb_settings_combo_int(asettings, "AudioTrack");
542 codec = ghb_settings_combo_option(asettings, "AudioEncoderActual");
543 br = ghb_settings_combo_option(asettings, "AudioBitrate");
544 sr = ghb_settings_combo_option(asettings, "AudioSamplerate");
545 mix = ghb_settings_combo_option(asettings, "AudioMixdown");
547 drc = ghb_settings_get_double(asettings, "AudioTrackDRCSlider");
549 s_drc = g_strdup("Off");
551 s_drc = g_strdup_printf("%.1f", drc);
553 gtk_list_store_set(GTK_LIST_STORE(store), &iter,
554 // These are displayed in list
563 done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
570 validate_settings(signal_user_data_t *ud)
572 // Check to see if the dest file exists or is
573 // already in the queue
574 gchar *message, *dest;
578 titleindex = ghb_settings_combo_int(ud->settings, "title");
579 if (titleindex < 0) return FALSE;
580 dest = ghb_settings_get_string(ud->settings, "destination");
581 count = ghb_array_len(ud->queue);
582 for (ii = 0; ii < count; ii++)
587 js = ghb_array_get_nth(ud->queue, ii);
588 filename = ghb_settings_get_string(js, "destination");
589 if (strcmp(dest, filename) == 0)
591 message = g_strdup_printf(
592 "Destination: %s\n\n"
593 "Another queued job has specified the same destination.\n"
594 "Do you want to overwrite?",
596 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Overwrite"))
608 gchar *destdir = g_path_get_dirname(dest);
609 if (!g_file_test(destdir, G_FILE_TEST_IS_DIR))
611 message = g_strdup_printf(
612 "Destination: %s\n\n"
613 "This is not a valid directory.",
615 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
622 // This doesn't work properly on windows
623 if (g_access(destdir, R_OK|W_OK) != 0)
625 message = g_strdup_printf(
626 "Destination: %s\n\n"
627 "Can not read or write the directory.",
629 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
639 gchar *resolved = ghb_resolve_symlink(destdir);
641 gfile = g_file_new_for_path(resolved);
642 info = g_file_query_filesystem_info(gfile,
643 G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, NULL);
646 if (g_file_info_has_attribute(info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
648 size = g_file_info_get_attribute_uint64(info,
649 G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
651 gint64 fsize = (guint64)10 * 1024 * 1024 * 1024;
654 message = g_strdup_printf(
655 "Destination filesystem is almost full: %uM free\n\n"
656 "Encode may be incomplete if you proceed.\n",
657 (guint)(size / (1024L*1024L)));
658 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Proceed"))
667 g_object_unref(info);
669 g_object_unref(gfile);
672 if (g_file_test(dest, G_FILE_TEST_EXISTS))
674 message = g_strdup_printf(
675 "Destination: %s\n\n"
676 "File already exists.\n"
677 "Do you want to overwrite?",
679 if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Overwrite"))
689 // Validate video quality is in a reasonable range
690 if (!ghb_validate_vquality(ud->settings))
694 // Validate audio settings
695 if (!ghb_validate_audio(ud))
699 // Validate audio settings
700 if (!ghb_validate_subtitles(ud))
704 // Validate video settings
705 if (!ghb_validate_video(ud))
709 // Validate filter settings
710 if (!ghb_validate_filters(ud))
714 audio_list_refresh(ud);
719 queue_add(signal_user_data_t *ud)
721 // Add settings to the queue
726 g_debug("queue_add ()");
727 if (!validate_settings(ud))
732 if (ud->queue == NULL)
733 ud->queue = ghb_array_value_new(32);
734 // Make a copy of current settings to be used for the new job
735 settings = ghb_value_dup(ud->settings);
736 ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING);
737 ghb_settings_set_int(settings, "job_unique_id", 0);
738 titleindex = ghb_settings_combo_int(settings, "title");
739 titlenum = ghb_get_title_number(titleindex);
740 ghb_settings_set_int(settings, "titlenum", titlenum);
741 ghb_array_append(ud->queue, settings);
742 add_to_queue_list(ud, settings, NULL);
743 ghb_save_queue(ud->queue);
744 ghb_update_pending(ud);
750 queue_add_clicked_cb(GtkWidget *widget, signal_user_data_t *ud)
752 g_debug("queue_add_clicked_cb ()");
757 queue_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
759 GtkTreeView *treeview;
760 GtkTreePath *treepath;
769 g_debug("queue_remove_clicked_cb ()");
770 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
771 store = gtk_tree_view_get_model(treeview);
772 treepath = gtk_tree_path_new_from_string (path);
773 if (gtk_tree_path_get_depth(treepath) > 1) return;
774 if (gtk_tree_model_get_iter(store, &iter, treepath))
776 // Find the entry in the queue
777 indices = gtk_tree_path_get_indices (treepath);
779 // Can only free the treepath After getting what I need from
780 // indices since this points into treepath somewhere.
781 gtk_tree_path_free (treepath);
783 if (row >= ghb_array_len(ud->queue))
785 settings = ghb_array_get_nth(ud->queue, row);
786 status = ghb_settings_get_int(settings, "job_status");
787 if (status == GHB_QUEUE_RUNNING)
789 // Ask if wants to stop encode.
790 if (!ghb_cancel_encode2(ud, NULL))
794 unique_id = ghb_settings_get_int(settings, "job_unique_id");
795 ghb_remove_job(unique_id);
797 // Remove the selected item
798 gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
799 // Remove the corresponding item from the queue list
800 GValue *old = ghb_array_get_nth(ud->queue, row);
802 ghb_array_remove(ud->queue, row);
803 ghb_save_queue(ud->queue);
807 gtk_tree_path_free (treepath);
809 ghb_update_pending(ud);
813 find_last_finished(GValue *queue)
819 g_debug("find_last_finished");
820 count = ghb_array_len(queue);
821 for (ii = 0; ii < count; ii++)
823 js = ghb_array_get_nth(queue, ii);
824 status = ghb_settings_get_int(js, "job_status");
825 if (status != GHB_QUEUE_DONE && status != GHB_QUEUE_RUNNING)
833 // This little bit is needed to prevent the default drag motion
834 // handler from expanding rows if you hover over them while
836 // Also controls where valid drop locations are
837 G_MODULE_EXPORT gboolean
838 queue_drag_motion_cb(
844 signal_user_data_t *ud)
846 GtkTreePath *path = NULL;
847 GtkTreeViewDropPosition pos;
848 gint *indices, row, status, finished;
853 GtkTreeSelection *select;
856 widget = gtk_drag_get_source_widget(ctx);
857 if (widget == NULL || widget != GTK_WIDGET(tv))
860 // This bit checks to see if the source is allowed to be
861 // moved. Only pending and canceled items may be moved.
862 srctv = GTK_TREE_VIEW(gtk_drag_get_source_widget(ctx));
863 select = gtk_tree_view_get_selection (srctv);
864 gtk_tree_selection_get_selected (select, &model, &iter);
865 path = gtk_tree_model_get_path (model, &iter);
866 indices = gtk_tree_path_get_indices(path);
868 gtk_tree_path_free(path);
869 js = ghb_array_get_nth(ud->queue, row);
870 status = ghb_settings_get_int(js, "job_status");
871 if (status != GHB_QUEUE_PENDING && status != GHB_QUEUE_CANCELED)
873 gdk_drag_status(ctx, 0, time);
877 // The reset checks that the destination is a valid position
878 // in the list. Can not move above any finished or running items
879 gtk_tree_view_get_dest_row_at_pos (tv, x, y, &path, &pos);
882 gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
885 // Don't allow *drop into*
886 if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
887 pos = GTK_TREE_VIEW_DROP_BEFORE;
888 if (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
889 pos = GTK_TREE_VIEW_DROP_AFTER;
890 // Don't allow droping int child items
891 if (gtk_tree_path_get_depth(path) > 1)
893 gtk_tree_path_up(path);
894 pos = GTK_TREE_VIEW_DROP_AFTER;
896 indices = gtk_tree_path_get_indices(path);
898 js = ghb_array_get_nth(ud->queue, row);
900 finished = find_last_finished(ud->queue);
903 gtk_tree_path_free(path);
904 gdk_drag_status(ctx, 0, time);
907 if (pos != GTK_TREE_VIEW_DROP_AFTER &&
910 gtk_tree_path_free(path);
911 gdk_drag_status(ctx, 0, time);
914 gtk_tree_view_set_drag_dest_row(tv, path, pos);
915 gtk_tree_path_free(path);
916 gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
922 GtkTreeView *dstwidget,
925 GtkSelectionData *selection_data,
927 signal_user_data_t *ud)
929 GtkTreePath *path = NULL;
930 //GtkTreeModel *model;
931 GtkTreeViewDropPosition pos;
932 GtkTreeIter dstiter, srciter;
936 GtkTreeModel *dstmodel = gtk_tree_view_get_model(dstwidget);
938 g_debug("queue_drag_cb ()");
939 // This doesn't work here for some reason...
940 // gtk_tree_view_get_drag_dest_row(dstwidget, &path, &pos);
941 gtk_tree_view_get_dest_row_at_pos (dstwidget, x, y, &path, &pos);
942 // This little hack is needed because attempting to drop after
943 // the last item gives us no path or pos.
948 n_children = gtk_tree_model_iter_n_children(dstmodel, NULL);
951 pos = GTK_TREE_VIEW_DROP_AFTER;
952 path = gtk_tree_path_new_from_indices(n_children-1, -1);
956 pos = GTK_TREE_VIEW_DROP_BEFORE;
957 path = gtk_tree_path_new_from_indices(0, -1);
962 if (gtk_tree_path_get_depth(path) > 1)
963 gtk_tree_path_up(path);
964 if (gtk_tree_model_get_iter (dstmodel, &dstiter, path))
967 GtkTreeView *srcwidget;
968 GtkTreeModel *srcmodel;
969 GtkTreeSelection *select;
970 GtkTreePath *srcpath = NULL;
971 GtkTreePath *dstpath = NULL;
973 srcwidget = GTK_TREE_VIEW(gtk_drag_get_source_widget(dc));
974 //srcmodel = gtk_tree_view_get_model(srcwidget);
975 select = gtk_tree_view_get_selection (srcwidget);
976 gtk_tree_selection_get_selected (select, &srcmodel, &srciter);
978 srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
979 indices = gtk_tree_path_get_indices(srcpath);
981 gtk_tree_path_free(srcpath);
982 js = ghb_array_get_nth(ud->queue, row);
986 case GTK_TREE_VIEW_DROP_BEFORE:
987 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
988 gtk_tree_store_insert_before (GTK_TREE_STORE (dstmodel),
989 &iter, NULL, &dstiter);
992 case GTK_TREE_VIEW_DROP_AFTER:
993 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
994 gtk_tree_store_insert_after (GTK_TREE_STORE (dstmodel),
995 &iter, NULL, &dstiter);
1001 // Reset job to pending
1002 ghb_settings_set_int(js, "job_status", GHB_QUEUE_PENDING);
1003 add_to_queue_list(ud, js, &iter);
1005 dstpath = gtk_tree_model_get_path (dstmodel, &iter);
1006 indices = gtk_tree_path_get_indices(dstpath);
1008 gtk_tree_path_free(dstpath);
1009 ghb_array_insert(ud->queue, row, js);
1011 srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
1012 indices = gtk_tree_path_get_indices(srcpath);
1014 gtk_tree_path_free(srcpath);
1015 ghb_array_remove(ud->queue, row);
1016 gtk_tree_store_remove (GTK_TREE_STORE (srcmodel), &srciter);
1017 ghb_save_queue(ud->queue);
1019 gtk_tree_path_free(path);
1024 ghb_queue_buttons_grey(signal_user_data_t *ud)
1030 gint queue_state, scan_state;
1031 gboolean show_start, show_stop, paused;
1033 queue_count = ghb_array_len(ud->queue);
1034 titleindex = ghb_settings_combo_int(ud->settings, "title");
1036 queue_state = ghb_get_queue_state();
1037 scan_state = ghb_get_scan_state();
1039 show_stop = queue_state &
1040 (GHB_STATE_WORKING | GHB_STATE_SEARCHING |
1041 GHB_STATE_SCANNING | GHB_STATE_MUXING);
1042 show_start = !(scan_state & GHB_STATE_SCANNING) &&
1043 (titleindex >= 0 || queue_count > 0);
1046 paused = queue_state & GHB_STATE_PAUSED;
1048 widget = GHB_WIDGET(ud->builder, "queue_add");
1049 gtk_widget_set_sensitive(widget, show_start);
1050 action = GHB_ACTION(ud->builder, "queue_add_menu");
1051 gtk_action_set_sensitive(action, show_start);
1053 widget = GHB_WIDGET (ud->builder, "queue_start1");
1056 gtk_widget_set_sensitive (widget, TRUE);
1057 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop");
1058 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Stop");
1059 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Stop Encoding");
1063 gtk_widget_set_sensitive (widget, show_start);
1064 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-play");
1065 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Start");
1066 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Start Encoding");
1068 widget = GHB_WIDGET (ud->builder, "queue_start2");
1071 gtk_widget_set_sensitive (widget, TRUE);
1072 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop");
1073 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Stop");
1074 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Stop Encoding");
1078 gtk_widget_set_sensitive (widget, show_start);
1079 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-play");
1080 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Start");
1081 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Start Encoding");
1083 widget = GHB_WIDGET (ud->builder, "queue_pause1");
1086 gtk_widget_set_sensitive (widget, show_stop);
1087 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-play");
1088 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Resume");
1089 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Resume Encoding");
1093 gtk_widget_set_sensitive (widget, show_stop);
1094 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-pause");
1095 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Pause");
1096 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Pause Encoding");
1098 widget = GHB_WIDGET (ud->builder, "queue_pause2");
1101 gtk_widget_set_sensitive (widget, show_stop);
1102 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-play");
1103 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Resume");
1104 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Resume Encoding");
1108 gtk_widget_set_sensitive (widget, show_stop);
1109 gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-pause");
1110 gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), "Pause");
1111 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), "Pause Encoding");
1114 action = GHB_ACTION (ud->builder, "queue_start_menu");
1117 gtk_action_set_sensitive (action, TRUE);
1118 #if GTK_CHECK_VERSION(2, 16, 0)
1119 gtk_action_set_icon_name(action, "hb-stop");
1120 gtk_action_set_label(action, "S_top Queue");
1121 gtk_action_set_tooltip(action, "Stop Encoding");
1123 g_object_set_property(G_OBJECT(action), "icon-name",
1124 ghb_string_value("hb-stop"));
1125 g_object_set_property(G_OBJECT(action), "label",
1126 ghb_string_value("S_top Queue"));
1127 g_object_set_property(G_OBJECT(action), "tooltip",
1128 ghb_string_value("Stop Encoding"));
1133 gtk_action_set_sensitive (action, show_start);
1134 #if GTK_CHECK_VERSION(2, 16, 0)
1135 gtk_action_set_icon_name(action, "hb-play");
1136 gtk_action_set_label(action, "_Start Queue");
1137 gtk_action_set_tooltip(action, "Start Encoding");
1139 g_object_set_property(G_OBJECT(action), "icon-name",
1140 ghb_string_value("hb-play"));
1141 g_object_set_property(G_OBJECT(action), "label",
1142 ghb_string_value("_Start Queue"));
1143 g_object_set_property(G_OBJECT(action), "tooltip",
1144 ghb_string_value("Start Encoding"));
1147 action = GHB_ACTION (ud->builder, "queue_pause_menu");
1150 gtk_action_set_sensitive (action, show_start);
1151 #if GTK_CHECK_VERSION(2, 16, 0)
1152 gtk_action_set_icon_name(action, "hb-play");
1153 gtk_action_set_label(action, "_Resume Queue");
1154 gtk_action_set_tooltip(action, "Resume Encoding");
1156 g_object_set_property(G_OBJECT(action), "icon-name",
1157 ghb_string_value("hb-play"));
1158 g_object_set_property(G_OBJECT(action), "label",
1159 ghb_string_value("_Resume Queue"));
1160 g_object_set_property(G_OBJECT(action), "tooltip",
1161 ghb_string_value("Resume Encoding"));
1166 gtk_action_set_sensitive (action, show_stop);
1167 #if GTK_CHECK_VERSION(2, 16, 0)
1168 gtk_action_set_icon_name(action, "hb-pause");
1169 gtk_action_set_label(action, "_Pause Queue");
1170 gtk_action_set_tooltip(action, "Pause Encoding");
1172 g_object_set_property(G_OBJECT(action), "icon-name",
1173 ghb_string_value("hb-pause"));
1174 g_object_set_property(G_OBJECT(action), "label",
1175 ghb_string_value("_Pause Queue"));
1176 g_object_set_property(G_OBJECT(action), "tooltip",
1177 ghb_string_value("Pause Encoding"));
1182 G_MODULE_EXPORT void
1183 queue_list_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, GtkCellRenderer *cell)
1185 GtkTreeViewColumn *column;
1188 column = gtk_tree_view_get_column (GTK_TREE_VIEW(widget), 0);
1189 width = gtk_tree_view_column_get_width(column);
1190 g_debug("col width %d alloc width %d", width, allocation->width);
1191 // Set new wrap-width. Shave a little off to accomidate the icons
1192 // that share this column.
1193 if (width >= 564) // Don't allow below a certain size
1194 g_object_set(cell, "wrap-width", width-70, NULL);
1197 G_MODULE_EXPORT void
1198 queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1201 gboolean running = FALSE;
1206 state = ghb_get_queue_state();
1207 if (state & (GHB_STATE_WORKING | GHB_STATE_SEARCHING |
1208 GHB_STATE_SCANNING | GHB_STATE_MUXING))
1210 ghb_cancel_encode(ud, "You are currently encoding. "
1211 "What would you like to do?");
1215 count = ghb_array_len(ud->queue);
1216 for (ii = 0; ii < count; ii++)
1218 js = ghb_array_get_nth(ud->queue, ii);
1219 status = ghb_settings_get_int(js, "job_status");
1220 if ((status == GHB_QUEUE_RUNNING) ||
1221 (status == GHB_QUEUE_PENDING))
1229 // The queue has no running or pending jobs.
1230 // Add current settings to the queue, then run.
1234 if (state == GHB_STATE_IDLE)
1236 // Add the first pending queue item and start
1237 ud->current_job = ghb_start_next_job(ud, TRUE);
1241 G_MODULE_EXPORT void
1242 queue_pause_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1248 ghb_reload_queue(signal_user_data_t *ud)
1251 gint unfinished = 0;
1258 g_debug("ghb_reload_queue");
1261 pid = ghb_find_pid_file();
1265 queue = ghb_load_old_queue(pid);
1266 ghb_remove_old_queue_file(pid);
1267 // Look for unfinished entries
1268 count = ghb_array_len(queue);
1269 for (ii = 0; ii < count; ii++)
1271 settings = ghb_array_get_nth(queue, ii);
1272 status = ghb_settings_get_int(settings, "job_status");
1273 if (status != GHB_QUEUE_DONE && status != GHB_QUEUE_CANCELED)
1283 message = g_strdup_printf(
1284 "You have %d unfinished job%s in a saved queue.\n\n"
1285 "Would you like to reload %s?",
1287 (unfinished > 1) ? "s" : "",
1288 (unfinished > 1) ? "them" : "it");
1289 if (ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "No", "Yes"))
1291 GtkWidget *widget = GHB_WIDGET (ud->builder, "queue_window");
1292 gtk_widget_show (widget);
1293 widget = GHB_WIDGET (ud->builder, "show_queue");
1294 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), TRUE);
1297 // First get rid of any old items we don't want
1298 for (ii = count-1; ii >= 0; ii--)
1300 settings = ghb_array_get_nth(queue, ii);
1301 status = ghb_settings_get_int(settings, "job_status");
1302 if (status == GHB_QUEUE_DONE || status == GHB_QUEUE_CANCELED)
1304 GValue *old = ghb_array_get_nth(queue, ii);
1305 ghb_value_free(old);
1306 ghb_array_remove(queue, ii);
1309 count = ghb_array_len(queue);
1310 for (ii = 0; ii < count; ii++)
1312 settings = ghb_array_get_nth(queue, ii);
1313 ghb_settings_set_int(settings, "job_unique_id", 0);
1314 ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING);
1315 add_to_queue_list(ud, settings, NULL);
1317 ghb_queue_buttons_grey(ud);
1318 ghb_save_queue(ud->queue);
1322 ghb_value_free(queue);
1329 G_MODULE_EXPORT gboolean
1333 signal_user_data_t *ud)
1335 GtkTreeView *treeview;
1336 GtkTreeSelection *selection;
1337 GtkTreeModel *store;
1345 g_debug("queue_key_press_cb ()");
1346 if (event->keyval != GDK_Delete)
1348 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
1349 store = gtk_tree_view_get_model(treeview);
1351 selection = gtk_tree_view_get_selection (treeview);
1352 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1354 GtkTreePath *treepath;
1356 treepath = gtk_tree_model_get_path (store, &iter);
1357 // Find the entry in the queue
1358 indices = gtk_tree_path_get_indices (treepath);
1360 // Can only free the treepath After getting what I need from
1361 // indices since this points into treepath somewhere.
1362 gtk_tree_path_free (treepath);
1363 if (row < 0) return FALSE;
1364 if (row >= ghb_array_len(ud->queue))
1366 settings = ghb_array_get_nth(ud->queue, row);
1367 status = ghb_settings_get_int(settings, "job_status");
1368 if (status == GHB_QUEUE_RUNNING)
1370 // Ask if wants to stop encode.
1371 if (!ghb_cancel_encode2(ud, NULL))
1375 unique_id = ghb_settings_get_int(settings, "job_unique_id");
1376 ghb_remove_job(unique_id);
1378 // Remove the selected item
1379 gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
1380 // Remove the corresponding item from the queue list
1381 GValue *old = ghb_array_get_nth(ud->queue, row);
1382 ghb_value_free(old);
1383 ghb_array_remove(ud->queue, row);
1384 ghb_save_queue(ud->queue);
1390 GValue *ghb_queue_edit_settings = NULL;
1392 G_MODULE_EXPORT void
1393 queue_edit_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1395 GtkTreeView *treeview;
1396 GtkTreeSelection *selection;
1397 GtkTreeModel *store;
1403 g_debug("queue_key_press_cb ()");
1404 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
1405 store = gtk_tree_view_get_model(treeview);
1407 selection = gtk_tree_view_get_selection (treeview);
1408 if (gtk_tree_selection_get_selected(selection, &store, &iter))
1410 GtkTreePath *treepath;
1412 treepath = gtk_tree_model_get_path (store, &iter);
1413 // Find the entry in the queue
1414 indices = gtk_tree_path_get_indices (treepath);
1416 // Can only free the treepath After getting what I need from
1417 // indices since this points into treepath somewhere.
1418 gtk_tree_path_free (treepath);
1419 if (row < 0) return;
1420 if (row >= ghb_array_len(ud->queue))
1422 ghb_queue_edit_settings = ghb_array_get_nth(ud->queue, row);
1423 status = ghb_settings_get_int(ghb_queue_edit_settings, "job_status");
1424 if (status == GHB_QUEUE_PENDING)
1426 // Remove the selected item
1427 gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
1428 // Remove the corresponding item from the queue list
1429 ghb_array_remove(ud->queue, row);
1433 ghb_queue_edit_settings = ghb_value_dup(ghb_queue_edit_settings);
1436 source = ghb_settings_get_string(ghb_queue_edit_settings, "source");
1437 ghb_do_scan(ud, source, 0, FALSE);