diff options
author | jstebbins <[email protected]> | 2015-05-27 17:14:42 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2015-05-27 17:14:42 +0000 |
commit | f127b802bec8ca3394b155f15fde5519d04f4897 (patch) | |
tree | 77e9ea4dfafb8bac3a23ce01b0941fa74b04beeb | |
parent | 0863f72ab94e5ad4bb7652a5cbc6d2e7dc194420 (diff) |
LinGui: use libhb to initialize job...
...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
-rw-r--r-- | gtk/src/audiohandler.c | 67 | ||||
-rw-r--r-- | gtk/src/callbacks.c | 251 | ||||
-rw-r--r-- | gtk/src/ghb-3.12.ui | 18 | ||||
-rw-r--r-- | gtk/src/ghb-3.14.ui | 18 | ||||
-rw-r--r-- | gtk/src/ghb.ui | 18 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 647 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 4 | ||||
-rw-r--r-- | gtk/src/presets.c | 49 | ||||
-rw-r--r-- | gtk/src/presets.h | 1 | ||||
-rw-r--r-- | gtk/src/preview.c | 20 | ||||
-rw-r--r-- | gtk/src/queuehandler.c | 47 | ||||
-rw-r--r-- | gtk/src/queuehandler.h | 1 | ||||
-rw-r--r-- | gtk/src/settings.c | 181 | ||||
-rw-r--r-- | gtk/src/settings.h | 17 | ||||
-rw-r--r-- | gtk/src/subtitlehandler.c | 85 | ||||
-rw-r--r-- | libhb/preset.c | 680 | ||||
-rw-r--r-- | libhb/preset.h | 17 |
17 files changed, 923 insertions, 1198 deletions
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c index 067300f1c..68a114d26 100644 --- a/gtk/src/audiohandler.c +++ b/gtk/src/audiohandler.c @@ -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); diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index 5c5160880..dc2db46b1 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -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)) { diff --git a/gtk/src/ghb-3.12.ui b/gtk/src/ghb-3.12.ui index 95cc6521d..e66881fad 100644 --- a/gtk/src/ghb-3.12.ui +++ b/gtk/src/ghb-3.12.ui @@ -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> diff --git a/gtk/src/ghb-3.14.ui b/gtk/src/ghb-3.14.ui index 738075217..9a3cf537d 100644 --- a/gtk/src/ghb-3.14.ui +++ b/gtk/src/ghb-3.14.ui @@ -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> diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index 413d1637a..add5b6c6c 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -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> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 90d25f3ee..29c0493b4 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -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,513 +3839,21 @@ 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) { hb_job_t * job; diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 84033cf65..940a4340a 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -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( diff --git a/gtk/src/presets.c b/gtk/src/presets.c index 9af423803..d75f9f9ef 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -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) { diff --git a/gtk/src/presets.h b/gtk/src/presets.h index 9cb546ca7..3041c9d57 100644 --- a/gtk/src/presets.h +++ b/gtk/src/presets.h @@ -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_ diff --git a/gtk/src/preview.c b/gtk/src/preview.c index 9f79486bf..b4bcc4fe2 100644 --- a/gtk/src/preview.c +++ b/gtk/src/preview.c @@ -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); } diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index 8e8a2b7ee..960b3a619 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -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. diff --git a/gtk/src/queuehandler.h b/gtk/src/queuehandler.h index 2b1a18850..9ca8907f5 100644 --- a/gtk/src/queuehandler.h +++ b/gtk/src/queuehandler.h @@ -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_ diff --git a/gtk/src/settings.c b/gtk/src/settings.c index 4fde72e7b..5a1ed6fb2 100644 --- a/gtk/src/settings.c +++ b/gtk/src/settings.c @@ -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> diff --git a/gtk/src/settings.h b/gtk/src/settings.h index c60d547f4..cffb04350 100644 --- a/gtk/src/settings.h +++ b/gtk/src/settings.h @@ -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); diff --git a/gtk/src/subtitlehandler.c b/gtk/src/subtitlehandler.c index a5e837a9d..e2cde7dc4 100644 --- a/gtk/src/subtitlehandler.c +++ b/gtk/src/subtitlehandler.c @@ -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); diff --git a/libhb/preset.c b/libhb/preset.c index 5035cacc9..4066b2bec 100644 --- a/libhb/preset.c +++ b/libhb/preset.c @@ -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, ©_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 diff --git a/libhb/preset.h b/libhb/preset.h index a24b45cf2..d9ca23394 100644 --- a/libhb/preset.h +++ b/libhb/preset.h @@ -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); |