]> granicus.if.org Git - handbrake/commitdiff
LinGui: use libhb to initialize job...
authorjstebbins <jstebbins.hb@gmail.com>
Wed, 27 May 2015 17:14:42 +0000 (17:14 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Wed, 27 May 2015 17:14:42 +0000 (17:14 +0000)
...and set some job settings as values change in the UI.  This
eliminates a large chunk of job setup code.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@7230 b64f7644-9d1e-0410-96f1-a4d463321fa5

17 files changed:
gtk/src/audiohandler.c
gtk/src/callbacks.c
gtk/src/ghb-3.12.ui
gtk/src/ghb-3.14.ui
gtk/src/ghb.ui
gtk/src/hb-backend.c
gtk/src/hb-backend.h
gtk/src/presets.c
gtk/src/presets.h
gtk/src/preview.c
gtk/src/queuehandler.c
gtk/src/queuehandler.h
gtk/src/settings.c
gtk/src/settings.h
gtk/src/subtitlehandler.c
libhb/preset.c
libhb/preset.h

index 067300f1c97279862c8553d78762c0c564be9201..68a114d268a9e931260f7bd852112309efb41be6 100644 (file)
@@ -31,43 +31,6 @@ static void ghb_adjust_audio_rate_combos(signal_user_data_t *ud);
 
 static gboolean block_updates = FALSE;
 
-static GhbValue *get_audio_settings(GhbValue *settings)
-{
-    GhbValue *audio, *job;
-    job = ghb_get_job_settings(settings);
-    audio = ghb_dict_get(job, "Audio");
-    if (audio == NULL)
-    {
-        audio = ghb_dict_new();
-        ghb_dict_set(job, "Audio", audio);
-    }
-    return audio;
-}
-
-GhbValue *ghb_get_audio_settings(GhbValue *settings)
-{
-    return get_audio_settings(settings);
-}
-
-
-static GhbValue *get_audio_list(GhbValue *settings)
-{
-    GhbValue *audio_dict, *audio_list = NULL;
-    audio_dict = get_audio_settings(settings);
-    audio_list = ghb_dict_get(audio_dict, "AudioList");
-    if (audio_list == NULL)
-    {
-        audio_list = ghb_array_new();
-        ghb_dict_set(audio_dict, "AudioList", audio_list);
-    }
-    return audio_list;
-}
-
-GhbValue *ghb_get_audio_list(GhbValue *settings)
-{
-    return get_audio_list(settings);
-}
-
 static void enable_quality_widget(signal_user_data_t *ud, int acodec)
 {
     GtkWidget *widget1, *widget2;
@@ -457,7 +420,7 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
 void ghb_sanitize_audio_tracks(signal_user_data_t *ud)
 {
     int ii;
-    GhbValue *alist = get_audio_list(ud->settings);
+    GhbValue *alist = ghb_get_job_audio_list(ud->settings);
     int count = ghb_array_len(alist);
 
     for (ii = 0; ii < count; ii++)
@@ -574,7 +537,7 @@ ghb_get_user_audio_lang(GhbValue *settings, const hb_title_t *title, gint track)
     GhbValue *audio_list, *asettings;
     const gchar *lang;
 
-    audio_list = get_audio_list(settings);
+    audio_list = ghb_get_job_audio_list(settings);
     if (ghb_array_len(audio_list) <= track)
         return "und";
     asettings = ghb_array_get(audio_list, track);
@@ -735,7 +698,7 @@ audio_get_selected_settings(signal_user_data_t *ud, int *index)
         // find audio settings
         if (row < 0) return NULL;
 
-        audio_list = get_audio_list(ud->settings);
+        audio_list = ghb_get_job_audio_list(ud->settings);
         if (row >= ghb_array_len(audio_list))
             return NULL;
 
@@ -921,7 +884,7 @@ ghb_audio_list_refresh_selected(signal_user_data_t *ud)
         gtk_tree_path_free(tp);
         if (row < 0) return;
 
-        audio_list = get_audio_list(ud->settings);
+        audio_list = ghb_get_job_audio_list(ud->settings);
         if (row >= ghb_array_len(audio_list))
             return;
 
@@ -945,7 +908,7 @@ audio_refresh_list_ui(signal_user_data_t *ud)
 
     tm_count = gtk_tree_model_iter_n_children(tm, NULL);
 
-    audio_list = get_audio_list(ud->settings);
+    audio_list = ghb_get_job_audio_list(ud->settings);
     count = ghb_array_len(audio_list);
     if (count != tm_count)
     {
@@ -1187,7 +1150,7 @@ audio_passthru_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
 
     ghb_widget_to_setting(ud->settings, widget);
     copy_mask = ghb_create_copy_mask(ud->settings);
-    audio = get_audio_settings(ud->settings);
+    audio = ghb_get_job_audio_settings(ud->settings);
     ghb_dict_set(audio, "CopyMask", copy_mask);
     ghb_clear_presets_selection(ud);
 }
@@ -1281,7 +1244,7 @@ ghb_clear_audio_list_settings(GhbValue *settings)
     GhbValue *audio_list;
 
     g_debug("clear_audio_list_settings ()");
-    audio_list = get_audio_list(settings);
+    audio_list = ghb_get_job_audio_list(settings);
     ghb_array_reset(audio_list);
 }
 
@@ -1375,7 +1338,7 @@ audio_list_selection_changed_cb(GtkTreeSelection *ts, signal_user_data_t *ud)
         gtk_tree_path_free(tp);
 
         if (row < 0) return;
-        audio_list = get_audio_list(ud->settings);
+        audio_list = ghb_get_job_audio_list(ud->settings);
         if (row >= 0 && row < ghb_array_len(audio_list))
             asettings = ghb_array_get(audio_list, row);
     }
@@ -1393,7 +1356,7 @@ audio_add_to_settings(GhbValue *settings, GhbValue *asettings)
 
     title_id = ghb_dict_get_int(settings, "title");
     title = ghb_lookup_title(title_id, &titleindex);
-    audio_list = get_audio_list(settings);
+    audio_list = ghb_get_job_audio_list(settings);
 
     int track = ghb_dict_get_int(asettings, "Track");
     aconfig = ghb_get_audio_info(title, track);
@@ -1420,8 +1383,8 @@ audio_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
     title = ghb_lookup_title(title_id, &titleindex);
 
     // Back up settings in case we need to revert.
-    audio_dict = get_audio_settings(ud->settings);
-    backup = ghb_value_dup(get_audio_list(ud->settings));
+    audio_dict = ghb_get_job_audio_settings(ud->settings);
+    backup = ghb_value_dup(ghb_get_job_audio_list(ud->settings));
     GhbValue *pref_audio = ghb_dict_get_value(ud->settings, "AudioList");
     asettings = audio_select_and_add_track(title, ud->settings, pref_audio,
                                            "und", 0, 0);
@@ -1508,9 +1471,9 @@ audio_edit_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
 
         gtk_tree_selection_select_iter(ts, &ti);
 
-        audio_dict = get_audio_settings(ud->settings);
+        audio_dict = ghb_get_job_audio_settings(ud->settings);
         // Back up settings in case we need to revert.
-        backup = ghb_value_dup(get_audio_list(ud->settings));
+        backup = ghb_value_dup(ghb_get_job_audio_list(ud->settings));
 
         // Pop up the edit dialog
         GtkResponseType response;
@@ -1567,7 +1530,7 @@ audio_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
             gtk_tree_selection_select_iter(ts, &nextIter);
         }
 
-        audio_list = get_audio_list(ud->settings);
+        audio_list = ghb_get_job_audio_list(ud->settings);
 
         // Get the row number
         indices = gtk_tree_path_get_indices (tp);
@@ -2215,7 +2178,7 @@ G_MODULE_EXPORT void
 audio_fallback_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
 {
     ghb_widget_to_setting(ud->settings, widget);
-    GhbValue *audio = get_audio_settings(ud->settings);
+    GhbValue *audio = ghb_get_job_audio_settings(ud->settings);
     ghb_dict_set(audio, "FallbackEncoder", ghb_value_dup(
                  ghb_dict_get(ud->settings, "AudioEncoderFallback")));
     audio_def_set_all_limits(ud);
index 5c51608809db02d630fd273e6af83807da4499a0..dc2db46b15b1d2f7e5e9fd5a620fa77233db4e27 100644 (file)
@@ -78,7 +78,6 @@
 #include "x264handler.h"
 
 static void load_all_titles(signal_user_data_t *ud, int titleindex);
-static void update_chapter_list_settings(GhbValue *settings);
 static GList* dvd_device_list();
 static void prune_logs(signal_user_data_t *ud);
 void ghb_notify_done(signal_user_data_t *ud);
@@ -1137,24 +1136,6 @@ check_chapter_markers(signal_user_data_t *ud)
     }
 }
 
-#if 0
-void
-show_settings(GhbValue *settings)
-{
-    GhbDictIter iter;
-    const gchar *key;
-    GhbValue *gval;
-
-    iter = ghb_dict_iter_init(settings);
-    while (ghb_dict_iter_next(settings, &iter, &key, &gval))
-    {
-        char *str = ghb_value_get_string_xform(gval);
-        printf("show key %s val %s\n", key, str);
-        g_free(str);
-    }
-}
-#endif
-
 void
 ghb_load_settings(signal_user_data_t * ud)
 {
@@ -1531,6 +1512,8 @@ dest_dir_set_cb(GtkFileChooserButton *dest_chooser, signal_user_data_t *ud)
     dest_dir = ghb_dict_get_string(ud->settings, "dest_dir");
     dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
     ghb_dict_set_string(ud->settings, "destination", dest);
+    GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
+    ghb_dict_set_string(dest_dict, "File", dest);
     g_free(dest);
     update_default_destination = TRUE;
 }
@@ -1550,6 +1533,8 @@ dest_file_changed_cb(GtkEntry *entry, signal_user_data_t *ud)
     dest_dir = ghb_dict_get_string(ud->settings, "dest_dir");
     dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
     ghb_dict_set_string(ud->settings, "destination", dest);
+    GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
+    ghb_dict_set_string(dest_dict, "File", dest);
     g_free(dest);
     update_default_destination = TRUE;
 }
@@ -1808,6 +1793,16 @@ ghb_update_title_info(signal_user_data_t *ud)
     update_scale_info(ud);
 }
 
+static void update_meta(GhbValue *settings, const char *name, const char *val)
+{
+    GhbValue *metadata = ghb_get_job_metadata_settings(settings);
+
+    if (val == NULL || val[0] == 0)
+        ghb_dict_remove(metadata, name);
+    else
+        ghb_dict_set_string(metadata, name, val);
+}
+
 void
 set_title_settings(signal_user_data_t *ud, GhbValue *settings)
 {
@@ -1870,34 +1865,44 @@ set_title_settings(signal_user_data_t *ud, GhbValue *settings)
         ghb_dict_set_int(settings, "angle_count", title->angle_count);
 
         ghb_dict_set_string(settings, "MetaName", title->name);
+        update_meta(settings, "Name", title->name);
         if (title->metadata)
         {
             if (title->metadata->name)
             {
                 ghb_dict_set_string(settings, "MetaName",
                     title->metadata->name);
+                update_meta(settings, "Name", title->metadata->name);
             }
             ghb_dict_set_string(settings, "MetaArtist",
                     title->metadata->artist);
+            update_meta(settings, "Artist", title->metadata->artist);
             ghb_dict_set_string(settings, "MetaReleaseDate",
                     title->metadata->release_date);
+            update_meta(settings, "ReleaseDate", title->metadata->release_date);
             ghb_dict_set_string(settings, "MetaComment",
                     title->metadata->comment);
+            update_meta(settings, "Comment", title->metadata->comment);
             if (!title->metadata->name && title->metadata->album)
             {
                 ghb_dict_set_string(settings, "MetaName",
                     title->metadata->album);
+                update_meta(settings, "Name", title->metadata->album);
             }
             ghb_dict_set_string(settings, "MetaAlbumArtist",
                     title->metadata->album_artist);
+            update_meta(settings, "AlbumArtist", title->metadata->album_artist);
             ghb_dict_set_string(settings, "MetaGenre",
                     title->metadata->genre);
+            update_meta(settings, "Genre", title->metadata->genre);
             ghb_dict_set_string(settings, "MetaDescription",
                     title->metadata->description);
+            update_meta(settings, "Description", title->metadata->description);
             ghb_dict_set_string(settings, "MetaLongDescription",
                     title->metadata->long_description);
+            update_meta(settings, "LongDescription",
+                title->metadata->long_description);
         }
-        update_chapter_list_settings(settings);
     }
 
     set_destination_settings(ud, settings);
@@ -1910,6 +1915,8 @@ set_title_settings(signal_user_data_t *ud, GhbValue *settings)
     dest_dir = ghb_dict_get_string(settings, "dest_dir");
     dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
     ghb_dict_set_string(settings, "destination", dest);
+    GhbValue *dest_dict = ghb_get_job_dest_settings(ud->settings);
+    ghb_dict_set_string(dest_dict, "File", dest);
     g_free(dest);
 
     ghb_dict_set_int(settings, "preview_frame", 2);
@@ -2009,11 +2016,17 @@ ptop_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
     const hb_title_t * title;
     gboolean numeric = TRUE;
     GtkSpinButton *spin;
+    GhbValue *range;
 
     ghb_widget_to_setting(ud->settings, widget);
     ghb_check_dependency(ud, widget, NULL);
     ghb_live_reset(ud);
 
+    // Update type in Job
+    range = ghb_get_job_range_settings(ud->settings);
+    ghb_dict_set_string(range, "Type",
+                        ghb_dict_get_string(ud->settings, "PtoPType"));
+
     title_id = ghb_dict_get_int(ud->settings, "title");
     title = ghb_lookup_title(title_id, &titleindex);
     if (title == NULL)
@@ -2079,18 +2092,98 @@ setting_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
     ghb_live_reset(ud);
 }
 
+G_MODULE_EXPORT void
+title_angle_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+    ghb_widget_to_setting(ud->settings, widget);
+    ghb_check_dependency(ud, widget, NULL);
+    ghb_clear_presets_selection(ud);
+    ghb_live_reset(ud);
+
+    GhbValue *source = ghb_get_job_source_settings(ud->settings);
+    ghb_dict_set_int(source, "Angle", ghb_dict_get_int(ud->settings, "angle"));
+}
+
 G_MODULE_EXPORT gboolean
 meta_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
     signal_user_data_t *ud)
 {
+    const char *val;
+
     ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaLongDescription");
+    update_meta(ud->settings, "LongDescription", val);
     return FALSE;
 }
 
 G_MODULE_EXPORT void
-meta_setting_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+meta_name_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+    const char *val;
+
+    ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaName");
+    update_meta(ud->settings, "Name", val);
+}
+
+G_MODULE_EXPORT void
+meta_artist_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+    const char *val;
+
+    ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaArtist");
+    update_meta(ud->settings, "Artist", val);
+}
+
+G_MODULE_EXPORT void
+meta_album_artist_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+    const char *val;
+
+    ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaAlbumArtist");
+    update_meta(ud->settings, "AlbumArtist", val);
+}
+
+G_MODULE_EXPORT void
+meta_release_date_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+    const char *val;
+
+    ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaReleaseDate");
+    update_meta(ud->settings, "ReleaseDate", val);
+}
+
+G_MODULE_EXPORT void
+meta_comment_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
 {
+    const char *val;
+
     ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaComment");
+    update_meta(ud->settings, "Comment", val);
+}
+
+G_MODULE_EXPORT void
+meta_genre_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+    const char *val;
+
+    ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaGenre");
+    update_meta(ud->settings, "Genre", val);
+}
+
+G_MODULE_EXPORT void
+meta_description_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+    const char *val;
+
+    ghb_widget_to_setting(ud->settings, widget);
+    val = ghb_dict_get_string(ud->settings, "MetaDescription");
+    update_meta(ud->settings, "Description", val);
 }
 
 G_MODULE_EXPORT void
@@ -2108,6 +2201,16 @@ chapter_markers_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
     ghb_check_dependency(ud, widget, NULL);
     ghb_clear_presets_selection(ud);
     ghb_live_reset(ud);
+
+    GhbValue *dest;
+    int start, end;
+    bool markers;
+    dest     = ghb_get_job_dest_settings(ud->settings);
+    markers  = ghb_dict_get_bool(ud->settings, "ChapterMarkers");
+    start    = ghb_dict_get_int(ud->settings, "start_point");
+    end      = ghb_dict_get_int(ud->settings, "end_point");
+    markers &= (end > start);
+    ghb_dict_set_bool(dest, "ChapterMarkers", markers);
 }
 
 G_MODULE_EXPORT void
@@ -2165,17 +2268,6 @@ vquality_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
         set_destination(ud);
 }
 
-G_MODULE_EXPORT void
-http_opt_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
-{
-    ghb_widget_to_setting(ud->settings, widget);
-    ghb_check_dependency(ud, widget, NULL);
-    ghb_clear_presets_selection(ud);
-    ghb_live_reset(ud);
-    // AC3 is not allowed when Web optimized
-    ghb_grey_combo_options (ud);
-}
-
 G_MODULE_EXPORT gboolean
 ptop_input_cb(GtkWidget *widget, gdouble *val, signal_user_data_t *ud)
 {
@@ -2228,82 +2320,128 @@ ptop_output_cb(GtkWidget *widget, signal_user_data_t *ud)
 G_MODULE_EXPORT void
 start_point_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
 {
-    gint start, end;
+    int64_t start, end;
 
     ghb_widget_to_setting(ud->settings, widget);
+
+    GhbValue *dest  = ghb_get_job_dest_settings(ud->settings);
+    GhbValue *range = ghb_get_job_range_settings(ud->settings);
     if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
     {
         start = ghb_dict_get_int(ud->settings, "start_point");
-        end = ghb_dict_get_int(ud->settings, "end_point");
+        end   = ghb_dict_get_int(ud->settings, "end_point");
         if (start > end)
+        {
             ghb_ui_update(ud, "end_point", ghb_int_value(start));
+            end = start;
+        }
         ghb_check_dependency(ud, widget, NULL);
         if (check_name_template(ud, "{chapters}"))
             set_destination(ud);
         widget = GHB_WIDGET (ud->builder, "ChapterMarkers");
-        // End may have been changed above, get it again
-        end = ghb_dict_get_int(ud->settings, "end_point");
         gtk_widget_set_sensitive(widget, end > start);
         update_title_duration(ud);
+
+        bool markers;
+        markers  = ghb_dict_get_int(ud->settings, "ChapterMarkers");
+        markers &= (end > start);
+        ghb_dict_set_bool(dest, "ChapterMarkers", markers);
+        ghb_dict_set_int(range, "Start", start);
+        ghb_dict_set_int(range, "End", end);
     }
     else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
     {
         start = ghb_dict_get_int(ud->settings, "start_point");
-        end = ghb_dict_get_int(ud->settings, "end_point");
+        end   = ghb_dict_get_int(ud->settings, "end_point");
         if (start >= end)
+        {
             ghb_ui_update(ud, "end_point", ghb_int_value(start+1));
+            end = start + 1;
+        }
         ghb_check_dependency(ud, widget, NULL);
         update_title_duration(ud);
+
+        ghb_dict_set_int(range, "Start", start * 90000);
+        ghb_dict_set_int(range, "End", (end - start) * 90000);
     }
     else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
     {
         start = ghb_dict_get_int(ud->settings, "start_point");
-        end = ghb_dict_get_int(ud->settings, "end_point");
+        end   = ghb_dict_get_int(ud->settings, "end_point");
         if (start > end)
+        {
             ghb_ui_update(ud, "end_point", ghb_int_value(start));
+            end = start;
+        }
         ghb_check_dependency(ud, widget, NULL);
         update_title_duration(ud);
+
+        ghb_dict_set_int(range, "Start", start - 1);
+        ghb_dict_set_int(range, "End", end - 1 - start);
     }
 }
 
 G_MODULE_EXPORT void
 end_point_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
 {
-    gint start, end;
+    int64_t start, end;
 
     ghb_widget_to_setting(ud->settings, widget);
+
+    GhbValue *dest  = ghb_get_job_dest_settings(ud->settings);
+    GhbValue *range = ghb_get_job_range_settings(ud->settings);
     if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
     {
         start = ghb_dict_get_int(ud->settings, "start_point");
-        end = ghb_dict_get_int(ud->settings, "end_point");
+        end   = ghb_dict_get_int(ud->settings, "end_point");
         if (start > end)
+        {
             ghb_ui_update(ud, "start_point", ghb_int_value(end));
+            start = end;
+        }
         ghb_check_dependency(ud, widget, NULL);
         if (check_name_template(ud, "{chapters}"))
             set_destination(ud);
         widget = GHB_WIDGET (ud->builder, "ChapterMarkers");
-        // Start may have been changed above, get it again
-        start = ghb_dict_get_int(ud->settings, "start_point");
         gtk_widget_set_sensitive(widget, end > start);
         update_title_duration(ud);
+
+        bool markers;
+        markers  = ghb_dict_get_int(ud->settings, "ChapterMarkers");
+        markers &= (end > start);
+        ghb_dict_set_bool(dest, "ChapterMarkers", markers);
+        ghb_dict_set_int(range, "Start", start);
+        ghb_dict_set_int(range, "End", end);
     }
     else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
     {
         start = ghb_dict_get_int(ud->settings, "start_point");
-        end = ghb_dict_get_int(ud->settings, "end_point");
+        end   = ghb_dict_get_int(ud->settings, "end_point");
         if (start >= end)
+        {
             ghb_ui_update(ud, "start_point", ghb_int_value(end-1));
+            start = end - 1;
+        }
         ghb_check_dependency(ud, widget, NULL);
         update_title_duration(ud);
+
+        ghb_dict_set_int(range, "Start", start * 90000);
+        ghb_dict_set_int(range, "End", (end - start) * 90000);
     }
     else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
     {
         start = ghb_dict_get_int(ud->settings, "start_point");
-        end = ghb_dict_get_int(ud->settings, "end_point");
+        end   = ghb_dict_get_int(ud->settings, "end_point");
         if (start > end)
+        {
             ghb_ui_update(ud, "start_point", ghb_int_value(end));
+            start = end;
+        }
         ghb_check_dependency(ud, widget, NULL);
         update_title_duration(ud);
+
+        ghb_dict_set_int(range, "Start", start - 1);
+        ghb_dict_set_int(range, "End", end - 1 - start);
     }
 }
 
@@ -2777,7 +2915,7 @@ submit_job(signal_user_data_t *ud, GhbValue *settings)
     ghb_dict_set_int(settings, "job_unique_id", unique_id);
     ghb_dict_set_int(settings, "job_status", GHB_QUEUE_RUNNING);
     start_new_log(ud, settings);
-    ghb_add_job(settings, unique_id);
+    ghb_add_job(ghb_queue_handle(), settings, unique_id);
     ghb_start_queue();
 
     // Start queue activity spinner
@@ -3699,7 +3837,7 @@ chapter_refresh_list_row_ui(
 
     // Update row with settings data
     g_debug("Updating chapter row ui");
-    chapter = ghb_value_get_string(ghb_array_get(chapter_list, index));
+    chapter = ghb_dict_get_string(ghb_array_get(chapter_list, index), "Name");
     duration = ghb_get_chapter_duration(title, index) / 90000;
     break_duration(duration, &hh, &mm, &ss);
     s_duration = g_strdup_printf("%02d:%02d:%02d", hh, mm, ss);
@@ -3746,7 +3884,7 @@ chapter_refresh_list_ui(signal_user_data_t *ud)
 
     title_id = ghb_dict_get_int(ud->settings, "title");
     title = ghb_lookup_title(title_id, &titleindex);
-    chapter_list = ghb_dict_get_value(ud->settings, "chapter_list");
+    chapter_list = ghb_get_job_chapter_list(ud->settings);
     count = ghb_array_len(chapter_list);
     if (count != tm_count)
     {
@@ -3769,21 +3907,6 @@ ghb_chapter_list_refresh_all(signal_user_data_t *ud)
     chapter_refresh_list_ui(ud);
 }
 
-static void
-update_chapter_list_settings(GhbValue *settings)
-{
-    GhbValue *chapters;
-    gint title_id, titleindex;
-    const hb_title_t *title;
-
-    g_debug("update_chapter_list_settings ()");
-    title_id = ghb_dict_get_int(settings, "title");
-    title = ghb_lookup_title(title_id, &titleindex);
-    chapters = ghb_get_chapters(title);
-    if (chapters)
-        ghb_dict_set(settings, "chapter_list", chapters);
-}
-
 static gint chapter_edit_key = 0;
 
 G_MODULE_EXPORT gboolean
@@ -3829,9 +3952,9 @@ chapter_edited_cb(
     const GhbValue *chapters;
     GhbValue *chapter;
 
-    chapters = ghb_dict_get_value(ud->settings, "chapter_list");
+    chapters = ghb_get_job_chapter_list(ud->settings);
     chapter = ghb_array_get(chapters, index-1);
-    ghb_string_value_set(chapter, text);
+    ghb_dict_set_string(chapter, "Name", text);
     if ((chapter_edit_key == GDK_KEY_Return || chapter_edit_key == GDK_KEY_Down) &&
         gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))
     {
index 95cc6521d699ebce1a708ed7ae1544f012b35093..e66881fad4d2abc25ad0e3ac87de058505a29dc6 100644 (file)
@@ -1170,7 +1170,7 @@ This is often the feature title of a DVD.</property>
                                 <property name="secondary_icon_activatable">False</property>
                                 <property name="adjustment">adjustment27</property>
                                 <property name="halign">end</property>
-                                <signal name="value-changed" handler="setting_widget_changed_cb" swapped="no"/>
+                                <signal name="value-changed" handler="title_angle_changed_cb" swapped="no"/>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -1498,7 +1498,7 @@ This is often the feature title of a DVD.</property>
 This allows a player to initiate playback before downloading the entire file.</property>
                                 <property name="halign">start</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="http_opt_changed_cb" swapped="no"/>
+                                <signal name="toggled" handler="setting_widget_changed_cb" swapped="no"/>
                               </object>
                               <packing>
                                 <property name="top_attach">1</property>
@@ -6214,7 +6214,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_name_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">0</property>
@@ -6251,7 +6251,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_artist_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">1</property>
@@ -6288,7 +6288,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_album_artist_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">2</property>
@@ -6325,7 +6325,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_release_date_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">3</property>
@@ -6362,7 +6362,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_comment_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">4</property>
@@ -6399,7 +6399,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_genre_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">5</property>
@@ -6436,7 +6436,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_description_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">6</property>
index 7380752173f5833e297e89baa8e9d9af2f03fb0d..9a3cf537dcc523af180001e94b7f4fa1d40e8c4c 100644 (file)
@@ -1171,7 +1171,7 @@ This is often the feature title of a DVD.</property>
                                 <property name="secondary_icon_activatable">False</property>
                                 <property name="adjustment">adjustment27</property>
                                 <property name="halign">end</property>
-                                <signal name="value-changed" handler="setting_widget_changed_cb" swapped="no"/>
+                                <signal name="value-changed" handler="title_angle_changed_cb" swapped="no"/>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -1499,7 +1499,7 @@ This is often the feature title of a DVD.</property>
 This allows a player to initiate playback before downloading the entire file.</property>
                                 <property name="halign">start</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="http_opt_changed_cb" swapped="no"/>
+                                <signal name="toggled" handler="setting_widget_changed_cb" swapped="no"/>
                               </object>
                               <packing>
                                 <property name="top_attach">1</property>
@@ -6218,7 +6218,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_name_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">0</property>
@@ -6255,7 +6255,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_artist_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">1</property>
@@ -6292,7 +6292,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_album_artist_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">2</property>
@@ -6329,7 +6329,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_release_date_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">3</property>
@@ -6366,7 +6366,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_comment_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">4</property>
@@ -6403,7 +6403,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_genre_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">5</property>
@@ -6440,7 +6440,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_description_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">6</property>
index 413d1637af2d32a18138d025c13068f70d7b565a..add5b6c6c72d799db54f6d56d26dd60f7263497e 100644 (file)
@@ -1170,7 +1170,7 @@ This is often the feature title of a DVD.</property>
                                 <property name="secondary_icon_activatable">False</property>
                                 <property name="adjustment">adjustment27</property>
                                 <property name="halign">end</property>
-                                <signal name="value-changed" handler="setting_widget_changed_cb" swapped="no"/>
+                                <signal name="value-changed" handler="title_angle_changed_cb" swapped="no"/>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -1498,7 +1498,7 @@ This is often the feature title of a DVD.</property>
 This allows a player to initiate playback before downloading the entire file.</property>
                                 <property name="halign">start</property>
                                 <property name="draw_indicator">True</property>
-                                <signal name="toggled" handler="http_opt_changed_cb" swapped="no"/>
+                                <signal name="toggled" handler="setting_widget_changed_cb" swapped="no"/>
                               </object>
                               <packing>
                                 <property name="top_attach">1</property>
@@ -6214,7 +6214,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_name_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">0</property>
@@ -6251,7 +6251,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_artist_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">1</property>
@@ -6288,7 +6288,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_album_artist_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">2</property>
@@ -6325,7 +6325,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_release_date_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">3</property>
@@ -6362,7 +6362,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_comment_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">4</property>
@@ -6399,7 +6399,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_genre_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">5</property>
@@ -6436,7 +6436,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="truncate_multiline">True</property>
                             <property name="primary_icon_activatable">False</property>
                             <property name="secondary_icon_activatable">False</property>
-                            <signal name="changed" handler="meta_setting_widget_changed_cb" swapped="no"/>
+                            <signal name="changed" handler="meta_description_changed_cb" swapped="no"/>
                           </object>
                           <packing>
                             <property name="top_attach">6</property>
index 90d25f3eecbbe0792af59704274a478a399dba62..29c0493b4a48696b9cae2e3c11e1dcc079ae0ffc 100644 (file)
@@ -36,6 +36,7 @@
 #include "videohandler.h"
 #include "x264handler.h"
 #include "preview.h"
+#include "presets.h"
 #include "values.h"
 #include "lang.h"
 #include "jansson.h"
@@ -2365,33 +2366,6 @@ ghb_find_subtitle_track(const hb_title_t * title, const gchar * lang, int start)
     return -1;
 }
 
-#if 0
-static void
-generic_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
-{
-    GtkTreeIter iter;
-    GtkListStore *store;
-    gint ii;
-
-    g_debug("generic_opts_set ()\n");
-    if (name == NULL || opts == NULL) return;
-    GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name));
-    store = GTK_LIST_STORE(gtk_combo_box_get_model (combo));
-    gtk_list_store_clear(store);
-    for (ii = 0; ii < opts->count; ii++)
-    {
-        gtk_list_store_append(store, &iter);
-        gtk_list_store_set(store, &iter,
-                           0, gettext(opts->map[ii].option),
-                           1, TRUE,
-                           2, opts->map[ii].shortOpt,
-                           3, opts->map[ii].ivalue,
-                           4, opts->map[ii].svalue,
-                           -1);
-    }
-}
-#endif
-
 static void
 small_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts)
 {
@@ -2666,80 +2640,6 @@ ghb_build_advanced_opts_string(GhbValue *settings)
     }
 }
 
-void ghb_set_video_encoder_opts(hb_dict_t *dict, GhbValue *js)
-{
-    gint vcodec = ghb_settings_video_encoder_codec(js, "VideoEncoder");
-    switch (vcodec)
-    {
-        case HB_VCODEC_X265:
-        case HB_VCODEC_X264:
-        {
-            if (vcodec == HB_VCODEC_X264 &&
-                ghb_dict_get_bool(js, "x264UseAdvancedOptions"))
-            {
-                const char *opts;
-                opts = ghb_dict_get_string(js, "x264Option");
-                hb_dict_set(dict, "Options", hb_value_string(opts));
-            }
-            else
-            {
-                const char *preset, *tune, *profile, *level, *opts;
-                GString *str = g_string_new("");
-                preset = ghb_dict_get_string(js, "VideoPreset");
-                tune = ghb_dict_get_string(js, "VideoTune");
-                profile = ghb_dict_get_string(js, "VideoProfile");
-                level = ghb_dict_get_string(js, "VideoLevel");
-                opts = ghb_dict_get_string(js, "VideoOptionExtra");
-                char *tunes;
-
-                g_string_append_printf(str, "%s", tune);
-                if (vcodec == HB_VCODEC_X264)
-                {
-                    if (ghb_dict_get_bool(js, "x264FastDecode"))
-                    {
-                        g_string_append_printf(str, "%s%s", str->str[0] ? "," : "", "fastdecode");
-                    }
-                    if (ghb_dict_get_bool(js, "x264ZeroLatency"))
-                    {
-                        g_string_append_printf(str, "%s%s", str->str[0] ? "," : "", "zerolatency");
-                    }
-                }
-                tunes = g_string_free(str, FALSE);
-
-                if (preset != NULL)
-                    hb_dict_set(dict, "Preset", hb_value_string(preset));
-                if (tunes != NULL && strcasecmp(tune, "none"))
-                    hb_dict_set(dict, "Tune", hb_value_string(tunes));
-                if (profile != NULL && strcasecmp(profile, "auto"))
-                    hb_dict_set(dict, "Profile", hb_value_string(profile));
-                if (level != NULL && strcasecmp(level, "auto"))
-                    hb_dict_set(dict, "Level", hb_value_string(level));
-                if (opts != NULL)
-                    hb_dict_set(dict, "Options", hb_value_string(opts));
-
-                g_free(tunes);
-            }
-        } break;
-
-        case HB_VCODEC_FFMPEG_MPEG2:
-        case HB_VCODEC_FFMPEG_MPEG4:
-        case HB_VCODEC_FFMPEG_VP8:
-        {
-            const char *opts;
-            opts = ghb_dict_get_string(js, "VideoOptionExtra");
-            if (opts != NULL && opts[0])
-            {
-                hb_dict_set(dict, "Options", hb_value_string(opts));
-            }
-        } break;
-
-        case HB_VCODEC_THEORA:
-        default:
-        {
-        } break;
-    }
-}
-
 void
 ghb_part_duration(const hb_title_t *title, gint sc, gint ec, gint *hh, gint *mm, gint *ss)
 {
@@ -2805,36 +2705,6 @@ ghb_get_chapter_start(const hb_title_t *title, gint chap)
     return start;
 }
 
-GhbValue*
-ghb_get_chapters(const hb_title_t *title)
-{
-    hb_chapter_t * chapter;
-    gint count, ii;
-    GhbValue *chapters = NULL;
-
-    chapters = ghb_array_new();
-
-    if (title == NULL) return chapters;
-    count = hb_list_count( title->list_chapter );
-    for (ii = 0; ii < count; ii++)
-    {
-        chapter = hb_list_item(title->list_chapter, ii);
-        if (chapter == NULL) break;
-        if (chapter->title == NULL || chapter->title[0] == 0)
-        {
-            gchar *str;
-            str = g_strdup_printf (_("Chapter %2d"), ii+1);
-            ghb_array_append(chapters, ghb_string_value_new(str));
-            g_free(str);
-        }
-        else
-        {
-            ghb_array_append(chapters, ghb_string_value_new(chapter->title));
-        }
-    }
-    return chapters;
-}
-
 void
 ghb_audio_bitrate_opts_filter(
     GtkComboBox *combo,
@@ -3504,6 +3374,11 @@ ghb_set_scale_settings(GhbValue *settings, gint mode)
     ghb_dict_set_int(settings, "PicturePARHeight", resultGeo.par.den);
     ghb_dict_set_int(settings, "PictureDisplayWidth", disp_width);
     ghb_dict_set_int(settings, "PictureDisplayHeight", resultGeo.height);
+
+    // Update Job PAR
+    GhbValue *par = ghb_get_job_par_settings(settings);
+    ghb_dict_set_int(par, "Num", resultGeo.par.num);
+    ghb_dict_set_int(par, "Den", resultGeo.par.den);
 }
 
 void
@@ -3780,7 +3655,7 @@ ghb_validate_subtitles(GhbValue *settings, GtkWindow *parent)
     gint count, ii, track;
     gboolean burned, one_burned = FALSE;
 
-    slist = ghb_get_subtitle_list(settings);
+    slist = ghb_get_job_subtitle_list(settings);
     count = ghb_array_len(slist);
     for (ii = 0; ii < count; ii++)
     {
@@ -3859,7 +3734,7 @@ ghb_validate_audio(GhbValue *settings, GtkWindow *parent)
     const GhbValue *audio_list;
     gint count, ii;
 
-    audio_list = ghb_get_audio_list(settings);
+    audio_list = ghb_get_job_audio_list(settings);
     count = ghb_array_len(audio_list);
     for (ii = 0; ii < count; ii++)
     {
@@ -3964,512 +3839,20 @@ ghb_validate_audio(GhbValue *settings, GtkWindow *parent)
     return TRUE;
 }
 
-static void
-add_job(hb_handle_t *h, GhbValue *js, gint unique_id)
+void
+ghb_add_job(hb_handle_t *h, GhbValue *js, gint unique_id)
 {
-    hb_dict_t * dict;
-    json_error_t error;
-
-    // Assumes that the UI has reduced geometry settings to only the
-    // necessary PAR value
-
-    const char *mux_name;
-    const hb_container_t *mux;
-    int mux_id;
-
-    mux_name = ghb_dict_get_string(js, "FileFormat");
-    mux = ghb_lookup_container_by_name(mux_name);
-
-    mux_id = mux->format;
-
-    int p_to_p = -1, range_seek_points = 0, chapter_markers = 0;
-    int64_t range_start = 0, range_end = 0;
-    range_start = ghb_dict_get_int(js, "start_frame") + 1;
-    const char *range_type = "chapter";
-    if (range_start != 0)
-    {
-        range_type = "preview";
-        GhbValue *prefs = ghb_dict_get_value(js, "Preferences");
-        range_seek_points = ghb_dict_get_int(prefs, "preview_count");
-        range_end = ghb_dict_get_int(prefs, "live_duration") * 90000LL;
-    }
-    else
-    {
-        chapter_markers = ghb_dict_get_bool(js, "ChapterMarkers");
-        p_to_p = ghb_settings_combo_int(js, "PtoPType");
-        switch (p_to_p)
-        {
-            default:
-            case 0: // Chapter range
-            {
-                range_type = "chapter";
-                range_start = ghb_dict_get_int(js, "start_point");
-                range_end  = ghb_dict_get_int(js, "end_point");
-                if (range_start == range_end)
-                    chapter_markers = 0;
-            } break;
-            case 1: // PTS range
-            {
-                double start, end;
-                range_type = "time";
-                start = ghb_dict_get_double(js, "start_point");
-                end   = ghb_dict_get_double(js, "end_point");
-                range_start = (int64_t)start * 90000;
-                range_end  = (int64_t)end   * 90000 - range_start;
-            } break;
-            case 2: // Frame range
-            {
-                range_type = "frame";
-                range_start = ghb_dict_get_int(js, "start_point") - 1;
-                range_end  = ghb_dict_get_int(js, "end_point")   - 1 -
-                              range_start;
-            } break;
-        }
-    }
-
-    const char *path = ghb_dict_get_string(js, "source");
-    int title_id = ghb_dict_get_int(js, "title");
-
-    int angle = ghb_dict_get_int(js, "angle");
-
-    hb_rational_t par;
-    par.num = ghb_dict_get_int(js, "PicturePARWidth");
-    par.den = ghb_dict_get_int(js, "PicturePARHeight");
-
-    int vcodec, grayscale;
-    vcodec = ghb_settings_video_encoder_codec(js, "VideoEncoder");
-    grayscale   = ghb_dict_get_bool(js, "VideoGrayScale");
-
-    dict = json_pack_ex(&error, 0,
-    "{"
-    // SequenceID
-    "s:o,"
-    // Destination {Mux, ChapterMarkers, ChapterList}
-    "s:{s:o, s:o, s[]},"
-    // Source {Path, Title, Angle}
-    "s:{s:o, s:o, s:o,},"
-    // PAR {Num, Den}
-    "s:{s:o, s:o},"
-    // Video {Codec}
-    "s:{s:o},"
-    // Metadata
-    "s:{},"
-    // Filters {Grayscale, FilterList []}
-    "s:{s:o, s:[]}"
-    "}",
-        "SequenceID",           hb_value_int(unique_id),
-        "Destination",
-            "Mux",              hb_value_int(mux_id),
-            "ChapterMarkers",   hb_value_bool(chapter_markers),
-            "ChapterList",
-        "Source",
-            "Path",             hb_value_string(path),
-            "Title",            hb_value_int(title_id),
-            "Angle",            hb_value_int(angle),
-        "PAR",
-            "Num",              hb_value_int(par.num),
-            "Den",              hb_value_int(par.den),
-        "Video",
-            "Encoder",          hb_value_int(vcodec),
-        "Metadata",
-        "Filters",
-            "Grayscale",        hb_value_bool(grayscale),
-            "FilterList"
-    );
-    if (dict == NULL)
-    {
-        g_warning("json pack job failure: %s", error.text);
-        return;
-    }
-    const char *dest = ghb_dict_get_string(js, "destination");
-    hb_dict_t *dest_dict = hb_dict_get(dict, "Destination");
-    if (dest != NULL)
-    {
-        hb_dict_set(dest_dict, "File", hb_value_string(dest));
-    }
-    if (mux_id & HB_MUX_MASK_MP4)
-    {
-        int mp4_optimize, ipod_atom = 0;
-        mp4_optimize = ghb_dict_get_bool(js, "Mp4HttpOptimize");
-        if (vcodec == HB_VCODEC_X264)
-        {
-            ipod_atom = ghb_dict_get_bool(js, "Mp4iPodCompatible");
-        }
-        hb_dict_t *mp4_dict;
-        mp4_dict = json_pack_ex(&error, 0, "{s:o, s:o}",
-            "Mp4Optimize",      hb_value_bool(mp4_optimize),
-            "IpodAtom",         hb_value_bool(ipod_atom));
-        if (mp4_dict == NULL)
-        {
-            g_warning("json pack mp4 failure: %s", error.text);
-            return;
-        }
-        hb_dict_set(dest_dict, "Mp4Options", mp4_dict);
-    }
-    hb_dict_t *source_dict = hb_dict_get(dict, "Source");
-    if (range_start || range_end)
-    {
-        hb_dict_t *range_dict = hb_dict_init();
-        hb_dict_set(range_dict, "Type", hb_value_string(range_type));
-        if (range_start)
-            hb_dict_set(range_dict, "Start", hb_value_int(range_start));
-        if (range_end)
-            hb_dict_set(range_dict, "End",   hb_value_int(range_end));
-        if (range_seek_points)
-        {
-            hb_dict_set(range_dict, "SeekPoints",
-                    hb_value_int(range_seek_points));
-        }
-        hb_dict_set(source_dict, "Range", range_dict);
-    }
-
-    hb_dict_t *video_dict = hb_dict_get(dict, "Video");
-    if (ghb_dict_get_bool(js, "vquality_type_constant"))
-    {
-        double vquality = ghb_dict_get_double(js, "VideoQualitySlider");
-        hb_dict_set(video_dict, "Quality", hb_value_double(vquality));
-    }
-    else if (ghb_dict_get_bool(js, "vquality_type_bitrate"))
-    {
-        int vbitrate, twopass, fastfirstpass;
-        vbitrate = ghb_dict_get_int(js, "VideoAvgBitrate");
-        twopass = ghb_dict_get_bool(js, "VideoTwoPass");
-        fastfirstpass = ghb_dict_get_bool(js, "VideoTurboTwoPass");
-        hb_dict_set(video_dict, "Bitrate", hb_value_int(vbitrate));
-        hb_dict_set(video_dict, "TwoPass", hb_value_bool(twopass));
-        hb_dict_set(video_dict, "Turbo", hb_value_bool(fastfirstpass));
-    }
-    ghb_set_video_encoder_opts(video_dict, js);
+    GhbValue *job;
+    char     *json_job;
 
-    hb_dict_t *meta_dict = hb_dict_get(dict, "Metadata");
-    const char * meta;
-
-    meta = ghb_dict_get_string(js, "MetaName");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "Name", hb_value_string(meta));
-    }
-    meta = ghb_dict_get_string(js, "MetaArtist");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "Artist", hb_value_string(meta));
-    }
-    meta = ghb_dict_get_string(js, "MetaAlbumArtist");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "AlbumArtist", hb_value_string(meta));
-    }
-    meta = ghb_dict_get_string(js, "MetaReleaseDate");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "ReleaseDate", hb_value_string(meta));
-    }
-    meta = ghb_dict_get_string(js, "MetaComment");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "Comment", hb_value_string(meta));
-    }
-    meta = ghb_dict_get_string(js, "MetaGenre");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "Genre", hb_value_string(meta));
-    }
-    meta = ghb_dict_get_string(js, "MetaDescription");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "Description", hb_value_string(meta));
-    }
-    meta = ghb_dict_get_string(js, "MetaLongDescription");
-    if (meta && *meta)
-    {
-        hb_dict_set(meta_dict, "LongDescription", hb_value_string(meta));
-    }
-
-    // process chapter list
-    if (chapter_markers)
-    {
-        hb_value_array_t *chapter_list = hb_dict_get(dest_dict, "ChapterList");
-        GhbValue *chapters;
-        GhbValue *chapter;
-        gint chap;
-        gint count;
-
-        chapters = ghb_dict_get_value(js, "chapter_list");
-        count = ghb_array_len(chapters);
-        for(chap = 0; chap < count; chap++)
-        {
-            hb_dict_t *chapter_dict;
-            gchar *name;
-
-            name = NULL;
-            chapter = ghb_array_get(chapters, chap);
-            name = ghb_value_get_string_xform(chapter);
-            if (name == NULL)
-            {
-                name = g_strdup_printf (_("Chapter %2d"), chap+1);
-            }
-            chapter_dict = json_pack_ex(&error, 0, "{s:o}",
-                                    "Name", hb_value_string(name));
-            if (chapter_dict == NULL)
-            {
-                g_warning("json pack chapter failure: %s", error.text);
-                return;
-            }
-            hb_value_array_append(chapter_list, chapter_dict);
-            g_free(name);
-        }
-    }
-
-    // Create filter list
-    hb_dict_t *filters_dict = hb_dict_get(dict, "Filters");
-    hb_value_array_t *filter_list = hb_dict_get(filters_dict, "FilterList");
-    hb_dict_t *filter_dict;
-    char *filter_str;
-
-    // Crop scale filter
-    int width, height, crop[4];
-    width = ghb_dict_get_int(js, "scale_width");
-    height = ghb_dict_get_int(js, "scale_height");
-
-    crop[0] = ghb_dict_get_int(js, "PictureTopCrop");
-    crop[1] = ghb_dict_get_int(js, "PictureBottomCrop");
-    crop[2] = ghb_dict_get_int(js, "PictureLeftCrop");
-    crop[3] = ghb_dict_get_int(js, "PictureRightCrop");
-
-    filter_str = g_strdup_printf("%d:%d:%d:%d:%d:%d",
-                            width, height, crop[0], crop[1], crop[2], crop[3]);
-    filter_dict = json_pack_ex(&error, 0, "{s:o, s:o}",
-                            "ID",       hb_value_int(HB_FILTER_CROP_SCALE),
-                            "Settings", hb_value_string(filter_str));
-    if (filter_dict == NULL)
-    {
-        g_warning("json pack scale filter failure: %s", error.text);
-        return;
-    }
-    hb_value_array_append(filter_list, filter_dict);
-    g_free(filter_str);
-
-    // detelecine filter
-    gint detel = ghb_settings_combo_int(js, "PictureDetelecine");
-    if (detel)
-    {
-        const char *filter_str = NULL;
-        if (detel != 1)
-        {
-            if (detel_opts.map[detel].svalue != NULL)
-                filter_str = detel_opts.map[detel].svalue;
-        }
-        else
-        {
-            filter_str = ghb_dict_get_string(js, "PictureDetelecineCustom");
-        }
-        filter_dict = json_pack_ex(&error, 0, "{s:o}",
-                                "ID", hb_value_int(HB_FILTER_DETELECINE));
-        if (filter_dict == NULL)
-        {
-            g_warning("json pack detelecine filter failure: %s", error.text);
-            return;
-        }
-        if (filter_str != NULL)
-        {
-            hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
-        }
-        hb_value_array_append(filter_list, filter_dict);
-    }
-
-    // Decomb filter
-    gboolean decomb_deint;
-    gint decomb, deint;
-    decomb_deint = ghb_dict_get_bool(js, "PictureDecombDeinterlace");
-    decomb = ghb_settings_combo_int(js, "PictureDecomb");
-    deint = ghb_settings_combo_int(js, "PictureDeinterlace");
-    if (decomb_deint && decomb)
-    {
-        const char *filter_str = NULL;
-        if (decomb != 1)
-        {
-            if (decomb_opts.map[decomb].svalue != NULL)
-                filter_str = decomb_opts.map[decomb].svalue;
-        }
-        else
-        {
-            filter_str = ghb_dict_get_string(js, "PictureDecombCustom");
-        }
-        filter_dict = json_pack_ex(&error, 0, "{s:o}",
-                                "ID", hb_value_int(HB_FILTER_DECOMB));
-        if (filter_dict == NULL)
-        {
-            g_warning("json pack decomb filter failure: %s", error.text);
-            return;
-        }
-        if (filter_str != NULL)
-        {
-            hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
-        }
-        hb_value_array_append(filter_list, filter_dict);
-    }
-
-    // Deinterlace filter
-    if ( !decomb_deint && deint )
-    {
-        const char *filter_str = NULL;
-        if (deint != 1)
-        {
-            if (deint_opts.map[deint].svalue != NULL)
-                filter_str = deint_opts.map[deint].svalue;
-        }
-        else
-        {
-            filter_str = ghb_dict_get_string(js, "PictureDeinterlaceCustom");
-        }
-        filter_dict = json_pack_ex(&error, 0, "{s:o}",
-                                "ID", hb_value_int(HB_FILTER_DEINTERLACE));
-        if (filter_dict == NULL)
-        {
-            g_warning("json pack deinterlace filter failure: %s", error.text);
-            return;
-        }
-        if (filter_str != NULL)
-        {
-            hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
-        }
-        hb_value_array_append(filter_list, filter_dict);
-    }
-
-    // Denoise filter
-    if (strcmp(ghb_dict_get_string(js, "PictureDenoiseFilter"), "off"))
-    {
-        int filter_id = HB_FILTER_HQDN3D;
-        if (!strcmp(ghb_dict_get_string(js, "PictureDenoiseFilter"), "nlmeans"))
-            filter_id = HB_FILTER_NLMEANS;
-
-        if (!strcmp(ghb_dict_get_string(js, "PictureDenoisePreset"), "custom"))
-        {
-            const char *filter_str;
-            filter_str = ghb_dict_get_string(js, "PictureDenoiseCustom");
-            filter_dict = json_pack_ex(&error, 0, "{s:o}",
-                                       "ID", hb_value_int(filter_id));
-            if (filter_dict == NULL)
-            {
-                g_warning("json pack denoise filter failure: %s", error.text);
-                return;
-            }
-            if (filter_str != NULL)
-            {
-                hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
-            }
-            hb_value_array_append(filter_list, filter_dict);
-        }
-        else
-        {
-            const char *preset, *tune;
-            preset = ghb_dict_get_string(js, "PictureDenoisePreset");
-            tune = ghb_dict_get_string(js, "PictureDenoiseTune");
-            filter_str = hb_generate_filter_settings(filter_id, preset, tune);
-            if (filter_str == NULL)
-            {
-                g_warning("Invalid %s preset %s and/or tune %s",
-                    filter_id == HB_FILTER_HQDN3D ? "HQDN3D" : "NLMeans",
-                    preset, tune);
-            }
-            filter_dict = json_pack_ex(&error, 0, "{s:o}",
-                                       "ID", hb_value_int(filter_id));
-            if (filter_dict == NULL)
-            {
-                g_warning("json pack denoise filter failure: %s", error.text);
-                return;
-            }
-            if (filter_str != NULL)
-            {
-                hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
-            }
-            hb_value_array_append(filter_list, filter_dict);
-            g_free(filter_str);
-        }
-    }
-
-    // Deblock filter
-    gint deblock = ghb_dict_get_int(js, "PictureDeblock");
-    if( deblock >= 5 )
-    {
-        filter_str = g_strdup_printf("%d", deblock);
-        filter_dict = json_pack_ex(&error, 0, "{s:o}",
-                                   "ID", hb_value_int(HB_FILTER_DEBLOCK));
-        if (filter_dict == NULL)
-        {
-            g_warning("json pack deblock filter failure: %s", error.text);
-            return;
-        }
-        if (filter_str != NULL)
-        {
-            hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
-        }
-        hb_value_array_append(filter_list, filter_dict);
-        g_free(filter_str);
-    }
-
-    // VFR filter
-    gint vrate_den = ghb_settings_video_framerate_rate(js, "VideoFramerate");
-    gint cfr;
-    if (ghb_dict_get_bool(js, "VideoFrameratePFR"))
-        cfr = 2;
-    else if (ghb_dict_get_bool(js, "VideoFramerateCFR"))
-        cfr = 1;
-    else
-        cfr = 0;
-
-    // x264 zero latency requires CFR encode
-    if (ghb_dict_get_bool(js, "x264ZeroLatency"))
-    {
-        cfr = 1;
-        ghb_log("zerolatency x264 tune selected, forcing constant framerate");
-    }
-
-    if (vrate_den == 0)
-    {
-        filter_str = g_strdup_printf("%d", cfr);
-    }
-    else
-    {
-        filter_str = g_strdup_printf("%d:%d:%d", cfr, 27000000, vrate_den);
-    }
-    filter_dict = json_pack_ex(&error, 0, "{s:o, s:o}",
-                        "ID",       hb_value_int(HB_FILTER_VFR),
-                        "Settings", hb_value_string(filter_str));
-    if (filter_dict == NULL)
-    {
-        g_warning("json pack vfr filter failure: %s", error.text);
-        return;
-    }
-    hb_value_array_append(filter_list, filter_dict);
-    g_free(filter_str);
-
-    // Create audio list
-    hb_dict_t *audios_dict = ghb_get_audio_settings(js);
-    hb_dict_set(dict, "Audio", ghb_value_dup(audios_dict));
-
-    GhbValue *subtitle_dict = ghb_get_subtitle_settings(js);
-    hb_dict_set(dict, "Subtitle", ghb_value_dup(subtitle_dict));
-
-    char *json_job = hb_value_get_json(dict);
-    hb_value_free(&dict);
+    job      = ghb_dict_get(js, "Job");
+    ghb_dict_set_int(job, "SequenceID", unique_id);
+    json_job = hb_value_get_json(job);
 
     hb_add_json(h, json_job);
     free(json_job);
 }
 
-void
-ghb_add_job(GhbValue *js, gint unique_id)
-{
-    add_job(h_queue, js, unique_id);
-}
-
-void
-ghb_add_live_job(GhbValue *js, gint unique_id)
-{
-    add_job(h_live, js, unique_id);
-}
-
 void
 ghb_remove_job(gint unique_id)
 {
index 84033cf65abc7a35f5774bc18b44d526717a5307..940a4340ad9d7a9f02026dcf7ce0f2a46f81a462 100644 (file)
@@ -90,13 +90,12 @@ float ghb_vquality_default(signal_user_data_t *ud);
 void ghb_combo_init(signal_user_data_t *ud);
 void ghb_backend_init(gint debug);
 void ghb_backend_close(void);
-void ghb_add_job(GhbValue *js, gint unique_id);
+void ghb_add_job(hb_handle_t *h, GhbValue *js, gint unique_id);
 void ghb_remove_job(gint unique_id);
 void ghb_start_queue(void);
 void ghb_stop_queue(void);
 void ghb_pause_queue(void);
 
-void ghb_add_live_job(GhbValue *js, gint unique_id);
 void ghb_start_live_encode();
 void ghb_stop_live_encode();
 
@@ -117,7 +116,6 @@ void ghb_par_init(signal_user_data_t *ud);
 void ghb_set_scale(signal_user_data_t *ud, gint mode);
 void ghb_set_scale_settings(GhbValue *settings, gint mode);
 void ghb_picture_settings_deps(signal_user_data_t *ud);
-GhbValue* ghb_get_chapters(const hb_title_t *title);
 gint64 ghb_get_chapter_duration(const hb_title_t *title, gint chap);
 gint64 ghb_get_chapter_start(const hb_title_t *title, gint chap);
 void ghb_part_duration(
index 9af4238032ccede87d3ab03efae92e7cda77abb9..d75f9f9ef7fea668a184da4703f7059d75630245 100644 (file)
@@ -289,14 +289,7 @@ ghb_preset_to_settings(GhbValue *settings, GhbValue *preset)
     vqtype = ghb_dict_get_int(settings, "VideoQualityType");
 
     // "Use max" or "strict anamorphic" imply autoscale
-    if (uses_pic == 2)
-    {
-        ghb_dict_set_bool(settings, "autoscale", TRUE);
-    }
-    else if (uses_pic == 1)
-    {
-        ghb_dict_set_bool(settings, "autoscale", FALSE);
-    }
+    ghb_dict_set_bool(settings, "autoscale", uses_pic == 2);
 
     // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant
     // *note: target is no longer used
@@ -1358,8 +1351,8 @@ GhbValue* ghb_create_copy_mask(GhbValue *settings)
 }
 
 // Translate internal values to preset key, value pairs
-static GhbValue*
-settings_to_preset(GhbValue *settings)
+GhbValue*
+ghb_settings_to_preset(GhbValue *settings)
 {
     GhbValue *preset = ghb_value_dup(settings);
 
@@ -1446,26 +1439,28 @@ settings_to_preset(GhbValue *settings)
         ghb_dict_remove(preset, "VideoLevel");
         ghb_dict_remove(preset, "VideoOptionExtra");
     }
+
+    GString *str = g_string_new("");
+    const char *sep = "";
     const char *tune = ghb_dict_get_string(preset, "VideoTune");
-    if (tune != NULL)
+    if (tune != NULL && strcasecmp(tune, "none"))
     {
-        GString *str = g_string_new("");
-        char *tunes;
-
         g_string_append_printf(str, "%s", tune);
-        if (ghb_dict_get_bool(preset, "x264FastDecode"))
-        {
-            g_string_append_printf(str, ",%s", "fastdecode");
-        }
-        if (ghb_dict_get_bool(preset, "x264ZeroLatency"))
-        {
-            g_string_append_printf(str, ",%s", "zerolatency");
-        }
-        tunes = g_string_free(str, FALSE);
-        ghb_dict_set_string(preset, "VideoTune", tunes);
-
-        g_free(tunes);
+        sep = ",";
+    }
+    if (ghb_dict_get_bool(preset, "x264FastDecode"))
+    {
+        g_string_append_printf(str, "%s%s", sep, "fastdecode");
+        sep = ",";
+    }
+    if (ghb_dict_get_bool(preset, "x264ZeroLatency"))
+    {
+        g_string_append_printf(str, "%s%s", sep, "zerolatency");
     }
+    char *tunes;
+    tunes = g_string_free(str, FALSE);
+    ghb_dict_set_string(preset, "VideoTune", tunes);
+    g_free(tunes);
 
     GhbValue *in_val, *out_val;
 
@@ -1563,7 +1558,7 @@ settings_save(signal_user_data_t *ud, hb_preset_index_t *path, const char *name)
             replace = TRUE;
         }
     }
-    dict = settings_to_preset(ud->settings);
+    dict = ghb_settings_to_preset(ud->settings);
     ghb_dict_set_string(dict, "PresetName", name);
     if (replace)
     {
index 9cb546ca7c9106784af10fa718297f0e31ef3a5a..3041c9d57d1c36f61cfe12635cb63d30097c042a 100644 (file)
@@ -45,5 +45,6 @@ void ghb_prefs_to_settings(GhbValue *settings);
 GhbValue* ghb_read_settings_file(const gchar *path);
 void ghb_write_settings_file(const gchar *path, GhbValue *dict);
 GhbValue* ghb_create_copy_mask(GhbValue *settings);
+GhbValue* ghb_settings_to_preset(GhbValue *settings);
 
 #endif // _GHB_PRESETS_H_
index 9f79486bf363e5fd65d28857e1418c52815adfec..b4bcc4fe2a46c5a2dcdd39e313729ac733d86b25 100644 (file)
@@ -39,6 +39,7 @@
 #include "hb-backend.h"
 #include "preview.h"
 #include "values.h"
+#include "queuehandler.h"
 #include "hb.h"
 
 #define PREVIEW_STATE_IMAGE 0
@@ -759,14 +760,25 @@ live_preview_start_cb(GtkWidget *xwidget, signal_user_data_t *ud)
     else
     {
         GhbValue *js;
+        GhbValue *range, *dest;
 
         ud->preview->encode_frame = frame;
         js = ghb_value_dup(ud->settings);
-        ghb_dict_set_string(js, "destination", name);
-        ghb_dict_set_int(js, "start_frame", ud->preview->frame);
+
+        ghb_finalize_job(js);
+        range = ghb_get_job_range_settings(js);
+        dest = ghb_get_job_dest_settings(js);
+
+        ghb_dict_set_string(dest, "File", name);
+        ghb_dict_set_string(range, "Type", "preview");
+        ghb_dict_set_int(range, "Start", ud->preview->frame);
+        ghb_dict_set_int(range, "End",
+            ghb_dict_get_int(ud->prefs, "live_duration") * 90000);
+        ghb_dict_set_int(range, "SeekPoints",
+            ghb_dict_get_int(ud->prefs, "preview_count"));
+
         ud->preview->live_id = 0;
-        ghb_dict_set(js, "Preferences", ghb_value_dup(ud->prefs));
-        ghb_add_live_job(js, ud->preview->live_id);
+        ghb_add_job(ghb_live_handle(), js, ud->preview->live_id);
         ghb_start_live_encode();
         ghb_value_free(&js);
     }
index 8e8a2b7ee4e869c9aa4c043991e6a17296cddd59..960b3a619284991a64ed942e0648766533a7b3a2 100644 (file)
@@ -535,7 +535,7 @@ add_to_queue_list(signal_user_data_t *ud, GhbValue *settings, GtkTreeIter *piter
     gint count, ii;
     const GhbValue *audio_list;
 
-    audio_list = ghb_get_audio_list(settings);
+    audio_list = ghb_get_job_audio_list(settings);
     count = ghb_array_len(audio_list);
     if (count == 1)
     {
@@ -601,7 +601,7 @@ add_to_queue_list(signal_user_data_t *ud, GhbValue *settings, GtkTreeIter *piter
     const GhbValue *sub_dict, *sub_list, *sub_search;
     gboolean search;
 
-    sub_dict = ghb_get_subtitle_settings(settings);
+    sub_dict = ghb_get_job_subtitle_settings(settings);
     sub_list = ghb_dict_get(sub_dict, "SubtitleList");
     sub_search = ghb_dict_get(sub_dict, "Search");
     search = ghb_dict_get_bool(sub_search, "Enable");
@@ -1040,6 +1040,43 @@ validate_settings(signal_user_data_t *ud, GhbValue *settings, gint batch)
     return TRUE;
 }
 
+void ghb_finalize_job(GhbValue *settings)
+{
+    GhbValue *preset, *job;
+
+    preset = ghb_settings_to_preset(settings);
+    job    = ghb_dict_get(settings, "Job");
+
+    // Apply selected preset settings
+    hb_preset_apply_mux(preset, job);
+    hb_preset_apply_video(preset, job);
+    hb_preset_apply_filters(preset, job);
+
+    // Add scale filter since the above does not
+    GhbValue *filter_list, *filter_dict;
+    int width, height, crop[4];
+    char *filter_str;
+
+    filter_list = ghb_get_job_filter_list(settings);
+    width = ghb_dict_get_int(settings, "scale_width");
+    height = ghb_dict_get_int(settings, "scale_height");
+
+    crop[0] = ghb_dict_get_int(settings, "PictureTopCrop");
+    crop[1] = ghb_dict_get_int(settings, "PictureBottomCrop");
+    crop[2] = ghb_dict_get_int(settings, "PictureLeftCrop");
+    crop[3] = ghb_dict_get_int(settings, "PictureRightCrop");
+
+    filter_str = g_strdup_printf("%d:%d:%d:%d:%d:%d",
+                            width, height, crop[0], crop[1], crop[2], crop[3]);
+    filter_dict = ghb_dict_new();
+    ghb_dict_set_int(filter_dict, "ID", HB_FILTER_CROP_SCALE);
+    ghb_dict_set_string(filter_dict, "Settings", filter_str);
+    hb_value_array_append(filter_list, filter_dict);
+    g_free(filter_str);
+
+    ghb_value_free(&preset);
+}
+
 static gboolean
 queue_add(signal_user_data_t *ud, GhbValue *settings, gint batch)
 {
@@ -1053,6 +1090,8 @@ queue_add(signal_user_data_t *ud, GhbValue *settings, gint batch)
     if (ud->queue == NULL)
         ud->queue = ghb_array_new();
 
+    ghb_finalize_job(settings);
+
     // Copy current prefs into settings
     // The job should run with the preferences that existed
     // when the job was added to the queue.
@@ -1417,6 +1456,8 @@ title_dest_file_cb(GtkWidget *widget, signal_user_data_t *ud)
     dest_dir = ghb_dict_get_string(settings, "dest_dir");
     dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
     ghb_dict_set_string(settings, "destination", dest);
+    GhbValue *dest_dict = ghb_get_job_dest_settings(settings);
+    ghb_dict_set_string(dest_dict, "File", dest);
 
     // Check if changing the destination file name resolves
     // a file name conflict.  Enable selection if so.
@@ -1451,6 +1492,8 @@ title_dest_dir_cb(GtkWidget *widget, signal_user_data_t *ud)
     dest_file = ghb_dict_get_string(settings, "dest_file");
     dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file);
     ghb_dict_set_string(settings, "destination", dest);
+    GhbValue *dest_dict = ghb_get_job_dest_settings(settings);
+    ghb_dict_set_string(dest_dict, "File", dest);
 
     // Check if changing the destination file name resolves
     // a file name conflict.  Enable selection if so.
index 2b1a1885004e8e921a1a1e71539a96036dab16e6..9ca8907f5945724a398eb293d16dfd7849b8db90 100644 (file)
@@ -31,5 +31,6 @@
 void ghb_queue_buttons_grey(signal_user_data_t *ud);
 gboolean ghb_reload_queue(signal_user_data_t *ud);
 void ghb_queue_remove_row(signal_user_data_t *ud, int row);
+void ghb_finalize_job(GhbValue *settings);
 
 #endif // _QUEUEHANDLER_H_
index 4fde72e7b0bf68278d06670deba34e1a7299517c..5a1ed6fb23e908a0cd8088be17dbf5a94ac67194 100644 (file)
@@ -61,6 +61,187 @@ GhbValue *ghb_get_job_settings(GhbValue *settings)
     return job;
 }
 
+GhbValue* ghb_get_job_dest_settings(GhbValue *settings)
+{
+    GhbValue *job  = ghb_get_job_settings(settings);
+    GhbValue *dest = ghb_dict_get(job, "Destination");
+    if (dest == NULL)
+    {
+        dest = ghb_dict_new();
+        ghb_dict_set(job, "Destination", dest);
+    }
+    return dest;
+}
+
+GhbValue* ghb_get_job_chapter_list(GhbValue *settings)
+{
+    GhbValue *dest     = ghb_get_job_dest_settings(settings);
+    GhbValue *chapters = ghb_dict_get(dest, "ChapterList");
+    if (chapters == NULL)
+    {
+        chapters = ghb_array_new();
+        ghb_dict_set(dest, "ChapterList", chapters);
+    }
+    return chapters;
+}
+
+GhbValue* ghb_get_job_mp4_settings(GhbValue *settings)
+{
+    GhbValue *dest = ghb_get_job_dest_settings(settings);
+    GhbValue *mp4  = ghb_dict_get(dest, "Mp4Options");
+    if (mp4 == NULL)
+    {
+        mp4 = ghb_dict_new();
+        ghb_dict_set(dest, "Mp4Options", mp4);
+    }
+    return mp4;
+}
+
+GhbValue* ghb_get_job_source_settings(GhbValue *settings)
+{
+    GhbValue *job    = ghb_get_job_settings(settings);
+    GhbValue *source = ghb_dict_get(job, "Source");
+    if (source == NULL)
+    {
+        source = ghb_dict_new();
+        ghb_dict_set(job, "Source", source);
+    }
+    return source;
+}
+
+GhbValue* ghb_get_job_range_settings(GhbValue *settings)
+{
+    GhbValue *source = ghb_get_job_source_settings(settings);
+    GhbValue *range  = ghb_dict_get(source, "Range");
+    if (range == NULL)
+    {
+        range = ghb_dict_new();
+        ghb_dict_set(source, "Range", range);
+    }
+    return range;
+}
+
+GhbValue* ghb_get_job_par_settings(GhbValue *settings)
+{
+    GhbValue *job = ghb_get_job_settings(settings);
+    GhbValue *par = ghb_dict_get(job, "PAR");
+    if (par == NULL)
+    {
+        par = ghb_dict_new();
+        ghb_dict_set(job, "PAR", par);
+    }
+    return par;
+}
+
+GhbValue* ghb_get_job_video_settings(GhbValue *settings)
+{
+    GhbValue *job   = ghb_get_job_settings(settings);
+    GhbValue *video = ghb_dict_get(job, "Video");
+    if (video == NULL)
+    {
+        video = ghb_dict_new();
+        ghb_dict_set(job, "Video", video);
+    }
+    return video;
+}
+
+GhbValue *ghb_get_job_audio_settings(GhbValue *settings)
+{
+    GhbValue *job   = ghb_get_job_settings(settings);
+    GhbValue *audio = ghb_dict_get(job, "Audio");
+    if (audio == NULL)
+    {
+        audio = ghb_dict_new();
+        ghb_dict_set(job, "Audio", audio);
+    }
+    return audio;
+}
+
+GhbValue *ghb_get_job_audio_list(GhbValue *settings)
+{
+    GhbValue *audio_dict = ghb_get_job_audio_settings(settings);
+    GhbValue *audio_list = ghb_dict_get(audio_dict, "AudioList");
+    if (audio_list == NULL)
+    {
+        audio_list = ghb_array_new();
+        ghb_dict_set(audio_dict, "AudioList", audio_list);
+    }
+    return audio_list;
+}
+
+GhbValue *ghb_get_job_subtitle_settings(GhbValue *settings)
+{
+    GhbValue *job = ghb_get_job_settings(settings);
+    GhbValue *sub = ghb_dict_get(job, "Subtitle");
+    if (sub == NULL)
+    {
+        sub = ghb_dict_new();
+        ghb_dict_set(job, "Subtitle", sub);
+    }
+    return sub;
+}
+
+GhbValue *ghb_get_job_subtitle_list(GhbValue *settings)
+{
+    GhbValue *sub_dict = ghb_get_job_subtitle_settings(settings);
+    GhbValue *sub_list = ghb_dict_get(sub_dict, "SubtitleList");
+    if (sub_list == NULL)
+    {
+        sub_list = ghb_array_new();
+        ghb_dict_set(sub_dict, "SubtitleList", sub_list);
+    }
+    return sub_list;
+}
+
+GhbValue *ghb_get_job_subtitle_search(GhbValue *settings)
+{
+    GhbValue *sub_dict   = ghb_get_job_subtitle_settings(settings);
+    GhbValue *sub_search = ghb_dict_get(sub_dict, "Search");
+    if (sub_search == NULL)
+    {
+        sub_search = ghb_dict_new();
+        ghb_dict_set(sub_dict, "Search", sub_search);
+        ghb_dict_set_bool(sub_search, "Enable", 0);
+    }
+    return sub_search;
+}
+
+GhbValue* ghb_get_job_metadata_settings(GhbValue *settings)
+{
+    GhbValue *job  = ghb_get_job_settings(settings);
+    GhbValue *meta = ghb_dict_get(job, "Metadata");
+    if (meta == NULL)
+    {
+        meta = ghb_dict_new();
+        ghb_dict_set(job, "Metadata", meta);
+    }
+    return meta;
+}
+
+GhbValue* ghb_get_job_filter_settings(GhbValue *settings)
+{
+    GhbValue *job    = ghb_get_job_settings(settings);
+    GhbValue *filter = ghb_dict_get(job, "Filters");
+    if (filter == NULL)
+    {
+        filter = ghb_dict_new();
+        ghb_dict_set(job, "Filters", filter);
+    }
+    return filter;
+}
+
+GhbValue* ghb_get_job_filter_list(GhbValue *settings)
+{
+    GhbValue *filter = ghb_get_job_filter_settings(settings);
+    GhbValue *list   = ghb_dict_get(filter, "FilterList");
+    if (list == NULL)
+    {
+        list = ghb_dict_new();
+        ghb_dict_set(filter, "FilterList", list);
+    }
+    return list;
+}
+
 // Map widget names to setting keys
 // Widgets that map to settings have names
 // of this format: s_<setting key>
index c60d547f46911b6ceb95562e8dc13dcfc721b2f4..cffb04350c75102dab096a809f29b05902f051c0 100644 (file)
@@ -80,6 +80,23 @@ enum
     GHB_QUEUE_DONE,
 };
 
+GhbValue *ghb_get_job_settings(GhbValue *settings);
+GhbValue* ghb_get_job_source_settings(GhbValue *settings);
+GhbValue* ghb_get_job_range_settings(GhbValue *settings);
+GhbValue* ghb_get_job_par_settings(GhbValue *settings);
+GhbValue* ghb_get_job_dest_settings(GhbValue *settings);
+GhbValue* ghb_get_job_video_settings(GhbValue *settings);
+GhbValue* ghb_get_job_metadata_settings(GhbValue *settings);
+GhbValue* ghb_get_job_chapter_list(GhbValue *settings);
+GhbValue* ghb_get_job_mp4_settings(GhbValue *settings);
+GhbValue *ghb_get_job_audio_settings(GhbValue *settings);
+GhbValue *ghb_get_job_audio_list(GhbValue *settings);
+GhbValue *ghb_get_job_subtitle_settings(GhbValue *settings);
+GhbValue *ghb_get_job_subtitle_list(GhbValue *settings);
+GhbValue *ghb_get_job_subtitle_search(GhbValue *settings);
+GhbValue* ghb_get_job_filter_settings(GhbValue *settings);
+GhbValue* ghb_get_job_filter_list(GhbValue *settings);
+
 void ghb_settings_copy(
     GhbValue *settings, const gchar *key, const GhbValue *value);
 gint ghb_settings_combo_int(const GhbValue *settings, const gchar *key);
index a5e837a9d735455360be4f2c6341f846a05fe229..e2cde7dc461459ddb06c4bf223f6afa58b882ab2 100644 (file)
@@ -33,57 +33,6 @@ static void add_to_subtitle_list_ui(signal_user_data_t *ud, GhbValue *settings);
 static void clear_subtitle_list_settings(GhbValue *settings);
 static void clear_subtitle_list_ui(GtkBuilder *builder);
 
-static GhbValue *get_sub_settings(GhbValue *settings)
-{
-    GhbValue *sub, *job;
-    job = ghb_get_job_settings(settings);
-    sub = ghb_dict_get(job, "Subtitle");
-    if (sub == NULL)
-    {
-        sub = ghb_dict_new();
-        ghb_dict_set(job, "Subtitle", sub);
-    }
-    return sub;
-}
-
-GhbValue *ghb_get_subtitle_settings(GhbValue *settings)
-{
-    return get_sub_settings(settings);
-}
-
-
-static GhbValue *get_sub_list(GhbValue *settings)
-{
-    GhbValue *sub_dict, *sub_list = NULL;
-    sub_dict = get_sub_settings(settings);
-    sub_list = ghb_dict_get(sub_dict, "SubtitleList");
-    if (sub_list == NULL)
-    {
-        sub_list = ghb_array_new();
-        ghb_dict_set(sub_dict, "SubtitleList", sub_list);
-    }
-    return sub_list;
-}
-
-GhbValue *ghb_get_subtitle_list(GhbValue *settings)
-{
-    return get_sub_list(settings);
-}
-
-static GhbValue *get_sub_search(GhbValue *settings)
-{
-    GhbValue *sub_dict, *sub_search = NULL;
-    sub_dict = get_sub_settings(settings);
-    sub_search = ghb_dict_get(sub_dict, "Search");
-    if (sub_search == NULL)
-    {
-        sub_search = ghb_dict_new();
-        ghb_dict_set(sub_dict, "Search", sub_search);
-        ghb_dict_set_bool(sub_search, "Enable", 0);
-    }
-    return sub_search;
-}
-
 static int get_sub_source(GhbValue *settings, GhbValue *subsettings)
 {
     if (ghb_dict_get(subsettings, "SRT") != NULL)
@@ -218,8 +167,8 @@ subtitle_refresh_list_ui_from_settings(signal_user_data_t *ud, GhbValue *setting
 
     tm_count = gtk_tree_model_iter_n_children(tm, NULL);
 
-    subtitle_list = get_sub_list(settings);
-    subtitle_search = get_sub_search(settings);
+    subtitle_list = ghb_get_job_subtitle_list(settings);
+    subtitle_search = ghb_get_job_subtitle_search(settings);
     search = ghb_dict_get_bool(subtitle_search, "Enable");
     count = ghb_array_len(subtitle_list);
     if (count + search != tm_count)
@@ -260,7 +209,7 @@ subtitle_exclusive_burn_settings(GhbValue *settings, gint index)
     GhbValue *subsettings;
     gint ii, count;
 
-    subtitle_list = get_sub_list(settings);
+    subtitle_list = ghb_get_job_subtitle_list(settings);
     count = ghb_array_len(subtitle_list);
     for (ii = 0; ii < count; ii++)
     {
@@ -286,7 +235,7 @@ subtitle_exclusive_default_settings(GhbValue *settings, gint index)
     GhbValue *subtitle;
     gint ii, count;
 
-    subtitle_list = get_sub_list(settings);
+    subtitle_list = ghb_get_job_subtitle_list(settings);
     count = ghb_array_len(subtitle_list);
     for (ii = 0; ii < count; ii++)
     {
@@ -325,7 +274,7 @@ subtitle_add_to_settings(GhbValue *settings, GhbValue *subsettings)
     gboolean burn, forced, def;
     gint source;
 
-    subtitle_list = get_sub_list(settings);
+    subtitle_list = ghb_get_job_subtitle_list(settings);
     if (subtitle_list == NULL)
     {
         g_warning("No subtitle list!");
@@ -625,7 +574,7 @@ subtitle_get_selected_settings(signal_user_data_t *ud, int *index)
         row = indices[0];
         gtk_tree_path_free(tp);
 
-        subtitle_search = get_sub_search(ud->settings);
+        subtitle_search = ghb_get_job_subtitle_search(ud->settings);
         search = ghb_dict_get_bool(subtitle_search, "Enable");
         if (search)
         {
@@ -638,7 +587,7 @@ subtitle_get_selected_settings(signal_user_data_t *ud, int *index)
             row--;
         }
 
-        subtitle_list = get_sub_list(ud->settings);
+        subtitle_list = ghb_get_job_subtitle_list(ud->settings);
         if (row < 0 || row >= ghb_array_len(subtitle_list))
             return NULL;
 
@@ -984,8 +933,8 @@ clear_subtitle_list_settings(GhbValue *settings)
 {
     GhbValue *subtitle_list, *subtitle_search;
 
-    subtitle_list = get_sub_list(settings);
-    subtitle_search = get_sub_search(settings);
+    subtitle_list = ghb_get_job_subtitle_list(settings);
+    subtitle_search = ghb_get_job_subtitle_search(settings);
     ghb_array_reset(subtitle_list);
     ghb_dict_set_bool(subtitle_search, "Enable", 0);
 }
@@ -1070,7 +1019,7 @@ static gboolean subtitle_is_one_burned(GhbValue *settings)
     GhbValue *subtitle_list, *subsettings;
     int count, ii;
 
-    subtitle_list = get_sub_list(settings);
+    subtitle_list = ghb_get_job_subtitle_list(settings);
     if (subtitle_list == NULL)
         return FALSE;
 
@@ -1105,7 +1054,7 @@ subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
     }
 
     // Back up settings in case we need to revert.
-    backup = ghb_value_dup(get_sub_settings(ud->settings));
+    backup = ghb_value_dup(ghb_get_job_subtitle_settings(ud->settings));
     one_burned = subtitle_is_one_burned(ud->settings);
 
     const char *mux_id;
@@ -1153,14 +1102,14 @@ subtitle_add_fas_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
     GhbValue *subtitle_search, *backup;
 
-    subtitle_search = get_sub_search(ud->settings);
+    subtitle_search = ghb_get_job_subtitle_search(ud->settings);
     if (ghb_dict_get_bool(subtitle_search, "Enable"))
     {
         // Foreign audio search is already enabled
         return;
     }
 
-    backup = ghb_value_dup(get_sub_settings(ud->settings));
+    backup = ghb_value_dup(ghb_get_job_subtitle_settings(ud->settings));
 
     ghb_dict_set_bool(subtitle_search, "Enable", 1);
     ghb_dict_set_bool(subtitle_search, "Forced", 1);
@@ -1256,7 +1205,7 @@ ghb_subtitle_prune(signal_user_data_t *ud)
     gint ii;
     gboolean one_burned = FALSE;
 
-    subtitle_list = get_sub_list(ud->settings);
+    subtitle_list = ghb_get_job_subtitle_list(ud->settings);
     if (subtitle_list == NULL)
         return;
 
@@ -1555,7 +1504,7 @@ subtitle_edit_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
         gtk_tree_selection_select_iter(ts, &ti);
 
         // Back up settings in case we need to revert.
-        backup = ghb_value_dup(get_sub_settings(ud->settings));
+        backup = ghb_value_dup(ghb_get_job_subtitle_settings(ud->settings));
 
         // Pop up the edit dialog
         GtkResponseType response;
@@ -1612,8 +1561,8 @@ subtitle_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *u
             gtk_tree_selection_select_iter(ts, &nextIter);
         }
 
-        subtitle_search = get_sub_search(ud->settings);
-        subtitle_list = get_sub_list(ud->settings);
+        subtitle_search = ghb_get_job_subtitle_search(ud->settings);
+        subtitle_list = ghb_get_job_subtitle_list(ud->settings);
 
         // Get the row number
         indices = gtk_tree_path_get_indices(tp);
index 5035cacc95610e432ecf4c41184fa6b3f4de131c..4066b2bec40970c6e6af8fa353694fd6775d7af3 100644 (file)
@@ -305,21 +305,24 @@ static int get_job_mux(hb_dict_t *job_dict)
     return mux;
 }
 
-static int get_audio_copy_mask(const hb_dict_t * preset)
+static hb_value_t* get_audio_copy_mask(const hb_dict_t * preset, int *mask)
 {
-    int mask = HB_ACODEC_PASS_FLAG;
+    int copy_mask;
+    hb_value_array_t *out_copy_mask, *in_copy_mask;
 
-    hb_value_array_t *copy_mask_array = hb_dict_get(preset, "AudioCopyMask");
-    if (copy_mask_array != NULL)
+    if (mask != NULL)
+        *mask = 0;
+    in_copy_mask  = hb_dict_get(preset, "AudioCopyMask");
+    out_copy_mask = hb_value_array_init();
+    if (in_copy_mask != NULL)
     {
-        mask = HB_ACODEC_PASS_FLAG;
-        int count = hb_value_array_len(copy_mask_array);
-        int ii;
+        int count, ii;
+        count = hb_value_array_len(in_copy_mask);
         for (ii = 0; ii < count; ii++)
         {
             int codec;
             hb_value_t *value;
-            value = hb_value_array_get(copy_mask_array, ii);
+            value = hb_value_array_get(in_copy_mask, ii);
             if (hb_value_type(value) == HB_VALUE_TYPE_STRING)
             {
                 char *tmp = NULL;
@@ -335,7 +338,8 @@ static int get_audio_copy_mask(const hb_dict_t * preset)
                     hb_error("Invalid audio codec in autopassthru copy mask (%s)", s);
                     hb_error("Codec name is invalid or can not be copied");
                     free(tmp);
-                    return HB_ACODEC_INVALID;
+                    hb_value_free(&out_copy_mask);
+                    return NULL;
                 }
                 free(tmp);
             }
@@ -343,10 +347,14 @@ static int get_audio_copy_mask(const hb_dict_t * preset)
             {
                 codec = hb_value_get_int(value);
             }
-            mask |= codec;
+            hb_value_array_append(out_copy_mask, hb_value_string(
+                hb_audio_encoder_get_short_name(codec)));
+            copy_mask |= codec;
         }
     }
-    return mask;
+    if (mask != NULL)
+        *mask = copy_mask;
+    return out_copy_mask;
 }
 
 static hb_dict_t * source_audio_track_used(hb_dict_t *track_dict, int track)
@@ -535,7 +543,8 @@ static void add_audio_for_lang(hb_value_array_t *list, const hb_dict_t *preset,
             }
             // Save the encoder value before sanitizing.  This value is
             // useful to the frontends.
-            hb_dict_set(audio_dict, "PresetEncoder", hb_value_int(out_codec));
+            hb_dict_set(audio_dict, "PresetEncoder",
+                hb_value_string(hb_audio_encoder_get_short_name(out_codec)));
 
             hb_audio_config_t *aconfig;
             aconfig = hb_list_audio_config_item(title->list_audio, track);
@@ -639,13 +648,14 @@ int hb_preset_job_add_audio(hb_handle_t *h, int title_index,
         audio_dict = hb_dict_init();
         hb_dict_set(job_dict, "Audio", audio_dict);
     }
-    int copy_mask = get_audio_copy_mask(preset);
-    if (copy_mask == HB_ACODEC_INVALID)
+    int copy_mask;
+    hb_value_t *copy_mask_array = get_audio_copy_mask(preset, &copy_mask);
+    if (copy_mask_array == NULL)
     {
         return -1;
     }
     int fallback = 0;
-    hb_dict_set(audio_dict, "CopyMask", hb_value_int(copy_mask));
+    hb_dict_set(audio_dict, "CopyMask", copy_mask_array);
     hb_value_t *fallback_value = hb_dict_get(preset, "AudioEncoderFallback");
     if (fallback_value != NULL)
     {
@@ -1041,243 +1051,19 @@ static int get_video_framerate(hb_value_t *rate_value)
     return rate;
 }
 
-/**
- * Initialize an hb_job_t and return a hb_dict_t representation of the job.
- * This dict will have key/value pairs compatible with json jobs.
- * @param h             - Pointer to hb_handle_t instance that contains the
- *                        specified title_index
- * @param title_index   - Index of hb_title_t to use for job initialization.
- *                        Index comes from title->index or "Index" key
- *                        in json representation of a title.
- * @param preset        - Preset to initialize job with
- */
-hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
-                              const hb_dict_t *preset)
+int hb_preset_apply_filters(const hb_dict_t *preset, hb_dict_t *job_dict)
 {
-    hb_title_t *title = hb_find_title_by_index(h, title_index);
-    if (title == NULL)
-    {
-        hb_error("Invalid title index (%d)", title_index);
-        return NULL;
-    }
-
-    hb_job_t *job = hb_job_init(title);
-    hb_dict_t *job_dict = hb_job_to_dict(job);
-    hb_job_close(&job);
-
-    // Now apply preset settings to the job dict
-
-    hb_value_t *mux_value = hb_dict_get(preset, "FileFormat");
-    int mux;
-    if (hb_value_type(mux_value) == HB_VALUE_TYPE_STRING)
-    {
-        mux = hb_container_get_from_name(hb_value_get_string(mux_value));
-        if (mux == 0)
-            mux = hb_container_get_from_extension(
-                                            hb_value_get_string(mux_value));
-    }
-    else
-    {
-        mux = hb_value_get_int(mux_value);
-    }
-    hb_container_t *container = hb_container_get_from_format(mux);
-    if (container == NULL)
-    {
-        char *str = hb_value_get_string_xform(mux_value);
-        hb_error("Invalid container (%s)", str);
-        free(str);
-        goto fail;
-    }
-
-    hb_value_t *vcodec_value = hb_dict_get(preset, "VideoEncoder");
-    int vcodec;
-    if (hb_value_type(vcodec_value) == HB_VALUE_TYPE_STRING)
-    {
-        vcodec = hb_video_encoder_get_from_name(
-                    hb_value_get_string(vcodec_value));
-    }
-    else
-    {
-        vcodec = hb_value_get_int(vcodec_value);
-    }
-    hb_encoder_t *encoder = hb_video_encoder_get_from_codec(vcodec);
-    if (encoder == NULL)
-    {
-        char *str = hb_value_get_string_xform(vcodec_value);
-        hb_error("Invalid video encoder (%s)", str);
-        free(str);
-        goto fail;
-    }
-    if (!(encoder->muxers & mux))
-    {
-        hb_error("Incompatible video encoder (%s) for muxer (%s)",
-                  hb_video_encoder_get_name(vcodec),
-                  hb_container_get_name(mux));
-        goto fail;
-    }
-
-    int chapters;
-    chapters = hb_value_get_bool(hb_dict_get(preset, "ChapterMarkers"));
-    if (hb_list_count(title->list_chapter) <= 1)
-        chapters = 0;
-
-    // Set "Destination" settings in job
-    hb_dict_t *dest_dict = hb_dict_get(job_dict, "Destination");
-    hb_dict_set(dest_dict, "ChapterMarkers", hb_value_bool(chapters));
-    hb_dict_set(dest_dict, "Mux", hb_value_dup(mux_value));
-    if (mux & HB_MUX_MASK_MP4)
-    {
-        hb_dict_t *mp4_dict = hb_dict_init();
-        hb_dict_set(mp4_dict, "Mp4Optimize",
-                    hb_value_xform(hb_dict_get(preset, "Mp4HttpOptimize"),
-                                   HB_VALUE_TYPE_BOOL));
-        if (vcodec == HB_VCODEC_X264)
-        {
-            hb_dict_set(mp4_dict, "IpodAtom",
-                        hb_value_xform(hb_dict_get(preset, "Mp4iPodCompatible"),
-                                       HB_VALUE_TYPE_BOOL));
-        }
-        hb_dict_set(dest_dict, "Mp4Options", mp4_dict);
-    }
-    dest_dict = NULL;
-
-    // Calculate default job geometry settings
-    hb_geometry_t srcGeo, resultGeo;
-    hb_geometry_settings_t geo;
-    int keep_aspect;
-
-    srcGeo = title->geometry;
-    if (!hb_value_get_bool(hb_dict_get(preset, "PictureAutoCrop")))
-    {
-        geo.crop[0] = hb_value_get_int(hb_dict_get(preset, "PictureTopCrop"));
-        geo.crop[1] = hb_value_get_int(hb_dict_get(preset, "PictureBottomCrop"));
-        geo.crop[2] = hb_value_get_int(hb_dict_get(preset, "PictureLeftCrop"));
-        geo.crop[3] = hb_value_get_int(hb_dict_get(preset, "PictureRightCrop"));
-    }
-    else
-    {
-        memcpy(geo.crop, title->crop, sizeof(geo.crop));
-    }
-    geo.modulus = hb_value_get_int(hb_dict_get(preset, "PictureModulus"));
-    if (geo.modulus < 2)
-        geo.modulus = 2;
-    if (hb_value_get_bool(hb_dict_get(preset, "PictureLooseCrop")))
-    {
-        // Crop a few extra pixels to avoid scaling to fit Modulus
-        int extra1, extra2, crop_width, crop_height, width, height;
-
-        crop_width = srcGeo.width - geo.crop[2] - geo.crop[3];
-        crop_height = srcGeo.height - geo.crop[0] - geo.crop[1];
-        width = MULTIPLE_MOD_DOWN(crop_width, geo.modulus);
-        height = MULTIPLE_MOD_DOWN(crop_height, geo.modulus);
+    hb_value_t *filters_dict, *filter_list, *filter_dict;
+    char *filter_str;
 
-        extra1 = EVEN((crop_height - height) / 2);
-        extra2 = crop_height - height - extra1;
-        geo.crop[0] += extra1;
-        geo.crop[1] += extra2;
-        extra1 = EVEN((crop_width - width) / 2);
-        extra2 = crop_width - width - extra1;
-        geo.crop[2] += extra1;
-        geo.crop[3] += extra2;
-    }
-    hb_value_t *ana_mode_value = hb_dict_get(preset, "PicturePAR");
-    if (hb_value_type(ana_mode_value) == HB_VALUE_TYPE_STRING)
-    {
-        const char *s = hb_value_get_string(ana_mode_value);
-        if (!strcasecmp(s, "none"))
-            geo.mode = 0;
-        else if (!strcasecmp(s, "strict"))
-            geo.mode = 1;
-        else if (!strcasecmp(s, "custom"))
-            geo.mode = 3;
-        else // default loose
-            geo.mode = 2;
-    }
-    else
-    {
-        geo.mode = hb_value_get_int(hb_dict_get(preset, "PicturePAR"));
-    }
-    keep_aspect = hb_value_get_bool(hb_dict_get(preset, "PictureKeepRatio"));
-    if (geo.mode == HB_ANAMORPHIC_STRICT || geo.mode == HB_ANAMORPHIC_LOOSE)
-        keep_aspect = 1;
-    geo.keep = keep_aspect * HB_KEEP_DISPLAY_ASPECT;
-    geo.itu_par = hb_value_get_bool(hb_dict_get(preset, "PictureItuPAR"));
-    geo.maxWidth = hb_value_get_int(hb_dict_get(preset, "PictureWidth"));
-    geo.maxHeight = hb_value_get_int(hb_dict_get(preset, "PictureHeight"));
-    geo.geometry = title->geometry;
-    int width = hb_value_get_int(hb_dict_get(preset, "PictureForceWidth"));
-    int height = hb_value_get_int(hb_dict_get(preset, "PictureForceHeight"));
-    if (width > 0)
-    {
-        geo.geometry.width = width;
-        geo.keep |= HB_KEEP_WIDTH;
-    }
-    else
-    {
-        geo.geometry.width -= geo.crop[2] + geo.crop[3];
-    }
-    if (height > 0)
-    {
-        geo.geometry.height = height;
-        geo.keep |= HB_KEEP_HEIGHT;
-    }
-    else
-    {
-        geo.geometry.height -= geo.crop[0] + geo.crop[1];
-    }
-    if (geo.mode == HB_ANAMORPHIC_CUSTOM && !keep_aspect)
-    {
-        int dar_width;
-        dar_width = hb_value_get_int(hb_dict_get(preset, "PictureDARWidth"));
-        if (dar_width > 0)
-        {
-            geo.geometry.par.num = dar_width;
-            geo.geometry.par.num = geo.geometry.width;
-        }
-        else
-        {
-            geo.geometry.par.num =
-                hb_value_get_int(hb_dict_get(preset, "PicturePARWidth"));
-            geo.geometry.par.num =
-                hb_value_get_int(hb_dict_get(preset, "PicturePARHeight"));
-        }
-    }
-    hb_set_anamorphic_size2(&srcGeo, &geo, &resultGeo);
-    hb_dict_t *par_dict = hb_dict_get(job_dict, "PAR");
-    hb_dict_set(par_dict, "Num", hb_value_int(resultGeo.par.num));
-    hb_dict_set(par_dict, "Den", hb_value_int(resultGeo.par.den));
-    par_dict = NULL;
+    // Create new filters
+    filters_dict = hb_dict_init();
+    hb_dict_set(job_dict, "Filters", filters_dict);
+    filter_list = hb_value_array_init();
+    hb_dict_set(filters_dict, "FilterList", filter_list);
 
-    // Filters
-    hb_dict_t *filters_dict = hb_dict_get(job_dict, "Filters");
-    if (filters_dict == NULL)
-    {
-        filters_dict = hb_dict_init();
-        hb_dict_set(job_dict, "Filters", filters_dict);
-    }
     hb_dict_set(filters_dict, "Grayscale", hb_value_xform(
                 hb_dict_get(preset, "VideoGrayScale"), HB_VALUE_TYPE_BOOL));
-    hb_value_array_t *filter_list = hb_dict_get(filters_dict, "FilterList");
-    if (filter_list == NULL)
-    {
-        filter_list = hb_value_array_init();
-        hb_dict_set(filters_dict, "FilterList", filter_list);
-    }
-
-    hb_dict_t *filter_dict;
-    char *filter_str;
-
-    // Setup scale filter
-    filter_str = hb_strdup_printf("%d:%d:%d:%d:%d:%d",
-                                  resultGeo.width, resultGeo.height,
-                                  geo.crop[0], geo.crop[1],
-                                  geo.crop[2], geo.crop[3]);
-
-    filter_dict = hb_dict_init();
-    hb_dict_set(filter_dict, "ID", hb_value_int(HB_FILTER_CROP_SCALE));
-    hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
-    free(filter_str);
-    hb_value_array_append(filter_list, filter_dict);
 
     // Detelecine filter
     hb_value_t *detel_val = hb_dict_get(preset, "PictureDetelecine");
@@ -1301,7 +1087,7 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
             char *s = hb_value_get_string_xform(detel_val);
             hb_error("Invalid detelecine filter settings (%s)", s);
             free(s);
-            goto fail;
+            return -1;
         }
         else if (filter_str != hb_filter_off)
         {
@@ -1338,7 +1124,7 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
             char *s = hb_value_get_string_xform(decomb_val);
             hb_error("Invalid decomb filter settings (%s)", s);
             free(s);
-            goto fail;
+            return -1;
         }
         else if (filter_str != hb_filter_off)
         {
@@ -1371,7 +1157,7 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
             char *s = hb_value_get_string_xform(deint_val);
             hb_error("Invalid deinterlace filter settings (%s)", s);
             free(s);
-            goto fail;
+            return -1;
         }
         else if (filter_str != hb_filter_off)
         {
@@ -1414,7 +1200,7 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
                          denoise_preset,
                          denoise_tune ? "," : "",
                          denoise_tune ? denoise_tune : "");
-                goto fail;
+                return -1;
             }
             else if (filter_str != hb_filter_off)
             {
@@ -1438,7 +1224,7 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
         if (filter_str == NULL)
         {
             hb_error("Invalid deblock filter settings (%s)", deblock);
-            goto fail;
+            return -1;
         }
         else if (filter_str != hb_filter_off)
         {
@@ -1461,7 +1247,7 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
         if (filter_str == NULL)
         {
             hb_error("Invalid rotate filter settings (%s)", rotate);
-            goto fail;
+            return -1;
         }
         else if (filter_str != hb_filter_off)
         {
@@ -1481,7 +1267,7 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
         char *str = hb_value_get_string_xform(fr_value);
         hb_error("Invalid video framerate (%s)", str);
         free(str);
-        goto fail;
+        return -1;
     }
 
     int fr_mode;
@@ -1491,9 +1277,6 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
         !strcasecmp(hb_value_get_string(fr_mode_value), "pfr") ? 2 : 0) :
         hb_value_get_int(fr_mode_value);
 
-    if (hb_value_get_bool(hb_dict_get(preset, "x264ZeroLatency")))
-        fr_mode = 1;
-
     if (vrate_den == 0)
         filter_str = hb_strdup_printf("%d", fr_mode);
     else
@@ -1505,73 +1288,79 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
     hb_value_array_append(filter_list, filter_dict);
     free(filter_str);
 
-    // Video encoder settings
-    hb_dict_t *video_dict = hb_dict_get(job_dict, "Video");
-    hb_value_t *color_value;
+    return 0;
+}
+
+int hb_preset_apply_video(const hb_dict_t *preset, hb_dict_t *job_dict)
+{
+    hb_dict_t    *dest_dict, *video_dict, *qsv;
+    hb_value_t   *value, *vcodec_value, *color_value;
+    int           mux, vcodec, vqtype;
+    hb_encoder_t *encoder;
+
+    dest_dict    = hb_dict_get(job_dict, "Destination");
+    mux          = hb_container_get_from_name(hb_value_get_string(
+                                                hb_dict_get(dest_dict, "Mux")));
+    vcodec_value = hb_dict_get(preset, "VideoEncoder");
+    if (hb_value_type(vcodec_value) == HB_VALUE_TYPE_STRING)
+    {
+        vcodec = hb_video_encoder_get_from_name(
+                    hb_value_get_string(vcodec_value));
+    }
+    else
+    {
+        vcodec = hb_value_get_int(vcodec_value);
+    }
+    encoder = hb_video_encoder_get_from_codec(vcodec);
+    if (encoder == NULL)
+    {
+        char *str = hb_value_get_string_xform(vcodec_value);
+        hb_error("Invalid video encoder (%s)", str);
+        free(str);
+        return -1;
+    }
+    if (!(encoder->muxers & mux))
+    {
+        hb_error("Incompatible video encoder (%s) for muxer (%s)",
+                  hb_video_encoder_get_name(vcodec),
+                  hb_container_get_name(mux));
+        return -1;
+    }
+
+    video_dict = hb_dict_get(job_dict, "Video");
+    hb_dict_set(video_dict, "Encoder", hb_value_string(encoder->short_name));
+
     if ((color_value = hb_dict_get(preset, "VideoColorMatrixCode")) != NULL)
         hb_dict_set(video_dict, "ColorMatrixCode", hb_value_dup(color_value));
     hb_dict_set(video_dict, "Encoder", hb_value_dup(vcodec_value));
-    switch (vcodec)
-    {
-        case HB_VCODEC_X264:
-        {
-            if (hb_value_get_bool(
-                hb_dict_get(preset, "x264UseAdvancedOptions")))
-            {
-                hb_dict_set(video_dict, "Options",
-                            hb_value_dup(hb_dict_get(preset, "x264Option")));
-                break;
-            }
-        }
-        // Falling through to next case...
-
-        case HB_VCODEC_X265:
-        {
-            hb_value_t *value, *array;
-            if ((value = hb_dict_get(preset, "VideoPreset")) != NULL)
-                hb_dict_set(video_dict, "Preset", hb_value_dup(value));
-            if ((value = hb_dict_get(preset, "VideoProfile")) != NULL)
-                hb_dict_set(video_dict, "Profile", hb_value_dup(value));
-            if ((value = hb_dict_get(preset, "VideoLevel")) != NULL)
-                hb_dict_set(video_dict, "Level", hb_value_dup(value));
-            if ((value = hb_dict_get(preset, "VideoOptionExtra")) != NULL)
-                hb_dict_set(video_dict, "Options", hb_value_dup(value));
-            array = hb_value_array_init();
-            if ((value = hb_dict_get(preset, "VideoTune")) != NULL)
-                hb_value_array_append(array, hb_value_dup(value));
-            if (vcodec == HB_VCODEC_X264)
-            {
-                if (hb_value_get_bool(hb_dict_get(preset, "x264FastDecode")))
-                    hb_value_array_append(array, hb_value_string("fastdecode"));
-                if (hb_value_get_bool(hb_dict_get(preset, "x264ZeroLatency")))
-                    hb_value_array_append(array, hb_value_string("zerolatency"));
-            }
-            if (hb_value_array_len(array) > 0)
-            hb_dict_set(video_dict, "Tune",
-                        hb_value_xform(array, HB_VALUE_TYPE_STRING));
-            hb_value_decref(array);
-        } break;
-
-        case HB_VCODEC_FFMPEG_MPEG2:
-        case HB_VCODEC_FFMPEG_MPEG4:
-        case HB_VCODEC_FFMPEG_VP8:
-        {
-            hb_value_t *value;
-            if ((value = hb_dict_get(preset, "VideoOptionExtra")) != NULL)
-                hb_dict_set(video_dict, "Options", hb_value_dup(value));
-        } break;
 
-        case HB_VCODEC_THEORA:
-        default:
-        {
-        } break;
+    if (vcodec == HB_VCODEC_X264 &&
+        hb_value_get_bool(hb_dict_get(preset, "x264UseAdvancedOptions")))
+    {
+        hb_dict_set(video_dict, "Options",
+                    hb_value_dup(hb_dict_get(preset, "x264Option")));
+    }
+    else
+    {
+        if ((value = hb_dict_get(preset, "VideoPreset")) != NULL)
+            hb_dict_set(video_dict, "Preset", hb_value_dup(value));
+        if ((value = hb_dict_get(preset, "VideoProfile")) != NULL)
+            hb_dict_set(video_dict, "Profile", hb_value_dup(value));
+        if ((value = hb_dict_get(preset, "VideoLevel")) != NULL)
+            hb_dict_set(video_dict, "Level", hb_value_dup(value));
+        if ((value = hb_dict_get(preset, "VideoTune")) != NULL)
+            hb_dict_set(video_dict, "Tune", hb_value_dup(value));
+        if ((value = hb_dict_get(preset, "VideoOptionExtra")) != NULL)
+            hb_dict_set(video_dict, "Options", hb_value_dup(value));
     }
-    int vqtype = hb_value_get_int(hb_dict_get(preset, "VideoQualityType"));
+
+    vqtype = hb_value_get_int(hb_dict_get(preset, "VideoQualityType"));
     if (vqtype == 2)        // Constant quality
     {
         hb_dict_set(video_dict, "Quality",
                     hb_value_xform(hb_dict_get(preset, "VideoQualitySlider"),
                                    HB_VALUE_TYPE_DOUBLE));
+        hb_dict_set(video_dict, "Bitrate", hb_value_int(-1));
     }
     else if (vqtype == 1)   // ABR
     {
@@ -1584,13 +1373,17 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
         hb_dict_set(video_dict, "Turbo",
                     hb_value_xform(hb_dict_get(preset, "VideoTurboTwoPass"),
                                    HB_VALUE_TYPE_BOOL));
+        hb_dict_set(video_dict, "Quality", hb_value_double(-1.0));
     }
     else
     {
-        hb_value_t *value = hb_dict_get(preset, "VideoQualitySlider");
+        value = hb_dict_get(preset, "VideoQualitySlider");
         if (value != NULL && hb_value_get_double(value) >= 0)
+        {
             hb_dict_set(video_dict, "Quality",
                         hb_value_xform(value, HB_VALUE_TYPE_DOUBLE));
+            hb_dict_set(video_dict, "Bitrate", hb_value_int(-1));
+        }
         else
         {
             hb_dict_set(video_dict, "Bitrate",
@@ -1602,15 +1395,15 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
             hb_dict_set(video_dict, "Turbo",
                         hb_value_xform(hb_dict_get(preset, "VideoTurboTwoPass"),
                                        HB_VALUE_TYPE_BOOL));
+            hb_dict_set(video_dict, "Quality", hb_value_double(-1.0));
         }
     }
-    hb_dict_t *qsv = hb_dict_get(video_dict, "QSV");
+    qsv = hb_dict_get(video_dict, "QSV");
     if (qsv == NULL)
     {
         qsv = hb_dict_init();
         hb_dict_set(video_dict, "QSV", qsv);
     }
-    hb_value_t *value;
     if ((value = hb_dict_get(preset, "VideoQSVDecode")) != NULL)
     {
         hb_dict_set(qsv, "Decode",
@@ -1635,7 +1428,193 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
         hb_dict_set(video_dict, "HWDecode",
                     hb_value_xform(value, HB_VALUE_TYPE_BOOL));
     }
-    video_dict = NULL;
+
+    return 0;
+}
+
+int hb_preset_apply_mux(const hb_dict_t *preset, hb_dict_t *job_dict)
+{
+    hb_value_t *mux_value = hb_dict_get(preset, "FileFormat");
+    int mux;
+    if (hb_value_type(mux_value) == HB_VALUE_TYPE_STRING)
+    {
+        mux = hb_container_get_from_name(hb_value_get_string(mux_value));
+        if (mux == 0)
+            mux = hb_container_get_from_extension(
+                                            hb_value_get_string(mux_value));
+    }
+    else
+    {
+        mux = hb_value_get_int(mux_value);
+    }
+    hb_container_t *container = hb_container_get_from_format(mux);
+    if (container == NULL)
+    {
+        char *str = hb_value_get_string_xform(mux_value);
+        hb_error("Invalid container (%s)", str);
+        free(str);
+        return -1;
+    }
+
+    hb_dict_t *dest_dict = hb_dict_get(job_dict, "Destination");
+    hb_dict_set(dest_dict, "Mux", hb_value_string(container->short_name));
+
+    if (mux & HB_MUX_MASK_MP4)
+    {
+        hb_dict_t *mp4_dict = hb_dict_init();
+        hb_dict_set(mp4_dict, "Mp4Optimize",
+                    hb_value_xform(hb_dict_get(preset, "Mp4HttpOptimize"),
+                                   HB_VALUE_TYPE_BOOL));
+        hb_dict_set(mp4_dict, "IpodAtom",
+                    hb_value_xform(hb_dict_get(preset, "Mp4iPodCompatible"),
+                                   HB_VALUE_TYPE_BOOL));
+        hb_dict_set(dest_dict, "Mp4Options", mp4_dict);
+    }
+
+    return 0;
+}
+
+int hb_preset_apply_title(hb_handle_t *h, int title_index,
+                          const hb_dict_t *preset, hb_dict_t *job_dict)
+{
+    // Apply preset settings  that requires the title
+    hb_title_t *title = hb_find_title_by_index(h, title_index);
+    if (title == NULL)
+        return -1;
+
+    int chapters;
+    chapters = hb_value_get_bool(hb_dict_get(preset, "ChapterMarkers"));
+    if (title != NULL && hb_list_count(title->list_chapter) <= 1)
+        chapters = 0;
+
+    // Set "Destination" settings in job
+    hb_dict_t *dest_dict = hb_dict_get(job_dict, "Destination");
+    hb_dict_set(dest_dict, "ChapterMarkers", hb_value_bool(chapters));
+
+    hb_dict_t *filters_dict = hb_dict_get(job_dict, "Filters");
+    hb_value_array_t *filter_list = hb_dict_get(filters_dict, "FilterList");
+
+    // Calculate default job geometry settings
+    hb_geometry_t srcGeo, resultGeo;
+    hb_geometry_settings_t geo;
+    int keep_aspect;
+
+    srcGeo = title->geometry;
+    if (!hb_value_get_bool(hb_dict_get(preset, "PictureAutoCrop")))
+    {
+        geo.crop[0] = hb_value_get_int(hb_dict_get(preset, "PictureTopCrop"));
+        geo.crop[1] = hb_value_get_int(hb_dict_get(preset, "PictureBottomCrop"));
+        geo.crop[2] = hb_value_get_int(hb_dict_get(preset, "PictureLeftCrop"));
+        geo.crop[3] = hb_value_get_int(hb_dict_get(preset, "PictureRightCrop"));
+    }
+    else
+    {
+        memcpy(geo.crop, title->crop, sizeof(geo.crop));
+    }
+    geo.modulus = hb_value_get_int(hb_dict_get(preset, "PictureModulus"));
+    if (geo.modulus < 2)
+        geo.modulus = 2;
+    if (hb_value_get_bool(hb_dict_get(preset, "PictureLooseCrop")))
+    {
+        // Crop a few extra pixels to avoid scaling to fit Modulus
+        int extra1, extra2, crop_width, crop_height, width, height;
+
+        crop_width = srcGeo.width - geo.crop[2] - geo.crop[3];
+        crop_height = srcGeo.height - geo.crop[0] - geo.crop[1];
+        width = MULTIPLE_MOD_DOWN(crop_width, geo.modulus);
+        height = MULTIPLE_MOD_DOWN(crop_height, geo.modulus);
+
+        extra1 = EVEN((crop_height - height) / 2);
+        extra2 = crop_height - height - extra1;
+        geo.crop[0] += extra1;
+        geo.crop[1] += extra2;
+        extra1 = EVEN((crop_width - width) / 2);
+        extra2 = crop_width - width - extra1;
+        geo.crop[2] += extra1;
+        geo.crop[3] += extra2;
+    }
+    hb_value_t *ana_mode_value = hb_dict_get(preset, "PicturePAR");
+    if (hb_value_type(ana_mode_value) == HB_VALUE_TYPE_STRING)
+    {
+        const char *s = hb_value_get_string(ana_mode_value);
+        if (!strcasecmp(s, "none"))
+            geo.mode = 0;
+        else if (!strcasecmp(s, "strict"))
+            geo.mode = 1;
+        else if (!strcasecmp(s, "custom"))
+            geo.mode = 3;
+        else // default loose
+            geo.mode = 2;
+    }
+    else
+    {
+        geo.mode = hb_value_get_int(hb_dict_get(preset, "PicturePAR"));
+    }
+    keep_aspect = hb_value_get_bool(hb_dict_get(preset, "PictureKeepRatio"));
+    if (geo.mode == HB_ANAMORPHIC_STRICT || geo.mode == HB_ANAMORPHIC_LOOSE)
+        keep_aspect = 1;
+    geo.keep = keep_aspect * HB_KEEP_DISPLAY_ASPECT;
+    geo.itu_par = hb_value_get_bool(hb_dict_get(preset, "PictureItuPAR"));
+    geo.maxWidth = hb_value_get_int(hb_dict_get(preset, "PictureWidth"));
+    geo.maxHeight = hb_value_get_int(hb_dict_get(preset, "PictureHeight"));
+    geo.geometry = title->geometry;
+    int width = hb_value_get_int(hb_dict_get(preset, "PictureForceWidth"));
+    int height = hb_value_get_int(hb_dict_get(preset, "PictureForceHeight"));
+    if (width > 0)
+    {
+        geo.geometry.width = width;
+        geo.keep |= HB_KEEP_WIDTH;
+    }
+    else
+    {
+        geo.geometry.width -= geo.crop[2] + geo.crop[3];
+    }
+    if (height > 0)
+    {
+        geo.geometry.height = height;
+        geo.keep |= HB_KEEP_HEIGHT;
+    }
+    else
+    {
+        geo.geometry.height -= geo.crop[0] + geo.crop[1];
+    }
+    if (geo.mode == HB_ANAMORPHIC_CUSTOM && !keep_aspect)
+    {
+        int dar_width;
+        dar_width = hb_value_get_int(hb_dict_get(preset, "PictureDARWidth"));
+        if (dar_width > 0)
+        {
+            geo.geometry.par.num = dar_width;
+            geo.geometry.par.num = geo.geometry.width;
+        }
+        else
+        {
+            geo.geometry.par.num =
+                hb_value_get_int(hb_dict_get(preset, "PicturePARWidth"));
+            geo.geometry.par.num =
+                hb_value_get_int(hb_dict_get(preset, "PicturePARHeight"));
+        }
+    }
+    hb_set_anamorphic_size2(&srcGeo, &geo, &resultGeo);
+    hb_dict_t *par_dict = hb_dict_get(job_dict, "PAR");
+    hb_dict_set(par_dict, "Num", hb_value_int(resultGeo.par.num));
+    hb_dict_set(par_dict, "Den", hb_value_int(resultGeo.par.den));
+    par_dict = NULL;
+
+    hb_dict_t *filter_dict;
+    char *filter_str;
+
+    // Setup scale filter
+    filter_str = hb_strdup_printf("%d:%d:%d:%d:%d:%d",
+                                  resultGeo.width, resultGeo.height,
+                                  geo.crop[0], geo.crop[1],
+                                  geo.crop[2], geo.crop[3]);
+
+    filter_dict = hb_dict_init();
+    hb_dict_set(filter_dict, "ID", hb_value_int(HB_FILTER_CROP_SCALE));
+    hb_dict_set(filter_dict, "Settings", hb_value_string(filter_str));
+    free(filter_str);
+    hb_value_array_append(filter_list, filter_dict);
 
     // Audio settings
     if (hb_preset_job_add_audio(h, title_index, preset, job_dict) != 0)
@@ -1648,11 +1627,52 @@ hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
     {
         goto fail;
     }
+    return 0;
+
+fail:
+    return -1;
+}
+
+/**
+ * Initialize an hb_job_t and return a hb_dict_t representation of the job.
+ * This dict will have key/value pairs compatible with json jobs.
+ * @param h             - Pointer to hb_handle_t instance that contains the
+ *                        specified title_index
+ * @param title_index   - Index of hb_title_t to use for job initialization.
+ *                        Index comes from title->index or "Index" key
+ *                        in json representation of a title.
+ * @param preset        - Preset to initialize job with
+ */
+hb_dict_t* hb_preset_job_init(hb_handle_t *h, int title_index,
+                              const hb_dict_t *preset)
+{
+    hb_title_t *title = hb_find_title_by_index(h, title_index);
+    if (title == NULL)
+    {
+        hb_error("Invalid title index (%d)", title_index);
+        return NULL;
+    }
+
+    hb_job_t *job = hb_job_init(title);
+    hb_dict_t *job_dict = hb_job_to_dict(job);
+    hb_job_close(&job);
+
+    if (hb_preset_apply_mux(preset, job_dict) < 0)
+        goto fail;
+
+    if (hb_preset_apply_video(preset, job_dict) < 0)
+        goto fail;
+
+    if (hb_preset_apply_filters(preset, job_dict) < 0)
+        goto fail;
+
+    if (hb_preset_apply_title(h, title_index, preset, job_dict) < 0)
+        goto fail;
 
     return job_dict;
 
 fail:
-    hb_dict_free(&job_dict);
+    hb_value_free(&job_dict);
     return NULL;
 }
 
@@ -2099,6 +2119,28 @@ static void import_video(hb_value_t *preset)
     if ((val = hb_dict_get(preset, "x264OptionExtra")) != NULL)
         hb_dict_set(preset, "VideoOptionExtra", hb_value_dup(val));
 
+    // Remove invalid "none" tune from VideoTune.  Frontends should
+    // be removing this before saving a preset.
+    if ((val = hb_dict_get(preset, "VideoTune")) != NULL)
+    {
+        const char *tune;
+        tune = hb_value_get_string(val);
+        // "none" is not a valid tune, but is used by HandBrake
+        // to indicate no tune options.
+        if (tune != NULL && !strncasecmp(tune, "none", 4))
+        {
+            tune += 4;
+            if (tune[0] == ',')
+            {
+                tune++;
+            }
+        }
+        if (tune != NULL)
+        {
+            hb_dict_set(preset, "VideoTune", hb_value_string(tune));
+        }
+    }
+
     if (hb_value_get_int(hb_dict_get(preset, "VideoQualityType")) == 0)
     {
         // Target size no longer supported
index a24b45cf2d0059b29847c8e7436407b32368ccdc..d9ca233942fbc35f5c92ff613e68e5b9e1f8ea33 100644 (file)
@@ -114,6 +114,23 @@ hb_value_t * hb_presets_get(void);
 // Get list of all presets registered with libhb as json string
 char       * hb_presets_get_json(void);
 
+// Apply preset Muxer settings to a job
+int hb_preset_apply_mux(const hb_dict_t *preset, hb_dict_t *job_dict);
+
+// Apply preset Video settings to a job
+int hb_preset_apply_video(const hb_dict_t *preset, hb_dict_t *job_dict);
+
+// Apply preset Filter settings to a job
+//
+// Note that this does not apply scale filter settings.  A title is
+// required to set the default scale filter settings, so this filter
+// is applied in hb_preset_apply_title()
+int hb_preset_apply_filters(const hb_dict_t *preset, hb_dict_t *job_dict);
+
+// Apply preset settings that require a title to a job
+int hb_preset_apply_title(hb_handle_t *h, int title_index,
+                          const hb_dict_t *preset, hb_dict_t *job_dict);
+
 // Initialize a job from the given title and preset
 hb_dict_t  * hb_preset_job_init(hb_handle_t *h, int title_index,
                                 const hb_dict_t *preset);