#include "settings.h"
#include "callbacks.h"
#include "subtitlehandler.h"
+#include "audiohandler.h"
+#include "x264handler.h"
#include "preview.h"
#include "values.h"
#include "lang.h"
}
}
+static options_map_t d_when_complete_opts[] =
+{
+ {"Do Nothing", "nothing", 0, "0"},
+ {"Show Notification", "notify", 1, "1"},
+ {"Put Computer To Sleep", "sleep", 2, "2"},
+ {"Shutdown Computer", "shutdown", 3, "3"},
+};
+combo_opts_t when_complete_opts =
+{
+ sizeof(d_when_complete_opts)/sizeof(options_map_t),
+ d_when_complete_opts
+};
+
static options_map_t d_par_opts[] =
{
{"Off", "0", 0, "0"},
d_logging_opts
};
+static options_map_t d_log_longevity_opts[] =
+{
+ {"Week", "week", 7, "7"},
+ {"Month", "month", 30, "30"},
+ {"Year", "year", 365, "365"},
+ {"Immortal", "immortal", 366, "366"},
+};
+combo_opts_t log_longevity_opts =
+{
+ sizeof(d_log_longevity_opts)/sizeof(options_map_t),
+ d_log_longevity_opts
+};
+
+static options_map_t d_appcast_update_opts[] =
+{
+ {"Never", "never", 0, "never"},
+ {"Daily", "daily", 1, "daily"},
+ {"Weekly", "weekly", 2, "weekly"},
+ {"Monthly", "monthly", 3, "monthly"},
+};
+combo_opts_t appcast_update_opts =
+{
+ sizeof(d_appcast_update_opts)/sizeof(options_map_t),
+ d_appcast_update_opts
+};
+
static options_map_t d_vqual_granularity_opts[] =
{
{"0.2", "0.2", 0.2, "0.2"},
{
{"MKV", "mkv", HB_MUX_MKV, "mkv"},
{"MP4", "mp4", HB_MUX_MP4, "mp4"},
- {"M4V", "m4v", HB_MUX_MP4, "m4v"},
};
combo_opts_t container_opts =
{
{"7", "7", 7, "7"},
{"8", "8", 8, "8"},
{"9", "9", 9, "9"},
+ {"10", "10", 10, "10"},
};
combo_opts_t subme_opts =
{
combo_name_map_t combo_name_map[] =
{
+ {"WhenComplete", &when_complete_opts},
{"PicturePAR", &par_opts},
{"PictureModulus", &alignment_opts},
{"LoggingLevel", &logging_opts},
+ {"LogLongevity", &log_longevity_opts},
+ {"check_updates", &appcast_update_opts},
{"VideoQualityGranularity", &vqual_granularity_opts},
{"FileFormat", &container_opts},
{"PictureDeinterlace", &deint_opts},
{NULL, NULL}
};
+const gchar *srt_codeset_table[] =
+{
+ "ANSI_X3.4-1968",
+ "ANSI_X3.4-1986",
+ "ANSI_X3.4",
+ "ANSI_X3.110-1983",
+ "ANSI_X3.110",
+ "ASCII",
+ "ECMA-114",
+ "ECMA-118",
+ "ECMA-128",
+ "ECMA-CYRILLIC",
+ "IEC_P27-1",
+ "ISO-8859-1",
+ "ISO-8859-2",
+ "ISO-8859-3",
+ "ISO-8859-4",
+ "ISO-8859-5",
+ "ISO-8859-6",
+ "ISO-8859-7",
+ "ISO-8859-8",
+ "ISO-8859-9",
+ "ISO-8859-9E",
+ "ISO-8859-10",
+ "ISO-8859-11",
+ "ISO-8859-13",
+ "ISO-8859-14",
+ "ISO-8859-15",
+ "ISO-8859-16",
+ "UTF-7",
+ "UTF-8",
+ "UTF-16",
+ "UTF-16LE",
+ "UTF-16BE",
+ "UTF-32",
+ "UTF-32LE",
+ "UTF-32BE",
+ NULL
+};
+#define SRT_TABLE_SIZE (sizeof(srt_codeset_table)/ sizeof(char*)-1)
+
#if 0
typedef struct iso639_lang_t
{
{ "Cree", "", "cr", "cre" },
{ "Czech", "", "cs", "ces", "cze" },
{ "Danish", "Dansk", "da", "dan" },
+ { "German", "Deutsch", "de", "deu", "ger" },
{ "Divehi", "", "dv", "div" },
- { "Dutch", "Nederlands", "nl", "nld", "dut" },
{ "Dzongkha", "", "dz", "dzo" },
{ "English", "English", "en", "eng" },
+ { "Spanish", "Espanol", "es", "spa" },
{ "Esperanto", "", "eo", "epo" },
{ "Estonian", "", "et", "est" },
{ "Ewe", "", "ee", "ewe" },
{ "Faroese", "", "fo", "fao" },
{ "Fijian", "", "fj", "fij" },
- { "Finnish", "Suomi", "fi", "fin" },
{ "French", "Francais", "fr", "fra", "fre" },
{ "Western Frisian", "", "fy", "fry" },
{ "Fulah", "", "ff", "ful" },
{ "Georgian", "", "ka", "kat", "geo" },
- { "German", "Deutsch", "de", "deu", "ger" },
{ "Gaelic (Scots)", "", "gd", "gla" },
{ "Irish", "", "ga", "gle" },
{ "Galician", "", "gl", "glg" },
{ "Herero", "", "hz", "her" },
{ "Hindi", "", "hi", "hin" },
{ "Hiri Motu", "", "ho", "hmo" },
- { "Hungarian", "Magyar", "hu", "hun" },
+ { "Croatian", "Hrvatski", "hr", "hrv", "scr" },
{ "Igbo", "", "ig", "ibo" },
- { "Icelandic", "Islenska", "is", "isl", "ice" },
{ "Ido", "", "io", "ido" },
+ { "Icelandic", "Islenska", "is", "isl", "ice" },
{ "Sichuan Yi", "", "ii", "iii" },
{ "Inuktitut", "", "iu", "iku" },
{ "Interlingue", "", "ie", "ile" },
{ "Luba-Katanga", "", "lu", "lub" },
{ "Ganda", "", "lg", "lug" },
{ "Macedonian", "", "mk", "mkd", "mac" },
+ { "Hungarian", "Magyar", "hu", "hun" },
{ "Marshallese", "", "mh", "mah" },
{ "Malayalam", "", "ml", "mal" },
{ "Maori", "", "mi", "mri", "mao" },
{ "Mongolian", "", "mn", "mon" },
{ "Nauru", "", "na", "nau" },
{ "Navajo", "", "nv", "nav" },
+ { "Dutch", "Nederlands", "nl", "nld", "dut" },
{ "Ndebele, South", "", "nr", "nbl" },
{ "Ndebele, North", "", "nd", "nde" },
{ "Ndonga", "", "ng", "ndo" },
{ "Nepali", "", "ne", "nep" },
+ { "Norwegian", "Norsk", "no", "nor" },
{ "Norwegian Nynorsk", "", "nn", "nno" },
{ "Norwegian Bokmål", "", "nb", "nob" },
- { "Norwegian", "Norsk", "no", "nor" },
{ "Chichewa; Nyanja", "", "ny", "nya" },
{ "Occitan", "", "oc", "oci" },
{ "Ojibwa", "", "oj", "oji" },
{ "Sango", "", "sg", "sag" },
{ "Sanskrit", "", "sa", "san" },
{ "Serbian", "", "sr", "srp", "scc" },
- { "Croatian", "Hrvatski", "hr", "hrv", "scr" },
{ "Sinhala", "", "si", "sin" },
{ "Slovak", "", "sk", "slk", "slo" },
{ "Slovenian", "", "sl", "slv" },
{ "Sindhi", "", "sd", "snd" },
{ "Somali", "", "so", "som" },
{ "Sotho, Southern", "", "st", "sot" },
- { "Spanish", "Espanol", "es", "spa" },
{ "Sardinian", "", "sc", "srd" },
{ "Swati", "", "ss", "ssw" },
{ "Sundanese", "", "su", "sun" },
+ { "Finnish", "Suomi", "fi", "fin" },
{ "Swahili", "", "sw", "swa" },
{ "Swedish", "Svenska", "sv", "swe" },
{ "Tahitian", "", "ty", "tah" },
*inverted = TRUE;
} break;
- case HB_VCODEC_XVID:
case HB_VCODEC_FFMPEG:
{
*min = 1;
{
if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
{
- result = ghb_language_table[ii].eng_name;
+ if (ghb_language_table[ii].native_name[0] != 0)
+ result = ghb_language_table[ii].native_name;
+ else
+ result = ghb_language_table[ii].eng_name;
break;
}
}
gint titleindex;
if (track == -2)
- return CC608SUB;
+ return SRTSUB;
if (track < 0)
return VOBSUB;
titleindex = ghb_settings_combo_int(ud->settings, "title");
if (track == -2)
{
- name = "Text";
+ name = "SRT";
goto done;
}
if (track == -1)
break;
case CC708SUB:
case CC608SUB:
- case SRTSUB:
name = "Text";
break;
+ case SRTSUB:
+ name = "SRT";
+ break;
default:
break;
}
return name;
}
+gchar*
+ghb_subtitle_track_lang(signal_user_data_t *ud, gint track)
+{
+ gint titleindex;
+
+ titleindex = ghb_settings_combo_int(ud->settings, "title");
+ if (titleindex < 0)
+ goto fail;
+ if (track == -1)
+ return ghb_get_user_audio_lang(ud, titleindex, 0);
+ if (track < 0)
+ goto fail;
+
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_subtitle_t * sub;
+
+ if (h_scan == NULL)
+ goto fail;
+
+ list = hb_get_titles( h_scan );
+ if( !hb_list_count( list ) )
+ {
+ /* No valid title, stop right there */
+ goto fail;
+ }
+ title = hb_list_item( list, titleindex );
+ if (title == NULL) // Bad titleindex
+ goto fail;
+ sub = hb_list_item( title->list_subtitle, track);
+ if (sub != NULL)
+ return g_strdup(sub->iso639_2);
+
+fail:
+ return g_strdup("und");
+}
gint
ghb_get_title_number(gint titleindex)
}
static void
+srt_codeset_opts_set(GtkBuilder *builder, const gchar *name)
+{
+ GtkTreeIter iter;
+ GtkListStore *store;
+ gint ii;
+
+ g_debug("srt_codeset_opts_set ()\n");
+ store = get_combo_box_store(builder, name);
+ gtk_list_store_clear(store);
+ for (ii = 0; ii < SRT_TABLE_SIZE; ii++)
+ {
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, srt_codeset_table[ii],
+ 1, TRUE,
+ 2, srt_codeset_table[ii],
+ 3, (gdouble)ii,
+ 4, srt_codeset_table[ii],
+ -1);
+ }
+ GtkComboBoxEntry *cbe;
+
+ cbe = GTK_COMBO_BOX_ENTRY(GHB_WIDGET(builder, name));
+ //gtk_combo_box_entry_set_text_column(cbe, 0);
+}
+
+static void
language_opts_set(GtkBuilder *builder, const gchar *name)
{
GtkTreeIter iter;
gtk_list_store_clear(store);
for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
{
+ const gchar *lang;
+
+ if (ghb_language_table[ii].native_name[0] != 0)
+ lang = ghb_language_table[ii].native_name;
+ else
+ lang = ghb_language_table[ii].eng_name;
+
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
- 0, ghb_language_table[ii].eng_name,
+ 0, lang,
1, TRUE,
2, ghb_language_table[ii].iso639_2,
3, (gdouble)ii,
}
void
-ghb_subtitle_track_model(signal_user_data_t *ud, gint titleindex)
+subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
{
GtkTreeIter iter;
GtkListStore *store;
hb_title_t * title = NULL;
hb_subtitle_t * subtitle;
gint ii, count = 0;
+ static char ** options = NULL;
- g_debug("ghb_subtitle_track_model ()\n");
+ g_debug("subtitle_track_opts_set ()\n");
+ store = get_combo_box_store(builder, name);
+ gtk_list_store_clear(store);
if (h_scan != NULL)
{
list = hb_get_titles( h_scan );
}
else
{
- subtitle_opts.count = LANG_TABLE_SIZE+2;
- subtitle_opts.map = g_malloc((LANG_TABLE_SIZE+2)*sizeof(options_map_t));
- }
- if (ud->subtitle_track_model == NULL)
- {
- // Store contains:
- // 1 - String to display
- // 2 - bool indicating whether the entry is selectable (grey or not)
- // 3 - String that is used for presets
- // 4 - Int value determined by backend
- // 5 - String value determined by backend
- store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_BOOLEAN,
- G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_STRING);
- ud->subtitle_track_model = store;
- }
- else
- {
- store = ud->subtitle_track_model;
- gtk_list_store_clear(store);
+ subtitle_opts.count = LANG_TABLE_SIZE+1;
+ subtitle_opts.map = g_malloc((LANG_TABLE_SIZE+1)*sizeof(options_map_t));
}
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
- 0, "Autoselect",
+ 0, "Foreign Audio Search",
1, TRUE,
2, "-1",
3, -1.0,
4, "auto",
-1);
- subtitle_opts.map[0].option = "Same as audio";
+ subtitle_opts.map[0].option = "Foreign Audio Search";
subtitle_opts.map[0].shortOpt = "-1";
subtitle_opts.map[0].ivalue = -1;
subtitle_opts.map[0].svalue = "auto";
if (count > 0)
{
+ if (options != NULL)
+ g_strfreev(options);
+ options = g_malloc((count+1)*sizeof(gchar*));
index_str_init(count-1);
for (ii = 0; ii < count; ii++)
{
subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, ii);
// Skip subtitles that must be burned if there is already
// a burned subtitle in the list
- subtitle_opts.map[ii+1].option = subtitle->lang;
+ options[ii] = g_strdup_printf("%d - %s", ii+1, subtitle->lang);
+ subtitle_opts.map[ii+1].option = options[ii];
subtitle_opts.map[ii+1].shortOpt = index_str[ii];
subtitle_opts.map[ii+1].ivalue = ii;
subtitle_opts.map[ii+1].svalue = subtitle->iso639_2;
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
- 0, subtitle->lang,
+ 0, options[ii],
1, TRUE,
2, index_str[ii],
3, (gdouble)ii,
4, subtitle->iso639_2,
-1);
}
+ options[count] = NULL;
}
else
{
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter,
- 0, "Closed Captions",
- 1, TRUE,
- 2, "-2",
- 3, -2.0,
- 4, "und",
- -1);
- subtitle_opts.map[1].option = "Closed Captions";
- subtitle_opts.map[1].shortOpt = "-2";
- subtitle_opts.map[1].ivalue = -2;
- subtitle_opts.map[1].svalue = "und";
index_str_init(LANG_TABLE_SIZE-1);
for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
{
- subtitle_opts.map[ii+2].option = ghb_language_table[ii].eng_name;
- subtitle_opts.map[ii+2].shortOpt = index_str[ii];
- subtitle_opts.map[ii+2].ivalue = ii;
- subtitle_opts.map[ii+2].svalue = ghb_language_table[ii].iso639_2;
+ const gchar *lang;
+
+ if (ghb_language_table[ii].native_name[0] != 0)
+ lang = ghb_language_table[ii].native_name;
+ else
+ lang = ghb_language_table[ii].eng_name;
+
+ subtitle_opts.map[ii+1].option = lang;
+ subtitle_opts.map[ii+1].shortOpt = index_str[ii];
+ subtitle_opts.map[ii+1].ivalue = ii;
+ subtitle_opts.map[ii+1].svalue = ghb_language_table[ii].iso639_2;
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
- 0, ghb_language_table[ii].eng_name,
+ 0, lang,
1, TRUE,
2, index_str[ii],
3, (gdouble)ii,
return titleindex;
}
+gchar*
+ghb_get_source_audio_lang(gint titleindex, gint track)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_audio_config_t * audio;
+ gchar *lang = NULL;
+
+ g_debug("ghb_lookup_1st_audio_lang ()\n");
+ if (h_scan == NULL)
+ return NULL;
+ list = hb_get_titles( h_scan );
+ title = (hb_title_t*)hb_list_item( list, titleindex );
+ if (title == NULL)
+ return NULL;
+ if (hb_list_count( title->list_audio ) <= track)
+ return NULL;
+
+ audio = hb_list_audio_config_item(title->list_audio, track);
+ if (audio == NULL)
+ return NULL;
+
+ lang = g_strdup(audio->lang.iso639_2);
+ return lang;
+}
+
gint
ghb_find_audio_track(
gint titleindex,
}
gint
+ghb_find_pref_subtitle_track(const gchar *lang)
+{
+ gint ii, count;
+ count = subtitle_opts.count;
+ for (ii = 0; ii < count; ii++)
+ {
+ if (strcmp(lang, subtitle_opts.map[ii].svalue) == 0)
+ {
+ return subtitle_opts.map[ii].ivalue;
+ }
+ }
+ return -2;
+}
+
+gint
+ghb_find_cc_track(gint titleindex)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_subtitle_t * subtitle;
+ gint count, ii;
+
+ g_debug("ghb_find_cc_track ()\n");
+ if (h_scan == NULL) return -2;
+ list = hb_get_titles( h_scan );
+ title = (hb_title_t*)hb_list_item( list, titleindex );
+ if (title != NULL)
+ {
+ count = hb_list_count( title->list_subtitle );
+ // Try to find an item that matches the preferred language
+ for (ii = 0; ii < count; ii++)
+ {
+ subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
+ if (subtitle->source == CC608SUB || subtitle->source == CC708SUB)
+ return ii;
+ }
+ }
+ return -2;
+}
+
+gint
ghb_find_subtitle_track(
gint titleindex,
const gchar *lang,
hb_list_t * list;
hb_title_t * title;
hb_subtitle_t * subtitle;
- gint ii;
- gint count = 0;
+ gint count, ii;
gboolean *used;
g_debug("find_subtitle_track ()\n");
return ii;
}
}
- return -1;
- }
- else
- {
- count = subtitle_opts.count;
- for (ii = 0; ii < count; ii++)
- {
- if (strcmp(lang, subtitle_opts.map[ii].svalue) == 0)
- {
- return subtitle_opts.map[ii].ivalue;
- }
- }
- return -1;
- }
-}
-
-gint
-ghb_pick_subtitle_track(signal_user_data_t *ud)
-{
- gint ii, count, track, candidate, first;
- GValue *settings, *subtitle_list;
-
- first = candidate = ghb_settings_combo_int(ud->settings, "SubtitleTrack");
- subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list");
- count = ghb_array_len(subtitle_list);
- for (ii = 0; ii < count; ii++)
- {
- settings = ghb_array_get_nth(subtitle_list, ii);
- track = ghb_settings_combo_int(settings, "SubtitleTrack");
- if (candidate == track)
- {
- // Already in use, pick another
- candidate++;
- if (candidate >= subtitle_opts.count-1)
- {
- candidate = 0;
- }
- if (candidate == first)
- {
- candidate = -1;
- break;
- }
- ii = -1;
- }
}
- return candidate;
+ return -2;
}
static void
return lookup_video_rate_int(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_int(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_int(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_int(gval);
else
{
return lookup_video_rate_int(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_int(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_int(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_int(gval);
else
{
return lookup_video_rate_option(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_option(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_option(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_option(gval);
else
{
return lookup_video_rate_option(gval);
else if (strcmp(name, "AudioMixdown") == 0)
return lookup_mix_option(gval);
- else if (strcmp(name, "SourceAudioLang") == 0)
+ else if (strcmp(name, "SrtLanguage") == 0)
+ return lookup_audio_lang_option(gval);
+ else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_option(gval);
else
{
audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
mix_opts_set(ud->builder, "AudioMixdown");
- language_opts_set(ud->builder, "SourceAudioLang");
+ language_opts_set(ud->builder, "SrtLanguage");
+ language_opts_set(ud->builder, "PreferredLanguage");
+ srt_codeset_opts_set(ud->builder, "SrtCodeset");
title_opts_set(ud->builder, "title");
audio_track_opts_set(ud->builder, "AudioTrack", user_data);
+ subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data);
generic_opts_set(ud->builder, "VideoQualityGranularity", &vqual_granularity_opts);
+ generic_opts_set(ud->builder, "WhenComplete", &when_complete_opts);
generic_opts_set(ud->builder, "PicturePAR", &par_opts);
generic_opts_set(ud->builder, "PictureModulus", &alignment_opts);
generic_opts_set(ud->builder, "LoggingLevel", &logging_opts);
+ generic_opts_set(ud->builder, "LogLongevity", &log_longevity_opts);
+ generic_opts_set(ud->builder, "check_updates", &appcast_update_opts);
generic_opts_set(ud->builder, "FileFormat", &container_opts);
generic_opts_set(ud->builder, "PictureDeinterlace", &deint_opts);
generic_opts_set(ud->builder, "PictureDetelecine", &detel_opts);
video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
else if (strcmp(name, "AudioMixdown") == 0)
mix_opts_set(ud->builder, "AudioMixdown");
- else if (strcmp(name, "SourceAudioLang") == 0)
- language_opts_set(ud->builder, "SourceAudioLang");
+ else if (strcmp(name, "SrtLanguage") == 0)
+ language_opts_set(ud->builder, "SrtLanguage");
+ else if (strcmp(name, "PreferredLanguage") == 0)
+ language_opts_set(ud->builder, "PreferredLanguage");
+ else if (strcmp(name, "SrtCodeset") == 0)
+ srt_codeset_opts_set(ud->builder, "SrtCodeset");
else if (strcmp(name, "title") == 0)
title_opts_set(ud->builder, "title");
+ else if (strcmp(name, "SubtitleTrack") == 0)
+ subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data);
else if (strcmp(name, "AudioTrack") == 0)
audio_track_opts_set(ud->builder, "AudioTrack", user_data);
else
init_combo_box(builder, "AudioSamplerate");
init_combo_box(builder, "VideoFramerate");
init_combo_box(builder, "AudioMixdown");
- init_combo_box(builder, "SourceAudioLang");
+ init_combo_box(builder, "SrtLanguage");
+ init_combo_box(builder, "PreferredLanguage");
+ init_combo_box(builder, "SrtCodeset");
init_combo_box(builder, "title");
init_combo_box(builder, "AudioTrack");
for (ii = 0; combo_name_map[ii].name != NULL; ii++)
static const char * turbo_opts =
"ref=1:subme=1:me=dia:analyse=none:trellis=0:"
- "no-fast-pskip=0:8x8dct=0:weightb=0";
+ "no-fast-pskip=0:8x8dct=0";
// Construct the x264 options string
// The result is allocated, so someone must free it at some point.
asettings = ghb_array_get_nth(audio_list, ii);
acodec = ghb_settings_combo_int(asettings, "AudioEncoder");
- if (acodec == HB_ACODEC_AC3)
+ if (acodec & HB_ACODEC_AC3)
return TRUE;
}
return FALSE;
{
gboolean autoscale, keep_aspect, enable_keep_aspect;
gboolean enable_scale_width, enable_scale_height;
- gboolean enable_disp_width, enable_disp_height;
+ gboolean enable_disp_width, enable_disp_height, enable_par;
gint pic_par;
GtkWidget *widget;
enable_scale_width = !autoscale && (pic_par != 1);
enable_scale_height = !autoscale && (pic_par != 1);
enable_disp_width = (pic_par == 3) && !keep_aspect;
+ enable_par = (pic_par == 3) && !keep_aspect;
enable_disp_height = FALSE;
widget = GHB_WIDGET(ud->builder, "PictureModulus");
gtk_widget_set_sensitive(widget, enable_disp_width);
widget = GHB_WIDGET(ud->builder, "PictureDisplayHeight");
gtk_widget_set_sensitive(widget, enable_disp_height);
+ widget = GHB_WIDGET(ud->builder, "PicturePARWidth");
+ gtk_widget_set_sensitive(widget, enable_par);
+ widget = GHB_WIDGET(ud->builder, "PicturePARHeight");
+ gtk_widget_set_sensitive(widget, enable_par);
widget = GHB_WIDGET(ud->builder, "PictureKeepRatio");
gtk_widget_set_sensitive(widget, enable_keep_aspect);
widget = GHB_WIDGET(ud->builder, "autoscale");
// The scaler crashes if the dimensions are not divisible by 2
// Align mod 2. And so does something in x264_encoder_headers()
job->anamorphic.modulus = mod;
+ job->anamorphic.par_width = title->pixel_aspect_width;
+ job->anamorphic.par_height = title->pixel_aspect_height;
+ job->anamorphic.dar_width = 0;
+ job->anamorphic.dar_height = 0;
+
if (keep_height && pic_par == 2)
width = ((double)height * crop_width / crop_height) + 0.5;
job->width = width;
job->height = height;
- if (max_width)
- job->maxWidth = max_width;
- if (max_height)
- job->maxHeight = max_height;
+ job->maxWidth = max_width;
+ job->maxHeight = max_height;
job->crop[0] = crop[0]; job->crop[1] = crop[1];
job->crop[2] = crop[2]; job->crop[3] = crop[3];
if (job->anamorphic.mode == 3 && !keep_aspect)
{
- gint dar_width, dar_height;
+ job->anamorphic.keep_display_aspect = 0;
if (mode & GHB_PIC_KEEP_PAR)
{
- par_width = ghb_settings_get_int(ud->settings,
- "PicturePARWidth");
- par_height = ghb_settings_get_int(ud->settings,
- "PicturePARHeight");
- dar_width = ((gdouble)width * par_width / par_height) + 0.5;
- dar_height = height;
+ job->anamorphic.par_width =
+ ghb_settings_get_int(ud->settings, "PicturePARWidth");
+ job->anamorphic.par_height =
+ ghb_settings_get_int(ud->settings, "PicturePARHeight");
}
else
{
- dar_width = ghb_settings_get_int(ud->settings,
- "PictureDisplayWidth");
- dar_height = ghb_settings_get_int(ud->settings,
- "PictureDisplayHeight");
+ job->anamorphic.dar_width =
+ ghb_settings_get_int(ud->settings,
+ "PictureDisplayWidth");
+ job->anamorphic.dar_height = height;
}
- job->anamorphic.dar_width = dar_width;
- job->anamorphic.dar_height = dar_height;
}
else
{
- job->anamorphic.dar_width = 0;
- job->anamorphic.dar_height = 0;
+ job->anamorphic.keep_display_aspect = 1;
}
hb_set_anamorphic_size( job, &width, &height,
&par_width, &par_height );
+ if (job->anamorphic.mode == 3 && !keep_aspect &&
+ mode & GHB_PIC_KEEP_PAR)
+ {
+ // hb_set_anamorphic_size reduces the par, which we
+ // don't want in this case because the user is
+ // explicitely specifying it.
+ par_width = ghb_settings_get_int(ud->settings,
+ "PicturePARWidth");
+ par_height = ghb_settings_get_int(ud->settings,
+ "PicturePARHeight");
+ }
}
else
{
}
ghb_ui_update(ud, "display_aspect", ghb_string_value(str));
g_free(str);
- ghb_ui_update(ud, "par_width", ghb_int64_value(par_width));
- ghb_ui_update(ud, "par_height", ghb_int64_value(par_height));
+ ghb_ui_update(ud, "PicturePARWidth", ghb_int64_value(par_width));
+ ghb_ui_update(ud, "PicturePARHeight", ghb_int64_value(par_height));
ghb_ui_update(ud, "PictureDisplayWidth", ghb_int64_value(disp_width));
ghb_ui_update(ud, "PictureDisplayHeight", ghb_int64_value(height));
busy = FALSE;
job->height = ghb_settings_get_int(settings, "scale_height");
if (ghb_settings_get_boolean(settings, "show_crop"))
{
+ gdouble xscale = (gdouble)job->width /
+ (gdouble)(job->title->width - job->crop[2] - job->crop[3]);
+ gdouble yscale = (gdouble)job->height /
+ (gdouble)(job->title->height - job->crop[0] - job->crop[1]);
+
+ job->width += xscale * (job->crop[2] + job->crop[3]);
+ job->height += yscale * (job->crop[0] + job->crop[1]);
job->crop[0] = 0;
job->crop[1] = 0;
job->crop[2] = 0;
job->crop[3] = 0;
- job->width = job->title->width;
- job->height = job->title->height;
job->anamorphic.modulus = 2;
}
gboolean keep_aspect;
keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio");
- if (job->anamorphic.mode == 3 && !keep_aspect)
- {
- gint disp_width, disp_height;
- disp_width = ghb_settings_get_int(settings, "PictureDisplayWidth");
- disp_height = ghb_settings_get_int(settings, "PictureDisplayHeight");
- job->anamorphic.dar_width = disp_width;
- job->anamorphic.dar_height = disp_height;
- }
- else
+ if (job->anamorphic.mode)
{
+ job->anamorphic.par_width = job->title->pixel_aspect_width;
+ job->anamorphic.par_height = job->title->pixel_aspect_height;
job->anamorphic.dar_width = 0;
job->anamorphic.dar_height = 0;
+
+ if (job->anamorphic.mode == 3 && !keep_aspect)
+ {
+ job->anamorphic.keep_display_aspect = 0;
+ job->anamorphic.par_width =
+ ghb_settings_get_int(settings, "PicturePARWidth");
+ job->anamorphic.par_height =
+ ghb_settings_get_int(settings, "PicturePARHeight");
+ }
+ else
+ {
+ job->anamorphic.keep_display_aspect = 1;
+ }
}
}
gint index;
gchar *message;
- // deinte 4
+ // deinte
index = ghb_settings_combo_int(ud->settings, "PictureDeinterlace");
if (index == 1)
{
}
g_free(str);
}
- // decomb 4
+ // decomb
index = ghb_settings_combo_int(ud->settings, "PictureDecomb");
if (index == 1)
{
str = ghb_settings_get_string(ud->settings, "PictureDecombCustom");
- if (!ghb_validate_filter_string(str, 7))
+ if (!ghb_validate_filter_string(str, 15))
{
message = g_strdup_printf(
"Invalid Decomb Settings:\n\n%s\n",
}
g_free(str);
}
- // denois 4
+ // denois
index = ghb_settings_combo_int(ud->settings, "PictureDenoise");
if (index == 1)
{
message = g_strdup_printf(
"Theora is not supported in the MP4 and AVI containers.\n\n"
"You should choose a different video codec or container.\n"
- "If you continue, XviD will be chosen for you.");
+ "If you continue, FFMPEG will be chosen for you.");
if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
{
g_free(message);
return FALSE;
}
g_free(message);
- vcodec = HB_VCODEC_XVID;
+ vcodec = HB_VCODEC_FFMPEG;
ghb_ui_update(ud, "VideoEncoder", ghb_int64_value(vcodec));
}
return TRUE;
gint mux = ghb_settings_combo_int(ud->settings, "FileFormat");
const GValue *slist, *settings;
- gint count, ii, track, source;
- gboolean burned;
+ gint count, ii, source;
+ gboolean burned, one_burned = FALSE;
slist = ghb_settings_get_value(ud->settings, "subtitle_list");
count = ghb_array_len(slist);
for (ii = 0; ii < count; ii++)
{
settings = ghb_array_get_nth(slist, ii);
- track = ghb_settings_combo_int(settings, "SubtitleTrack");
+ source = ghb_settings_get_int(settings, "SubtitleSource");
burned = ghb_settings_get_boolean(settings, "SubtitleBurned");
- source = ghb_subtitle_track_source(ud, track);
+ if (burned && one_burned)
+ {
+ // MP4 can only handle burned vobsubs. make sure there isn't
+ // already something burned in the list
+ message = g_strdup_printf(
+ "Only one subtitle may be burned into the video.\n\n"
+ "You should change your subtitle selections.\n"
+ "If you continue, some subtitles will be lost.");
+ if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
+ {
+ g_free(message);
+ return FALSE;
+ }
+ g_free(message);
+ break;
+ }
+ else if (burned)
+ {
+ one_burned = TRUE;
+ }
if (!burned && mux == HB_MUX_MP4 && source == VOBSUB)
{
// MP4 can only handle burned vobsubs. make sure there isn't
"Your chosen container does not support soft bitmap subtitles.\n\n"
"You should change your subtitle selections.\n"
"If you continue, some subtitles will be lost.");
- if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message, "Cancel", "Continue"))
+ if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message,
+ "Cancel", "Continue"))
{
g_free(message);
return FALSE;
}
g_free(message);
+ break;
+ }
+ if (source == SRTSUB)
+ {
+ gchar *filename;
+
+ filename = ghb_settings_get_string(settings, "SrtFile");
+ if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
+ {
+ message = g_strdup_printf(
+ "Srt file does not exist or not a regular file.\n\n"
+ "You should choose a valid file.\n"
+ "If you continue, this subtitle will be ignored.");
+ if (!ghb_message_dialog(GTK_MESSAGE_WARNING, message,
+ "Cancel", "Continue"))
+ {
+ g_free(message);
+ return FALSE;
+ }
+ g_free(message);
+ break;
+ }
}
}
return TRUE;
max = 30;
} break;
- case HB_VCODEC_XVID:
case HB_VCODEC_FFMPEG:
{
min = 1;
job->deinterlace = 0;
job->grayscale = ghb_settings_get_boolean(js, "VideoGrayScale");
+ gboolean keep_aspect;
+ keep_aspect = ghb_settings_get_boolean(js, "PictureKeepRatio");
job->anamorphic.mode = ghb_settings_combo_int(js, "PicturePAR");
job->anamorphic.modulus = ghb_settings_combo_int(js, "PictureModulus");
+ if (job->anamorphic.mode)
+ {
+ job->anamorphic.par_width = title->pixel_aspect_width;
+ job->anamorphic.par_height = title->pixel_aspect_height;
+ job->anamorphic.dar_width = 0;
+ job->anamorphic.dar_height = 0;
+
+ if (job->anamorphic.mode == 3 && !keep_aspect)
+ {
+ job->anamorphic.keep_display_aspect = 0;
+ job->anamorphic.par_width =
+ ghb_settings_get_int(js, "PicturePARWidth");
+ job->anamorphic.par_height =
+ ghb_settings_get_int(js, "PicturePARHeight");
+ }
+ else
+ {
+ job->anamorphic.keep_display_aspect = 1;
+ }
+ }
/* Add selected filters */
job->filters = hb_list_init();
(job->vcodec == HB_VCODEC_THEORA))
{
// mp4|avi/theora combination is not supported.
- job->vcodec = HB_VCODEC_XVID;
+ job->vcodec = HB_VCODEC_FFMPEG;
}
if ((job->vcodec == HB_VCODEC_X264) && (job->mux == HB_MUX_MP4))
{
job->cfr = 1;
}
- // First remove any audios that are already in the list
- // This happens if you are encoding the same title a second time.
- gint num_audio_tracks = hb_list_count(job->list_audio);
- gint ii;
- for(ii = 0; ii < num_audio_tracks; ii++)
- {
- hb_audio_t *audio = (hb_audio_t*)hb_list_item(job->list_audio, 0);
- hb_list_rem(job->list_audio, audio);
- }
-
const GValue *audio_list;
- gint count;
+ gint count, ii;
gint tcount = 0;
audio_list = ghb_settings_get_value(js, "audio_list");
}
audio.out.dynamic_range_compression =
ghb_settings_get_double(asettings, "AudioTrackDRCSlider");
+ if (audio.out.dynamic_range_compression < 1.0)
+ audio.out.dynamic_range_compression = 0.0;
+
// It would be better if this were done in libhb for us, but its not yet.
if (audio.out.codec == HB_ACODEC_AC3 || audio.out.codec == HB_ACODEC_DCA)
{
dest_str = ghb_settings_get_string(js, "destination");
job->file = dest_str;
job->crf = ghb_settings_get_boolean(js, "constant_rate_factor");
- // TODO: libhb holds onto a reference to the x264opts and is not
- // finished with it until encoding the job is done. But I can't
- // find a way to get at the job before it is removed in order to
- // free up the memory I am allocating here.
- // The short story is THIS LEAKS.
- x264opts = ghb_build_x264opts_string(js);
-
- if( x264opts != NULL && *x264opts != '\0' )
- {
- job->x264opts = x264opts;
- }
- else /*avoids a bus error crash when options aren't specified*/
- {
- job->x264opts = NULL;
- }
const GValue *subtitle_list;
gint subtitle;
+ gboolean force, burned, def, one_burned = FALSE;
+ ghb_settings_set_boolean(js, "subtitle_scan", FALSE);
subtitle_list = ghb_settings_get_value(js, "subtitle_list");
count = ghb_array_len(subtitle_list);
for (ii = 0; ii < count; ii++)
{
GValue *ssettings;
- gboolean burned, one_burned = FALSE;
+ gint source;
ssettings = ghb_array_get_nth(subtitle_list, ii);
- subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack");
+ force = ghb_settings_get_boolean(ssettings, "SubtitleForced");
burned = ghb_settings_get_boolean(ssettings, "SubtitleBurned");
+ def = ghb_settings_get_boolean(ssettings, "SubtitleDefaultTrack");
+ source = ghb_settings_get_int(ssettings, "SubtitleSource");
+
+ if (source == SRTSUB)
+ {
+ hb_subtitle_config_t sub_config;
+ gchar *filename, *lang, *code;
+
+ filename = ghb_settings_get_string(ssettings, "SrtFile");
+ if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
+ {
+ continue;
+ }
+ sub_config.offset = ghb_settings_get_int(ssettings, "SrtOffset");
+ lang = ghb_settings_get_string(ssettings, "SrtLanguage");
+ code = ghb_settings_get_string(ssettings, "SrtCodeset");
+ strncpy(sub_config.src_filename, filename, 128);
+ strncpy(sub_config.src_codeset, code, 40);
+ sub_config.force = 0;
+ sub_config.dest = PASSTHRUSUB;
+ sub_config.default_track = def;
+
+ hb_srt_add( job, &sub_config, lang);
+
+ g_free(filename);
+ g_free(lang);
+ g_free(code);
+ continue;
+ }
+
+ subtitle = ghb_settings_get_int(ssettings, "SubtitleTrack");
if (subtitle == -1)
{
+ if (!burned && job->mux == HB_MUX_MKV)
+ {
+ job->select_subtitle_config.dest = PASSTHRUSUB;
+ }
+ else if (!burned && job->mux == HB_MUX_MP4)
+ {
+ // Skip any non-burned vobsubs when output is mp4
+ continue;
+ }
+ else if (burned)
+ {
+ // Only allow one subtitle to be burned into the video
+ if (one_burned)
+ continue;
+ job->select_subtitle_config.dest = RENDERSUB;
+ one_burned = TRUE;
+ }
+ job->select_subtitle_config.force = force;
+ job->select_subtitle_config.default_track = def;
job->indepth_scan = 1;
+ ghb_settings_set_boolean(js, "subtitle_scan", TRUE);
}
else if (subtitle >= 0)
{
hb_subtitle_t * subt;
+ hb_subtitle_config_t sub_config;
subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, subtitle);
+ sub_config = subt->config;
if (subt != NULL)
{
if (!burned && job->mux == HB_MUX_MKV &&
subt->format == PICTURESUB)
{
- subt->dest = PASSTHRUSUB;
+ sub_config.dest = PASSTHRUSUB;
}
else if (!burned && job->mux == HB_MUX_MP4 &&
subt->format == PICTURESUB)
// Skip any non-burned vobsubs when output is mp4
continue;
}
- else if (subt->format == PICTURESUB)
+ else if ( burned && subt->format == PICTURESUB )
{
// Only allow one subtitle to be burned into the video
if (one_burned)
continue;
one_burned = TRUE;
}
- subt->force = ghb_settings_get_boolean(ssettings, "SubtitleForced");
- hb_list_add(job->list_subtitle, subt);
+ sub_config.force = force;
+ sub_config.default_track = def;
+ hb_subtitle_add( job, &sub_config, subtitle );
}
}
}
+ // TODO: libhb holds onto a reference to the x264opts and is not
+ // finished with it until encoding the job is done. But I can't
+ // find a way to get at the job before it is removed in order to
+ // free up the memory I am allocating here.
+ // The short story is THIS LEAKS.
+ x264opts = ghb_build_x264opts_string(js);
+
+ if( *x264opts == '\0' )
+ {
+ g_free(x264opts);
+ x264opts = NULL;
+ }
+
if (job->indepth_scan == 1)
{
// Subtitle scan. Look for subtitle matching audio language
- char *x264opts_tmp;
/*
* When subtitle scan is enabled do a fast pre-scan job
*/
job->pass = -1;
job->indepth_scan = 1;
-
- x264opts_tmp = job->x264opts;
job->x264opts = NULL;
- job->select_subtitle = malloc(sizeof(hb_subtitle_t*));
- *(job->select_subtitle) = NULL;
-
/*
* Add the pre-scan job
*/
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
hb_add( h, job );
- //if (job->x264opts != NULL)
- // g_free(job->x264opts);
-
- job->x264opts = x264opts_tmp;
- }
- else
- {
- job->select_subtitle = NULL;
}
+
if( ghb_settings_get_boolean(js, "VideoTwoPass") &&
!ghb_settings_get_boolean(js, "vquality_type_constant"))
{
* for the second pass and then off again for the
* second.
*/
- hb_subtitle_t **subtitle_tmp = job->select_subtitle;
- job->select_subtitle = NULL;
job->pass = 1;
job->indepth_scan = 0;
- gchar *x264opts2 = NULL;
- if (x264opts)
- {
- x264opts2 = g_strdup(x264opts);
- }
+
/*
* If turbo options have been selected then append them
* to the x264opts now (size includes one ':' and the '\0')
*/
if( ghb_settings_get_boolean(js, "VideoTurboTwoPass") )
{
- char *tmp_x264opts;
+ gchar *tmp_x264opts;
+ gchar *extra_opts;
+ gint badapt;
+ badapt = ghb_lookup_badapt(x264opts);
+ if (badapt == 2)
+ {
+ extra_opts = g_strdup_printf("%s", turbo_opts);
+ }
+ else
+ {
+ extra_opts = g_strdup_printf("%s:weightb=0", turbo_opts);
+ }
+
if ( x264opts )
{
- tmp_x264opts = g_strdup_printf("%s:%s", x264opts, turbo_opts);
- g_free(x264opts);
+ tmp_x264opts = g_strdup_printf("%s:%s", x264opts, extra_opts);
}
else
{
* No x264opts to modify, but apply the turbo options
* anyway as they may be modifying defaults
*/
- tmp_x264opts = g_strdup_printf("%s", turbo_opts);
+ tmp_x264opts = g_strdup_printf("%s", extra_opts);
}
- x264opts = tmp_x264opts;
+ g_free(extra_opts);
+ job->x264opts = tmp_x264opts;
+ }
+ else
+ {
job->x264opts = x264opts;
}
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
//if (job->x264opts != NULL)
// g_free(job->x264opts);
- job->select_subtitle = subtitle_tmp;
job->pass = 2;
/*
* On the second pass we turn off subtitle scan so that we
* attribute of the job).
*/
job->indepth_scan = 0;
- job->x264opts = x264opts2;
+ job->x264opts = x264opts;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
hb_add( h, job );
//if (job->x264opts != NULL)
}
else
{
+ job->x264opts = x264opts;
job->indepth_scan = 0;
job->pass = 0;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
//if (job->x264opts != NULL)
// g_free(job->x264opts);
}
+
+ // clean up audio list
+ gint num_audio_tracks = hb_list_count(job->list_audio);
+ for(ii = 0; ii < num_audio_tracks; ii++)
+ {
+ hb_audio_t *audio = (hb_audio_t*)hb_list_item(job->list_audio, 0);
+ hb_list_rem(job->list_audio, audio);
+ free(audio);
+ }
+
+ // clean up subtitle list
+ gint num_subtitle_tracks = hb_list_count(job->list_subtitle);
+ for(ii = 0; ii < num_subtitle_tracks; ii++)
+ {
+ hb_subtitle_t *subtitle = hb_list_item(job->list_subtitle, 0);
+ hb_list_rem(job->list_subtitle, subtitle);
+ free(subtitle);
+ }
+
if (detel_str) g_free(detel_str);
if (decomb_str) g_free(decomb_str);
if (deint_str) g_free(deint_str);
if( s.state == HB_STATE_PAUSED )
{
- hb_resume( h_queue );
+ hb_status.queue.state &= ~GHB_STATE_PAUSED;
+ hb_resume( h_queue );
}
else
{
- hb_pause( h_queue );
+ hb_status.queue.state |= GHB_STATE_PAUSED;
+ hb_pause( h_queue );
}
}
w *= (gdouble)dstWidth / orig_w;
h *= (gdouble)dstHeight / orig_h;
}
- g_debug("scaled %d x %d", dstWidth, dstHeight);
GdkPixbuf *scaled_preview;
scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);
if (ghb_settings_get_boolean(settings, "show_crop"))