]> granicus.if.org Git - handbrake/commitdiff
Create separate fake iso639 "any" entry
authorJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 12 Jul 2019 21:06:18 +0000 (14:06 -0700)
committerJohn Stebbins <jstebbins.hb@gmail.com>
Tue, 10 Sep 2019 16:09:52 +0000 (09:09 -0700)
Allows us to distinguish a selection of "any" which means match any
language from "und" which means the language is not known.

Fixes https://github.com/HandBrake/HandBrake/issues/731

gtk/src/hb-backend.c
libhb/lang.c
libhb/lang.h
libhb/preset.c
macosx/HBLanguagesSelection.m

index 9f842ee89539087c83c4fd888a230b22b81c794c..e54b8964f6eee4fcde4e890fbd6b66b5f5dc8621 100644 (file)
@@ -2000,16 +2000,16 @@ language_opts_set(signal_user_data_t *ud, const gchar *name,
     (void)data; // Silence "unused variable" warning
     GtkTreeIter iter;
     GtkListStore *store;
-    gint ii;
 
     GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(ud->builder, name));
     store = GTK_LIST_STORE(gtk_combo_box_get_model (combo));
     gtk_list_store_clear(store);
     const iso639_lang_t *iso639;
-    for (iso639 = lang_get_next(NULL), ii = 0; iso639 != NULL;
-         iso639 = lang_get_next(iso639), ii++)
+    for (iso639 = lang_get_next(NULL); iso639 != NULL;
+         iso639 = lang_get_next(iso639))
     {
-        gchar *lang;
+        int     index = lang_lookup_index(iso639->iso639_1);
+        gchar * lang;
 
         if (iso639->native_name[0] != 0)
             lang = g_strdup_printf("%s", iso639->native_name);
@@ -2021,7 +2021,7 @@ language_opts_set(signal_user_data_t *ud, const gchar *name,
                            0, lang,
                            1, TRUE,
                            2, iso639->iso639_2,
-                           3, (gdouble)ii,
+                           3, (gdouble)index,
                            -1);
         g_free(lang);
     }
@@ -3050,22 +3050,17 @@ void ghb_init_lang_list(GtkTreeView *tv, signal_user_data_t *ud)
 {
     GtkTreeIter    iter;
     GtkTreeStore * ts;
-    int            ii;
 
     ghb_init_lang_list_model(tv);
     ts = GTK_TREE_STORE(gtk_tree_view_get_model(tv));
 
     const iso639_lang_t *iso639;
-    for (iso639 = lang_get_next(NULL), ii = 0; iso639 != NULL;
-         iso639 = lang_get_next(iso639), ii++)
+    for (iso639 = lang_get_any(); iso639 != NULL;
+         iso639 = lang_get_next(iso639))
     {
+        int          index = lang_lookup_index(iso639->iso639_2);
         const char * lang;
-        if (ii == 0)
-        {
-            lang = _("Any");
-        }
-        else if (iso639->native_name != NULL &&
-                 iso639->native_name[0] != 0)
+        if (iso639->native_name != NULL && iso639->native_name[0] != 0)
         {
             lang = iso639->native_name;
         }
@@ -3074,7 +3069,7 @@ void ghb_init_lang_list(GtkTreeView *tv, signal_user_data_t *ud)
             lang = iso639->eng_name;
         }
         gtk_tree_store_append(ts, &iter, NULL);
-        gtk_tree_store_set(ts, &iter, 0, lang, 1, ii, -1);
+        gtk_tree_store_set(ts, &iter, 0, lang, 1, index, -1);
     }
 }
 
index c7a7e47e1c13bce9cdc77bd6fe95ef5f971f4e3a..cd3c8887fbf2bc424dbdadfe446dc6e6eb7a880f 100644 (file)
 #include <string.h>
 #include <ctype.h>
 
+// Fake iso639 entry to deal with selection of "any" language
+static iso639_lang_t lang_any =
+  { "Any", "", "", "any" };
+
 static const iso639_lang_t languages[] =
 { { "Unknown", "", "", "und" },
   { "Afar", "Qafar", "aa", "aar" },
@@ -207,21 +211,26 @@ const int lang_lookup_index( const char * str )
     int             ii = 0;
     const iso639_lang_t * lang;
 
-    // We use "Any" as a synonym for undefined
-    if (!strcasecmp("any", str))
+    // We use fake lang_any iso639 to designate a match for "Any" language
+    if ((lang_any.iso639_1    && !strcasecmp(lang_any.iso639_1,    str)) ||
+        (lang_any.iso639      && !strcasecmp(lang_any.iso639,      str)) ||
+        (lang_any.iso639_2    && !strcasecmp(lang_any.iso639_2,    str)) ||
+        (lang_any.iso639_2b   && !strcasecmp(lang_any.iso639_2b,   str)) ||
+        (lang_any.eng_name    && !strcasecmp(lang_any.eng_name,    str)) ||
+        (lang_any.native_name && !strcasecmp(lang_any.native_name, str)))
     {
-        return 0;
+        return -1;
     }
 
     for (ii = 0; languages[ii].eng_name; ii++)
     {
         lang = &languages[ii];
-        if ((lang->iso639_1    != NULL && !strcasecmp(lang->iso639_1,  str)) ||
-            (lang->iso639      != NULL && !strcasecmp(lang->iso639,    str)) ||
-            (lang->iso639_2    != NULL && !strcasecmp(lang->iso639_2,  str)) ||
-            (lang->iso639_2b   != NULL && !strcasecmp(lang->iso639_2b, str)) ||
-            (lang->eng_name    != NULL && !strcasecmp(lang->eng_name,  str)) ||
-            (lang->native_name != NULL && !strcasecmp(lang->native_name, str)))
+        if ((lang->iso639_1    && !strcasecmp(lang->iso639_1,    str)) ||
+            (lang->iso639      && !strcasecmp(lang->iso639,      str)) ||
+            (lang->iso639_2    && !strcasecmp(lang->iso639_2,    str)) ||
+            (lang->iso639_2b   && !strcasecmp(lang->iso639_2b,   str)) ||
+            (lang->eng_name    && !strcasecmp(lang->eng_name,    str)) ||
+            (lang->native_name && !strcasecmp(lang->native_name, str)))
         {
             return ii;
         }
@@ -237,6 +246,9 @@ const iso639_lang_t * lang_lookup( const char * str )
 
 const iso639_lang_t * lang_for_index( int index )
 {
+    if (index == -1)
+        return &lang_any;
+
     if (index < 0 || index >= lang_count)
         return NULL;
 
@@ -251,15 +263,21 @@ iso639_lang_t * lang_for_code( int code )
     code_string[0] = tolower( ( code >> 8 ) & 0xFF );
     code_string[1] = tolower( code & 0xFF );
 
-    for( lang = (iso639_lang_t*) languages; lang->eng_name; lang++ )
+    if ((lang_any.iso639_1 && !strncmp(lang_any.iso639_1, code_string, 2)) ||
+        (lang_any.iso639   && !strncmp(lang_any.iso639,   code_string, 2)))
+    {
+        return &lang_any;
+    }
+    for (lang = (iso639_lang_t*) languages; lang->eng_name; lang++)
     {
-        if( !strncmp( lang->iso639_1, code_string, 2 ) ||
-               (lang->iso639 != NULL && !strncmp(lang->iso639, code_string, 2)) )
+        if ((lang->iso639_1 && !strncmp( lang->iso639_1, code_string, 2)) ||
+            (lang->iso639   && !strncmp(lang->iso639,    code_string, 2)))
         {
             return lang;
         }
     }
 
+    // Not found, return "Unknown"
     return (iso639_lang_t*) languages;
 }
 
@@ -273,18 +291,22 @@ iso639_lang_t * lang_for_code2( const char *code )
     code_string[2] = tolower( code[2] );
     code_string[3] = 0;
 
+    if ((lang_any.iso639_2  && !strcmp(lang_any.iso639_2,  code_string)) ||
+        (lang_any.iso639_2b && !strcmp(lang_any.iso639_2b, code_string)))
+    {
+        return &lang_any;
+    }
+
     for( lang = (iso639_lang_t*) languages; lang->eng_name; lang++ )
     {
-        if( !strcmp( lang->iso639_2, code_string ) )
-        {
-            return lang;
-        }
-        if( lang->iso639_2b && !strcmp( lang->iso639_2b, code_string ) )
+        if ((lang->iso639_2  && !strcmp(lang->iso639_2,  code_string)) ||
+            (lang->iso639_2b && !strcmp(lang->iso639_2b, code_string)))
         {
             return lang;
         }
     }
 
+    // Not found, return "Unknown"
     return (iso639_lang_t*) languages;
 }
 
@@ -302,20 +324,30 @@ iso639_lang_t * lang_for_english( const char * english )
 {
     iso639_lang_t * lang;
 
-    for( lang = (iso639_lang_t*) languages; lang->eng_name; lang++ )
+    if (!strcmp(lang_any.eng_name, english))
+    {
+        return &lang_any;
+    }
+    for (lang = (iso639_lang_t*) languages; lang->eng_name; lang++)
     {
-        if( !strcmp( lang->eng_name, english ) )
+        if (!strcmp(lang->eng_name, english))
         {
             return lang;
         }
     }
 
+    // Not found, return "Unknown"
     return (iso639_lang_t*) languages;
 }
 
+const iso639_lang_t* lang_get_any(void)
+{
+    return &lang_any;
+}
+
 const iso639_lang_t* lang_get_next(const iso639_lang_t *last)
 {
-    if (last == NULL)
+    if (last == NULL || last == &lang_any)
     {
         return (const iso639_lang_t*)languages;
     }
@@ -327,4 +359,3 @@ const iso639_lang_t* lang_get_next(const iso639_lang_t *last)
     return ++last;
 }
 
-
index ed3e08e5b21a17eefff408a8c61725c9783e8868..9017de06688fe98984a6b0f1a4d443992500ffb7 100644 (file)
@@ -43,6 +43,15 @@ int lang_to_code(const iso639_lang_t *lang);
 
 iso639_lang_t * lang_for_english( const char * english );
 
+/*
+ * Get fake iso639 cooresponding to "Any"
+ * "Any" is used when a match for any language is desired.
+ *
+ * Calling lang_get_next() with pointer returned by lang_get_any()
+ * returns the first entry in the languages list
+ */
+const iso639_lang_t* lang_get_any(void);
+
 /*
  * Get the next language in the list.
  * Returns NULL if there are no more languages.
index be4d773db4e6c2f641251c46a288468f931ae3b1..057de4ec0a3ec5715d09216dfe079c41d36ae274 100644 (file)
@@ -11,6 +11,7 @@
 #include "hb.h"
 #include "hb_dict.h"
 #include "plist.h"
+#include "lang.h"
 
 #if HB_PROJECT_FEATURE_QSV
 #include "qsv_common.h"
@@ -401,8 +402,9 @@ static hb_dict_t * source_audio_track_used(hb_dict_t *track_dict, int track)
 static int find_audio_track(const hb_title_t *title,
                             const char *lang, int start, int behavior)
 {
-    hb_audio_config_t * audio;
-    int ii, count;
+    hb_audio_config_t   * audio;
+    int                   ii, count;
+    const iso639_lang_t * lang_any = lang_get_any();
 
     count = hb_list_count(title->list_audio);
     for (ii = start; ii < count; ii++)
@@ -416,7 +418,8 @@ static int find_audio_track(const hb_title_t *title,
         if ((behavior == 2 ||
              audio->lang.attributes == HB_AUDIO_ATTR_NONE ||
              (audio->lang.attributes & HB_AUDIO_ATTR_REGULAR_MASK)) &&
-            (!strcmp(lang, audio->lang.iso639_2) || !strcmp(lang, "und")))
+            (!strcmp(lang, audio->lang.iso639_2) ||
+             !strcmp(lang, lang_any->iso639_2)))
         {
             return ii;
         }
@@ -861,11 +864,13 @@ int hb_preset_job_add_audio(hb_handle_t *h, int title_index,
         add_audio_for_lang(list, preset, title, mux, copy_mask, fallback,
                            lang, behavior, mode, track_dict);
     }
-    // If no audios found, try "und" language option
+    // If no audios found, try "any" language option
+    // This can happen if AudioLanguageList is empty or if no audio
+    // matches the users preferred languages in AudioLanguageList
     if (hb_value_array_len(list) <= 0)
     {
         add_audio_for_lang(list, preset, title, mux, copy_mask, fallback,
-                           "und", behavior, mode, track_dict);
+                           "any", behavior, mode, track_dict);
     }
     hb_dict_free(&track_dict);
     return 0;
@@ -875,14 +880,16 @@ int hb_preset_job_add_audio(hb_handle_t *h, int title_index,
 static int find_subtitle_track(const hb_title_t *title,
                                const char *lang, int start)
 {
-    hb_subtitle_t * subtitle;
-    int ii, count;
+    hb_subtitle_t       * subtitle;
+    int                   ii, count;
+    const iso639_lang_t * lang_any = lang_get_any();
 
     count = hb_list_count(title->list_subtitle);
     for (ii = start; ii < count; ii++)
     {
         subtitle = hb_list_item(title->list_subtitle, ii);
-        if (!strcmp(lang, subtitle->iso639_2) || !strcmp(lang, "und"))
+        if (!strcmp(lang, subtitle->iso639_2) ||
+            !strcmp(lang, lang_any->iso639_2))
         {
             return ii;
         }
@@ -1091,14 +1098,16 @@ int hb_preset_job_add_subtitles(hb_handle_t *h, int title_index,
 
 
     // Add tracks for all languages in the language list
-    hb_value_array_t *lang_list = hb_dict_get(preset, "SubtitleLanguageList");
+    hb_value_array_t * lang_list = hb_dict_get(preset, "SubtitleLanguageList");
+    const iso639_lang_t * lang_any  = lang_get_any();
+    const char          * pref_lang = lang_any->iso639_2;
+
     count = hb_value_array_len(lang_list);
-    const char *pref_lang = "und";
     if (count > 0)
     {
         pref_lang = hb_value_get_string(hb_value_array_get(lang_list, 0));
     }
-    if (!strcmp(pref_lang, "und"))
+    if (!strcmp(pref_lang, lang_any->iso639_2))
     {
         if (first_audio_lang != NULL)
         {
@@ -1163,6 +1172,7 @@ int hb_preset_job_add_subtitles(hb_handle_t *h, int title_index,
         }
         if (count <= 0)
         {
+            // No matching language.  Try "Unknown" language
             add_subtitle_for_lang(list, title, mux, "und", &behavior);
         }
     }
index 566d8266e5a0c2c77936ea55a1504237ff1b5f7d..3fedddd6d691dc65415e116103b4e8aa8d214ddd 100644 (file)
@@ -68,8 +68,8 @@
         NSMutableArray<HBLang *> *internal = [[NSMutableArray alloc] init];
         NSMutableArray<HBLang *> *selected = [[NSMutableArray alloc] init];
 
-        const iso639_lang_t *lang = lang_get_next(NULL);
-        for (lang = lang_get_next(lang); lang != NULL; lang = lang_get_next(lang))
+        const iso639_lang_t *lang;
+        for (lang = lang_get_any(); lang != NULL; lang = lang_get_next(lang))
         {
             NSString *nativeLanguage = strlen(lang->native_name) ? @(lang->native_name) : @(lang->eng_name);
 
             
         }
 
-        // Add the (Any) item.
-        HBLang *item = [[HBLang alloc] initWithLanguage:NSLocalizedString(@"(Any)", @"Language selection")
-                                            iso639_2code:@"und"];
-        if ([languages containsObject:item.iso639_2])
-        {
-            item.isSelected = YES;
-        }
-        [internal insertObject:item atIndex:0];
-
         // Insert the selected items
         // in the original order.
         [selected sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {