+ 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 );
+ if (count > 100) count = 100;
+ if (count < 1) return 0;
+ title = (hb_title_t*)hb_list_item(list, 0);
+ feature = title->job->feature;
+ for (ii = 0; ii < count; ii++)
+ {
+ title = (hb_title_t*)hb_list_item(list, ii);
+ if (title->index == feature)
+ {
+ return ii;
+ }
+ }
+ return titleindex;
+}
+
+gchar*
+ghb_get_source_audio_lang(gint titleindex, gint track)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_audio_config_t * audio;
+ gchar *lang = NULL;
+
+ g_debug("ghb_lookup_1st_audio_lang ()\n");
+ if (h_scan == NULL)
+ return NULL;
+ list = hb_get_titles( h_scan );
+ title = (hb_title_t*)hb_list_item( list, titleindex );
+ if (title == NULL)
+ return NULL;
+ if (hb_list_count( title->list_audio ) <= track)
+ return NULL;
+
+ audio = hb_list_audio_config_item(title->list_audio, track);
+ if (audio == NULL)
+ return NULL;
+
+ lang = g_strdup(audio->lang.iso639_2);
+ return lang;
+}
+
+static gboolean*
+get_track_used(gint acodec, GHashTable *track_indices, gint count)
+{
+ gboolean *used;
+
+ used = g_hash_table_lookup(track_indices, &acodec);
+ if (used == NULL)
+ {
+ gint *key;
+
+ used = g_malloc0(count * sizeof(gboolean));
+ key = g_malloc(sizeof(gint));
+ *key = acodec;
+ g_hash_table_insert(track_indices, key, used);
+ }
+ return used;
+}
+
+gint
+ghb_find_audio_track(
+ gint titleindex,
+ const gchar *lang,
+ gint acodec,
+ gint fallback_acodec,
+ GHashTable *track_indices)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_audio_config_t * audio;
+ gint ii;
+ gint count = 0;
+ gint track = -1;
+ gint max_chan;
+ gboolean *used = NULL;
+ gboolean *passthru_used;
+ gint try_acodec;
+ gint passthru_acodec;
+ gboolean passthru;
+ 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 );
+ if (title != NULL)
+ {
+ count = hb_list_count( title->list_audio );
+ }
+ if (count > 10) count = 10;
+ // Try to find an item that matches the preferred language and
+ // the passthru codec type
+ max_chan = 0;
+ passthru = (acodec & (HB_ACODEC_AC3 | HB_ACODEC_DCA)) != 0;
+ if (passthru)
+ {
+ for (ii = 0; ii < count; ii++)
+ {
+ audio = (hb_audio_config_t*)hb_list_audio_config_item(
+ title->list_audio, ii );
+ passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+ // Is the source track use a passthru capable codec?
+ if (passthru_acodec == 0)
+ continue;
+ used = get_track_used(passthru_acodec, track_indices, count);
+ // Has the track already been used with this codec?
+ if (used[ii])
+ continue;
+
+ channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
+ audio->in.channel_layout);
+ // Find a track that is not visually impaired or dirctor's
+ // commentary, and has the highest channel count.
+ if ((audio->lang.type < 2) &&
+ ((strcmp(lang, audio->lang.iso639_2) == 0) ||
+ (strcmp(lang, "und") == 0)))
+ {
+ if (channels > max_chan)
+ {
+ track = ii;
+ max_chan = channels;
+ }
+ }
+ }
+ try_acodec = fallback_acodec;
+ }
+ else
+ {
+ try_acodec = acodec;
+ }
+ if (track > -1)
+ {
+ used[track] = TRUE;
+ return track;
+ }
+ // Try to find an item that matches the preferred language
+ max_chan = 0;
+ used = get_track_used(try_acodec, track_indices, count);
+ for (ii = 0; ii < count; ii++)
+ {
+ // Has the track already been used with this codec?
+ if (used[ii])
+ continue;
+ audio = (hb_audio_config_t*)hb_list_audio_config_item(
+ title->list_audio, ii );
+ passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+ if (passthru_acodec && passthru)
+ {
+ passthru_used = get_track_used(passthru_acodec, track_indices, count);
+ // Has the track already been used with this codec for passthru?
+ if (passthru_used[ii])
+ continue;
+ }
+ channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
+ audio->in.channel_layout);
+ // Find a track that is not visually impaired or dirctor's commentary
+ if ((audio->lang.type < 2) &&
+ ((strcmp(lang, audio->lang.iso639_2) == 0) ||
+ (strcmp(lang, "und") == 0)))
+ {
+ if (channels > max_chan)
+ {
+ track = ii;
+ max_chan = channels;
+ }
+ }
+ }
+ if (track > -1)
+ {
+ used[track] = TRUE;
+ return track;
+ }
+ // Try to fine an item that does not match the preferred language and
+ // matches the passthru codec type
+ max_chan = 0;
+ if (passthru)
+ {
+ for (ii = 0; ii < count; ii++)
+ {
+ audio = (hb_audio_config_t*)hb_list_audio_config_item(
+ title->list_audio, ii );
+ passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+ // Is the source track use a passthru capable codec?
+ if (passthru_acodec == 0)
+ continue;
+ used = get_track_used(passthru_acodec, track_indices, count);
+ // Has the track already been used with this codec?
+ if (used[ii])
+ continue;
+
+ channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
+ audio->in.channel_layout);
+ // Find a track that is not visually impaired or dirctor's
+ // commentary, and has the highest channel count.
+ if (audio->lang.type < 2)
+ {
+ if (channels > max_chan)
+ {
+ track = ii;
+ max_chan = channels;
+ }
+ }
+ }
+ try_acodec = fallback_acodec;
+ }
+ else
+ {
+ try_acodec = acodec;
+ }
+ if (track > -1)
+ {
+ used[track] = TRUE;
+ return track;
+ }
+ // Try to fine an item that does not match the preferred language
+ max_chan = 0;
+ used = get_track_used(try_acodec, track_indices, count);
+ for (ii = 0; ii < count; ii++)
+ {
+ // Has the track already been used with this codec?
+ if (used[ii])
+ continue;
+ audio = (hb_audio_config_t*)hb_list_audio_config_item(
+ title->list_audio, ii );
+ passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+ channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
+ audio->in.channel_layout);
+ if (passthru_acodec && passthru)
+ {
+ passthru_used = get_track_used(passthru_acodec, track_indices, count);
+ // Has the track already been used with this codec for passthru?
+ if (passthru_used[ii])
+ continue;
+ }
+ // Find a track that is not visually impaired or dirctor's commentary
+ if (audio->lang.type < 2)
+ {
+ if (channels > max_chan)
+ {
+ track = ii;
+ max_chan = channels;
+ }
+ }
+ }
+ if (track > -1)
+ {
+ used[track] = TRUE;
+ return track;
+ }
+ // Last ditch, anything goes
+ for (ii = 0; ii < count; ii++)
+ {
+ audio = (hb_audio_config_t*)hb_list_audio_config_item(
+ title->list_audio, ii );
+ passthru_acodec = (HB_ACODEC_AC3 | HB_ACODEC_DCA) & audio->in.codec;
+ if (passthru_acodec && passthru)
+ {
+ passthru_used = get_track_used(passthru_acodec, track_indices, count);
+ // Has the track already been used with this codec for passthru?
+ if (passthru_used[ii])
+ continue;
+ }
+ // Has the track already been used with this codec?
+ if (!used[ii])
+ {
+ track = ii;
+ break;
+ }
+ }
+ if (track > -1)
+ {
+ used[track] = TRUE;
+ }
+ return track;
+}
+
+gint
+ghb_find_pref_subtitle_track(const gchar *lang)
+{
+ gint ii, count;
+ count = subtitle_opts.count;
+ for (ii = 0; ii < count; ii++)
+ {
+ if (strcmp(lang, subtitle_opts.map[ii].svalue) == 0)
+ {
+ return subtitle_opts.map[ii].ivalue;
+ }
+ }
+ return -2;
+}
+
+gint
+ghb_find_cc_track(gint titleindex)
+{
+ hb_list_t * list;
+ hb_title_t * title;
+ hb_subtitle_t * subtitle;
+ gint count, ii;