summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/callbacks.c184
-rw-r--r--gtk/src/ghb.ui311
-rw-r--r--gtk/src/hb-backend.c411
-rw-r--r--gtk/src/hb-backend.h25
-rw-r--r--gtk/src/internal_defaults.xml16
-rw-r--r--gtk/src/presets.c30
-rw-r--r--gtk/src/values.c9
-rw-r--r--libhb/bd.c4
-rw-r--r--libhb/common.c742
-rw-r--r--libhb/common.h101
-rw-r--r--libhb/decavcodec.c2
-rw-r--r--libhb/decmetadata.c114
-rw-r--r--libhb/decmpeg2.c8
-rw-r--r--libhb/decsrtsub.c5
-rw-r--r--libhb/dvd.c4
-rw-r--r--libhb/dvdnav.c4
-rw-r--r--libhb/hb.c326
-rw-r--r--libhb/hb.h18
-rw-r--r--libhb/internal.h4
-rw-r--r--libhb/muxcommon.c9
-rw-r--r--libhb/muxmkv.c72
-rw-r--r--libhb/muxmp4.c73
-rw-r--r--libhb/reader.c20
-rw-r--r--libhb/rendersub.c6
-rw-r--r--libhb/scan.c104
-rw-r--r--libhb/stream.c100
-rw-r--r--libhb/sync.c7
-rw-r--r--libhb/work.c113
-rw-r--r--macosx/ChapterTitles.m17
-rw-r--r--macosx/Controller.m62
-rw-r--r--macosx/HBPreviewController.m4
-rw-r--r--test/test.c78
32 files changed, 1960 insertions, 1023 deletions
diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c
index 0ff45d1c1..29c767c17 100644
--- a/gtk/src/callbacks.c
+++ b/gtk/src/callbacks.c
@@ -1328,9 +1328,8 @@ update_title_duration(signal_user_data_t *ud)
}
else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
{
- ghb_title_info_t tinfo;
-
- if (ghb_get_title_info (&tinfo, ti))
+ hb_title_t * title = ghb_get_title_info (ti);
+ if (title != NULL)
{
gint64 frames;
gint duration;
@@ -1338,7 +1337,7 @@ update_title_duration(signal_user_data_t *ud)
start = ghb_settings_get_int(ud->settings, "start_point");
end = ghb_settings_get_int(ud->settings, "end_point");
frames = end - start + 1;
- duration = frames * tinfo.rate_base / tinfo.rate;
+ duration = frames * title->rate_base / title->rate;
hh = duration / (60*60);
mm = (duration / 60) % 60;
ss = duration % 60;
@@ -1354,19 +1353,19 @@ update_title_duration(signal_user_data_t *ud)
}
static void
-show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
+show_title_info(signal_user_data_t *ud, hb_title_t *title)
{
GtkWidget *widget;
gchar *text;
- ghb_settings_set_string(ud->settings, "source", tinfo->path);
- if (tinfo->type == HB_STREAM_TYPE || tinfo->type == HB_FF_STREAM_TYPE)
+ ghb_settings_set_string(ud->settings, "source", title->path);
+ if (title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE)
{
GtkWidget *widget = GHB_WIDGET (ud->builder, "source_title");
- if (tinfo->name != NULL && tinfo->name[0] != 0)
+ if (title->name != NULL && title->name[0] != 0)
{
- gtk_label_set_text (GTK_LABEL(widget), tinfo->name);
- ghb_settings_set_string(ud->settings, "volume_label", tinfo->name);
+ gtk_label_set_text (GTK_LABEL(widget), title->name);
+ ghb_settings_set_string(ud->settings, "volume_label", title->name);
set_destination(ud);
}
else
@@ -1380,31 +1379,35 @@ show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
ud->scale_busy = TRUE;
update_title_duration(ud);
widget = GHB_WIDGET (ud->builder, "source_codec");
- if ( tinfo->video_codec_name )
- gtk_label_set_text (GTK_LABEL(widget), tinfo->video_codec_name);
+ if ( title->video_codec_name )
+ gtk_label_set_text (GTK_LABEL(widget), title->video_codec_name);
else
gtk_label_set_text (GTK_LABEL(widget), "Unknown");
widget = GHB_WIDGET (ud->builder, "source_dimensions");
- text = g_strdup_printf ("%d x %d", tinfo->width, tinfo->height);
+ text = g_strdup_printf ("%d x %d", title->width, title->height);
gtk_label_set_text (GTK_LABEL(widget), text);
- ghb_settings_set_int(ud->settings, "source_width", tinfo->width);
- ghb_settings_set_int(ud->settings, "source_height", tinfo->height);
+ ghb_settings_set_int(ud->settings, "source_width", title->width);
+ ghb_settings_set_int(ud->settings, "source_height", title->height);
g_free(text);
widget = GHB_WIDGET (ud->builder, "source_aspect");
- text = get_aspect_string(tinfo->aspect_n, tinfo->aspect_d);
+ gint aspect_n, aspect_d;
+ hb_reduce(&aspect_n, &aspect_d,
+ title->width * title->pixel_aspect_width,
+ title->height * title->pixel_aspect_height);
+ text = get_aspect_string(aspect_n, aspect_d);
gtk_label_set_text (GTK_LABEL(widget), text);
g_free(text);
widget = GHB_WIDGET (ud->builder, "source_frame_rate");
- text = (gchar*)get_rate_string(tinfo->rate_base, tinfo->rate);
+ text = (gchar*)get_rate_string(title->rate_base, title->rate);
gtk_label_set_text (GTK_LABEL(widget), text);
g_free(text);
//widget = GHB_WIDGET (ud->builder, "source_interlaced");
- //gtk_label_set_text (GTK_LABEL(widget), tinfo->interlaced ? "Yes" : "No");
+ //gtk_label_set_text (GTK_LABEL(widget), title->interlaced ? "Yes" : "No");
ghb_ui_update(ud, "scale_width",
- ghb_int64_value(tinfo->width - tinfo->crop[2] - tinfo->crop[3]));
+ ghb_int64_value(title->width - title->crop[2] - title->crop[3]));
// If anamorphic or keep_aspect, the hight will be automatically calculated
gboolean keep_aspect;
gint pic_par;
@@ -1413,28 +1416,28 @@ show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
if (!(keep_aspect || pic_par) || pic_par == 3)
{
ghb_ui_update(ud, "scale_height",
- ghb_int64_value(tinfo->height - tinfo->crop[0] - tinfo->crop[1]));
+ ghb_int64_value(title->height - title->crop[0] - title->crop[1]));
}
// Set the limits of cropping. hb_set_anamorphic_size crashes if
// you pass it a cropped width or height == 0.
gint bound;
- bound = tinfo->height / 2 - 8;
+ bound = title->height / 2 - 8;
widget = GHB_WIDGET (ud->builder, "PictureTopCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
widget = GHB_WIDGET (ud->builder, "PictureBottomCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
- bound = tinfo->width / 2 - 8;
+ bound = title->width / 2 - 8;
widget = GHB_WIDGET (ud->builder, "PictureLeftCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
widget = GHB_WIDGET (ud->builder, "PictureRightCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
if (ghb_settings_get_boolean(ud->settings, "PictureAutoCrop"))
{
- ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(tinfo->crop[0]));
- ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(tinfo->crop[1]));
- ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(tinfo->crop[2]));
- ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(tinfo->crop[3]));
+ ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(title->crop[0]));
+ ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(title->crop[1]));
+ ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(title->crop[2]));
+ ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(title->crop[3]));
}
ud->scale_busy = FALSE;
ghb_set_scale (ud, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX);
@@ -1443,25 +1446,26 @@ show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
crop[1] = ghb_settings_get_int(ud->settings, "PictureBottomCrop");
crop[2] = ghb_settings_get_int(ud->settings, "PictureLeftCrop");
crop[3] = ghb_settings_get_int(ud->settings, "PictureRightCrop");
- width = tinfo->width - crop[2] - crop[3];
- height = tinfo->height - crop[0] - crop[1];
+ width = title->width - crop[2] - crop[3];
+ height = title->height - crop[0] - crop[1];
widget = GHB_WIDGET (ud->builder, "crop_dimensions");
text = g_strdup_printf ("%d x %d", width, height);
gtk_label_set_text (GTK_LABEL(widget), text);
g_free(text);
- gint duration = tinfo->duration / 90000;
+ gint duration = title->duration / 90000;
+ gint num_chapters = hb_list_count(title->list_chapter);
if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
{
widget = GHB_WIDGET (ud->builder, "start_point");
- gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, tinfo->num_chapters);
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, num_chapters);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), 1);
widget = GHB_WIDGET (ud->builder, "end_point");
- gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, tinfo->num_chapters);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), tinfo->num_chapters);
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, num_chapters);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), num_chapters);
}
else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
{
@@ -1476,7 +1480,7 @@ show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
}
else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
{
- gdouble max_frames = (gdouble)duration * tinfo->rate / tinfo->rate_base;
+ gdouble max_frames = (gdouble)duration * title->rate / title->rate_base;
widget = GHB_WIDGET (ud->builder, "start_point");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, max_frames);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), 1);
@@ -1488,29 +1492,57 @@ show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo)
widget = GHB_WIDGET (ud->builder, "angle");
gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), 1);
- gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, tinfo->angle_count);
- ghb_settings_set_int(ud->settings, "angle_count", tinfo->angle_count);
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, title->angle_count);
+ ghb_settings_set_int(ud->settings, "angle_count", title->angle_count);
ud->dont_clear_presets = FALSE;
+ // Set default metadata name
+ ghb_ui_update(ud, "MetaName", ghb_string_value(title->name));
+ if (title->metadata)
+ {
+ if (title->metadata->name)
+ {
+ ghb_ui_update(ud, "MetaName",
+ ghb_string_value(title->metadata->name));
+ }
+ ghb_ui_update(ud, "MetaArtist",
+ ghb_string_value(title->metadata->artist));
+ ghb_ui_update(ud, "MetaReleaseDate",
+ ghb_string_value(title->metadata->release_date));
+ ghb_ui_update(ud, "MetaComment",
+ ghb_string_value(title->metadata->comment));
+ if (!title->metadata->name && title->metadata->album)
+ {
+ ghb_ui_update(ud, "MetaName",
+ ghb_string_value(title->metadata->album));
+ }
+ ghb_ui_update(ud, "MetaAlbumArtist",
+ ghb_string_value(title->metadata->album_artist));
+ ghb_ui_update(ud, "MetaGenre",
+ ghb_string_value(title->metadata->genre));
+ ghb_ui_update(ud, "MetaDescription",
+ ghb_string_value(title->metadata->description));
+ ghb_ui_update(ud, "MetaLongDescription",
+ ghb_string_value(title->metadata->long_description));
+ }
}
void
set_title_settings(GValue *settings, gint titleindex)
{
- ghb_title_info_t tinfo;
-
ghb_settings_set_int(settings, "title", titleindex);
ghb_settings_set_int(settings, "title_no", titleindex);
- if (ghb_get_title_info (&tinfo, titleindex))
+ hb_title_t * title = ghb_get_title_info(titleindex);
+ if (title != NULL)
{
- ghb_settings_set_int(settings, "source_width", tinfo.width);
- ghb_settings_set_int(settings, "source_height", tinfo.height);
- ghb_settings_set_string(settings, "source", tinfo.path);
- if (tinfo.type == HB_STREAM_TYPE || tinfo.type == HB_FF_STREAM_TYPE)
+ ghb_settings_set_int(settings, "source_width", title->width);
+ ghb_settings_set_int(settings, "source_height", title->height);
+ ghb_settings_set_string(settings, "source", title->path);
+ if (title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE)
{
- if (tinfo.name != NULL && tinfo.name[0] != 0)
+ if (title->name != NULL && title->name[0] != 0)
{
- ghb_settings_set_string(settings, "volume_label", tinfo.name);
+ ghb_settings_set_string(settings, "volume_label", title->name);
}
else
{
@@ -1519,7 +1551,7 @@ set_title_settings(GValue *settings, gint titleindex)
}
}
ghb_settings_set_int(settings, "scale_width",
- tinfo.width - tinfo.crop[2] - tinfo.crop[3]);
+ title->width - title->crop[2] - title->crop[3]);
// If anamorphic or keep_aspect, the hight will
// be automatically calculated
@@ -1530,11 +1562,11 @@ set_title_settings(GValue *settings, gint titleindex)
if (!(keep_aspect || pic_par) || pic_par == 3)
{
ghb_settings_set_int(settings, "scale_height",
- tinfo.width - tinfo.crop[0] - tinfo.crop[1]);
+ title->width - title->crop[0] - title->crop[1]);
}
ghb_set_scale_settings(settings, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX);
- ghb_settings_set_int(settings, "angle_count", tinfo.angle_count);
+ ghb_settings_set_int(settings, "angle_count", title->angle_count);
}
update_chapter_list_settings(settings);
ghb_set_pref_audio_settings(titleindex, settings);
@@ -1559,14 +1591,13 @@ ghb_add_all_titles(signal_user_data_t *ud)
for (ii = 0; ii < count; ii++)
{
- ghb_title_info_t tinfo;
-
GValue *settings = ghb_value_dup(ud->settings);
ghb_settings_set_boolean(settings, "use_source_name", TRUE);
- if (ghb_get_title_info (&tinfo, ii))
+ hb_title_t * title = ghb_get_title_info(ii);
+ if (title != NULL)
{
- if (tinfo.type == HB_DVD_TYPE ||
- tinfo.type == HB_BD_TYPE)
+ if (title->type == HB_DVD_TYPE ||
+ title->type == HB_BD_TYPE)
{
ghb_settings_set_boolean(settings,
"title_no_in_destination", TRUE);
@@ -1582,7 +1613,6 @@ static gboolean update_preview = FALSE;
G_MODULE_EXPORT void
title_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
- ghb_title_info_t tinfo;
gint titleindex;
g_debug("title_changed_cb ()");
@@ -1593,9 +1623,10 @@ title_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
ghb_update_ui_combo_box (ud, "AudioTrack", titleindex, FALSE);
ghb_update_ui_combo_box (ud, "SubtitleTrack", titleindex, FALSE);
- if (ghb_get_title_info (&tinfo, titleindex))
+ hb_title_t * title = ghb_get_title_info(titleindex);
+ if (title != NULL)
{
- show_title_info(ud, &tinfo);
+ show_title_info(ud, title);
}
ghb_check_dependency(ud, widget, NULL);
update_chapter_list_settings(ud->settings);
@@ -1640,26 +1671,28 @@ G_MODULE_EXPORT void
ptop_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
gint ti;
- ghb_title_info_t tinfo;
+ hb_title_t * title;
ghb_widget_to_setting(ud->settings, widget);
ghb_check_dependency(ud, widget, NULL);
ghb_live_reset(ud);
ti = ghb_settings_combo_int(ud->settings, "title");
- if (!ghb_get_title_info (&tinfo, ti))
+ title = ghb_get_title_info(ti);
+ if (title == NULL)
return;
- gint duration = tinfo.duration / 90000;
+ gint num_chapters = hb_list_count(title->list_chapter);
+ gint duration = title->duration / 90000;
if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0)
{
widget = GHB_WIDGET (ud->builder, "start_point");
- gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, tinfo.num_chapters);
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, num_chapters);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), 1);
widget = GHB_WIDGET (ud->builder, "end_point");
- gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, tinfo.num_chapters);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), tinfo.num_chapters);
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, num_chapters);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), num_chapters);
}
else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 1)
{
@@ -1673,7 +1706,7 @@ ptop_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
}
else if (ghb_settings_combo_int(ud->settings, "PtoPType") == 2)
{
- gdouble max_frames = (gdouble)duration * tinfo.rate / tinfo.rate_base;
+ gdouble max_frames = (gdouble)duration * title->rate / title->rate_base;
widget = GHB_WIDGET (ud->builder, "start_point");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 1, max_frames);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(widget), 1);
@@ -1715,6 +1748,20 @@ setting_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
ghb_live_reset(ud);
}
+G_MODULE_EXPORT gboolean
+meta_focus_out_cb(GtkWidget *widget, GdkEventFocus *event,
+ signal_user_data_t *ud)
+{
+ ghb_widget_to_setting(ud->settings, widget);
+ return FALSE;
+}
+
+G_MODULE_EXPORT void
+meta_setting_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ ghb_widget_to_setting(ud->settings, widget);
+}
+
G_MODULE_EXPORT void
chapter_markers_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
@@ -1926,7 +1973,6 @@ G_MODULE_EXPORT void
crop_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
{
gint titleindex, crop[4];
- ghb_title_info_t tinfo;
g_debug("crop_changed_cb ()");
ghb_widget_to_setting(ud->settings, widget);
@@ -1940,13 +1986,14 @@ crop_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
crop[2] = ghb_settings_get_int(ud->settings, "PictureLeftCrop");
crop[3] = ghb_settings_get_int(ud->settings, "PictureRightCrop");
titleindex = ghb_settings_combo_int(ud->settings, "title");
- if (ghb_get_title_info (&tinfo, titleindex))
+ hb_title_t * title = ghb_get_title_info(titleindex);
+ if (title != NULL)
{
gint width, height;
gchar *text;
- width = tinfo.width - crop[2] - crop[3];
- height = tinfo.height - crop[0] - crop[1];
+ width = title->width - crop[2] - crop[3];
+ height = title->height - crop[0] - crop[1];
widget = GHB_WIDGET (ud->builder, "crop_dimensions");
text = g_strdup_printf ("%d x %d", width, height);
gtk_label_set_text (GTK_LABEL(widget), text);
@@ -2787,15 +2834,14 @@ ghb_backend_events(signal_user_data_t *ud)
ghb_refresh_preset(ud);
}
- ghb_title_info_t tinfo;
-
ghb_update_ui_combo_box(ud, "title", 0, FALSE);
titleindex = ghb_longest_title();
ghb_ui_update(ud, "title", ghb_int64_value(titleindex));
label = GTK_LABEL(GHB_WIDGET (ud->builder, "source_title"));
// Are there really any titles.
- if (!ghb_get_title_info(&tinfo, titleindex))
+ hb_title_t * title = ghb_get_title_info(titleindex);
+ if (title == NULL)
{
gtk_label_set_text(label, "None");
}
diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui
index bf24d17d1..b5ca17ca2 100644
--- a/gtk/src/ghb.ui
+++ b/gtk/src/ghb.ui
@@ -4231,6 +4231,317 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkAlignment" id="alignment76">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="top_padding">48</property>
+ <property name="right_padding">24</property>
+ <property name="left_padding">24</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkTable" id="tags_table">
+ <property name="n_rows">8</property>
+ <property name="n_columns">2</property>
+ <property name="visible">True</property>
+ <property name="column_spacing">5</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <child>
+ <object class="GtkLabel" id="tag_title_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Title:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="MetaName">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="max_length">80</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">50</property>
+ <property name="truncate_multiline">True</property>
+ <signal name="changed" handler="meta_setting_widget_changed_cb"/>
+ </object>
+ <packing>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tag_actors_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Actors:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="MetaArtist">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="max_length">80</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">50</property>
+ <property name="truncate_multiline">True</property>
+ <signal name="changed" handler="meta_setting_widget_changed_cb"/>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tag_director_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Director:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="MetaAlbumArtist">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="max_length">80</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">50</property>
+ <property name="truncate_multiline">True</property>
+ <signal name="changed" handler="meta_setting_widget_changed_cb"/>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tag_release_date_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Release Date:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="MetaReleaseDate">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="max_length">80</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">50</property>
+ <property name="truncate_multiline">True</property>
+ <signal name="changed" handler="meta_setting_widget_changed_cb"/>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tag_comment_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Comment:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="MetaComment">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="max_length">80</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">50</property>
+ <property name="truncate_multiline">True</property>
+ <signal name="changed" handler="meta_setting_widget_changed_cb"/>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tag_genre_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Genre:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="MetaGenre">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="max_length">80</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">50</property>
+ <property name="truncate_multiline">True</property>
+ <signal name="changed" handler="meta_setting_widget_changed_cb"/>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tag_description_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Description:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="MetaDescription">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="max_length">80</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">50</property>
+ <property name="truncate_multiline">True</property>
+ <signal name="changed" handler="meta_setting_widget_changed_cb"/>
+ </object>
+ <packing>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tag_long_description_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Plot:</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="MetaLongDescriptionScroll">
+ <property name="height_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">etched-in</property>
+ <child>
+ <object class="GtkTextView" id="MetaLongDescription">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="wrap_mode">GTK_WRAP_CHAR</property>
+ <property name="accepts_tab">False</property>
+ <signal handler="meta_focus_out_cb" name="focus_out_event"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="metadata_label">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Tags</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
</object>
</child>
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c
index f2638bf73..cda5882e8 100644
--- a/gtk/src/hb-backend.c
+++ b/gtk/src/hb-backend.c
@@ -1404,18 +1404,11 @@ ghb_subtitle_track_source(GValue *settings, gint track)
if (titleindex < 0)
return VOBSUB;
- hb_list_t * list;
hb_title_t * title;
hb_subtitle_t * sub;
if (h_scan == NULL) return VOBSUB;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
- {
- /* No valid title, stop right there */
- return VOBSUB;
- }
- title = hb_list_item( list, titleindex );
+ title = ghb_get_title_info( titleindex );
if (title == NULL) return VOBSUB; // Bad titleindex
sub = hb_list_item( title->list_subtitle, track);
if (sub != NULL)
@@ -1445,17 +1438,10 @@ ghb_subtitle_track_source_name(GValue *settings, gint track)
if (titleindex < 0)
goto done;
- hb_list_t * list;
hb_title_t * title;
hb_subtitle_t * sub;
- if (h_scan == NULL)
- goto done;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
- goto done;
-
- title = hb_list_item( list, titleindex );
+ title = ghb_get_title_info( titleindex );
if (title == NULL)
goto done;
@@ -1482,20 +1468,10 @@ ghb_subtitle_track_lang(GValue *settings, gint track)
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 );
+ title = ghb_get_title_info( titleindex );
if (title == NULL) // Bad titleindex
goto fail;
sub = hb_list_item( title->list_subtitle, track);
@@ -1509,17 +1485,9 @@ fail:
gint
ghb_get_title_number(gint titleindex)
{
- hb_list_t * list;
hb_title_t * title;
- if (h_scan == NULL) return 1;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
- {
- /* No valid title, stop right there */
- return 1;
- }
- title = hb_list_item( list, titleindex );
+ title = ghb_get_title_info( titleindex );
if (title == NULL) return 1; // Bad titleindex
return title->index;
}
@@ -2104,7 +2072,6 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
{
GtkTreeIter iter;
GtkListStore *store;
- hb_list_t * list = NULL;
hb_title_t * title = NULL;
hb_audio_config_t * audio;
gint ii;
@@ -2114,14 +2081,10 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
g_debug("audio_track_opts_set ()\n");
store = get_combo_box_store(builder, name);
gtk_list_store_clear(store);
- if (h_scan != NULL)
+ title = ghb_get_title_info(titleindex);
+ if (title != NULL)
{
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, titleindex );
- if (title != NULL)
- {
- count = hb_list_count( title->list_audio );
- }
+ count = hb_list_count( title->list_audio );
}
if (count > 100) count = 100;
if (audio_track_opts.map)
@@ -2188,16 +2151,13 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
const gchar*
ghb_audio_track_description(gint track, int titleindex)
{
- hb_list_t * list = NULL;
hb_title_t * title = NULL;
hb_audio_config_t * audio;
gchar * desc = "Unknown";
g_debug("ghb_audio_track_description ()\n");
- if (h_scan == NULL) return desc;
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, titleindex );
+ title = ghb_get_title_info( titleindex );
if (title == NULL) return desc;
if (track >= hb_list_count( title->list_audio )) return desc;
@@ -2211,7 +2171,6 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
{
GtkTreeIter iter;
GtkListStore *store;
- hb_list_t * list = NULL;
hb_title_t * title = NULL;
hb_subtitle_t * subtitle;
gint ii, count = 0;
@@ -2220,14 +2179,10 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
g_debug("subtitle_track_opts_set ()\n");
store = get_combo_box_store(builder, name);
gtk_list_store_clear(store);
- if (h_scan != NULL)
+ title = ghb_get_title_info(titleindex);
+ if (title != NULL)
{
- 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 );
- }
+ count = hb_list_count( title->list_subtitle );
}
if (count > 100) count = 100;
if (subtitle_opts.map) g_free(subtitle_opts.map);
@@ -2313,44 +2268,39 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
gint
ghb_longest_title()
{
- hb_list_t * list;
+ hb_title_set_t * title_set;
hb_title_t * title;
gint ii;
gint count = 0;
- gint titleindex = 0;
gint feature;
g_debug("ghb_longest_title ()\n");
if (h_scan == NULL) return 0;
- list = hb_get_titles( h_scan );
- count = hb_list_count( list );
+ title_set = hb_get_title_set( h_scan );
+ count = hb_list_count( title_set->list_title );
if (count < 1) return 0;
- title = (hb_title_t*)hb_list_item(list, 0);
- feature = title->job->feature;
+ title = (hb_title_t*)hb_list_item(title_set->list_title, 0);
+ feature = title_set->feature;
for (ii = 0; ii < count; ii++)
{
- title = (hb_title_t*)hb_list_item(list, ii);
+ title = (hb_title_t*)hb_list_item(title_set->list_title, ii);
if (title->index == feature)
{
return ii;
}
}
- return titleindex;
+ return 0;
}
const gchar*
ghb_get_source_audio_lang(gint titleindex, gint track)
{
- hb_list_t * list;
hb_title_t * title;
hb_audio_config_t * audio;
const gchar *lang = "und";
g_debug("ghb_lookup_1st_audio_lang ()\n");
- if (h_scan == NULL)
- return lang;
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, titleindex );
+ title = ghb_get_title_info( titleindex );
if (title == NULL)
return lang;
if (hb_list_count( title->list_audio ) <= track)
@@ -2390,7 +2340,6 @@ ghb_find_audio_track(
gint fallback_acodec,
GHashTable *track_indices)
{
- hb_list_t * list;
hb_title_t * title;
hb_audio_config_t * audio;
gint ii;
@@ -2405,9 +2354,7 @@ ghb_find_audio_track(
gint channels;
g_debug("find_audio_track ()\n");
- if (h_scan == NULL) return -1;
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, titleindex );
+ title = ghb_get_title_info( titleindex );
if (title != NULL)
{
count = hb_list_count( title->list_audio );
@@ -2617,15 +2564,12 @@ ghb_find_pref_subtitle_track(const gchar *lang)
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 );
+ title = ghb_get_title_info( titleindex );
if (title != NULL)
{
count = hb_list_count( title->list_subtitle );
@@ -2649,57 +2593,55 @@ ghb_find_subtitle_track(
gint source,
GHashTable * track_indices)
{
- hb_list_t * list;
hb_title_t * title;
hb_subtitle_t * subtitle;
gint count, ii;
gboolean *used;
-
+
g_debug("find_subtitle_track ()\n");
if (strcmp(lang, "auto") == 0)
return -1;
- if (h_scan == NULL) return -1;
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, titleindex );
- if (title != NULL)
+
+ title = ghb_get_title_info( titleindex );
+ if (title == NULL)
+ return -2;
+
+ count = hb_list_count( title->list_subtitle );
+ used = g_hash_table_lookup(track_indices, lang);
+ if (used == NULL)
{
- count = hb_list_count( title->list_subtitle );
- used = g_hash_table_lookup(track_indices, lang);
- if (used == NULL)
+ used = g_malloc0(count * sizeof(gboolean));
+ g_hash_table_insert(track_indices, g_strdup(lang), used);
+ }
+ // Try to find an item that matches the preferred language and source
+ for (ii = 0; ii < count; ii++)
+ {
+ if (used[ii])
+ continue;
+
+ subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
+ if (source == subtitle->source &&
+ ((strcmp(lang, subtitle->iso639_2) == 0) ||
+ (strcmp(lang, "und") == 0)))
{
- used = g_malloc0(count * sizeof(gboolean));
- g_hash_table_insert(track_indices, g_strdup(lang), used);
+ used[ii] = TRUE;
+ return ii;
}
- // Try to find an item that matches the preferred language and source
- for (ii = 0; ii < count; ii++)
- {
- if (used[ii])
- continue;
+ }
+ // Try to find an item that matches the preferred language
+ for (ii = 0; ii < count; ii++)
+ {
+ if (used[ii])
+ continue;
- subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
- if (source == subtitle->source &&
- ((strcmp(lang, subtitle->iso639_2) == 0) ||
- (strcmp(lang, "und") == 0)))
- {
- used[ii] = TRUE;
- return ii;
- }
- }
- // 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 (((!force || (force && ghb_canForceSub(subtitle->source))) &&
+ (!burn || (burn && ghb_canBurnSub(subtitle->source)))) &&
+ ((strcmp(lang, subtitle->iso639_2) == 0) ||
+ (strcmp(lang, "und") == 0)))
{
- if (used[ii])
- continue;
-
- subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii );
- if (((!force || (force && ghb_canForceSub(subtitle->source))) &&
- (!burn || (burn && ghb_canBurnSub(subtitle->source)))) &&
- ((strcmp(lang, subtitle->iso639_2) == 0) ||
- (strcmp(lang, "und") == 0)))
- {
- used[ii] = TRUE;
- return ii;
- }
+ used[ii] = TRUE;
+ return ii;
}
}
return -2;
@@ -3081,16 +3023,13 @@ ghb_build_advanced_opts_string(GValue *settings)
void
ghb_part_duration(gint tt, gint sc, gint ec, gint *hh, gint *mm, gint *ss)
{
- hb_list_t * list;
hb_title_t * title;
- hb_chapter_t * chapter;
+ hb_chapter_t * chapter;
gint count, c;
gint64 duration;
*hh = *mm = *ss = 0;
- if (h_scan == NULL) return;
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, tt );
+ title = ghb_get_title_info( tt );
if (title == NULL) return;
*hh = title->hours;
@@ -3119,16 +3058,13 @@ ghb_part_duration(gint tt, gint sc, gint ec, gint *hh, gint *mm, gint *ss)
void
ghb_get_chapter_duration(gint ti, gint ii, gint *hh, gint *mm, gint *ss)
{
- hb_list_t * list;
hb_title_t * title;
- hb_chapter_t * chapter;
+ hb_chapter_t * chapter;
gint count;
g_debug("ghb_get_chapter_duration (title = %d)\n", ti);
*hh = *mm = *ss = 0;
- if (h_scan == NULL) return;
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, ti );
+ title = ghb_get_title_info( ti );
if (title == NULL) return;
count = hb_list_count( title->list_chapter );
if (ii >= count) return;
@@ -3142,18 +3078,15 @@ ghb_get_chapter_duration(gint ti, gint ii, gint *hh, gint *mm, gint *ss)
GValue*
ghb_get_chapters(gint titleindex)
{
- hb_list_t * list;
hb_title_t * title;
- hb_chapter_t * chapter;
+ hb_chapter_t * chapter;
gint count, ii;
GValue *chapters = NULL;
g_debug("ghb_get_chapters (title = %d)\n", titleindex);
chapters = ghb_array_value_new(0);
- if (h_scan == NULL) return chapters;
- list = hb_get_titles( h_scan );
- title = (hb_title_t*)hb_list_item( list, titleindex );
+ title = ghb_get_title_info( titleindex );
if (title == NULL) return chapters;
count = hb_list_count( title->list_chapter );
for (ii = 0; ii < count; ii++)
@@ -3601,49 +3534,15 @@ ghb_track_status()
}
}
-gboolean
-ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
+hb_title_t *
+ghb_get_title_info(gint titleindex)
{
hb_list_t * list;
- hb_title_t * title;
-
- if (h_scan == NULL) return FALSE;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
- {
- /* No valid title, stop right there */
- return FALSE;
- }
- title = hb_list_item( list, titleindex );
- if (title == NULL) return FALSE; // Bad titleindex
- tinfo->index = titleindex;
- tinfo->video_codec_name = title->video_codec_name;
- tinfo->width = title->width;
- tinfo->height = title->height;
- memcpy(tinfo->crop, title->crop, 4 * sizeof(int));
- // Don't allow crop to 0
- if (title->crop[0] + title->crop[1] >= title->height)
- title->crop[0] = title->crop[1] = 0;
- if (title->crop[2] + title->crop[3] >= title->width)
- title->crop[2] = title->crop[3] = 0;
- tinfo->num_chapters = hb_list_count(title->list_chapter);
- tinfo->rate_base = title->rate_base;
- tinfo->rate = title->rate;
- tinfo->interlaced = title->detected_interlacing;
- hb_reduce(&(tinfo->aspect_n), &(tinfo->aspect_d),
- title->width * title->pixel_aspect_width,
- title->height * title->pixel_aspect_height);
- tinfo->hours = title->hours;
- tinfo->minutes = title->minutes;
- tinfo->seconds = title->seconds;
- tinfo->duration = title->duration;
-
- tinfo->angle_count = title->angle_count;
- tinfo->path = title->path;
- tinfo->name = title->name;
- tinfo->type = title->type;
- return TRUE;
+ if (h_scan == NULL) return NULL;
+ list = hb_get_titles( h_scan );
+ if (list == NULL) return NULL;
+ return hb_list_item( list, titleindex );
}
hb_audio_config_t*
@@ -3740,13 +3639,13 @@ ghb_limit_rational( gint *num, gint *den, gint limit )
void
ghb_set_scale_settings(GValue *settings, gint mode)
{
- hb_list_t * list;
hb_title_t * title;
hb_job_t * job;
gboolean keep_aspect;
gint pic_par;
gboolean autocrop, autoscale, noscale;
- gint crop[4], width, height, par_width, par_height;
+ gint crop[4] = {0,};
+ gint width, height, par_width, par_height;
gint crop_width, crop_height;
gint aspect_n, aspect_d;
gboolean keep_width = (mode & GHB_PIC_KEEP_WIDTH);
@@ -3769,19 +3668,13 @@ ghb_set_scale_settings(GValue *settings, gint mode)
ghb_settings_set_boolean(settings, "PictureKeepRatio", TRUE);
}
- if (h_scan == NULL) return;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
- {
- /* No valid title, stop right there */
- return;
- }
gint titleindex;
titleindex = ghb_settings_combo_int(settings, "title");
- title = hb_list_item( list, titleindex );
+ title = ghb_get_title_info (titleindex);
if (title == NULL) return;
- job = title->job;
+
+ job = hb_job_init( title );
if (job == NULL) return;
// First configure widgets
@@ -3801,14 +3694,12 @@ ghb_set_scale_settings(GValue *settings, gint mode)
keep_height = FALSE;
}
- ghb_title_info_t tinfo;
- ghb_get_title_info (&tinfo, titleindex);
if (autocrop)
{
- crop[0] = tinfo.crop[0];
- crop[1] = tinfo.crop[1];
- crop[2] = tinfo.crop[2];
- crop[3] = tinfo.crop[3];
+ crop[0] = title->crop[0];
+ crop[1] = title->crop[1];
+ crop[2] = title->crop[2];
+ crop[3] = title->crop[3];
ghb_settings_set_int(settings, "PictureTopCrop", crop[0]);
ghb_settings_set_int(settings, "PictureBottomCrop", crop[1]);
ghb_settings_set_int(settings, "PictureLeftCrop", crop[2]);
@@ -3826,8 +3717,8 @@ ghb_set_scale_settings(GValue *settings, gint mode)
gint need1, need2;
// Adjust the cropping to accomplish the desired width and height
- crop_width = tinfo.width - crop[2] - crop[3];
- crop_height = tinfo.height - crop[0] - crop[1];
+ crop_width = width - crop[2] - crop[3];
+ crop_height = height - crop[0] - crop[1];
width = MOD_DOWN(crop_width, mod);
height = MOD_DOWN(crop_height, mod);
@@ -3999,6 +3890,7 @@ ghb_set_scale_settings(GValue *settings, gint mode)
ghb_settings_set_int(settings, "PicturePARHeight", par_height);
ghb_settings_set_int(settings, "PictureDisplayWidth", disp_width);
ghb_settings_set_int(settings, "PictureDisplayHeight", height);
+ hb_job_close( &job );
}
void
@@ -4290,25 +4182,20 @@ ghb_validate_video(GValue *settings)
gboolean
ghb_validate_subtitles(GValue *settings)
{
- hb_list_t * list;
hb_title_t * title;
gchar *message;
- if (h_scan == NULL) return FALSE;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
+ gint titleindex;
+
+ titleindex = ghb_settings_combo_int(settings, "title");
+ title = ghb_get_title_info(titleindex);
+ if (title == NULL)
{
/* No valid title, stop right there */
g_message("No title found.\n");
return FALSE;
}
- gint titleindex;
-
- titleindex = ghb_settings_combo_int(settings, "title");
- title = hb_list_item( list, titleindex );
- if (title == NULL) return FALSE;
-
const GValue *slist, *subtitle;
gint count, ii, source;
gboolean burned, one_burned = FALSE;
@@ -4368,25 +4255,20 @@ ghb_validate_subtitles(GValue *settings)
gboolean
ghb_validate_audio(GValue *settings)
{
- hb_list_t * list;
hb_title_t * title;
gchar *message;
GValue *value;
- if (h_scan == NULL) return FALSE;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
+ gint titleindex;
+
+ titleindex = ghb_settings_combo_int(settings, "title");
+ title = ghb_get_title_info( titleindex );
+ if (title == NULL)
{
/* No valid title, stop right there */
g_message("No title found.\n");
return FALSE;
}
-
- gint titleindex;
-
- titleindex = ghb_settings_combo_int(settings, "title");
- title = hb_list_item( list, titleindex );
- if (title == NULL) return FALSE;
gint mux = ghb_settings_combo_int(settings, "FileFormat");
const GValue *audio_list;
@@ -4602,7 +4484,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
if (title == NULL) return;
/* Set job settings */
- job = title->job;
+ job = hb_job_init( title );
if (job == NULL) return;
job->angle = ghb_settings_get_int(js, "angle");
@@ -4686,9 +4568,8 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
{
name = g_strdup_printf ("Chapter %2d", chap+1);
}
- chapter_s = hb_list_item( job->title->list_chapter, chap);
- strncpy(chapter_s->title, name, 1023);
- chapter_s->title[1023] = '\0';
+ chapter_s = hb_list_item( job->list_chapter, chap);
+ hb_chapter_set_title(chapter_s, name);
g_free(name);
}
}
@@ -4945,7 +4826,8 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
}
dest_str = ghb_settings_get_string(js, "destination");
- job->file = dest_str;
+ hb_job_set_file( job, dest_str);
+ g_free(dest_str);
const GValue *subtitle_list;
gint subtitle;
@@ -5066,6 +4948,57 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
advanced_opts = NULL;
}
+ char * meta;
+
+ meta = ghb_settings_get_string(js, "MetaName");
+ if (meta && *meta)
+ {
+ hb_metadata_set_name(job->metadata, meta);
+ }
+ free(meta);
+ meta = ghb_settings_get_string(js, "MetaArtist");
+ if (meta && *meta)
+ {
+ hb_metadata_set_artist(job->metadata, meta);
+ }
+ free(meta);
+ meta = ghb_settings_get_string(js, "MetaAlbumArtist");
+ if (meta && *meta)
+ {
+ hb_metadata_set_album_artist(job->metadata, meta);
+ }
+ free(meta);
+ meta = ghb_settings_get_string(js, "MetaReleaseDate");
+ if (meta && *meta)
+ {
+ hb_metadata_set_release_date(job->metadata, meta);
+ }
+ free(meta);
+ meta = ghb_settings_get_string(js, "MetaComment");
+ if (meta && *meta)
+ {
+ hb_metadata_set_comment(job->metadata, meta);
+ }
+ free(meta);
+ meta = ghb_settings_get_string(js, "MetaGenre");
+ if (meta && *meta)
+ {
+ hb_metadata_set_genre(job->metadata, meta);
+ }
+ free(meta);
+ meta = ghb_settings_get_string(js, "MetaDescription");
+ if (meta && *meta)
+ {
+ hb_metadata_set_description(job->metadata, meta);
+ }
+ free(meta);
+ meta = ghb_settings_get_string(js, "MetaLongDescription");
+ if (meta && *meta)
+ {
+ hb_metadata_set_long_description(job->metadata, meta);
+ }
+ free(meta);
+
if (job->indepth_scan == 1)
{
// Subtitle scan. Look for subtitle matching audio language
@@ -5076,7 +5009,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
*/
job->pass = -1;
job->indepth_scan = 1;
- job->advanced_opts = NULL;
+ hb_job_set_advanced_opts(job, NULL);
/*
* Add the pre-scan job
@@ -5095,7 +5028,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
*/
job->pass = 1;
job->indepth_scan = 0;
- job->advanced_opts = advanced_opts;
+ hb_job_set_advanced_opts(job, advanced_opts);
/*
* If turbo options have been selected then set job->fastfirstpass
@@ -5109,10 +5042,9 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
{
job->fastfirstpass = 0;
}
+
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
hb_add( h, job );
- //if (job->advanced_opts != NULL)
- // g_free(job->advanced_opts);
job->pass = 2;
/*
@@ -5124,25 +5056,18 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
job->indepth_scan = 0;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
hb_add( h, job );
- //if (job->advanced_opts != NULL)
- // g_free(job->advanced_opts);
}
else
{
- job->advanced_opts = advanced_opts;
+ hb_job_set_advanced_opts(job, advanced_opts);
job->indepth_scan = 0;
job->pass = 0;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
hb_add( h, job );
- //if (job->advanced_opts != NULL)
- // g_free(job->advanced_opts);
}
+ g_free(advanced_opts);
- // Reset the job so it can be use again to add other jobs
- // for the same title.
- hb_reset_job(job);
-
- if (dest_str) g_free(dest_str);
+ hb_job_close(&job);
}
void
@@ -5327,19 +5252,16 @@ ghb_get_preview_image(
{
GValue *settings;
hb_title_t *title;
- hb_list_t *list;
+ hb_job_t *job;
settings = ud->settings;
- list = hb_get_titles( h_scan );
- if( !hb_list_count( list ) )
- {
- /* No valid title, stop right there */
- return NULL;
- }
- title = hb_list_item( list, titleindex );
- if (title == NULL) return NULL;
- if (title->job == NULL) return NULL;
- set_preview_job_settings(title->job, settings);
+ title = ghb_get_title_info( titleindex );
+ if( title == NULL ) return NULL;
+
+ job = hb_job_init( title );
+ if (job == NULL) return NULL;
+
+ set_preview_job_settings(job, settings);
// hb_get_preview doesn't compensate for anamorphic, so lets
// calculate scale factors
@@ -5347,13 +5269,13 @@ ghb_get_preview_image(
gint pic_par = ghb_settings_combo_int(settings, "PicturePAR");
if (pic_par)
{
- hb_set_anamorphic_size( title->job, &width, &height,
+ hb_set_anamorphic_size( job, &width, &height,
&par_width, &par_height );
}
// Make sure we have a big enough buffer to receive the image from libhb
- gint dstWidth = title->job->width;
- gint dstHeight= title->job->height;
+ gint dstWidth = job->width;
+ gint dstHeight= job->height;
static guint8 *buffer = NULL;
static gint bufferSize = 0;
@@ -5365,7 +5287,8 @@ ghb_get_preview_image(
bufferSize = newSize;
buffer = (guint8*) g_realloc( buffer, bufferSize );
}
- hb_get_preview( h_scan, title, index, buffer );
+ hb_get_preview( h_scan, job, index, buffer );
+ hb_job_close( &job );
// Create an GdkPixbuf and copy the libhb image into it, converting it from
// libhb's format something suitable.
diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h
index e1ff28a75..ded2fd8c0 100644
--- a/gtk/src/hb-backend.h
+++ b/gtk/src/hb-backend.h
@@ -62,29 +62,6 @@ typedef struct
#define GHB_PIC_KEEP_PAR 0x20
#define GHB_PIC_USE_MAX 0x40
-typedef struct
-{
- gchar *path;
- gchar *name;
- gint index;
- gint type;
- char *video_codec_name;
- gint width;
- gint height;
- gint crop[4];
- gint num_chapters;
- gint rate;
- gint rate_base;
- gint interlaced;
- gint aspect_n;
- gint aspect_d;
- gint hours;
- gint minutes;
- gint seconds;
- gint64 duration;
- gint angle_count;
-} ghb_title_info_t;
-
#define GHB_AUDIO_SAMPLERATE 1
#define GHB_AUDIO_BITRATE 2
#define GHB_FRAMERATE 3
@@ -123,7 +100,7 @@ void ghb_track_status(void);
void ghb_backend_scan(const gchar *path, gint titleindex, gint preview_count, guint64 min_duration);
void ghb_backend_scan_stop();
void ghb_backend_queue_scan(const gchar *path, gint titleindex);
-gboolean ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex);
+hb_title_t* ghb_get_title_info(gint titleindex);
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(GValue *settings, gint mode);
diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml
index 68667222a..e5d98cebe 100644
--- a/gtk/src/internal_defaults.xml
+++ b/gtk/src/internal_defaults.xml
@@ -24,6 +24,22 @@
<integer>100</integer>
<key>folder</key>
<string></string>
+ <key>MetaName</key>
+ <string></string>
+ <key>MetaArtist</key>
+ <string></string>
+ <key>MetaAlbumArtist</key>
+ <string></string>
+ <key>MetaReleaseDate</key>
+ <string></string>
+ <key>MetaComment</key>
+ <string></string>
+ <key>MetaGenre</key>
+ <string></string>
+ <key>MetaDescription</key>
+ <string></string>
+ <key>MetaLongDescription</key>
+ <string></string>
<key>preset</key>
<array>
<string>Normal</string>
diff --git a/gtk/src/presets.c b/gtk/src/presets.c
index eeacbde04..1905e5597 100644
--- a/gtk/src/presets.c
+++ b/gtk/src/presets.c
@@ -4195,12 +4195,12 @@ presets_row_expanded_cb(
}
static void
-preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo)
+preset_update_title_deps(signal_user_data_t *ud, hb_title_t *title)
{
GtkWidget *widget;
ghb_ui_update(ud, "scale_width",
- ghb_int64_value(tinfo->width - tinfo->crop[2] - tinfo->crop[3]));
+ ghb_int64_value(title->width - title->crop[2] - title->crop[3]));
// If anamorphic or keep_aspect, the hight will be automatically calculated
gboolean keep_aspect;
gint pic_par;
@@ -4209,35 +4209,34 @@ preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo)
if (!(keep_aspect || pic_par) || pic_par == 3)
{
ghb_ui_update(ud, "scale_height",
- ghb_int64_value(tinfo->height - tinfo->crop[0] - tinfo->crop[1]));
+ ghb_int64_value(title->height - title->crop[0] - title->crop[1]));
}
// Set the limits of cropping. hb_set_anamorphic_size crashes if
// you pass it a cropped width or height == 0.
gint bound;
- bound = tinfo->height / 2 - 2;
+ bound = title->height / 2 - 2;
widget = GHB_WIDGET (ud->builder, "PictureTopCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
widget = GHB_WIDGET (ud->builder, "PictureBottomCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
- bound = tinfo->width / 2 - 2;
+ bound = title->width / 2 - 2;
widget = GHB_WIDGET (ud->builder, "PictureLeftCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
widget = GHB_WIDGET (ud->builder, "PictureRightCrop");
gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
if (ghb_settings_get_boolean(ud->settings, "PictureAutoCrop"))
{
- ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(tinfo->crop[0]));
- ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(tinfo->crop[1]));
- ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(tinfo->crop[2]));
- ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(tinfo->crop[3]));
+ ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(title->crop[0]));
+ ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(title->crop[1]));
+ ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(title->crop[2]));
+ ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(title->crop[3]));
}
}
void
ghb_refresh_preset(signal_user_data_t *ud)
{
- ghb_title_info_t tinfo;
GValue *preset;
gint *indices, len;
@@ -4266,9 +4265,10 @@ ghb_refresh_preset(signal_user_data_t *ud)
ghb_set_pref_audio_from_settings(ud, ud->settings);
ghb_set_pref_subtitle(titleindex, ud);
ghb_settings_set_boolean(ud->settings, "preset_modified", FALSE);
- if (ghb_get_title_info (&tinfo, titleindex))
+ hb_title_t * title = ghb_get_title_info(titleindex);
+ if (title != NULL)
{
- preset_update_title_deps(ud, &tinfo);
+ preset_update_title_deps(ud, title);
}
ud->scale_busy = FALSE;
ghb_set_scale (ud, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX);
@@ -4306,7 +4306,6 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_
{
GtkTreeModel *store;
GtkTreeIter iter;
- ghb_title_info_t tinfo;
GtkWidget *widget;
g_debug("presets_list_selection_changed_cb ()");
@@ -4343,9 +4342,10 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_
ghb_set_pref_audio_from_settings(ud, ud->settings);
ghb_set_pref_subtitle(titleindex, ud);
ghb_settings_set_boolean(ud->settings, "preset_modified", FALSE);
- if (ghb_get_title_info (&tinfo, titleindex))
+ hb_title_t * title = ghb_get_title_info(titleindex);
+ if (title != NULL)
{
- preset_update_title_deps(ud, &tinfo);
+ preset_update_title_deps(ud, title);
}
ud->scale_busy = FALSE;
ghb_set_scale (ud, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX);
diff --git a/gtk/src/values.c b/gtk/src/values.c
index dd23d0e48..f755363e5 100644
--- a/gtk/src/values.c
+++ b/gtk/src/values.c
@@ -322,7 +322,14 @@ ghb_string_value(const gchar *str)
static GValue gval = {0,};
if (!G_IS_VALUE(&gval))
g_value_init(&gval, G_TYPE_STRING);
- g_value_set_string(&gval, str);
+ if (str == NULL)
+ {
+ g_value_set_string(&gval, "");
+ }
+ else
+ {
+ g_value_set_string(&gval, str);
+ }
return &gval;
}
diff --git a/libhb/bd.c b/libhb/bd.c
index 208782674..268cdaab0 100644
--- a/libhb/bd.c
+++ b/libhb/bd.c
@@ -491,10 +491,12 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
/* Chapters */
for ( ii = 0; ii < ti->chapter_count; ii++ )
{
+ char chapter_title[80];
chapter = calloc( sizeof( hb_chapter_t ), 1 );
chapter->index = ii + 1;
- sprintf( chapter->title, "Chapter %d", chapter->index );
+ sprintf( chapter_title, "Chapter %d", chapter->index );
+ hb_chapter_set_title( chapter, chapter_title );
chapter->duration = ti->chapters[ii].duration;
chapter->block_start = ti->chapters[ii].offset;
diff --git a/libhb/common.c b/libhb/common.c
index 821f17e76..80b526c2a 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -306,13 +306,13 @@ const char* hb_mixdown_get_short_name_from_mixdown(int amixdown)
return "";
}
-void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title )
+void hb_autopassthru_apply_settings( hb_job_t * job )
{
int i, j, already_printed;
hb_audio_t * audio;
- for( i = 0, already_printed = 0; i < hb_list_count( title->list_audio ); )
+ for( i = 0, already_printed = 0; i < hb_list_count( job->list_audio ); )
{
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
if( audio->config.out.codec == HB_ACODEC_AUTO_PASS )
{
if( !already_printed )
@@ -327,8 +327,8 @@ void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title )
{
hb_log( "Auto Passthru: passthru not possible and no valid fallback specified, dropping track %d",
audio->config.out.track );
- hb_list_rem( title->list_audio, audio );
- free( audio );
+ hb_list_rem( job->list_audio, audio );
+ hb_audio_close( &audio );
continue;
}
audio->config.out.samplerate = audio->config.in.samplerate;
@@ -1157,7 +1157,7 @@ hb_list_t * hb_list_init()
**********************************************************************
* Returns the number of items currently in the list
*********************************************************************/
-int hb_list_count( hb_list_t * l )
+int hb_list_count( const hb_list_t * l )
{
return l->items_count;
}
@@ -1252,7 +1252,7 @@ void hb_list_rem( hb_list_t * l, void * p )
* Returns item at position i, or NULL if there are not that many
* items in the list
*********************************************************************/
-void * hb_list_item( hb_list_t * l, int i )
+void * hb_list_item( const hb_list_t * l, int i )
{
if( i < 0 || i >= l->items_count )
{
@@ -1575,6 +1575,19 @@ void hb_register_error_handler( hb_error_handler_t * handler )
error_handler = handler;
}
+static void hb_update_str( char **dst, const char *src )
+{
+ if ( dst )
+ {
+ free( *dst );
+ *dst = NULL;
+ if ( src )
+ {
+ *dst = strdup( src );
+ }
+ }
+}
+
/**********************************************************************
* hb_title_init
**********************************************************************
@@ -1592,6 +1605,7 @@ hb_title_t * hb_title_init( char * path, int index )
t->list_chapter = hb_list_init();
t->list_subtitle = hb_list_init();
t->list_attachment = hb_list_init();
+ t->metadata = hb_metadata_init();
strcat( t->path, path );
// default to decoding mpeg2
t->video_id = 0xE0;
@@ -1616,65 +1630,252 @@ void hb_title_close( hb_title_t ** _t )
hb_subtitle_t * subtitle;
hb_attachment_t * attachment;
- while( ( audio = hb_list_item( t->list_audio, 0 ) ) )
- {
- hb_list_rem( t->list_audio, audio );
- free( audio );
- }
- hb_list_close( &t->list_audio );
-
while( ( chapter = hb_list_item( t->list_chapter, 0 ) ) )
{
hb_list_rem( t->list_chapter, chapter );
- free( chapter );
+ hb_chapter_close( &chapter );
}
hb_list_close( &t->list_chapter );
+ while( ( audio = hb_list_item( t->list_audio, 0 ) ) )
+ {
+ hb_list_rem( t->list_audio, audio );
+ hb_audio_close( &audio );
+ }
+ hb_list_close( &t->list_audio );
+
while( ( subtitle = hb_list_item( t->list_subtitle, 0 ) ) )
{
hb_list_rem( t->list_subtitle, subtitle );
- if ( subtitle->extradata )
- {
- free( subtitle->extradata );
- subtitle->extradata = NULL;
- }
- free( subtitle );
+ hb_subtitle_close( &subtitle );
}
hb_list_close( &t->list_subtitle );
while( ( attachment = hb_list_item( t->list_attachment, 0 ) ) )
{
hb_list_rem( t->list_attachment, attachment );
- if ( attachment->name )
+ hb_attachment_close( &attachment );
+ }
+ hb_list_close( &t->list_attachment );
+
+ hb_metadata_close( &t->metadata );
+
+ free( t->video_codec_name );
+ free(t->container_name);
+
+#if defined(HB_TITLE_JOBS)
+ hb_job_close( &t->job );
+#endif
+
+ free( t );
+ *_t = NULL;
+}
+
+/*
+ * Create a pristine job structure from a title
+ * title_index is 1 based
+ */
+hb_job_t * hb_job_init_by_index( hb_handle_t * h, int title_index )
+{
+ hb_title_set_t *title_set = hb_get_title_set( h );
+ hb_title_t * title = hb_list_item( title_set->list_title,
+ title_index - 1 );
+ return hb_job_init( title );
+}
+
+hb_job_t * hb_job_init( hb_title_t * title )
+{
+ hb_job_t * job;
+
+ if ( title == NULL )
+ return NULL;
+
+ job = calloc( sizeof( hb_job_t ), 1 );
+
+ job->title = title;
+
+ /* Set defaults settings */
+ job->chapter_start = 1;
+ job->chapter_end = hb_list_count( title->list_chapter );
+ job->list_chapter = hb_chapter_list_copy( title->list_chapter );
+
+ /* Autocrop by default. Gnark gnark */
+ memcpy( job->crop, title->crop, 4 * sizeof( int ) );
+
+ /* Preserve a source's pixel aspect, if it's available. */
+ if( title->pixel_aspect_width && title->pixel_aspect_height )
+ {
+ job->anamorphic.par_width = title->pixel_aspect_width;
+ job->anamorphic.par_height = title->pixel_aspect_height;
+ }
+
+ if( title->aspect != 0 && title->aspect != 1. &&
+ !job->anamorphic.par_width && !job->anamorphic.par_height)
+ {
+ hb_reduce( &job->anamorphic.par_width, &job->anamorphic.par_height,
+ (int)(title->aspect * title->height + 0.5), title->width );
+ }
+
+ job->width = title->width - job->crop[2] - job->crop[3];
+ hb_fix_aspect( job, HB_KEEP_WIDTH );
+ if( job->height > title->height - job->crop[0] - job->crop[1] )
+ {
+ job->height = title->height - job->crop[0] - job->crop[1];
+ hb_fix_aspect( job, HB_KEEP_HEIGHT );
+ }
+
+ job->keep_ratio = 1;
+
+ job->vcodec = HB_VCODEC_FFMPEG_MPEG4;
+ job->vquality = -1.0;
+ job->vbitrate = 1000;
+ job->pass = 0;
+ job->vrate = title->rate;
+ job->vrate_base = title->rate_base;
+
+ job->mux = HB_MUX_MP4;
+
+ job->list_audio = hb_list_init();
+ job->list_subtitle = hb_list_init();
+ job->list_filter = hb_list_init();
+
+ job->list_attachment = hb_attachment_list_copy( title->list_attachment );
+ job->metadata = hb_metadata_copy( title->metadata );
+
+ return job;
+}
+
+/**
+ * Clean up the job structure so that is is ready for setting up a new job.
+ * Should be called by front-ends after hb_add().
+ */
+/**********************************************************************
+ * hb_job_reset
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_job_reset( hb_job_t * job )
+{
+ if ( job )
+ {
+ hb_audio_t *audio;
+ hb_subtitle_t *subtitle;
+ hb_filter_object_t *filter;
+ hb_title_t * title = job->title;
+
+ // clean up audio list
+ while( ( audio = hb_list_item( job->list_audio, 0 ) ) )
+ {
+ hb_list_rem( job->list_audio, audio );
+ hb_audio_close( &audio );
+ }
+
+ // clean up subtitle list
+ while( ( subtitle = hb_list_item( job->list_subtitle, 0 ) ) )
{
- free( attachment->name );
- attachment->name = NULL;
+ hb_list_rem( job->list_subtitle, subtitle );
+ hb_subtitle_close( &subtitle );
}
- if ( attachment->data )
+
+ // clean up filter list
+ while( ( filter = hb_list_item( job->list_filter, 0 ) ) )
{
- free( attachment->data );
- attachment->data = NULL;
+ hb_list_rem( job->list_filter, filter );
+ hb_filter_close( &filter );
}
- free( attachment );
+
+ hb_metadata_close( &job->metadata );
+ job->metadata = hb_metadata_copy( title->metadata );
}
- hb_list_close( &t->list_attachment );
+}
- if( t->metadata )
+/**********************************************************************
+ * hb_job_close
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_job_close( hb_job_t ** _j )
+{
+ if (_j)
{
- if( t->metadata->coverart )
+ hb_job_t * job = *_j;
+
+ if (job)
{
- free( t->metadata->coverart );
+ hb_chapter_t *chapter;
+ hb_audio_t *audio;
+ hb_subtitle_t *subtitle;
+ hb_filter_object_t *filter;
+ hb_attachment_t *attachment;
+
+ free(job->file);
+ free(job->advanced_opts);
+
+ // clean up chapter list
+ while( ( chapter = hb_list_item( job->list_chapter, 0 ) ) )
+ {
+ hb_list_rem( job->list_chapter, chapter );
+ hb_chapter_close( &chapter );
+ }
+ hb_list_close( &job->list_chapter );
+
+ // clean up audio list
+ while( ( audio = hb_list_item( job->list_audio, 0 ) ) )
+ {
+ hb_list_rem( job->list_audio, audio );
+ hb_audio_close( &audio );
+ }
+ hb_list_close( &job->list_audio );
+
+ // clean up subtitle list
+ while( ( subtitle = hb_list_item( job->list_subtitle, 0 ) ) )
+ {
+ hb_list_rem( job->list_subtitle, subtitle );
+ hb_subtitle_close( &subtitle );
+ }
+ hb_list_close( &job->list_subtitle );
+
+ // clean up filter list
+ while( ( filter = hb_list_item( job->list_filter, 0 ) ) )
+ {
+ hb_list_rem( job->list_filter, filter );
+ hb_filter_close( &filter );
+ }
+ hb_list_close( &job->list_filter );
+
+ // clean up attachment list
+ while( ( attachment = hb_list_item( job->list_attachment, 0 ) ) )
+ {
+ hb_list_rem( job->list_attachment, attachment );
+ hb_attachment_close( &attachment );
+ }
+ hb_list_close( &job->list_attachment );
+
+ // clean up metadata
+ if ( job->metadata )
+ {
+ hb_metadata_close( &job->metadata );
+ }
+ free( job );
}
- free( t->metadata );
+ _j = NULL;
}
+}
- if ( t->video_codec_name )
+void hb_job_set_file( hb_job_t *job, const char *file )
+{
+ if ( job )
{
- free( t->video_codec_name );
+ hb_update_str( &job->file, file );
}
+}
- free( t );
- *_t = NULL;
+void hb_job_set_advanced_opts( hb_job_t *job, const char *advanced_opts )
+{
+ if ( job )
+ {
+ hb_update_str( &job->advanced_opts, advanced_opts );
+ }
}
hb_filter_object_t * hb_filter_copy( hb_filter_object_t * filter )
@@ -1689,6 +1890,30 @@ hb_filter_object_t * hb_filter_copy( hb_filter_object_t * filter )
return filter_copy;
}
+/**********************************************************************
+ * hb_filter_list_copy
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_list_t *hb_filter_list_copy(const hb_list_t *src)
+{
+ hb_list_t *list = hb_list_init();
+ hb_filter_object_t *filter = NULL;
+ int i;
+
+ if( src )
+ {
+ for( i = 0; i < hb_list_count(src); i++ )
+ {
+ if( ( filter = hb_list_item( src, i ) ) )
+ {
+ hb_list_add( list, hb_filter_copy(filter) );
+ }
+ }
+ }
+ return list;
+}
+
/**
* Gets a filter object with the given type
* @param filter_id The type of filter to get.
@@ -1759,6 +1984,93 @@ void hb_filter_close( hb_filter_object_t ** _f )
}
/**********************************************************************
+ * hb_chapter_copy
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_chapter_t *hb_chapter_copy(const hb_chapter_t *src)
+{
+ hb_chapter_t *chap = NULL;
+
+ if ( src )
+ {
+ chap = calloc( 1, sizeof(*chap) );
+ memcpy( chap, src, sizeof(*chap) );
+ if ( src->title )
+ {
+ chap->title = strdup( src->title );
+ }
+ }
+ return chap;
+}
+
+/**********************************************************************
+ * hb_chapter_list_copy
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_list_t *hb_chapter_list_copy(const hb_list_t *src)
+{
+ hb_list_t *list = hb_list_init();
+ hb_chapter_t *chapter = NULL;
+ int i;
+
+ if( src )
+ {
+ for( i = 0; i < hb_list_count(src); i++ )
+ {
+ if( ( chapter = hb_list_item( src, i ) ) )
+ {
+ hb_list_add( list, hb_chapter_copy(chapter) );
+ }
+ }
+ }
+ return list;
+}
+
+/**********************************************************************
+ * hb_chapter_close
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_chapter_close(hb_chapter_t **chap)
+{
+ if ( chap && *chap )
+ {
+ free((*chap)->title);
+ free(*chap);
+ *chap = NULL;
+ }
+}
+
+/**********************************************************************
+ * hb_chapter_set_title
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_chapter_set_title( hb_chapter_t *chapter, const char *title )
+{
+ if ( chapter )
+ {
+ hb_update_str( &chapter->title, title );
+ }
+}
+
+/**********************************************************************
+ * hb_chapter_set_title_by_index
+ **********************************************************************
+ * Applies information from the given job to the official job instance.
+ * @param job Handle to hb_job_t.
+ * @param chapter The chapter to apply the name to (1-based).
+ * @param titel to apply.
+ *********************************************************************/
+void hb_chapter_set_title_by_index( hb_job_t * job, int chapter_index, const char * title )
+{
+ hb_chapter_t * chapter = hb_list_item( job->list_chapter, chapter_index - 1 );
+ hb_chapter_set_title( chapter, title );
+}
+
+/**********************************************************************
* hb_audio_copy
**********************************************************************
*
@@ -1771,11 +2083,54 @@ hb_audio_t *hb_audio_copy(const hb_audio_t *src)
{
audio = calloc(1, sizeof(*audio));
memcpy(audio, src, sizeof(*audio));
+ if ( src->config.out.name )
+ {
+ audio->config.out.name = strdup(src->config.out.name);
+ }
}
return audio;
}
/**********************************************************************
+ * hb_audio_list_copy
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_list_t *hb_audio_list_copy(const hb_list_t *src)
+{
+ hb_list_t *list = hb_list_init();
+ hb_audio_t *audio = NULL;
+ int i;
+
+ if( src )
+ {
+ for( i = 0; i < hb_list_count(src); i++ )
+ {
+ if( ( audio = hb_list_item( src, i ) ) )
+ {
+ hb_list_add( list, hb_audio_copy(audio) );
+ }
+ }
+ }
+ return list;
+}
+
+/**********************************************************************
+ * hb_audio_close
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_audio_close( hb_audio_t **audio )
+{
+ if ( audio && *audio )
+ {
+ free((*audio)->config.out.name);
+ free(*audio);
+ *audio = NULL;
+ }
+}
+
+/**********************************************************************
* hb_audio_new
**********************************************************************
*
@@ -1878,7 +2233,7 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg)
}
if (audiocfg->out.name && *audiocfg->out.name)
{
- audio->config.out.name = audiocfg->out.name;
+ audio->config.out.name = strdup(audiocfg->out.name);
}
hb_list_add(job->list_audio, audio);
@@ -1918,6 +2273,45 @@ hb_subtitle_t *hb_subtitle_copy(const hb_subtitle_t *src)
}
/**********************************************************************
+ * hb_subtitle_list_copy
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_list_t *hb_subtitle_list_copy(const hb_list_t *src)
+{
+ hb_list_t *list = hb_list_init();
+ hb_subtitle_t *subtitle = NULL;
+ int i;
+
+ if( src )
+ {
+ for( i = 0; i < hb_list_count(src); i++ )
+ {
+ if( ( subtitle = hb_list_item( src, i ) ) )
+ {
+ hb_list_add( list, hb_subtitle_copy(subtitle) );
+ }
+ }
+ }
+ return list;
+}
+
+/**********************************************************************
+ * hb_subtitle_close
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_subtitle_close( hb_subtitle_t **sub )
+{
+ if ( sub && *sub )
+ {
+ free ((*sub)->extradata);
+ free(*sub);
+ *sub = NULL;
+ }
+}
+
+/**********************************************************************
* hb_subtitle_add
**********************************************************************
*
@@ -2026,6 +2420,238 @@ int hb_subtitle_can_pass( int source, int mux )
}
}
+/**********************************************************************
+ * hb_metadata_init
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_metadata_t *hb_metadata_init()
+{
+ hb_metadata_t *metadata = calloc( 1, sizeof(*metadata) );
+ return metadata;
+}
+
+/**********************************************************************
+ * hb_metadata_copy
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_metadata_t *hb_metadata_copy( const hb_metadata_t *src )
+{
+ hb_metadata_t *metadata = NULL;
+
+ if ( src )
+ {
+ metadata = calloc( 1, sizeof(*metadata) );
+ if ( src->name )
+ {
+ metadata->name = strdup(src->name);
+ }
+ if ( src->artist )
+ {
+ metadata->artist = strdup(src->artist);
+ }
+ if ( src->album_artist )
+ {
+ metadata->album_artist = strdup(src->album_artist);
+ }
+ if ( src->composer )
+ {
+ metadata->composer = strdup(src->composer);
+ }
+ if ( src->release_date )
+ {
+ metadata->release_date = strdup(src->release_date);
+ }
+ if ( src->comment )
+ {
+ metadata->comment = strdup(src->comment);
+ }
+ if ( src->album )
+ {
+ metadata->album = strdup(src->album);
+ }
+ if ( src->genre )
+ {
+ metadata->genre = strdup(src->genre);
+ }
+ if ( src->description )
+ {
+ metadata->description = strdup(src->description);
+ }
+ if ( src->long_description )
+ {
+ metadata->long_description = strdup(src->long_description);
+ }
+ if ( src->list_coverart )
+ {
+ int ii;
+ for ( ii = 0; ii < hb_list_count( src->list_coverart ); ii++ )
+ {
+ hb_coverart_t *art = hb_list_item( src->list_coverart, ii );
+ hb_metadata_add_coverart(
+ metadata, art->data, art->size, art->type );
+ }
+ }
+ }
+ return metadata;
+}
+
+/**********************************************************************
+ * hb_metadata_close
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_metadata_close( hb_metadata_t **_m )
+{
+ if ( _m && *_m )
+ {
+ hb_metadata_t *m = *_m;
+ hb_coverart_t *art;
+
+ free( m->name );
+ free( m->artist );
+ free( m->composer );
+ free( m->release_date );
+ free( m->comment );
+ free( m->album );
+ free( m->album_artist );
+ free( m->genre );
+ free( m->description );
+ free( m->long_description );
+
+ if ( m->list_coverart )
+ {
+ while( ( art = hb_list_item( m->list_coverart, 0 ) ) )
+ {
+ hb_list_rem( m->list_coverart, art );
+ free( art->data );
+ free( art );
+ }
+ hb_list_close( &m->list_coverart );
+ }
+
+ free( m );
+ *_m = NULL;
+ }
+}
+
+/**********************************************************************
+ * hb_metadata_set_*
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_metadata_set_name( hb_metadata_t *metadata, const char *name )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->name, name );
+ }
+}
+
+void hb_metadata_set_artist( hb_metadata_t *metadata, const char *artist )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->artist, artist );
+ }
+}
+
+void hb_metadata_set_composer( hb_metadata_t *metadata, const char *composer )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->composer, composer );
+ }
+}
+
+void hb_metadata_set_release_date( hb_metadata_t *metadata, const char *release_date )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->release_date, release_date );
+ }
+}
+
+void hb_metadata_set_comment( hb_metadata_t *metadata, const char *comment )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->comment, comment );
+ }
+}
+
+void hb_metadata_set_genre( hb_metadata_t *metadata, const char *genre )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->genre, genre );
+ }
+}
+
+void hb_metadata_set_album( hb_metadata_t *metadata, const char *album )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->album, album );
+ }
+}
+
+void hb_metadata_set_album_artist( hb_metadata_t *metadata, const char *album_artist )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->album_artist, album_artist );
+ }
+}
+
+void hb_metadata_set_description( hb_metadata_t *metadata, const char *description )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->description, description );
+ }
+}
+
+void hb_metadata_set_long_description( hb_metadata_t *metadata, const char *long_description )
+{
+ if ( metadata )
+ {
+ hb_update_str( &metadata->long_description, long_description );
+ }
+}
+
+void hb_metadata_add_coverart( hb_metadata_t *metadata, const uint8_t *data, int size, int type )
+{
+ if ( metadata )
+ {
+ if ( metadata->list_coverart == NULL )
+ {
+ metadata->list_coverart = hb_list_init();
+ }
+ hb_coverart_t *art = calloc( 1, sizeof(hb_coverart_t) );
+ art->data = malloc( size );
+ memcpy( art->data, data, size );
+ art->size = size;
+ art->type = type;
+ hb_list_add( metadata->list_coverart, art );
+ }
+}
+
+void hb_metadata_rem_coverart( hb_metadata_t *metadata, int idx )
+{
+ if ( metadata )
+ {
+ hb_coverart_t *art = hb_list_item( metadata->list_coverart, idx );
+ if ( art )
+ {
+ hb_list_rem( metadata->list_coverart, art );
+ free( art->data );
+ free( art );
+ }
+ }
+}
+
char * hb_strdup_printf( const char * fmt, ... )
{
int len;
@@ -2119,6 +2745,46 @@ hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src)
}
/**********************************************************************
+ * hb_attachment_list_copy
+ **********************************************************************
+ *
+ *********************************************************************/
+hb_list_t *hb_attachment_list_copy(const hb_list_t *src)
+{
+ hb_list_t *list = hb_list_init();
+ hb_attachment_t *attachment = NULL;
+ int i;
+
+ if( src )
+ {
+ for( i = 0; i < hb_list_count(src); i++ )
+ {
+ if( ( attachment = hb_list_item( src, i ) ) )
+ {
+ hb_list_add( list, hb_attachment_copy(attachment) );
+ }
+ }
+ }
+ return list;
+}
+
+/**********************************************************************
+ * hb_attachment_close
+ **********************************************************************
+ *
+ *********************************************************************/
+void hb_attachment_close( hb_attachment_t **attachment )
+{
+ if ( attachment && *attachment )
+ {
+ free((*attachment)->data);
+ free((*attachment)->name);
+ free(*attachment);
+ *attachment = NULL;
+ }
+}
+
+/**********************************************************************
* hb_yuv2rgb
**********************************************************************
* Converts a YCrCb pixel to an RGB pixel.
diff --git a/libhb/common.h b/libhb/common.h
index f7cc6dfef..41711e954 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -73,6 +73,7 @@ typedef struct hb_rate_s hb_rate_t;
typedef struct hb_mixdown_s hb_mixdown_t;
typedef struct hb_encoder_s hb_encoder_t;
typedef struct hb_job_s hb_job_t;
+typedef struct hb_title_set_s hb_title_set_t;
typedef struct hb_title_s hb_title_t;
typedef struct hb_chapter_s hb_chapter_t;
typedef struct hb_audio_s hb_audio_t;
@@ -81,6 +82,7 @@ typedef struct hb_subtitle_s hb_subtitle_t;
typedef struct hb_subtitle_config_s hb_subtitle_config_t;
typedef struct hb_attachment_s hb_attachment_t;
typedef struct hb_metadata_s hb_metadata_t;
+typedef struct hb_coverart_s hb_coverart_t;
typedef struct hb_state_s hb_state_t;
typedef union hb_esconfig_u hb_esconfig_t;
typedef struct hb_work_private_s hb_work_private_t;
@@ -102,11 +104,11 @@ typedef struct hb_lock_s hb_lock_t;
#include "libavutil/audioconvert.h"
hb_list_t * hb_list_init();
-int hb_list_count( hb_list_t * );
+int hb_list_count( const hb_list_t * );
void hb_list_add( hb_list_t *, void * );
void hb_list_insert( hb_list_t * l, int pos, void * p );
void hb_list_rem( hb_list_t *, void * );
-void * hb_list_item( hb_list_t *, int );
+void * hb_list_item( const hb_list_t *, int );
void hb_list_close( hb_list_t ** );
void hb_reduce( int *x, int *y, int num, int den );
@@ -117,12 +119,19 @@ void hb_limit_rational64( int64_t *x, int64_t *y, int64_t num, int64_t den, int6
#define HB_KEEP_HEIGHT 1
void hb_fix_aspect( hb_job_t * job, int keep );
+void hb_job_set_advanced_opts( hb_job_t *job, const char *advanced_opts );
+void hb_job_set_file( hb_job_t *job, const char *file );
+
hb_audio_t *hb_audio_copy(const hb_audio_t *src);
+hb_list_t *hb_audio_list_copy(const hb_list_t *src);
+void hb_audio_close(hb_audio_t **audio);
void hb_audio_config_init(hb_audio_config_t * audiocfg);
int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg);
hb_audio_config_t * hb_list_audio_config_item(hb_list_t * list, int i);
hb_subtitle_t *hb_subtitle_copy(const hb_subtitle_t *src);
+hb_list_t *hb_subtitle_list_copy(const hb_list_t *src);
+void hb_subtitle_close( hb_subtitle_t **sub );
int hb_subtitle_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg, int track);
int hb_srt_add(const hb_job_t * job, const hb_subtitle_config_t * subtitlecfg,
const char *lang);
@@ -131,6 +140,29 @@ int hb_subtitle_can_burn( int source );
int hb_subtitle_can_pass( int source, int mux );
hb_attachment_t *hb_attachment_copy(const hb_attachment_t *src);
+hb_list_t *hb_attachment_list_copy(const hb_list_t *src);
+void hb_attachment_close(hb_attachment_t **attachment);
+
+hb_metadata_t * hb_metadata_init();
+hb_metadata_t * hb_metadata_copy(const hb_metadata_t *src);
+void hb_metadata_close(hb_metadata_t **metadata);
+void hb_metadata_set_name( hb_metadata_t *metadata, const char *name );
+void hb_metadata_set_artist( hb_metadata_t *metadata, const char *artist );
+void hb_metadata_set_composer( hb_metadata_t *metadata, const char *composer );
+void hb_metadata_set_release_date( hb_metadata_t *metadata, const char *release_date );
+void hb_metadata_set_comment( hb_metadata_t *metadata, const char *comment );
+void hb_metadata_set_genre( hb_metadata_t *metadata, const char *genre );
+void hb_metadata_set_album( hb_metadata_t *metadata, const char *album );
+void hb_metadata_set_album_artist( hb_metadata_t *metadata, const char *album_artist );
+void hb_metadata_set_description( hb_metadata_t *metadata, const char *description );
+void hb_metadata_set_long_description( hb_metadata_t *metadata, const char *long_description );
+void hb_metadata_add_coverart( hb_metadata_t *metadata, const uint8_t *data, int size, int type );
+void hb_metadata_rem_coverart( hb_metadata_t *metadata, int ii );
+
+hb_chapter_t *hb_chapter_copy(const hb_chapter_t *src);
+hb_list_t *hb_chapter_list_copy(const hb_list_t *src);
+void hb_chapter_close(hb_chapter_t **chapter);
+void hb_chapter_set_title(hb_chapter_t *chapter, const char *title);
struct hb_rate_s
{
@@ -205,7 +237,9 @@ int hb_mixdown_get_low_freq_channel_count(int amixdown);
int hb_mixdown_get_mixdown_from_short_name(const char *short_name);
const char* hb_mixdown_get_short_name_from_mixdown(int amixdown);
-void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title );
+int hb_mixdown_get_mixdown_from_short_name( const char * short_name );
+const char * hb_mixdown_get_short_name_from_mixdown( int amixdown );
+void hb_autopassthru_apply_settings( hb_job_t * job );
void hb_autopassthru_print_settings( hb_job_t * job );
int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer );
int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown);
@@ -222,6 +256,12 @@ void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, fl
float hb_get_best_audio_compression( uint32_t codec, float compression);
float hb_get_default_audio_compression( uint32_t codec );
+struct hb_title_set_s
+{
+ hb_list_t * list_title;
+ int feature; // Detected DVD feature title
+};
+
/******************************************************************************
* hb_job_t: settings to be filled by the UI
*****************************************************************************/
@@ -333,6 +373,8 @@ struct hb_job_s
#define HB_COLR_MAT_SMPTE240M 7
// 0, 3-5, 8-65535: reserved
+ hb_list_t * list_chapter;
+
/* List of audio settings. */
hb_list_t * list_audio;
int acodec_copy_mask; // Auto Passthru allowed codecs
@@ -341,6 +383,10 @@ struct hb_job_s
/* Subtitles */
hb_list_t * list_subtitle;
+ hb_list_t * list_attachment;
+
+ hb_metadata_t * metadata;
+
/* Muxer settings
mux: output file format
file: file path */
@@ -349,7 +395,7 @@ struct hb_job_s
#define HB_MUX_MKV 0x200000
int mux;
- const char * file;
+ char * file;
/* Allow MP4 files > 4 gigs */
int largeFileSize;
@@ -534,7 +580,7 @@ struct hb_chapter_s
uint64_t duration;
/* Optional chapter title */
- char title[1024];
+ char *title;
};
/*
@@ -615,23 +661,38 @@ struct hb_subtitle_s
*/
struct hb_attachment_s
{
- enum attachtype { FONT_TTF_ATTACH } type;
+ enum attachtype { FONT_TTF_ATTACH, HB_ART_ATTACH } type;
char * name;
char * data;
int size;
};
+struct hb_coverart_s
+{
+ uint8_t *data;
+ uint32_t size;
+ enum arttype {
+ HB_ART_UNDEFINED,
+ HB_ART_BMP,
+ HB_ART_GIF,
+ HB_ART_PNG,
+ HB_ART_JPEG
+ } type;
+};
+
struct hb_metadata_s
{
- char name[255];
- char artist[255];
- char composer[255];
- char release_date[255];
- char comment[1024];
- char album[255];
- char genre[255];
- uint32_t coverart_size;
- uint8_t *coverart;
+ char *name;
+ char *artist; // Actors
+ char *composer;
+ char *release_date;
+ char *comment;
+ char *album; // DVD
+ char *album_artist; // Director
+ char *genre;
+ char *description;
+ char *long_description;
+ hb_list_t * list_coverart;
};
struct hb_title_s
@@ -682,7 +743,7 @@ struct hb_title_s
int video_codec_param; /* codec specific config */
char *video_codec_name;
int video_bitrate;
- const char *container_name;
+ char *container_name;
int data_rate;
hb_metadata_t *metadata;
@@ -692,12 +753,15 @@ struct hb_title_s
hb_list_t * list_subtitle;
hb_list_t * list_attachment;
- /* Job template for this title */
+#define HB_TITLE_JOBS
+#if defined(HB_TITLE_JOBS)
hb_job_t * job;
+#endif
uint32_t flags;
// set if video stream doesn't have IDR frames
#define HBTF_NO_IDR (1 << 0)
+#define HBTF_SCAN_COMPLETE (1 << 0)
};
@@ -941,7 +1005,8 @@ enum
hb_filter_object_t * hb_filter_init( int filter_id );
hb_filter_object_t * hb_filter_copy( hb_filter_object_t * filter );
-void hb_filter_close( hb_filter_object_t ** );
+hb_list_t *hb_filter_list_copy(const hb_list_t *src);
+void hb_filter_close( hb_filter_object_t ** );
typedef void hb_error_handler_t( const char *errmsg );
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index 4fd22c833..dd3c8879d 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -565,7 +565,7 @@ static void log_chapter( hb_work_private_t *pv, int chap_num, int64_t pts )
if ( !pv->job )
return;
- c = hb_list_item( pv->job->title->list_chapter, chap_num - 1 );
+ c = hb_list_item( pv->job->list_chapter, chap_num - 1 );
if ( c && c->title )
{
hb_log( "%s: \"%s\" (%d) at frame %u time %"PRId64,
diff --git a/libhb/decmetadata.c b/libhb/decmetadata.c
index e3829de09..513e64fbe 100644
--- a/libhb/decmetadata.c
+++ b/libhb/decmetadata.c
@@ -11,9 +11,10 @@
#include "common.h"
-static void decmp4metadata( hb_title_t *title )
+static int decmp4metadata( hb_title_t *title )
{
MP4FileHandle input_file;
+ int result = 0;
hb_deep_log( 2, "Got an MP4 input, read the metadata");
input_file = MP4Read( title->path, 0 );
@@ -31,35 +32,93 @@ static void decmp4metadata( hb_title_t *title )
if( tags->name ) {
hb_deep_log( 2, "Metadata Name in input file is '%s'", tags->name );
- strncpy( title->metadata->name, tags->name, sizeof(title->metadata->name) );
+ hb_metadata_set_name(title->metadata, tags->name);
+ result = 1;
}
if( tags->artist )
- strncpy( title->metadata->artist, tags->artist, sizeof(title->metadata->artist) );
+ {
+ hb_metadata_set_artist(title->metadata, tags->artist);
+ result = 1;
+ }
if( tags->composer )
- strncpy( title->metadata->composer, tags->composer, sizeof(title->metadata->composer) );
+ {
+ hb_metadata_set_composer(title->metadata, tags->composer);
+ result = 1;
+ }
if( tags->comments )
- strncpy( title->metadata->comment, tags->comments, sizeof(title->metadata->comment) );
+ {
+ hb_metadata_set_comment(title->metadata, tags->comments);
+ result = 1;
+ }
if( tags->releaseDate )
- strncpy( title->metadata->release_date, tags->releaseDate, sizeof(title->metadata->release_date) );
+ {
+ hb_metadata_set_release_date(title->metadata, tags->releaseDate);
+ result = 1;
+ }
if( tags->album )
- strncpy( title->metadata->album, tags->album, sizeof(title->metadata->album) );
+ {
+ hb_metadata_set_album(title->metadata, tags->album);
+ result = 1;
+ }
+
+ if( tags->albumArtist )
+ {
+ hb_metadata_set_album_artist(title->metadata, tags->albumArtist);
+ result = 1;
+ }
if( tags->genre )
- strncpy( title->metadata->genre, tags->genre, sizeof(title->metadata->genre) );
+ {
+ hb_metadata_set_genre(title->metadata, tags->genre);
+ result = 1;
+ }
+
+ if( tags->description )
+ {
+ hb_metadata_set_description(title->metadata, tags->description);
+ result = 1;
+ }
+
+ if( tags->longDescription )
+ {
+ hb_metadata_set_long_description(title->metadata, tags->longDescription);
+ result = 1;
+ }
- if( tags->artworkCount > 0 ) {
- const MP4TagArtwork* art = tags->artwork + 0; // first element
- title->metadata->coverart = (uint8_t*)malloc( art->size );
- title->metadata->coverart_size = art->size;
- memcpy( title->metadata->coverart, art->data, art->size );
+ int ii;
+ for ( ii = 0; ii < tags->artworkCount; ii++ )
+ {
+ const MP4TagArtwork* art = tags->artwork + ii;
+ int type;
+ switch ( art->type )
+ {
+ case MP4_ART_BMP:
+ type = HB_ART_BMP;
+ break;
+ case MP4_ART_GIF:
+ type = HB_ART_GIF;
+ break;
+ case MP4_ART_JPEG:
+ type = HB_ART_JPEG;
+ break;
+ case MP4_ART_PNG:
+ type = HB_ART_PNG;
+ break;
+ default:
+ type = HB_ART_UNDEFINED;
+ break;
+ }
+ hb_metadata_add_coverart(
+ title->metadata, art->data, art->size, type);
hb_deep_log( 2, "Got some cover art of type %d, size %d",
art->type,
- title->metadata->coverart_size );
+ art->size );
+ result = 1;
}
/* store,free tags */
@@ -91,11 +150,13 @@ static void decmp4metadata( hb_title_t *title )
if( chapter_list[i-1].title )
{
- strcpy( chapter->title, chapter_list[i-1].title );
+ hb_chapter_set_title( chapter, chapter_list[i-1].title );
}
else
{
- sprintf( chapter->title, "Chapter %d", chapter->index );
+ char chapter_title[80];
+ sprintf( chapter_title, "Chapter %d", chapter->index );
+ hb_chapter_set_title( chapter, chapter_title );
}
hb_deep_log( 2, "Added chapter %i, name='%s', dur=%"PRId64", (%02i:%02i:%02i)",
@@ -109,6 +170,7 @@ static void decmp4metadata( hb_title_t *title )
MP4Close( input_file );
}
+ return result;
}
/*
@@ -116,24 +178,16 @@ static void decmp4metadata( hb_title_t *title )
*
* Look at the title and extract whatever metadata we can from that title.
*/
-void decmetadata( hb_title_t *title )
+int decmetadata( hb_title_t *title )
{
if( !title )
{
- return;
+ return 0;
}
- if( title->metadata )
- {
- free( title->metadata );
- title->metadata = NULL;
- }
-
- title->metadata = calloc( sizeof(hb_metadata_t), 1);
-
if( !title->metadata )
{
- return;
+ return 0;
}
/*
@@ -141,9 +195,7 @@ void decmetadata( hb_title_t *title )
*/
if( title->container_name && strcmp(title->container_name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
{
- decmp4metadata( title );
- } else {
- free( title->metadata );
- title->metadata = NULL;
+ return decmp4metadata( title );
}
+ return 0;
}
diff --git a/libhb/decmpeg2.c b/libhb/decmpeg2.c
index 311fc93c8..991feb8e9 100644
--- a/libhb/decmpeg2.c
+++ b/libhb/decmpeg2.c
@@ -498,11 +498,11 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
m->look_for_iframe = 0;
const char *chap_name = "";
if ( m->job && new_chap > 0 &&
- hb_list_item( m->job->title->list_chapter,
+ hb_list_item( m->job->list_chapter,
new_chap - 1 ) )
{
hb_chapter_t * c = hb_list_item(
- m->job->title->list_chapter,
+ m->job->list_chapter,
new_chap - 1 );
chap_name = c->title;
}
@@ -514,10 +514,10 @@ static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
{
// this is the first frame returned by the decoder
m->first_pts = buf->s.start;
- if ( m->job && hb_list_item( m->job->title->list_chapter,
+ if ( m->job && hb_list_item( m->job->list_chapter,
m->job->chapter_start - 1 ) )
{
- hb_chapter_t * c = hb_list_item( m->job->title->list_chapter,
+ hb_chapter_t * c = hb_list_item( m->job->list_chapter,
m->job->chapter_start - 1 );
hb_log( "mpeg2: \"%s\" (%d) at frame %u time %"PRId64,
c->title, m->job->chapter_start, m->nframes, buf->s.start );
diff --git a/libhb/decsrtsub.c b/libhb/decsrtsub.c
index 55004c05f..6d1754068 100644
--- a/libhb/decsrtsub.c
+++ b/libhb/decsrtsub.c
@@ -464,7 +464,6 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job )
hb_buffer_t *buffer;
int i;
hb_chapter_t * chapter;
- hb_title_t *title = job->title;
pv = calloc( 1, sizeof( hb_work_private_t ) );
if( pv )
@@ -489,7 +488,7 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job )
pv->start_time = 0;
for( i = 1; i < job->chapter_start; ++i )
{
- chapter = hb_list_item( title->list_chapter, i - 1 );
+ chapter = hb_list_item( job->list_chapter, i - 1 );
if( chapter )
{
pv->start_time += chapter->duration;
@@ -501,7 +500,7 @@ static int decsrtInit( hb_work_object_t * w, hb_job_t * job )
pv->stop_time = pv->start_time;
for( i = job->chapter_start; i <= job->chapter_end; ++i )
{
- chapter = hb_list_item( title->list_chapter, i - 1 );
+ chapter = hb_list_item( job->list_chapter, i - 1 );
if( chapter )
{
pv->stop_time += chapter->duration;
diff --git a/libhb/dvd.c b/libhb/dvd.c
index 1a273f977..f342b5474 100644
--- a/libhb/dvd.c
+++ b/libhb/dvd.c
@@ -561,11 +561,13 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
for( i = 0;
i < vts->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts; i++ )
{
+ char chapter_title[80];
chapter = calloc( sizeof( hb_chapter_t ), 1 );
/* remember the on-disc chapter number */
chapter->index = i + 1;
- sprintf( chapter->title, "Chapter %d", chapter->index );
+ sprintf( chapter_title, "Chapter %d", chapter->index );
+ hb_chapter_set_title( chapter, chapter_title );
pgc_id = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgcn;
pgn = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgn;
diff --git a/libhb/dvdnav.c b/libhb/dvdnav.c
index 638b6e5af..c1f152efd 100644
--- a/libhb/dvdnav.c
+++ b/libhb/dvdnav.c
@@ -740,12 +740,14 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
for (i = pgn; i <= pgc->nr_of_programs; i++)
{
+ char chapter_title[80];
chapter = calloc( sizeof( hb_chapter_t ), 1 );
chapter->pgcn = pgcn;
chapter->pgn = i;
chapter->index = c + 1;
- sprintf( chapter->title, "Chapter %d", chapter->index );
+ sprintf( chapter_title, "Chapter %d", chapter->index );
+ hb_chapter_set_title( chapter, chapter_title );
hb_list_add( title->list_chapter, chapter );
c++;
diff --git a/libhb/hb.c b/libhb/hb.c
index 52ddc206b..8a1ec3b1e 100644
--- a/libhb/hb.c
+++ b/libhb/hb.c
@@ -36,7 +36,7 @@ struct hb_handle_s
int pid;
/* DVD/file scan thread */
- hb_list_t * list_title;
+ hb_title_set_t title_set;
hb_thread_t * scan_thread;
/* The thread which processes the jobs. Others threads are launched
@@ -71,7 +71,6 @@ int hb_instance_counter = 0;
int hb_process_initialized = 0;
static void thread_func( void * );
-hb_title_t * hb_get_title_by_index( hb_handle_t *, int );
static int ff_lockmgr_cb(void **mutex, enum AVLockOp op)
{
@@ -432,7 +431,7 @@ hb_handle_t * hb_init( int verbose, int update_check )
*/
hb_buffer_pool_init();
- h->list_title = hb_list_init();
+ h->title_set.list_title = hb_list_init();
h->jobs = hb_list_init();
h->state_lock = hb_lock_init();
@@ -531,7 +530,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check )
}
}
- h->list_title = hb_list_init();
+ h->title_set.list_title = hb_list_init();
h->jobs = hb_list_init();
h->current_job = NULL;
@@ -631,7 +630,7 @@ void hb_remove_previews( hb_handle_t * h )
dir = opendir( dirname );
if (dir == NULL) return;
- count = hb_list_count( h->list_title );
+ count = hb_list_count( h->title_set.list_title );
while( ( entry = readdir( dir ) ) )
{
if( entry->d_name[0] == '.' )
@@ -640,7 +639,7 @@ void hb_remove_previews( hb_handle_t * h )
}
for( i = 0; i < count; i++ )
{
- title = hb_list_item( h->list_title, i );
+ title = hb_list_item( h->title_set.list_title, i );
len = snprintf( filename, 1024, "%d_%d", h->id, title->index );
if (strncmp(entry->d_name, filename, len) == 0)
{
@@ -670,15 +669,15 @@ void hb_scan( hb_handle_t * h, const char * path, int title_index,
/* Clean up from previous scan */
hb_remove_previews( h );
- while( ( title = hb_list_item( h->list_title, 0 ) ) )
+ while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) )
{
- hb_list_rem( h->list_title, title );
+ hb_list_rem( h->title_set.list_title, title );
hb_title_close( &title );
}
hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
h->scan_thread = hb_scan_init( h, &h->scan_die, path, title_index,
- h->list_title, preview_count,
+ &h->title_set, preview_count,
store_previews, min_duration );
}
@@ -689,25 +688,12 @@ void hb_scan( hb_handle_t * h, const char * path, int title_index,
*/
hb_list_t * hb_get_titles( hb_handle_t * h )
{
- return h->list_title;
+ return h->title_set.list_title;
}
-/**
- * Create preview image of desired title a index of picture.
- * @param h Handle to hb_handle_t.
- * @param title_index Index of the title to get the preview for (1-based).
- * @param picture Index in title.
- * @param buffer Handle to buffer were image will be drawn.
- */
-void hb_get_preview_by_index( hb_handle_t * h, int title_index, int picture, uint8_t * buffer )
+hb_title_set_t * hb_get_title_set( hb_handle_t * h )
{
- hb_title_t * title;
-
- title = hb_get_title_by_index( h, title_index );
- if ( title != NULL )
- {
- hb_get_preview( h, title, picture, buffer );
- }
+ return &h->title_set;
}
int hb_save_preview( hb_handle_t * h, int title, int preview, hb_buffer_t *buf )
@@ -747,12 +733,16 @@ hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview )
{
FILE * file;
char filename[1024];
+ hb_title_set_t *title_set;
+
hb_title_t * title = NULL;
+ title_set = hb_get_title_set(h);
+
int ii;
- for (ii = 0; ii < hb_list_count(h->list_title); ii++)
+ for (ii = 0; ii < hb_list_count(title_set->list_title); ii++)
{
- title = hb_list_item( h->list_title, ii);
+ title = hb_list_item( title_set->list_title, ii);
if (title != NULL && title->index == title_idx)
{
break;
@@ -804,10 +794,10 @@ hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview )
* @param picture Index in title.
* @param buffer Handle to buffer were image will be drawn.
*/
-void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
+void hb_get_preview( hb_handle_t * h, hb_job_t * job, int picture,
uint8_t * buffer )
{
- hb_job_t * job = title->job;
+ hb_title_t * title = job->title;
char filename[1024];
hb_buffer_t * in_buf, * deint_buf = NULL, * preview_buf;
uint8_t * pen;
@@ -991,26 +981,6 @@ int hb_detect_comb( hb_buffer_t * buf, int color_equal, int color_diff, int thre
/**
* Calculates job width and height for anamorphic content,
*
- * @param h Instance handle
- * @param title_index Index of the title/job to inspect (1-based).
- * @param output_width Pointer to returned storage width
- * @param output_height Pointer to returned storage height
- * @param output_par_width Pointer to returned pixel width
- * @param output_par_height Pointer to returned pixel height
- */
-void hb_set_anamorphic_size_by_index( hb_handle_t * h, int title_index,
- int *output_width, int *output_height,
- int *output_par_width, int *output_par_height )
-{
- hb_title_t * title;
- title = hb_get_title_by_index( h, title_index );
-
- hb_set_anamorphic_size( title->job, output_width, output_height, output_par_width, output_par_height );
-}
-
-/**
- * Calculates job width and height for anamorphic content,
- *
* @param job Handle to hb_job_t
* @param output_width Pointer to returned storage width
* @param output_height Pointer to returned storage height
@@ -1423,53 +1393,6 @@ hb_job_t * hb_current_job( hb_handle_t * h )
}
/**
- * Applies information from the given job to the official job instance.
- * @param h Handle to hb_handle_t.
- * @param title_index Index of the title to apply the chapter name to (1-based).
- * @param chapter The chapter to apply the name to (1-based).
- * @param job Job information to apply.
- */
-void hb_set_chapter_name( hb_handle_t * h, int title_index, int chapter_index, const char * chapter_name )
-{
- hb_title_t * title;
- title = hb_get_title_by_index( h, title_index );
-
- hb_chapter_t * chapter = hb_list_item( title->list_chapter, chapter_index - 1 );
-
- strncpy(chapter->title, chapter_name, 1023);
- chapter->title[1023] = '\0';
-}
-
-/**
- * Applies information from the given job to the official job instance.
- * Currently only applies information needed for anamorphic size calculation and previews.
- * @param h Handle to hb_handle_t.
- * @param title_index Index of the title to apply the job information to (1-based).
- * @param job Job information to apply.
- */
-void hb_set_job( hb_handle_t * h, int title_index, hb_job_t * job )
-{
- int i;
-
- hb_title_t * title;
- title = hb_get_title_by_index( h, title_index );
-
- hb_job_t * job_target = title->job;
-
- job_target->deinterlace = job->deinterlace;
- job_target->width = job->width;
- job_target->height = job->height;
- job_target->maxWidth = job->maxWidth;
- job_target->maxHeight = job->maxHeight;
- for (i = 0; i < 4; i++)
- {
- job_target->crop[i] = job->crop[i];
- }
-
- job_target->anamorphic = job->anamorphic;
-}
-
-/**
* Adds a job to the job list.
* @param h Handle to hb_handle_t.
* @param job Handle to hb_job_t.
@@ -1477,85 +1400,21 @@ void hb_set_job( hb_handle_t * h, int title_index, hb_job_t * job )
void hb_add( hb_handle_t * h, hb_job_t * job )
{
hb_job_t * job_copy;
- hb_title_t * title, * title_copy;
- hb_chapter_t * chapter, * chapter_copy;
hb_audio_t * audio;
hb_subtitle_t * subtitle;
- hb_attachment_t * attachment;
int i;
char audio_lang[4];
- /* Copy the title */
- title = job->title;
- title_copy = malloc( sizeof( hb_title_t ) );
- memcpy( title_copy, title, sizeof( hb_title_t ) );
-
- title_copy->list_chapter = hb_list_init();
- for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
- {
- chapter = hb_list_item( title->list_chapter, i );
- chapter_copy = malloc( sizeof( hb_chapter_t ) );
- memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
- hb_list_add( title_copy->list_chapter, chapter_copy );
- }
-
- /*
- * Copy the metadata
- */
- if( title->metadata )
- {
- title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
-
- if( title_copy->metadata )
- {
- memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
-
- /*
- * Need to copy the artwork seperatly (TODO).
- */
- if( title->metadata->coverart )
- {
- title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
- if( title_copy->metadata->coverart )
- {
- memcpy( title_copy->metadata->coverart, title->metadata->coverart,
- title->metadata->coverart_size );
- } else {
- title_copy->metadata->coverart_size = 0;
- }
- }
- }
- }
-
- /* Copy the audio track(s) we want */
- title_copy->list_audio = hb_list_init();
- for( i = 0; i < hb_list_count(job->list_audio); i++ )
- {
- if( ( audio = hb_list_item( job->list_audio, i ) ) )
- {
- hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
- }
- }
-
- /* Initialize subtitle list - filled out further below */
- title_copy->list_subtitle = hb_list_init();
-
- /* Copy all the attachments */
- title_copy->list_attachment = hb_list_init();
- for( i = 0; i < hb_list_count(title->list_attachment); i++ )
- {
- if( ( attachment = hb_list_item( title->list_attachment, i ) ) )
- {
- hb_list_add( title_copy->list_attachment, hb_attachment_copy(attachment) );
- }
- }
- title_copy->video_codec_name = strdup( title->video_codec_name );
+ /* Copy the job */
+ job_copy = calloc( sizeof( hb_job_t ), 1 );
+ memcpy( job_copy, job, sizeof( hb_job_t ) );
- /* If we're doing Foreign Audio Search, copy all subtitles matching the first
- * audio track language we find in the audio list.
+ /* If we're doing Foreign Audio Search, copy all subtitles matching the
+ * first audio track language we find in the audio list.
*
- * Otherwise, copy all subtitles found in the input job (which can be manually
- * selected by the user, or added after the Foreign Audio Search pass). */
+ * Otherwise, copy all subtitles found in the input job (which can be
+ * manually selected by the user, or added after the Foreign Audio
+ * Search pass). */
memset( audio_lang, 0, sizeof( audio_lang ) );
if( job->indepth_scan )
@@ -1571,9 +1430,16 @@ void hb_add( hb_handle_t * h, hb_job_t * job )
break;
}
}
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+
+ /*
+ * If doing a subtitle scan then add all the matching subtitles for this
+ * language.
+ */
+ job_copy->list_subtitle = hb_list_init();
+
+ for( i = 0; i < hb_list_count( job->title->list_subtitle ); i++ )
{
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->title->list_subtitle, i );
if( strcmp( subtitle->iso639_2, audio_lang ) == 0 &&
hb_subtitle_can_force( subtitle->source ) )
{
@@ -1582,54 +1448,31 @@ void hb_add( hb_handle_t * h, hb_job_t * job )
*
* We will update the subtitle list on the next pass later, after
* the subtitle scan pass has completed. */
- hb_list_add( title_copy->list_subtitle, hb_subtitle_copy( subtitle ) );
+ hb_list_add( job_copy->list_subtitle,
+ hb_subtitle_copy( subtitle ) );
}
}
}
else
{
/* Copy all subtitles from the input job to title_copy/job_copy. */
- for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
- {
- if( ( subtitle = hb_list_item( job->list_subtitle, i ) ) )
- {
- hb_list_add( title_copy->list_subtitle, hb_subtitle_copy( subtitle ) );
- }
- }
+ job_copy->list_subtitle = hb_subtitle_list_copy( job->list_subtitle );
}
- /* Copy the job */
- job_copy = calloc( sizeof( hb_job_t ), 1 );
- memcpy( job_copy, job, sizeof( hb_job_t ) );
- title_copy->job = job_copy;
- job_copy->title = title_copy;
- job_copy->list_audio = title_copy->list_audio;
- job_copy->list_subtitle = title_copy->list_subtitle; // sharing list between title and job
- job_copy->file = strdup( job->file );
+ job_copy->list_chapter = hb_chapter_list_copy( job->list_chapter );
+ job_copy->list_audio = hb_audio_list_copy( job->list_audio );
+ job_copy->list_attachment = hb_attachment_list_copy( job->list_attachment );
+ job_copy->metadata = hb_metadata_copy( job->metadata );
+
+ if ( job->file )
+ job_copy->file = strdup( job->file );
+ if ( job->advanced_opts )
+ job_copy->advanced_opts = strdup( job->advanced_opts );
job_copy->h = h;
job_copy->pause = h->pause_lock;
/* Copy the job filter list */
- if( job->list_filter )
- {
- int i;
- int filter_count = hb_list_count( job->list_filter );
- job_copy->list_filter = hb_list_init();
- for( i = 0; i < filter_count; i++ )
- {
- /*
- * Copy the filters, since the MacGui reuses the global filter objects
- * meaning that queued up jobs overwrite the previous filter settings.
- * In reality, settings is probably the only field that needs duplicating
- * since it's the only value that is ever changed. But name is duplicated
- * as well for completeness. Not copying private_data since it gets
- * created for each job in renderInit.
- */
- hb_filter_object_t * filter = hb_list_item( job->list_filter, i );
- hb_filter_object_t * filter_copy = hb_filter_copy( filter );
- hb_list_add( job_copy->list_filter, filter_copy );
- }
- }
+ job_copy->list_filter = hb_filter_list_copy( job->list_filter );
/* Add the job to the list */
hb_list_add( h->jobs, job_copy );
@@ -1638,37 +1481,6 @@ void hb_add( hb_handle_t * h, hb_job_t * job )
}
/**
- * Clean up the job structure so that is is ready for setting up a new job.
- * Should be called by front-ends after hb_add().
- */
-void hb_reset_job( hb_job_t * job )
-{
- hb_audio_t *audio;
- hb_subtitle_t *subtitle;
- hb_filter_object_t *filter;
-
- // clean up audio list
- while( ( audio = hb_list_item( job->list_audio, 0 ) ) )
- {
- hb_list_rem( job->list_audio, audio );
- free( audio );
- }
- // clean up subtitle list
- while( ( subtitle = hb_list_item( job->list_subtitle, 0 ) ) )
- {
- hb_list_rem( job->list_subtitle, subtitle );
- free( subtitle );
- }
- // clean up filter list
- while( ( filter = hb_list_item( job->list_filter, 0 ) ) )
- {
- hb_list_rem( job->list_filter, filter );
- free( filter->settings );
- free( filter );
- }
-}
-
-/**
* Removes a job from the job list.
* @param h Handle to hb_handle_t.
* @param job Handle to hb_job_t.
@@ -1831,17 +1643,12 @@ void hb_close( hb_handle_t ** _h )
hb_thread_close( &h->main_thread );
- while( ( title = hb_list_item( h->list_title, 0 ) ) )
+ while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) )
{
- hb_list_rem( h->list_title, title );
- if( title->job )
- {
- hb_reset_job( title->job );
- }
- free( title->job );
+ hb_list_rem( h->title_set.list_title, title );
hb_title_close( &title );
}
- hb_list_close( &h->list_title );
+ hb_list_close( &h->title_set.list_title );
hb_list_close( &h->jobs );
hb_lock_close( &h->state_lock );
@@ -1925,9 +1732,9 @@ static void thread_func( void * _h )
hb_title_t * title;
hb_remove_previews( h );
- while( ( title = hb_list_item( h->list_title, 0 ) ) )
+ while( ( title = hb_list_item( h->title_set.list_title, 0 ) ) )
{
- hb_list_rem( h->list_title, title );
+ hb_list_rem( h->title_set.list_title, title );
hb_title_close( &title );
}
@@ -1936,7 +1743,7 @@ static void thread_func( void * _h )
else
{
hb_log( "libhb: scan thread found %d valid title(s)",
- hb_list_count( h->list_title ) );
+ hb_list_count( h->title_set.list_title ) );
}
hb_lock( h->state_lock );
h->state.state = HB_STATE_SCANDONE; //originally state.state
@@ -2024,29 +1831,6 @@ int hb_get_instance_id( hb_handle_t * h )
}
/**
- * Returns the title with the given title index.
- * @param h Handle to hb_handle_t
- * @param title_index the index of the title to get
- * @returns The requested title
- */
-hb_title_t * hb_get_title_by_index( hb_handle_t * h, int title_index )
-{
- hb_title_t * title;
- int i;
- int count = hb_list_count( h->list_title );
- for (i = 0; i < count; i++)
- {
- title = hb_list_item( h->list_title, i );
- if (title->index == title_index)
- {
- return title;
- }
- }
-
- return NULL;
-}
-
-/**
* Sets the current state.
* @param h Handle to hb_handle_t
* @param s Handle to new hb_state_t
diff --git a/libhb/hb.h b/libhb/hb.h
index da2311834..825032cfb 100644
--- a/libhb/hb.h
+++ b/libhb/hb.h
@@ -54,21 +54,23 @@ uint64_t hb_first_duration( hb_handle_t * );
Returns the list of valid titles detected by the latest scan. */
hb_list_t * hb_get_titles( hb_handle_t * );
+/* hb_get_title_set()
+ Returns the title set which contains a list of valid titles detected
+ by the latest scan and title set data. */
+hb_title_set_t * hb_get_title_set( hb_handle_t * );
+
/* hb_detect_comb()
Analyze a frame for interlacing artifacts, returns true if they're found.
Taken from Thomas Oestreich's 32detect filter in the Transcode project. */
int hb_detect_comb( hb_buffer_t * buf, int color_equal, int color_diff, int threshold, int prog_equal, int prog_diff, int prog_threshold );
+// JJJ: title->job?
int hb_save_preview( hb_handle_t * h, int title, int preview,
hb_buffer_t *buf );
hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview );
-void hb_get_preview_by_index( hb_handle_t *, int, int, uint8_t * );
-void hb_get_preview( hb_handle_t *, hb_title_t *, int,
+void hb_get_preview( hb_handle_t *, hb_job_t *, int,
uint8_t * );
void hb_set_size( hb_job_t *, double ratio, int pixels );
-void hb_set_anamorphic_size_by_index( hb_handle_t *, int,
- int *output_width, int *output_height,
- int *output_par_width, int *output_par_height );
void hb_set_anamorphic_size( hb_job_t *,
int *output_width, int *output_height,
int *output_par_width, int *output_par_height );
@@ -83,7 +85,11 @@ void hb_set_chapter_name( hb_handle_t *, int, int, const char * );
void hb_set_job( hb_handle_t *, int, hb_job_t * );
void hb_add( hb_handle_t *, hb_job_t * );
void hb_rem( hb_handle_t *, hb_job_t * );
-void hb_reset_job( hb_job_t * job );
+
+hb_job_t * hb_job_init_by_index( hb_handle_t *h, int title_index );
+hb_job_t * hb_job_init( hb_title_t * title );
+void hb_job_reset( hb_job_t * job );
+void hb_job_close( hb_job_t ** job );
void hb_start( hb_handle_t * );
void hb_pause( hb_handle_t * );
diff --git a/libhb/internal.h b/libhb/internal.h
index caa2e7189..1c02ffe85 100644
--- a/libhb/internal.h
+++ b/libhb/internal.h
@@ -228,7 +228,7 @@ static inline hb_buffer_t * hb_video_buffer_init( int width, int height )
hb_thread_t * hb_update_init( int * build, char * version );
hb_thread_t * hb_scan_init( hb_handle_t *, volatile int * die,
const char * path, int title_index,
- hb_list_t * list_title, int preview_count,
+ hb_title_set_t * title_set, int preview_count,
int store_previews, uint64_t min_duration );
hb_thread_t * hb_work_init( hb_list_t * jobs,
volatile int * die, int * error, hb_job_t ** job );
@@ -266,7 +266,7 @@ extern const hb_muxer_t hb_demux[];
/***********************************************************************
* decmetadata.c
**********************************************************************/
-extern void decmetadata( hb_title_t *title );
+extern int decmetadata( hb_title_t *title );
/***********************************************************************
* batch.c
diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c
index 6587a4dac..d5d9c7a92 100644
--- a/libhb/muxcommon.c
+++ b/libhb/muxcommon.c
@@ -441,7 +441,6 @@ static void mux_loop( void * _w )
hb_work_object_t * hb_muxer_init( hb_job_t * job )
{
- hb_title_t * title = job->title;
int i;
hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
hb_work_object_t * w;
@@ -490,9 +489,9 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job )
add_mux_track( mux, job->mux_data, 1 );
muxer->done = &muxer->private_data->mux->done;
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
- hb_audio_t *audio = hb_list_item( title->list_audio, i );
+ hb_audio_t *audio = hb_list_item( job->list_audio, i );
w = hb_get_work( WORK_MUX );
w->private_data = calloc( sizeof( hb_work_private_t ), 1 );
@@ -507,9 +506,9 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job )
w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY );
}
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
- hb_subtitle_t *subtitle = hb_list_item( title->list_subtitle, i );
+ hb_subtitle_t *subtitle = hb_list_item( job->list_subtitle, i );
if (subtitle->config.dest != PASSTHRUSUB)
continue;
diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c
index addd800de..2b629bc49 100644
--- a/libhb/muxmkv.c
+++ b/libhb/muxmkv.c
@@ -59,7 +59,6 @@ static uint8_t * create_flac_header( uint8_t *data, int size )
static int MKVInit( hb_mux_object_t * m )
{
hb_job_t * job = m->job;
- hb_title_t * title = job->title;
hb_audio_t * audio;
hb_mux_data_t * mux_data;
@@ -197,9 +196,9 @@ static int MKVInit( hb_mux_object_t * m )
mux_data->track = mk_createTrack(m->file, track);
/* add the audio tracks */
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
mux_data = calloc(1, sizeof( hb_mux_data_t ) );
audio->priv.mux_data = mux_data;
@@ -328,14 +327,14 @@ static int MKVInit( hb_mux_object_t * m )
"custom colors: OFF, tridx: 0000, "
"colors: 000000, 000000, 000000, 000000\n";
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
hb_subtitle_t * subtitle;
uint32_t rgb[16];
char subidx[2048];
int len;
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, i );
if (subtitle->config.dest != PASSTHRUSUB)
continue;
@@ -400,7 +399,7 @@ static int MKVInit( hb_mux_object_t * m )
if (need_fonts)
{
- hb_list_t * list_attachment = job->title->list_attachment;
+ hb_list_t * list_attachment = job->list_attachment;
int i;
for ( i = 0; i < hb_list_count(list_attachment); i++ )
{
@@ -437,7 +436,6 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
{
ogg_packet *op = NULL;
hb_job_t * job = m->job;
- hb_title_t * title = job->title;
uint64_t timecode = 0;
hb_chapter_t *chapter_data;
char tmp_buffer[1024];
@@ -457,7 +455,7 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
{
mux_data->current_chapter = buf->s.new_chap - 2;
}
- chapter_data = hb_list_item( title->list_chapter,
+ chapter_data = hb_list_item( job->list_chapter,
mux_data->current_chapter++ );
tmp_buffer[0] = '\0';
@@ -556,7 +554,6 @@ static int MKVEnd( hb_mux_object_t * m )
{
hb_job_t *job = m->job;
hb_mux_data_t *mux_data = job->mux_data;
- hb_title_t *title = job->title;
hb_chapter_t *chapter_data;
char tmp_buffer[1024];
char *string = tmp_buffer;
@@ -569,7 +566,7 @@ static int MKVEnd( hb_mux_object_t * m )
return 0;
}
- chapter_data = hb_list_item( title->list_chapter, mux_data->current_chapter++ );
+ chapter_data = hb_list_item( job->list_chapter, mux_data->current_chapter++ );
if(job->chapter_markers)
{
@@ -588,29 +585,62 @@ static int MKVEnd( hb_mux_object_t * m )
mk_createChapterSimple(m->file, mux_data->prev_chapter_tc, mux_data->prev_chapter_tc, string);
}
- if( title->metadata )
+ if( job->metadata )
{
- hb_metadata_t *md = title->metadata;
+ hb_metadata_t *md = job->metadata;
hb_deep_log( 2, "Writing Metadata to output file...");
- mk_createTagSimple( m->file, MK_TAG_TITLE, md->name );
- mk_createTagSimple( m->file, "ARTIST", md->artist );
- mk_createTagSimple( m->file, "COMPOSER", md->composer );
- mk_createTagSimple( m->file, MK_TAG_SYNOPSIS, md->comment );
- mk_createTagSimple( m->file, "DATE_RELEASED", md->release_date );
- // mk_createTagSimple( m->file, "", md->album );
- mk_createTagSimple( m->file, MK_TAG_GENRE, md->genre );
+ if ( md->name )
+ {
+ mk_createTagSimple( m->file, MK_TAG_TITLE, md->name );
+ }
+ if ( md->artist )
+ {
+ mk_createTagSimple( m->file, "ARTIST", md->artist );
+ }
+ if ( md->album_artist )
+ {
+ mk_createTagSimple( m->file, "DIRECTOR", md->album_artist );
+ }
+ if ( md->composer )
+ {
+ mk_createTagSimple( m->file, "COMPOSER", md->composer );
+ }
+ if ( md->release_date )
+ {
+ mk_createTagSimple( m->file, "DATE_RELEASED", md->release_date );
+ }
+ if ( md->comment )
+ {
+ mk_createTagSimple( m->file, "SUMMARY", md->comment );
+ }
+ if ( !md->name && md->album )
+ {
+ mk_createTagSimple( m->file, MK_TAG_TITLE, md->album );
+ }
+ if ( md->genre )
+ {
+ mk_createTagSimple( m->file, MK_TAG_GENRE, md->genre );
+ }
+ if ( md->description )
+ {
+ mk_createTagSimple( m->file, "DESCRIPTION", md->description );
+ }
+ if ( md->long_description )
+ {
+ mk_createTagSimple( m->file, "SYNOPSIS", md->long_description );
+ }
}
// Update and track private data that can change during
// encode.
int i;
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
mk_Track * track;
hb_audio_t * audio;
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
track = audio->priv.mux_data->track;
switch (audio->config.out.codec & HB_ACODEC_MASK)
diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c
index d21e4b767..f1380dc18 100644
--- a/libhb/muxmp4.c
+++ b/libhb/muxmp4.c
@@ -262,9 +262,9 @@ static int MP4Init( hb_mux_object_t * m )
}
/* add the audio tracks */
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
mux_data = calloc(1, sizeof( hb_mux_data_t ) );
audio->priv.mux_data = mux_data;
@@ -464,7 +464,7 @@ static int MP4Init( hb_mux_object_t * m )
/* Set the language for this track */
MP4SetTrackLanguage(m->file, mux_data->track, audio->config.lang.iso639_2);
- if( hb_list_count( title->list_audio ) > 1 )
+ if( hb_list_count( job->list_audio ) > 1 )
{
/* Set the audio track alternate group */
MP4SetTrackIntegerProperty(m->file, mux_data->track, "tkhd.alternate_group", 1);
@@ -944,7 +944,7 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
duration = m->sum_dur - m->chapter_duration + offset;
if ( duration >= (90000*3)/2 )
{
- chapter = hb_list_item( m->job->title->list_chapter,
+ chapter = hb_list_item( m->job->list_chapter,
buf->s.new_chap - 2 );
MP4AddChapter( m->file,
@@ -1248,7 +1248,6 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
static int MP4End( hb_mux_object_t * m )
{
hb_job_t * job = m->job;
- hb_title_t * title = job->title;
// Flush the delayed frame
if ( m->delay_buf )
@@ -1264,7 +1263,7 @@ static int MP4End( hb_mux_object_t * m )
if ( duration >= (90000*3)/2 )
{
- chapter = hb_list_item( m->job->title->list_chapter,
+ chapter = hb_list_item( m->job->list_chapter,
m->current_chapter - 1 );
MP4AddChapter( m->file,
@@ -1293,9 +1292,9 @@ static int MP4End( hb_mux_object_t * m )
/*
* Write the MP4 iTunes metadata if we have any metadata
*/
- if( title->metadata )
+ if( job->metadata )
{
- hb_metadata_t *md = title->metadata;
+ hb_metadata_t *md = job->metadata;
const MP4Tags* tags;
hb_deep_log( 2, "Writing Metadata to output file...");
@@ -1306,28 +1305,60 @@ static int MP4End( hb_mux_object_t * m )
MP4TagsFetch( tags, m->file );
/* populate */
- if( strlen( md->name ))
+ if( md->name )
MP4TagsSetName( tags, md->name );
- if( strlen( md->artist ))
+ if( md->artist )
MP4TagsSetArtist( tags, md->artist );
- if( strlen( md->composer ))
+ if( md->composer )
MP4TagsSetComposer( tags, md->composer );
- if( strlen( md->comment ))
+ if( md->comment )
MP4TagsSetComments( tags, md->comment );
- if( strlen( md->release_date ))
+ if( md->release_date )
MP4TagsSetReleaseDate( tags, md->release_date );
- if( strlen( md->album ))
+ if( md->album )
MP4TagsSetAlbum( tags, md->album );
- if( strlen( md->genre ))
+ if( md->album_artist )
+ MP4TagsSetAlbumArtist( tags, md->album_artist );
+ if( md->genre )
MP4TagsSetGenre( tags, md->genre );
+ if( md->description )
+ MP4TagsSetDescription( tags, md->description );
+ if( md->long_description )
+ MP4TagsSetLongDescription( tags, md->long_description );
- if( md->coverart )
+ if( md->list_coverart )
{
- MP4TagArtwork art;
- art.data = md->coverart;
- art.size = md->coverart_size;
- art.type = MP4_ART_UNDEFINED; // delegate typing to libmp4v2
- MP4TagsAddArtwork( tags, &art );
+ hb_coverart_t * coverart;
+ int ii;
+
+ for ( ii = 0; ii < hb_list_count( md->list_coverart ); ii++ )
+ {
+ coverart = hb_list_item( md->list_coverart, ii );
+ MP4TagArtwork art;
+ int type;
+ switch ( coverart->type )
+ {
+ case HB_ART_BMP:
+ type = MP4_ART_BMP;
+ break;
+ case HB_ART_GIF:
+ type = MP4_ART_GIF;
+ break;
+ case HB_ART_JPEG:
+ type = MP4_ART_JPEG;
+ break;
+ case HB_ART_PNG:
+ type = MP4_ART_PNG;
+ break;
+ default:
+ type = MP4_ART_UNDEFINED;
+ break;
+ }
+ art.data = coverart->data;
+ art.size = coverart->size;
+ art.type = type;
+ MP4TagsAddArtwork( tags, &art );
+ }
}
/* push data to MP4 file */
diff --git a/libhb/reader.c b/libhb/reader.c
index 8148e6590..d5c937422 100644
--- a/libhb/reader.c
+++ b/libhb/reader.c
@@ -386,12 +386,12 @@ void ReadLoop( void * _w )
* a media chapter that got merged, we'll stop ripping too early.
*/
int start = r->job->chapter_start;
- hb_chapter_t *chap = hb_list_item( r->title->list_chapter, chapter_end - 1 );
+ hb_chapter_t *chap = hb_list_item( r->job->list_chapter, chapter_end - 1 );
chapter_end = chap->index;
if (start > 1)
{
- chap = hb_list_item( r->title->list_chapter, start - 1 );
+ chap = hb_list_item( r->job->list_chapter, start - 1 );
start = chap->index;
}
/* end chapter mapping XXX */
@@ -453,12 +453,12 @@ void ReadLoop( void * _w )
* end chapter so that we end at the right time.
*/
int start = r->job->chapter_start;
- hb_chapter_t *chap = hb_list_item( r->title->list_chapter, chapter_end - 1 );
+ hb_chapter_t *chap = hb_list_item( r->job->list_chapter, chapter_end - 1 );
chapter_end = chap->index;
if (start > 1)
{
- chap = hb_list_item( r->title->list_chapter, start - 1 );
+ chap = hb_list_item( r->job->list_chapter, start - 1 );
start = chap->index;
}
@@ -670,14 +670,14 @@ void ReadLoop( void * _w )
push_buf( r, r->job->fifo_mpeg2, hb_buffer_init(0) );
hb_audio_t *audio;
- for( n = 0; (audio = hb_list_item( r->job->title->list_audio, n)); ++n )
+ for( n = 0; (audio = hb_list_item( r->job->list_audio, n)); ++n )
{
if ( audio->priv.fifo_in )
push_buf( r, audio->priv.fifo_in, hb_buffer_init(0) );
}
hb_subtitle_t *subtitle;
- for( n = 0; (subtitle = hb_list_item( r->job->title->list_subtitle, n)); ++n )
+ for( n = 0; (subtitle = hb_list_item( r->job->list_subtitle, n)); ++n )
{
if ( subtitle->fifo_in && subtitle->source == VOBSUB)
push_buf( r, subtitle->fifo_in, hb_buffer_init(0) );
@@ -780,11 +780,11 @@ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id )
}
}
- count = hb_list_count( title->list_subtitle );
+ count = hb_list_count( job->list_subtitle );
count = count > 99 ? 99 : count;
for( i = n = 0; i < count; i++ )
{
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, i );
if (id == subtitle->id)
{
/* pass the subtitles to be processed */
@@ -798,9 +798,9 @@ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id )
if( !job->indepth_scan )
{
- for( i = n = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = n = 0; i < hb_list_count( job->list_audio ); i++ )
{
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
if( id == audio->id )
{
r->fifos[n++] = audio->priv.fifo_in;
diff --git a/libhb/rendersub.c b/libhb/rendersub.c
index 568b7d1b0..c9e9f02cf 100644
--- a/libhb/rendersub.c
+++ b/libhb/rendersub.c
@@ -441,7 +441,7 @@ static int ssa_init( hb_filter_object_t * filter,
ass_set_message_cb( pv->ssa, ssa_log, NULL );
// Load embedded fonts
- hb_list_t * list_attachment = init->job->title->list_attachment;
+ hb_list_t * list_attachment = init->job->list_attachment;
int i;
for ( i = 0; i < hb_list_count(list_attachment); i++ )
{
@@ -678,9 +678,9 @@ static int hb_rendersub_init( hb_filter_object_t * filter,
}
// Find the subtitle we need
- for( ii = 0; ii < hb_list_count(init->job->title->list_subtitle); ii++ )
+ for( ii = 0; ii < hb_list_count(init->job->list_subtitle); ii++ )
{
- subtitle = hb_list_item( init->job->title->list_subtitle, ii );
+ subtitle = hb_list_item( init->job->list_subtitle, ii );
if( subtitle && subtitle->config.dest == RENDERSUB )
{
// Found it
diff --git a/libhb/scan.c b/libhb/scan.c
index 10ed35391..0163af406 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -18,7 +18,7 @@ typedef struct
char * path;
int title_index;
- hb_list_t * list_title;
+ hb_title_set_t * title_set;
hb_bd_t * bd;
hb_dvd_t * dvd;
@@ -51,7 +51,7 @@ static const char *aspect_to_string( double aspect )
hb_thread_t * hb_scan_init( hb_handle_t * handle, volatile int * die,
const char * path, int title_index,
- hb_list_t * list_title, int preview_count,
+ hb_title_set_t * title_set, int preview_count,
int store_previews, uint64_t min_duration )
{
hb_scan_t * data = calloc( sizeof( hb_scan_t ), 1 );
@@ -60,7 +60,7 @@ hb_thread_t * hb_scan_init( hb_handle_t * handle, volatile int * die,
data->die = die;
data->path = strdup( path );
data->title_index = title_index;
- data->list_title = list_title;
+ data->title_set = title_set;
data->preview_count = preview_count;
data->store_previews = store_previews;
@@ -88,7 +88,8 @@ static void ScanFunc( void * _data )
if( data->title_index )
{
/* Scan this title only */
- hb_list_add( data->list_title, hb_bd_title_scan( data->bd,
+ hb_list_add( data->title_set->list_title,
+ hb_bd_title_scan( data->bd,
data->title_index, 0 ) );
}
else
@@ -96,10 +97,12 @@ static void ScanFunc( void * _data )
/* Scan all titles */
for( i = 0; i < hb_bd_title_count( data->bd ); i++ )
{
- hb_list_add( data->list_title, hb_bd_title_scan( data->bd,
+ hb_list_add( data->title_set->list_title,
+ hb_bd_title_scan( data->bd,
i + 1, data->min_title_duration ) );
}
- feature = hb_bd_main_feature( data->bd, data->list_title );
+ feature = hb_bd_main_feature( data->bd,
+ data->title_set->list_title );
}
}
else if( ( data->dvd = hb_dvd_init( data->path ) ) )
@@ -109,7 +112,8 @@ static void ScanFunc( void * _data )
if( data->title_index )
{
/* Scan this title only */
- hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd,
+ hb_list_add( data->title_set->list_title,
+ hb_dvd_title_scan( data->dvd,
data->title_index, 0 ) );
}
else
@@ -117,10 +121,12 @@ static void ScanFunc( void * _data )
/* Scan all titles */
for( i = 0; i < hb_dvd_title_count( data->dvd ); i++ )
{
- hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd,
+ hb_list_add( data->title_set->list_title,
+ hb_dvd_title_scan( data->dvd,
i + 1, data->min_title_duration ) );
}
- feature = hb_dvd_main_feature( data->dvd, data->list_title );
+ feature = hb_dvd_main_feature( data->dvd,
+ data->title_set->list_title );
}
}
else if ( ( data->batch = hb_batch_init( data->path ) ) )
@@ -131,7 +137,7 @@ static void ScanFunc( void * _data )
title = hb_batch_title_scan( data->batch, data->title_index );
if ( title )
{
- hb_list_add( data->list_title, title );
+ hb_list_add( data->title_set->list_title, title );
}
}
else
@@ -144,7 +150,7 @@ static void ScanFunc( void * _data )
title = hb_batch_title_scan( data->batch, i + 1 );
if ( title != NULL )
{
- hb_list_add( data->list_title, title );
+ hb_list_add( data->title_set->list_title, title );
}
}
}
@@ -156,7 +162,7 @@ static void ScanFunc( void * _data )
{
title = hb_stream_title_scan( data->stream, title );
if ( title )
- hb_list_add( data->list_title, title );
+ hb_list_add( data->title_set->list_title, title );
}
else
{
@@ -166,7 +172,7 @@ static void ScanFunc( void * _data )
}
}
- for( i = 0; i < hb_list_count( data->list_title ); )
+ for( i = 0; i < hb_list_count( data->title_set->list_title ); )
{
int j;
hb_state_t state;
@@ -176,7 +182,7 @@ static void ScanFunc( void * _data )
{
goto finish;
}
- title = hb_list_item( data->list_title, i );
+ title = hb_list_item( data->title_set->list_title, i );
#define p state.param.scanning
/* Update the UI */
@@ -185,7 +191,7 @@ static void ScanFunc( void * _data )
p.title_count = data->dvd ? hb_dvd_title_count( data->dvd ) :
data->bd ? hb_bd_title_count( data->bd ) :
data->batch ? hb_batch_title_count( data->batch ) :
- hb_list_count(data->list_title);
+ hb_list_count(data->title_set->list_title);
hb_set_state( data->h, &state );
#undef p
@@ -194,7 +200,7 @@ static void ScanFunc( void * _data )
if( !DecodePreviews( data, title ) )
{
/* TODO: free things */
- hb_list_rem( data->list_title, title );
+ hb_list_rem( data->title_set->list_title, title );
for( j = 0; j < hb_list_count( title->list_audio ); j++)
{
audio = hb_list_item( title->list_audio, j );
@@ -247,64 +253,16 @@ static void ScanFunc( void * _data )
i++;
}
- /* Init jobs templates */
- for( i = 0; i < hb_list_count( data->list_title ); i++ )
- {
- hb_job_t * job;
-
- title = hb_list_item( data->list_title, i );
- job = calloc( sizeof( hb_job_t ), 1 );
- title->job = job;
-
- job->title = title;
- job->feature = feature;
+ data->title_set->feature = feature;
- /* Set defaults settings */
- job->chapter_start = 1;
- job->chapter_end = hb_list_count( title->list_chapter );
-
- /* Autocrop by default. Gnark gnark */
- memcpy( job->crop, title->crop, 4 * sizeof( int ) );
-
- /* Preserve a source's pixel aspect, if it's available. */
- if( title->pixel_aspect_width && title->pixel_aspect_height )
- {
- job->anamorphic.par_width = title->pixel_aspect_width;
- job->anamorphic.par_height = title->pixel_aspect_height;
- }
-
- if( title->aspect != 0 && title->aspect != 1. &&
- !job->anamorphic.par_width && !job->anamorphic.par_height)
- {
- hb_reduce( &job->anamorphic.par_width, &job->anamorphic.par_height,
- (int)(title->aspect * title->height + 0.5), title->width );
- }
-
- job->width = title->width - job->crop[2] - job->crop[3];
- hb_fix_aspect( job, HB_KEEP_WIDTH );
- if( job->height > title->height - job->crop[0] - job->crop[1] )
- {
- job->height = title->height - job->crop[0] - job->crop[1];
- hb_fix_aspect( job, HB_KEEP_HEIGHT );
- }
-
- hb_log( "scan: title (%d) job->width:%d, job->height:%d",
- i, job->width, job->height );
-
- job->keep_ratio = 1;
-
- job->vcodec = HB_VCODEC_FFMPEG_MPEG4;
- job->vquality = -1.0;
- job->vbitrate = 1000;
- job->pass = 0;
- job->vrate = title->rate;
- job->vrate_base = title->rate_base;
-
- job->list_audio = hb_list_init();
- job->list_subtitle = hb_list_init();
- job->list_filter = hb_list_init();
-
- job->mux = HB_MUX_MP4;
+ /* Mark title scan complete and init jobs */
+ for( i = 0; i < hb_list_count( data->title_set->list_title ); i++ )
+ {
+ title = hb_list_item( data->title_set->list_title, i );
+ title->flags |= HBTF_SCAN_COMPLETE;
+#if defined(HB_TITLE_JOBS)
+ title->job = hb_job_init( title );
+#endif
}
finish:
diff --git a/libhb/stream.c b/libhb/stream.c
index ede9f33d3..503e296dc 100644
--- a/libhb/stream.c
+++ b/libhb/stream.c
@@ -960,11 +960,10 @@ hb_stream_t * hb_bd_stream_open( hb_title_t *title )
update_ts_streams( d, pid, 0, stream_type, S, NULL );
}
- // When scanning, title->job == NULL. We don't need to wait for
- // a PCR when scanning. In fact, it trips us up on the first
- // preview of every title since we would have to read quite a
- // lot of data before finding the PCR.
- if ( title->job )
+ // We don't need to wait for a PCR when scanning. In fact, it
+ // trips us up on the first preview of every title since we would
+ // have to read quite a lot of data before finding the PCR.
+ if ( !(title->flags & HBTF_SCAN_COMPLETE) )
{
/* BD has PCRs, but the BD index always points to a packet
* after a PCR packet, so we will not see the initial PCR
@@ -2774,7 +2773,6 @@ int decode_program_map(hb_stream_t* stream)
stream->pmt_info.PCR_PID = bits_get(&bb, 13);
bits_get(&bb, 4);
int program_info_length = bits_get(&bb, 12);
-
int i;
for (i = 0; i < program_info_length - 2; )
{
@@ -5371,6 +5369,7 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id
static char *get_ffmpeg_metadata_value( AVDictionary *m, char *key )
{
AVDictionaryEntry *tag = NULL;
+
while ( (tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX)) )
{
if ( !strcmp( key, tag->key ) )
@@ -5425,6 +5424,64 @@ static void add_ffmpeg_attachment( hb_title_t *title, hb_stream_t *stream, int i
hb_list_add(title->list_attachment, attachment);
}
+static int ffmpeg_decmetadata( AVDictionary *m, hb_title_t *title )
+{
+ int result = 0;
+ AVDictionaryEntry *tag = NULL;
+ while ( (tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX)) )
+ {
+ if ( !strcasecmp( "TITLE", tag->key ) )
+ {
+ hb_metadata_set_name(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "ARTIST", tag->key ) )
+ {
+ hb_metadata_set_artist(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "DIRECTOR", tag->key ) ||
+ !strcasecmp( "album_artist", tag->key ) )
+ {
+ hb_metadata_set_album_artist(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "COMPOSER", tag->key ) )
+ {
+ hb_metadata_set_composer(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "DATE_RELEASED", tag->key ) ||
+ !strcasecmp( "date", tag->key ) )
+ {
+ hb_metadata_set_release_date(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "SUMMARY", tag->key ) ||
+ !strcasecmp( "comment", tag->key ) )
+ {
+ hb_metadata_set_comment(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "GENRE", tag->key ) )
+ {
+ hb_metadata_set_genre(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "DESCRIPTION", tag->key ) )
+ {
+ hb_metadata_set_description(title->metadata, tag->value);
+ result = 1;
+ }
+ else if ( !strcasecmp( "SYNOPSIS", tag->key ) )
+ {
+ hb_metadata_set_long_description(title->metadata, tag->value);
+ result = 1;
+ }
+ }
+ return result;
+}
+
static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title )
{
AVFormatContext *ic = stream->ffmpeg_ic;
@@ -5520,16 +5577,20 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title )
chapter->seconds = ( seconds % 60 );
tag = av_dict_get( m->metadata, "title", NULL, 0 );
- /* Ignore generic chapter names set by MakeMKV ("Chapter 00" etc.).
+ /* Ignore generic chapter names set by MakeMKV
+ * ("Chapter 00" etc.).
* Our default chapter names are better. */
if( tag && tag->value &&
- ( strncmp( "Chapter ", tag->value, 8 ) || strlen( tag->value ) > 11 ) )
+ ( strncmp( "Chapter ", tag->value, 8 ) ||
+ strlen( tag->value ) > 11 ) )
{
- strcpy( chapter->title, tag->value );
+ hb_chapter_set_title( chapter, tag->value );
}
else
{
- sprintf( chapter->title, "Chapter %d", chapter->index );
+ char chapter_title[80];
+ sprintf( chapter_title, "Chapter %d", chapter->index );
+ hb_chapter_set_title( chapter, chapter_title );
}
hb_deep_log( 2, "Added chapter %i, name='%s', dur=%"PRIu64", (%02i:%02i:%02i)",
@@ -5543,7 +5604,11 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title )
/*
* Fill the metadata.
*/
- decmetadata( title );
+ // JJJ: is this necessary? can we just get this metadata from libav api's?
+ if (!decmetadata( title ))
+ {
+ ffmpeg_decmetadata( ic->metadata, title );
+ }
if( hb_list_count( title->list_chapter ) == 0 )
{
@@ -5787,16 +5852,25 @@ hb_buffer_t * hb_ffmpeg_read( hb_stream_t *stream )
static int ffmpeg_seek( hb_stream_t *stream, float frac )
{
AVFormatContext *ic = stream->ffmpeg_ic;
+ int res;
if ( frac > 0. )
{
int64_t pos = (double)stream->ffmpeg_ic->duration * (double)frac +
ffmpeg_initial_timestamp( stream );
- avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD);
+ res = avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD);
+ if (res < 0)
+ {
+ hb_error("avformat_seek_file failed");
+ }
}
else
{
int64_t pos = ffmpeg_initial_timestamp( stream );
- avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD);
+ res = avformat_seek_file( ic, -1, 0, pos, pos, AVSEEK_FLAG_BACKWARD);
+ if (res < 0)
+ {
+ hb_error("avformat_seek_file failed");
+ }
}
stream->need_keyframe = 1;
return 1;
diff --git a/libhb/sync.c b/libhb/sync.c
index c3e4c37a1..f416d1664 100644
--- a/libhb/sync.c
+++ b/libhb/sync.c
@@ -167,7 +167,7 @@ hb_work_object_t * hb_sync_init( hb_job_t * job )
duration = 0;
for( i = job->chapter_start; i <= job->chapter_end; i++ )
{
- chapter = hb_list_item( title->list_chapter, i - 1 );
+ chapter = hb_list_item( job->list_chapter, i - 1 );
duration += chapter->duration;
}
}
@@ -179,7 +179,7 @@ hb_work_object_t * hb_sync_init( hb_job_t * job )
/* Initialize libsamplerate for every audio track we have */
if ( ! job->indepth_scan )
{
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
InitAudio( job, pv->common, i );
}
@@ -892,7 +892,6 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
{
hb_work_object_t * w;
hb_work_private_t * pv;
- hb_title_t * title = job->title;
hb_sync_audio_t * sync;
pv = calloc( 1, sizeof( hb_work_private_t ) );
@@ -905,7 +904,7 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
w = hb_get_work( WORK_SYNC_AUDIO );
w->private_data = pv;
- w->audio = hb_list_item( title->list_audio, i );
+ w->audio = hb_list_item( job->list_audio, i );
w->fifo_in = w->audio->priv.fifo_raw;
if ( w->audio->config.out.codec & HB_ACODEC_PASS_FLAG )
diff --git a/libhb/work.c b/libhb/work.c
index 277ebf033..030920c59 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -389,9 +389,9 @@ void hb_display_job_info( hb_job_t * job )
job->select_subtitle_config.default_track ? ", Default" : "" );
}
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, i );
if( subtitle )
{
@@ -425,9 +425,9 @@ void hb_display_job_info( hb_job_t * job )
if( !job->indepth_scan )
{
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
hb_log( " * audio track %d", audio->config.out.track );
@@ -529,6 +529,7 @@ static void do_job( hb_job_t * job )
hb_work_object_t * w;
hb_work_object_t * sync;
hb_work_object_t * muxer;
+ hb_work_object_t *reader = hb_get_work(WORK_READER);
hb_interjob_t * interjob;
hb_audio_t * audio;
@@ -563,21 +564,25 @@ static void do_job( hb_job_t * job )
{
interjob->select_subtitle->config.force = 0;
}
- for( i = 0; i < hb_list_count(title->list_subtitle); )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); )
{
- if( ( subtitle = hb_list_item( title->list_subtitle, i ) ) )
+ subtitle = hb_list_item( job->list_subtitle, i );
+ if( subtitle )
{
- /* Remove the scanned subtitle from the list if it would result in:
+ /* Remove the scanned subtitle from the list if
+ * it would result in:
* - an emty track (forced and no forced hits)
* - an identical, duplicate subtitle track:
* -> both (or neither) are forced
* -> subtitle is not forced but all its hits are forced */
if( ( interjob->select_subtitle->id == subtitle->id ) &&
- ( ( subtitle->config.force && interjob->select_subtitle->forced_hits == 0 ) ||
+ ( ( subtitle->config.force &&
+ interjob->select_subtitle->forced_hits == 0 ) ||
( subtitle->config.force == interjob->select_subtitle->config.force ) ||
- ( subtitle->config.force == 0 && interjob->select_subtitle->hits == interjob->select_subtitle->forced_hits ) ) )
+ ( !subtitle->config.force &&
+ interjob->select_subtitle->hits == interjob->select_subtitle->forced_hits ) ) )
{
- hb_list_rem( title->list_subtitle, subtitle );
+ hb_list_rem( job->list_subtitle, subtitle );
free( subtitle );
continue;
}
@@ -602,13 +607,13 @@ static void do_job( hb_job_t * job )
if (job->pass == 0 || job->pass == 2)
{
// final pass, interjob->select_subtitle is no longer needed
- hb_list_insert(title->list_subtitle, 0, interjob->select_subtitle);
+ hb_list_insert(job->list_subtitle, 0, interjob->select_subtitle);
interjob->select_subtitle = NULL;
}
else
{
// this is not the final pass, so we need to copy it instead
- hb_list_insert(title->list_subtitle, 0, hb_subtitle_copy(interjob->select_subtitle));
+ hb_list_insert(job->list_subtitle, 0, hb_subtitle_copy(interjob->select_subtitle));
}
}
@@ -616,10 +621,9 @@ static void do_job( hb_job_t * job )
{
// Sanitize subtitles
uint8_t one_burned = 0;
- for( i = 0; i < hb_list_count( title->list_subtitle ); )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); )
{
- subtitle = hb_list_item( title->list_subtitle, i );
-
+ subtitle = hb_list_item( job->list_subtitle, i );
if ( subtitle->config.dest == RENDERSUB )
{
if ( one_burned )
@@ -627,7 +631,7 @@ static void do_job( hb_job_t * job )
if ( !hb_subtitle_can_pass(subtitle->source, job->mux) )
{
hb_log( "More than one subtitle burn-in requested, dropping track %d.", i );
- hb_list_rem( title->list_subtitle, subtitle );
+ hb_list_rem( job->list_subtitle, subtitle );
free( subtitle );
continue;
}
@@ -661,7 +665,7 @@ static void do_job( hb_job_t * job )
else
{
hb_log( "Subtitle pass-thru requested and input track is not compatible with container. One track already burned, dropping track %d.", i );
- hb_list_rem( title->list_subtitle, subtitle );
+ hb_list_rem( job->list_subtitle, subtitle );
free( subtitle );
continue;
}
@@ -697,9 +701,9 @@ static void do_job( hb_job_t * job )
init.height = title->height;
init.par_width = job->anamorphic.par_width;
init.par_height = job->anamorphic.par_height;
- memcpy(init.crop, title->crop, sizeof(int[4]));
- init.vrate_base = title->rate_base;
- init.vrate = title->rate;
+ memcpy(init.crop, job->crop, sizeof(int[4]));
+ init.vrate_base = job->vrate_base;
+ init.vrate = job->vrate;
init.pfr_vrate_base = job->pfr_vrate_base;
init.pfr_vrate = job->pfr_vrate;
init.cfr = 0;
@@ -720,7 +724,7 @@ static void do_job( hb_job_t * job )
job->height = init.height;
job->anamorphic.par_width = init.par_width;
job->anamorphic.par_height = init.par_height;
- memcpy(title->crop, init.crop, sizeof(int[4]));
+ memcpy(job->crop, init.crop, sizeof(int[4]));
job->vrate_base = init.vrate_base;
job->vrate = init.vrate;
job->pfr_vrate_base = init.pfr_vrate_base;
@@ -761,18 +765,18 @@ static void do_job( hb_job_t * job )
if (!job->indepth_scan)
{
// apply Auto Passthru settings
- hb_autopassthru_apply_settings(job, title);
+ hb_autopassthru_apply_settings(job);
// sanitize audio settings
- for (i = 0; i < hb_list_count(title->list_audio);)
+ for (i = 0; i < hb_list_count(job->list_audio);)
{
- audio = hb_list_item(title->list_audio, i);
+ audio = hb_list_item(job->list_audio, i);
if (audio->config.out.codec == HB_ACODEC_AUTO_PASS)
{
// Auto Passthru should have been handled above
// remove track to avoid a crash
hb_log("Auto Passthru error, dropping track %d",
audio->config.out.track);
- hb_list_rem(title->list_audio, audio);
+ hb_list_rem(job->list_audio, audio);
free(audio);
continue;
}
@@ -782,7 +786,7 @@ static void do_job( hb_job_t * job )
{
hb_log("Passthru requested and input codec is not the same as output codec for track %d, dropping track",
audio->config.out.track);
- hb_list_rem(title->list_audio, audio);
+ hb_list_rem(job->list_audio, audio);
free(audio);
continue;
}
@@ -796,9 +800,9 @@ static void do_job( hb_job_t * job )
int best_bitrate = 0;
int best_samplerate = 0;
- for (i = 0; i < hb_list_count(title->list_audio); i++)
+ for (i = 0; i < hb_list_count(job->list_audio); i++)
{
- audio = hb_list_item(title->list_audio, i);
+ audio = hb_list_item(job->list_audio, i);
/* set up the audio work structures */
audio->priv.fifo_raw = hb_fifo_init(FIFO_SMALL, FIFO_SMALL_WAKE);
@@ -999,9 +1003,9 @@ static void do_job( hb_job_t * job )
w->fifo_in = job->fifo_mpeg2;
w->fifo_out = job->fifo_raw;
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, i );
if( subtitle )
{
@@ -1081,9 +1085,9 @@ static void do_job( hb_job_t * job )
hb_list_add( job->list_work, w );
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
/*
* Audio Decoder Thread
@@ -1140,7 +1144,6 @@ static void do_job( hb_job_t * job )
hb_display_job_info( job );
/* Init read & write threads */
- hb_work_object_t *reader = hb_get_work(WORK_READER);
if ( reader->init( reader, job ) )
{
hb_error( "Failure to initialise thread '%s'", reader->name );
@@ -1330,9 +1333,9 @@ cleanup:
hb_fifo_close( &job->fifo_sync );
hb_fifo_close( &job->fifo_mpeg4 );
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, i );
if( subtitle )
{
hb_fifo_close( &subtitle->fifo_in );
@@ -1341,9 +1344,9 @@ cleanup:
hb_fifo_close( &subtitle->fifo_out );
}
}
- for( i = 0; i < hb_list_count( title->list_audio ); i++ )
+ for( i = 0; i < hb_list_count( job->list_audio ); i++ )
{
- audio = hb_list_item( title->list_audio, i );
+ audio = hb_list_item( job->list_audio, i );
if( audio->priv.fifo_in != NULL )
hb_fifo_close( &audio->priv.fifo_in );
if( audio->priv.fifo_raw != NULL )
@@ -1354,13 +1357,22 @@ cleanup:
hb_fifo_close( &audio->priv.fifo_out );
}
+ if( job->list_filter )
+ {
+ for( i = 0; i < hb_list_count( job->list_filter ); i++ )
+ {
+ hb_filter_object_t * filter = hb_list_item( job->list_filter, i );
+ hb_fifo_close( &filter->fifo_out );
+ }
+ }
+
if( job->indepth_scan )
{
/* Before closing the title print out our subtitle stats if we need to
* find the highest and lowest. */
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, i );
hb_log( "Subtitle track %d (id 0x%x) '%s': %d hits (%d forced)",
subtitle->track, subtitle->id, subtitle->lang,
@@ -1415,34 +1427,23 @@ cleanup:
hb_log( "No candidate detected during subtitle scan" );
}
- for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
+ for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
{
- subtitle = hb_list_item( title->list_subtitle, i );
+ subtitle = hb_list_item( job->list_subtitle, i );
if( subtitle->id == subtitle_hit )
{
subtitle->config = job->select_subtitle_config;
- hb_list_rem( title->list_subtitle, subtitle );
+ // Remove from list since we are taking ownership
+ // of the subtitle.
+ hb_list_rem( job->list_subtitle, subtitle );
interjob->select_subtitle = subtitle;
break;
}
}
}
- if( job->list_filter )
- {
- for( i = 0; i < hb_list_count( job->list_filter ); i++ )
- {
- hb_filter_object_t * filter = hb_list_item( job->list_filter, i );
- hb_fifo_close( &filter->fifo_out );
- hb_filter_close( &filter );
- }
- hb_list_close( &job->list_filter );
- }
-
hb_buffer_pool_free();
-
- hb_title_close( &job->title );
- free( job );
+ hb_job_close( &job );
}
static inline void copy_chapter( hb_buffer_t * dst, hb_buffer_t * src )
diff --git a/macosx/ChapterTitles.m b/macosx/ChapterTitles.m
index 893c2dc22..2fcd77272 100644
--- a/macosx/ChapterTitles.m
+++ b/macosx/ChapterTitles.m
@@ -29,18 +29,18 @@
if (!title)
return;
- int count = hb_list_count( title->list_chapter );
+ hb_job_t * job = title->job;
+ int count = hb_list_count( job->list_chapter );
for( i = 0; i < count; i++ )
{
- hb_chapter_t *chapter = hb_list_item( title->list_chapter, i );
+ hb_chapter_t *chapter = hb_list_item( job->list_chapter, i );
- if( chapter != NULL && chapter->title[0] == '\0' )
+ if( chapter != NULL && chapter->title == NULL )
{
chapterString = [NSString stringWithFormat:@"Chapter %2d",(i+1)];
- strncpy( chapter->title, [chapterString UTF8String], 1023);
- chapter->title[1023] = '\0';
+ hb_chapter_set_title( chapter, [chapterString UTF8String]);
}
}
@@ -67,12 +67,11 @@
{
if( fTitle )
{
- hb_chapter_t *chapter = hb_list_item( fTitle->list_chapter, rowIndex );
+ hb_chapter_t *chapter = hb_list_item( fTitle->job->list_chapter, rowIndex );
if( chapter != NULL )
{
- strncpy( chapter->title, [anObject UTF8String], 1023);
- chapter->title[1023] = '\0';
+ hb_chapter_set_title( chapter, [anObject UTF8String]);
}
}
}
@@ -92,7 +91,7 @@
{
if( fTitle )
{
- hb_chapter_t *chapter = hb_list_item( fTitle->list_chapter, rowIndex );
+ hb_chapter_t *chapter = hb_list_item( fTitle->job->list_chapter, rowIndex );
if( chapter != NULL )
{
diff --git a/macosx/Controller.m b/macosx/Controller.m
index c3edceb1a..dea32a40c 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -1982,13 +1982,13 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
- (IBAction) showNewScan:(id)sender
{
- hb_list_t * list;
+ hb_title_set_t * title_set;
hb_title_t * title = NULL;
int feature_title=0; // Used to store the main feature title
- list = hb_get_titles( fHandle );
+ title_set = hb_get_title_set( fHandle );
- if( !hb_list_count( list ) )
+ if( !hb_list_count( title_set->list_title ) )
{
/* We display a message if a valid dvd source was not chosen */
[fSrcDVD2Field setStringValue: @"No Valid Source Found"];
@@ -2036,9 +2036,9 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
[[fWindow toolbar] validateVisibleItems];
[fSrcTitlePopUp removeAllItems];
- for( int i = 0; i < hb_list_count( list ); i++ )
+ for( int i = 0; i < hb_list_count( title_set->list_title ); i++ )
{
- title = (hb_title_t *) hb_list_item( list, i );
+ title = (hb_title_t *) hb_list_item( title_set->list_title, i );
currentSource = [NSString stringWithUTF8String: title->name];
/*Set DVD Name at top of window with the browsedSourceDisplayName grokked right before -performScan */
@@ -2081,7 +2081,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
}
/* See if this is the main feature according to libhb */
- if (title->index == title->job->feature)
+ if (title->index == title_set->feature)
{
feature_title = i;
}
@@ -2503,10 +2503,10 @@ fWorkingCount = 0;
*/
int i;
NSMutableArray *ChapterNamesArray = [[NSMutableArray alloc] init];
- int chaptercount = hb_list_count( fTitle->list_chapter );
+ int chaptercount = hb_list_count( fTitle->job->list_chapter );
for( i = 0; i < chaptercount; i++ )
{
- hb_chapter_t *chapter = (hb_chapter_t *) hb_list_item( fTitle->list_chapter, i );
+ hb_chapter_t *chapter = (hb_chapter_t *) hb_list_item( fTitle->job->list_chapter, i );
if( chapter != NULL )
{
[ChapterNamesArray addObject:[NSString stringWithUTF8String:chapter->title]];
@@ -2844,7 +2844,7 @@ fWorkingCount = 0;
NSMutableDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex];
[self writeToActivityLog: "Preset: %s", [[queueToApply objectForKey:@"PresetName"] UTF8String]];
[self writeToActivityLog: "processNewQueueEncode number of passes expected is: %d", ([[queueToApply objectForKey:@"VideoTwoPass"] intValue] + 1)];
- job->file = [[queueToApply objectForKey:@"DestinationPath"] UTF8String];
+ hb_job_set_file(job, [[queueToApply objectForKey:@"DestinationPath"] UTF8String]);
[self prepareJob];
/*
@@ -2852,16 +2852,14 @@ fWorkingCount = 0;
*/
if( job->indepth_scan == 1 )
{
- char *x264opts_tmp;
+ NSString *advanced_opts_tmp = [NSString stringWithUTF8String: job->advanced_opts];
/*
* When subtitle scan is enabled do a fast pre-scan job
* which will determine which subtitles to enable, if any.
*/
job->pass = -1;
- x264opts_tmp = job->advanced_opts;
-
- job->advanced_opts = NULL;
+ hb_job_set_advanced_opts(job, NULL);
job->indepth_scan = 1;
@@ -2870,7 +2868,7 @@ fWorkingCount = 0;
* Add the pre-scan job
*/
hb_add( fQueueEncodeLibhb, job );
- job->advanced_opts = x264opts_tmp;
+ hb_job_set_advanced_opts(job, [advanced_opts_tmp UTF8String] );
}
@@ -2900,8 +2898,10 @@ fWorkingCount = 0;
[queueToApply setObject:[NSNumber numberWithInt:1] forKey:@"Status"];
[self saveQueueFileItem];
- /* we need to clean up the various lists after the job(s) have been set */
- hb_reset_job( job );
+ /* libhb makes a copy of the job. So we need to free any resource
+ * that were allocated in construction of the job. This empties
+ * the audio, subtitle, and filter lists */
+ hb_job_reset(job);
/* We should be all setup so let 'er rip */
[self doRip];
@@ -3231,13 +3231,11 @@ fWorkingCount = 0;
/* Lets use this as per Nyx, Thanks Nyx! */
/* For previews we ignore the turbo option for the first pass of two since we only use 1 pass */
job->fastfirstpass = 0;
- job->advanced_opts = strdup( [[fAdvancedOptions optionsString] UTF8String] );
-
-
+ hb_job_set_advanced_opts(job, [[fAdvancedOptions optionsString] UTF8String] );
}
else if( job->vcodec & HB_VCODEC_FFMPEG_MASK )
{
- job->advanced_opts = strdup( [[fAdvancedOptions optionsStringLavc] UTF8String] );
+ hb_job_set_advanced_opts(job, [[fAdvancedOptions optionsStringLavc] UTF8String] );
}
/* Video settings */
@@ -3689,11 +3687,10 @@ bool one_burned = FALSE;
id tempObject;
while (tempObject = [enumerator nextObject])
{
- hb_chapter_t *chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
+ hb_chapter_t *chapter = (hb_chapter_t *) hb_list_item( job->list_chapter, i );
if( chapter != NULL )
{
- strncpy( chapter->title, [tempObject UTF8String], 1023);
- chapter->title[1023] = '\0';
+ hb_chapter_set_title( chapter, [tempObject UTF8String] );
}
i++;
}
@@ -3726,13 +3723,13 @@ bool one_burned = FALSE;
{
job->fastfirstpass = 0;
}
- job->advanced_opts = strdup( [[queueToApply objectForKey:@"x264Option"] UTF8String] );
+ hb_job_set_advanced_opts( job, [[queueToApply objectForKey:@"x264Option"] UTF8String] );
}
else if( job->vcodec & HB_VCODEC_FFMPEG_MASK )
{
if ([queueToApply objectForKey:@"lavcOption"])
{
- job->advanced_opts = strdup( [[queueToApply objectForKey:@"lavcOption"] UTF8String] );
+ hb_job_set_advanced_opts( job, [[queueToApply objectForKey:@"lavcOption"] UTF8String] );
}
}
@@ -4579,7 +4576,6 @@ bool one_burned = FALSE;
}
/* Start Get and set the initial pic size for display */
- hb_job_t * job = title->job;
fTitle = title;
/* Set Auto Crop to on upon selecting a new title */
@@ -4587,12 +4583,12 @@ bool one_burned = FALSE;
/* We get the originial output picture width and height and put them
in variables for use with some presets later on */
- PicOrigOutputWidth = job->width;
- PicOrigOutputHeight = job->height;
- AutoCropTop = job->crop[0];
- AutoCropBottom = job->crop[1];
- AutoCropLeft = job->crop[2];
- AutoCropRight = job->crop[3];
+ PicOrigOutputWidth = title->width;
+ PicOrigOutputHeight = title->height;
+ AutoCropTop = title->crop[0];
+ AutoCropBottom = title->crop[1];
+ AutoCropLeft = title->crop[2];
+ AutoCropRight = title->crop[3];
/* Reset the new title in fPictureController && fPreviewController*/
[fPictureController SetTitle:title];
@@ -4614,8 +4610,6 @@ bool one_burned = FALSE;
userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
[NSData dataWithBytesNoCopy: &fTitle length: sizeof(fTitle) freeWhenDone: NO], keyTitleTag,
nil]]];
-
-
[fVidRatePopUp selectItemAtIndex: 0];
/* we run the picture size values through calculatePictureSizing to get all picture setting information*/
diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m
index 7b59f712b..d7a07dc8a 100644
--- a/macosx/HBPreviewController.m
+++ b/macosx/HBPreviewController.m
@@ -698,7 +698,7 @@
buffer = (uint8_t *) realloc( buffer, bufferSize );
}
- hb_get_preview( handle, title, pictureIndex, buffer );
+ hb_get_preview( handle, title->job, pictureIndex, buffer );
// Create an NSBitmapImageRep and copy the libhb image into it, converting it from
// libhb's format to one suitable for NSImage. Along the way, we'll strip off the
@@ -907,7 +907,7 @@
hb_add( fPreviewLibhb, job );
/* we need to clean up the various lists after the job(s) have been set */
- hb_reset_job( job );
+ hb_job_reset( job );
[fEncodingControlBox setHidden: NO];
[fPictureControlBox setHidden: YES];
diff --git a/test/test.c b/test/test.c
index bf0c086b4..472fabd54 100644
--- a/test/test.c
+++ b/test/test.c
@@ -385,14 +385,14 @@ static void ShowCommands()
fprintf( stdout, " [r]esume Resume encoding\n" );
}
-static void PrintTitleInfo( hb_title_t * title )
+static void PrintTitleInfo( hb_title_t * title, int feature )
{
hb_chapter_t * chapter;
hb_subtitle_t * subtitle;
int i;
fprintf( stderr, "+ title %d:\n", title->index );
- if ( title->index == title->job->feature )
+ if ( title->index == feature )
{
fprintf( stderr, " + Main Feature\n" );
}
@@ -472,6 +472,18 @@ static void PrintTitleInfo( hb_title_t * title )
}
+static void PrintTitleSetInfo( hb_title_set_t * title_set )
+{
+ int i;
+ hb_title_t * title;
+
+ for( i = 0; i < hb_list_count( title_set->list_title ); i++ )
+ {
+ title = hb_list_item( title_set->list_title, i );
+ PrintTitleInfo( title, title_set->feature );
+ }
+}
+
static int test_sub_list( char ** list, int pos )
{
int i;
@@ -582,7 +594,7 @@ static int HandleEvents( hb_handle_t * h )
case HB_STATE_SCANDONE:
{
- hb_list_t * list;
+ hb_title_set_t * title_set;
hb_title_t * title;
hb_job_t * job;
int i;
@@ -599,9 +611,9 @@ static int HandleEvents( hb_handle_t * h )
double gain = 0;
/* Audio argument string parsing variables */
- list = hb_get_titles( h );
+ title_set = hb_get_title_set( h );
- if( !hb_list_count( list ) )
+ if( !title_set || !hb_list_count( title_set->list_title ) )
{
/* No valid title, stop right there */
fprintf( stderr, "No title found.\n" );
@@ -618,9 +630,9 @@ static int HandleEvents( hb_handle_t * h )
fprintf( stderr, "Searching for main feature title...\n" );
- for( i = 0; i < hb_list_count( list ); i++ )
+ for( i = 0; i < hb_list_count( title_set->list_title ); i++ )
{
- title = hb_list_item( list, i );
+ title = hb_list_item( title_set->list_title, i );
title_time = (title->hours*60*60 ) + (title->minutes *60) + (title->seconds);
fprintf( stderr, " + Title (%d) index %d has length %dsec\n",
i, title->index, title_time );
@@ -630,7 +642,7 @@ static int HandleEvents( hb_handle_t * h )
main_feature_pos = i;
main_feature_idx = title->index;
}
- if( title->job->feature == title->index )
+ if( title_set->feature == title->index )
{
main_feature_time = title_time;
main_feature_pos = i;
@@ -648,28 +660,24 @@ static int HandleEvents( hb_handle_t * h )
fprintf( stderr, "Found main feature title, setting title to %d\n",
main_feature_idx);
- title = hb_list_item( list, main_feature_pos);
+ title = hb_list_item( title_set->list_title, main_feature_pos);
} else {
- title = hb_list_item( list, 0 );
+ title = hb_list_item( title_set->list_title, 0 );
}
if( !titleindex || titlescan )
{
/* Scan-only mode, print infos and exit */
- int i;
- for( i = 0; i < hb_list_count( list ); i++ )
- {
- title = hb_list_item( list, i );
- PrintTitleInfo( title );
- }
+ PrintTitleSetInfo( title_set );
die = 1;
break;
}
+ PrintTitleInfo( title, title_set->feature );
+
/* Set job settings */
- job = title->job;
+ job = hb_job_init( title );
- PrintTitleInfo( title );
if( chapter_start && chapter_end && !stop_at_pts && !start_at_preview && !stop_at_frame && !start_at_pts && !start_at_frame )
{
@@ -1312,16 +1320,14 @@ static int HandleEvents( hb_handle_t * h )
{
hb_chapter_t * chapter_s;
- chapter_s = hb_list_item( job->title->list_chapter, chapter - 1);
- strncpy(chapter_s->title, cell->cell_text, 1023);
- chapter_s->title[1023] = '\0';
+ chapter_s = hb_list_item( job->list_chapter, chapter - 1);
+ hb_chapter_set_title(chapter_s, cell->cell_text);
}
}
hb_dispose_cell( cell );
}
-
hb_close_csv_file( file );
}
}
@@ -1705,8 +1711,8 @@ static int HandleEvents( hb_handle_t * h )
}
}
- if( hb_list_count( audios ) == 0 &&
- hb_list_count( job->title->list_audio ) > 0 )
+ if( hb_list_count(audios) == 0 &&
+ hb_list_count(title->list_audio) > 0 )
{
/* Create a new audio track with default settings */
audio = calloc( 1, sizeof( *audio ) );
@@ -2434,22 +2440,13 @@ static int HandleEvents( hb_handle_t * h )
job->ipod_atom = 1;
}
- job->file = strdup( output );
+ hb_job_set_file( job, output );
if( color_matrix_code )
{
job->color_matrix_code = color_matrix_code;
}
- if( advanced_opts != NULL && *advanced_opts != '\0' )
- {
- job->advanced_opts = advanced_opts;
- }
- else /*avoids a bus error crash when options aren't specified*/
- {
- job->advanced_opts = NULL;
- }
-
job->x264_profile = x264_profile;
job->x264_preset = x264_preset;
job->x264_tune = x264_tune;
@@ -2491,17 +2488,13 @@ static int HandleEvents( hb_handle_t * h )
if( subtitle_scan )
{
- char *advanced_opts_tmp;
-
/*
* When subtitle scan is enabled do a fast pre-scan job
* which will determine which subtitles to enable, if any.
*/
job->pass = -1;
- advanced_opts_tmp = job->advanced_opts;
-
- job->advanced_opts = NULL;
+ hb_job_set_advanced_opts(job, NULL);
job->indepth_scan = subtitle_scan;
fprintf( stderr, "Subtitle Scan Enabled - enabling "
@@ -2511,10 +2504,10 @@ static int HandleEvents( hb_handle_t * h )
* Add the pre-scan job
*/
hb_add( h, job );
-
- job->advanced_opts = advanced_opts_tmp;
}
+ hb_job_set_advanced_opts(job, advanced_opts);
+
if( twoPass )
{
/*
@@ -2558,9 +2551,10 @@ static int HandleEvents( hb_handle_t * h )
job->indepth_scan = 0;
job->pass = 0;
+
hb_add( h, job );
}
- hb_reset_job( job );
+ hb_job_close( &job );
hb_start( h );
break;
}