#include "hb-backend.h"
#include "settings.h"
#include "callbacks.h"
+#include "preview.h"
#include "values.h"
#include "lang.h"
"10",
};
+static options_map_t d_logging_opts[] =
+{
+ {"0", "0", 0, "0"},
+ {"1", "1", 1, "1"},
+ {"2", "2", 2, "2"},
+};
+combo_opts_t logging_opts =
+{
+ sizeof(d_logging_opts)/sizeof(options_map_t),
+ d_logging_opts
+};
+
static options_map_t d_container_opts[] =
{
{"MKV", "mkv", HB_MUX_MKV, "mkv"},
static options_map_t d_me_opts[] =
{
- {"Diamond", "dia", 0, "dia"},
- {"Hexagon", "hex", 1, "hex"},
- {"Uneven Multi-Hexagon", "umh", 2, "umh"},
- {"Exhaustive", "esa", 3, "esa"},
+ {"Diamond", "dia", 0, "dia"},
+ {"Hexagon", "hex", 1, "hex"},
+ {"Uneven Multi-Hexagon", "umh", 2, "umh"},
+ {"Exhaustive", "esa", 3, "esa"},
+ {"Hadamard Exhaustive", "tesa", 4, "tesa"},
};
combo_opts_t me_opts =
{
combo_name_map_t combo_name_map[] =
{
+ {"LoggingLevel", &logging_opts},
{"FileFormat", &container_opts},
{"PictureDeinterlace", &deint_opts},
{"tweak_PictureDeinterlace", &deint_opts},
extern void hb_get_tempory_directory(hb_handle_t *h, char path[512]);
+gchar*
+ghb_get_tmp_dir()
+{
+ char dir[512];
+
+ hb_get_tempory_directory(h_scan, dir);
+ return g_strdup(dir);
+}
+
void
ghb_hb_cleanup(gboolean partial)
{
subtitle_opts_set(builder, "Subtitles", user_data);
title_opts_set(builder, "title");
audio_track_opts_set(builder, "AudioTrack", user_data);
+ generic_opts_set(builder, "LoggingLevel", &logging_opts);
generic_opts_set(builder, "FileFormat", &container_opts);
generic_opts_set(builder, "PictureDeinterlace", &deint_opts);
generic_opts_set(builder, "tweak_PictureDeinterlace", &deint_opts);
static ghb_status_t hb_status;
void
-ghb_backend_init(GtkBuilder *builder, gint debug, gint update)
+ghb_combo_init(GtkBuilder *builder)
{
- /* Init libhb */
- h_scan = hb_init( debug, update );
- h_queue = hb_init( debug, 0 );
// Set up the list model for the combos
init_ui_combo_boxes(builder);
// Populate all the combos
}
void
+ghb_backend_init(gint debug)
+{
+ /* Init libhb */
+ h_scan = hb_init( debug, 0 );
+ h_queue = hb_init( debug, 0 );
+}
+
+void
ghb_backend_close()
{
hb_close(&h_queue);
}
void
-ghb_backend_scan(const gchar *path, gint titleindex)
+ghb_backend_scan(const gchar *path, gint titleindex, gint preview_count)
{
- hb_scan( h_scan, path, titleindex );
- hb_status.state |= GHB_STATE_SCANNING;
+ hb_scan( h_scan, path, titleindex, preview_count, 1 );
+ hb_status.scan.state |= GHB_STATE_SCANNING;
// initialize count and cur to something that won't cause FPE
// when computing progress
- hb_status.title_count = 1;
- hb_status.title_cur = 0;
+ hb_status.scan.title_count = 1;
+ hb_status.scan.title_cur = 0;
}
void
ghb_backend_queue_scan(const gchar *path, gint titlenum)
{
g_debug("ghb_backend_queue_scan()");
- hb_scan( h_queue, path, titlenum );
- hb_status.queue_state |= GHB_STATE_SCANNING;
+ hb_scan( h_queue, path, titlenum, 10, 0 );
+ hb_status.queue.state |= GHB_STATE_SCANNING;
}
gint
-ghb_get_state()
+ghb_get_scan_state()
{
- return hb_status.state;
+ return hb_status.scan.state;
}
gint
ghb_get_queue_state()
{
- return hb_status.queue_state;
+ return hb_status.queue.state;
}
void
-ghb_clear_state(gint state)
+ghb_clear_scan_state(gint state)
{
- hb_status.state &= ~state;
+ hb_status.scan.state &= ~state;
}
void
ghb_clear_queue_state(gint state)
{
- hb_status.queue_state &= ~state;
+ hb_status.queue.state &= ~state;
}
void
-ghb_set_state(gint state)
+ghb_set_scan_state(gint state)
{
- hb_status.state |= state;
+ hb_status.scan.state |= state;
}
void
ghb_set_queue_state(gint state)
{
- hb_status.queue_state |= state;
+ hb_status.queue.state |= state;
}
void
void
ghb_track_status()
{
- hb_state_t s;
+ hb_state_t s_scan;
hb_state_t s_queue;
if (h_scan == NULL) return;
- hb_get_state( h_scan, &s );
- switch( s.state )
+ hb_get_state( h_scan, &s_scan );
+ switch( s_scan.state )
{
-#define p s.param.scanning
+#define p s_scan.param.scanning
case HB_STATE_SCANNING:
{
- hb_status.state |= GHB_STATE_SCANNING;
- hb_status.title_count = p.title_count;
- hb_status.title_cur = p.title_cur;
+ hb_status.scan.state |= GHB_STATE_SCANNING;
+ hb_status.scan.title_count = p.title_count;
+ hb_status.scan.title_cur = p.title_cur;
} break;
#undef p
case HB_STATE_SCANDONE:
{
- hb_status.state &= ~GHB_STATE_SCANNING;
- hb_status.state |= GHB_STATE_SCANDONE;
+ hb_status.scan.state &= ~GHB_STATE_SCANNING;
+ hb_status.scan.state |= GHB_STATE_SCANDONE;
} break;
+#define p s_scan.param.working
+ case HB_STATE_WORKING:
+ hb_status.scan.state |= GHB_STATE_WORKING;
+ hb_status.scan.state &= ~GHB_STATE_PAUSED;
+ hb_status.scan.job_cur = p.job_cur;
+ hb_status.scan.job_count = p.job_count;
+ hb_status.scan.progress = p.progress;
+ hb_status.scan.rate_cur = p.rate_cur;
+ hb_status.scan.rate_avg = p.rate_avg;
+ hb_status.scan.hours = p.hours;
+ hb_status.scan.minutes = p.minutes;
+ hb_status.scan.seconds = p.seconds;
+ hb_status.scan.unique_id = p.sequence_id & 0xFFFFFF;
+ break;
+#undef p
+
+ case HB_STATE_PAUSED:
+ hb_status.scan.state |= GHB_STATE_PAUSED;
+ break;
+
+ case HB_STATE_MUXING:
+ {
+ hb_status.scan.state |= GHB_STATE_MUXING;
+ } break;
+
+#define p s_scan.param.workdone
+ case HB_STATE_WORKDONE:
+ {
+ hb_job_t *job;
+
+ hb_status.scan.state |= GHB_STATE_WORKDONE;
+ hb_status.scan.state &= ~GHB_STATE_MUXING;
+ hb_status.scan.state &= ~GHB_STATE_PAUSED;
+ hb_status.scan.state &= ~GHB_STATE_WORKING;
+ switch (p.error)
+ {
+ case HB_ERROR_NONE:
+ hb_status.scan.error = GHB_ERROR_NONE;
+ break;
+ case HB_ERROR_CANCELED:
+ hb_status.scan.error = GHB_ERROR_CANCELED;
+ break;
+ default:
+ hb_status.scan.error = GHB_ERROR_FAIL;
+ break;
+ }
+ // Delete all remaining jobs of this encode.
+ // An encode can be composed of multiple associated jobs.
+ // When a job is stopped, libhb removes it from the job list,
+ // but does not remove other jobs that may be associated with it.
+ // Associated jobs are taged in the sequence id.
+ while ((job = hb_job(h_scan, 0)) != NULL)
+ hb_rem( h_scan, job );
+ } break;
+#undef p
}
hb_get_state( h_queue, &s_queue );
switch( s_queue.state )
{
+#define p s_queue.param.scanning
case HB_STATE_SCANNING:
{
- hb_status.queue_state |= GHB_STATE_SCANNING;
+ hb_status.queue.state |= GHB_STATE_SCANNING;
+ hb_status.queue.title_count = p.title_count;
+ hb_status.queue.title_cur = p.title_cur;
} break;
+#undef p
case HB_STATE_SCANDONE:
{
- hb_status.queue_state &= ~GHB_STATE_SCANNING;
- hb_status.queue_state |= GHB_STATE_SCANDONE;
+ hb_status.queue.state &= ~GHB_STATE_SCANNING;
+ hb_status.queue.state |= GHB_STATE_SCANDONE;
} break;
#define p s_queue.param.working
case HB_STATE_WORKING:
- hb_status.queue_state |= GHB_STATE_WORKING;
- hb_status.queue_state &= ~GHB_STATE_PAUSED;
- hb_status.job_cur = p.job_cur;
- hb_status.job_count = p.job_count;
- hb_status.progress = p.progress;
- hb_status.rate_cur = p.rate_cur;
- hb_status.rate_avg = p.rate_avg;
- hb_status.hours = p.hours;
- hb_status.minutes = p.minutes;
- hb_status.seconds = p.seconds;
- hb_status.unique_id = p.sequence_id & 0xFFFFFF;
+ hb_status.queue.state |= GHB_STATE_WORKING;
+ hb_status.queue.state &= ~GHB_STATE_PAUSED;
+ hb_status.queue.job_cur = p.job_cur;
+ hb_status.queue.job_count = p.job_count;
+ hb_status.queue.progress = p.progress;
+ hb_status.queue.rate_cur = p.rate_cur;
+ hb_status.queue.rate_avg = p.rate_avg;
+ hb_status.queue.hours = p.hours;
+ hb_status.queue.minutes = p.minutes;
+ hb_status.queue.seconds = p.seconds;
+ hb_status.queue.unique_id = p.sequence_id & 0xFFFFFF;
break;
#undef p
case HB_STATE_PAUSED:
- hb_status.queue_state |= GHB_STATE_PAUSED;
+ hb_status.queue.state |= GHB_STATE_PAUSED;
break;
case HB_STATE_MUXING:
{
- hb_status.queue_state |= GHB_STATE_MUXING;
+ hb_status.queue.state |= GHB_STATE_MUXING;
} break;
#define p s_queue.param.workdone
{
hb_job_t *job;
- hb_status.queue_state |= GHB_STATE_WORKDONE;
- hb_status.queue_state &= ~GHB_STATE_MUXING;
- hb_status.queue_state &= ~GHB_STATE_PAUSED;
- hb_status.queue_state &= ~GHB_STATE_WORKING;
+ hb_status.queue.state |= GHB_STATE_WORKDONE;
+ hb_status.queue.state &= ~GHB_STATE_MUXING;
+ hb_status.queue.state &= ~GHB_STATE_PAUSED;
+ hb_status.queue.state &= ~GHB_STATE_WORKING;
switch (p.error)
{
case HB_ERROR_NONE:
- hb_status.error = GHB_ERROR_NONE;
+ hb_status.queue.error = GHB_ERROR_NONE;
+ break;
case HB_ERROR_CANCELED:
- hb_status.error = GHB_ERROR_CANCELED;
+ hb_status.queue.error = GHB_ERROR_CANCELED;
+ break;
default:
- hb_status.error = GHB_ERROR_FAIL;
+ hb_status.queue.error = GHB_ERROR_FAIL;
+ break;
}
- hb_status.error = p.error;
// Delete all remaining jobs of this encode.
// An encode can be composed of multiple associated jobs.
// When a job is stopped, libhb removes it from the job list,
{
width = crop_width;
height = crop_height;
- max_width = 0; //crop_width;
- max_height = 0; //crop_height;
+ max_width = 0;
+ max_height = 0;
}
else
{
return TRUE;
}
-void
-ghb_add_job(GValue *js, gint unique_id)
+static void
+add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
{
hb_list_t * list;
hb_title_t * title;
gchar *denoise_str = NULL;
gchar *dest_str = NULL;
- g_debug("ghb_add_job()\n");
- if (h_queue == NULL) return;
- list = hb_get_titles( h_queue );
+ g_debug("add_job()\n");
+ if (h == NULL) return;
+ list = hb_get_titles( h );
if( !hb_list_count( list ) )
{
/* No valid title, stop right there */
return;
}
- // Since I'm doing a scan of the single title I want just prior
- // to adding the job, there is only the one title to choose from.
- //gint titleindex = ghb_settings_get_int(js, "title");
- gint titleindex = 0;
title = hb_list_item( list, titleindex );
if (title == NULL) return;
job = title->job;
if (job == NULL) return;
+ job->start_at_preview = ghb_settings_get_int(js, "start_frame") + 1;
+ if (job->start_at_preview)
+ {
+g_message("duration %d", ghb_settings_get_int(js, "live_duration"));
+ job->seek_points = ghb_settings_get_int(js, "preview_count");
+ job->pts_to_stop = ghb_settings_get_int(js, "live_duration") * 90000LL;
+ }
+
tweaks = ghb_settings_get_boolean(js, "allow_tweaks");
job->mux = ghb_settings_combo_int(js, "FileFormat");
if (job->mux == HB_MUX_MP4)
job->largeFileSize = FALSE;
job->mp4_optimize = FALSE;
}
- gint chapter_start, chapter_end;
- chapter_start = ghb_settings_get_int(js, "start_chapter");
- chapter_end = ghb_settings_get_int(js, "end_chapter");
- gint num_chapters = hb_list_count(title->list_chapter);
- job->chapter_start = MIN( num_chapters, chapter_start );
- job->chapter_end = MAX( job->chapter_start, chapter_end );
-
- job->chapter_markers = ghb_settings_get_boolean(js, "ChapterMarkers");
- if ( job->chapter_markers )
+ if (!job->start_at_preview)
{
- GValue *chapters;
- GValue *chapter;
- gint chap;
- gint count;
-
- chapters = ghb_settings_get_value(js, "chapter_list");
- count = ghb_array_len(chapters);
- for(chap = chapter_start; chap <= chapter_end; chap++)
+ gint chapter_start, chapter_end;
+ chapter_start = ghb_settings_get_int(js, "start_chapter");
+ chapter_end = ghb_settings_get_int(js, "end_chapter");
+ gint num_chapters = hb_list_count(title->list_chapter);
+ job->chapter_start = MIN( num_chapters, chapter_start );
+ job->chapter_end = MAX( job->chapter_start, chapter_end );
+
+ job->chapter_markers = ghb_settings_get_boolean(js, "ChapterMarkers");
+ if ( job->chapter_markers )
{
- hb_chapter_t * chapter_s;
- gchar *name;
-
- name = NULL;
- if (chap-1 < count)
- {
- chapter = ghb_array_get_nth(chapters, chap-1);
- name = ghb_value_string(chapter);
- }
- if (name == NULL)
+ GValue *chapters;
+ GValue *chapter;
+ gint chap;
+ gint count;
+
+ chapters = ghb_settings_get_value(js, "chapter_list");
+ count = ghb_array_len(chapters);
+ for(chap = chapter_start; chap <= chapter_end; chap++)
{
- name = g_strdup_printf ("Chapter %2d", chap);
+ hb_chapter_t * chapter_s;
+ gchar *name;
+
+ name = NULL;
+ if (chap-1 < count)
+ {
+ chapter = ghb_array_get_nth(chapters, chap-1);
+ name = ghb_value_string(chapter);
+ }
+ if (name == NULL)
+ {
+ name = g_strdup_printf ("Chapter %2d", chap);
+ }
+ chapter_s = hb_list_item( job->title->list_chapter, chap - 1);
+ strncpy(chapter_s->title, name, 1023);
+ chapter_s->title[1023] = '\0';
+ g_free(name);
}
- chapter_s = hb_list_item( job->title->list_chapter, chap - 1);
- strncpy(chapter_s->title, name, 1023);
- chapter_s->title[1023] = '\0';
- g_free(name);
}
}
job->crop[0] = ghb_settings_get_int(js, "PictureTopCrop");
}
else
{
+printf("switching to faac\n");
audio.out.codec = HB_ACODEC_FAAC;
}
}
* Add the pre-scan job
*/
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
- hb_add( h_queue, job );
+ hb_add( h, job );
//if (job->x264opts != NULL)
// g_free(job->x264opts);
job->x264opts = x264opts;
}
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
- hb_add( h_queue, job );
+ hb_add( h, job );
//if (job->x264opts != NULL)
// g_free(job->x264opts);
job->indepth_scan = 0;
job->x264opts = x264opts2;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
- hb_add( h_queue, job );
+ hb_add( h, job );
//if (job->x264opts != NULL)
// g_free(job->x264opts);
}
job->indepth_scan = 0;
job->pass = 0;
job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
- hb_add( h_queue, job );
+ hb_add( h, job );
//if (job->x264opts != NULL)
// g_free(job->x264opts);
}
}
void
+ghb_add_job(GValue *js, gint unique_id)
+{
+ // Since I'm doing a scan of the single title I want just prior
+ // to adding the job, there is only the one title to choose from.
+ add_job(h_queue, js, unique_id, 0);
+}
+
+void
+ghb_add_live_job(GValue *js, gint unique_id)
+{
+ // Since I'm doing a scan of the single title I want just prior
+ // to adding the job, there is only the one title to choose from.
+ gint titleindex = ghb_settings_combo_int(js, "title");
+ add_job(h_scan, js, unique_id, titleindex);
+}
+
+void
ghb_remove_job(gint unique_id)
{
hb_job_t * job;
}
void
+ghb_start_live_encode()
+{
+ hb_start( h_scan );
+}
+
+void
+ghb_stop_live_encode()
+{
+ hb_stop( h_scan );
+}
+
+void
ghb_pause_queue()
{
hb_state_t s;
ghb_get_preview_image(
gint titleindex,
gint index,
- GValue *settings,
- gboolean borders)
+ signal_user_data_t *ud,
+ gboolean borders,
+ gint *out_width,
+ gint *out_height)
{
+ GValue *settings;
hb_title_t *title;
hb_list_t *list;
+ settings = ud->settings;
list = hb_get_titles( h_scan );
if( !hb_list_count( list ) )
{
if (anamorphic)
{
hb_set_anamorphic_size( title->job, &width, &height, &par_width, &par_height );
- if (par_width > par_height)
- dstWidth = dstWidth * par_width / par_height;
- else
- dstHeight = dstHeight * par_height / par_width;
+ ghb_par_scale(ud, &dstWidth, &dstHeight, par_width, par_height);
+ }
+ else
+ {
+ ghb_par_scale(ud, &dstWidth, &dstHeight, 1, 1);
}
+ *out_width = dstWidth;
+ *out_height = dstHeight;
if (ghb_settings_get_boolean(settings, "reduce_hd_preview"))
{
- gdouble factor = 1.0;
+ GdkScreen *ss;
+ gint s_w, s_h;
+ gint num, den;
+
+ ss = gdk_screen_get_default();
+ s_w = gdk_screen_get_width(ss);
+ s_h = gdk_screen_get_height(ss);
+ num = dstWidth * par_width;
+ den = dstHeight * par_height;
- if (dstHeight > RED_HEIGHT)
+ if (dstWidth > s_w * 80 / 100)
{
- factor = RED_HEIGHT / (gdouble)dstHeight;
+ dstWidth = s_w * 80 / 100;
+ dstHeight = dstWidth * den / num;
}
- if (dstWidth * factor > RED_WIDTH)
+ if (dstHeight > s_h * 80 / 100)
{
- factor = RED_WIDTH / (gdouble)dstWidth;
+ dstHeight = s_h * 80 / 100;
+ dstWidth = dstHeight * num / den;
}
- dstHeight = dstHeight * factor + 0.5;
- dstWidth = dstWidth * factor + 0.5;
}
-
g_debug("scaled %d x %d\n", dstWidth, dstHeight);
GdkPixbuf *scaled_preview;
scaled_preview = gdk_pixbuf_scale_simple(preview, dstWidth, dstHeight, GDK_INTERP_HYPER);