[totem/wip/hadess/track-lists: 1/7] backend: Move more sub/lang generation inside backend




commit 252354b8ab99a9e934381714dfae050b3070764f
Author: Bastien Nocera <hadess hadess net>
Date:   Fri Feb 11 14:54:17 2022 +0100

    backend: Move more sub/lang generation inside backend
    
    Instead of letting the front-end handle magic numbers for no subtitle,
    or automatic lang selection, add those directly to the backend, and
    export an opaque "id" for the front-end to use.

 src/backend/bacon-video-widget.c | 120 +++++++++++++++++++++++++--------------
 src/backend/bacon-video-widget.h |   2 +
 src/test-totem.c                 |  31 ++++++----
 src/totem-menu.c                 |  69 ++++++++++++++++------
 src/totem-menu.h                 |   6 ++
 5 files changed, 157 insertions(+), 71 deletions(-)
---
diff --git a/src/backend/bacon-video-widget.c b/src/backend/bacon-video-widget.c
index 8e3306952..3ca45043d 100644
--- a/src/backend/bacon-video-widget.c
+++ b/src/backend/bacon-video-widget.c
@@ -99,6 +99,9 @@
 #define REVERSE_RATE -1.0
 #define DIRECTION_STR (forward == FALSE ? "reverse" : "forward")
 
+#define BVW_TRACK_NONE -2
+#define BVW_TRACK_AUTO -1
+
 #define is_error(e, d, c) \
   (e->domain == GST_##d##_ERROR && \
    e->code == GST_##d##_ERROR_##c)
@@ -2585,12 +2588,9 @@ bacon_video_widget_get_property (GObject * object, guint property_id,
  * bacon_video_widget_get_subtitle:
  * @bvw: a #BaconVideoWidget
  *
- * Returns the index of the current subtitles.
- *
- * If the widget is not playing, <code class="literal">-2</code> will be returned. If no subtitles are
- * being used, <code class="literal">-1</code> is returned.
+ * Returns the id of the current subtitles.
  *
- * Return value: the subtitle index
+ * Return value: the subtitle id
  **/
 int
 bacon_video_widget_get_subtitle (BaconVideoWidget * bvw)
@@ -2598,13 +2598,13 @@ bacon_video_widget_get_subtitle (BaconVideoWidget * bvw)
   int subtitle = -1;
   gint flags;
 
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), -2);
-  g_return_val_if_fail (bvw->play != NULL, -2);
+  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), BVW_TRACK_NONE);
+  g_return_val_if_fail (bvw->play != NULL, BVW_TRACK_NONE);
 
   g_object_get (bvw->play, "flags", &flags, NULL);
 
   if ((flags & GST_PLAY_FLAG_TEXT) == 0)
-    return -2;
+    return BVW_TRACK_NONE;
 
   g_object_get (G_OBJECT (bvw->play), "current-text", &subtitle, NULL);
 
@@ -2615,8 +2615,8 @@ static gboolean
 sublang_is_valid (int sublang,
                  int n_sublang)
 {
-  if (sublang == -1 ||
-      sublang == -2)
+  if (sublang == BVW_TRACK_AUTO ||
+      sublang == BVW_TRACK_NONE)
     return TRUE;
   if (sublang < 0)
     return FALSE;
@@ -2628,10 +2628,9 @@ sublang_is_valid (int sublang,
 /**
  * bacon_video_widget_set_subtitle:
  * @bvw: a #BaconVideoWidget
- * @subtitle: a subtitle index
+ * @subtitle: a subtitle id
  *
- * Sets the subtitle index for @bvw. If @subtitle is <code class="literal">-1</code>, no subtitles will
- * be used.
+ * Sets the subtitle id for @bvw.
  **/
 void
 bacon_video_widget_set_subtitle (BaconVideoWidget * bvw, int subtitle)
@@ -2647,7 +2646,7 @@ bacon_video_widget_set_subtitle (BaconVideoWidget * bvw, int subtitle)
 
   g_return_if_fail (sublang_is_valid (subtitle, n_text));
 
-  if (subtitle == -2) {
+  if (subtitle == BVW_TRACK_NONE) {
     flags &= ~GST_PLAY_FLAG_TEXT;
     subtitle = -1;
   } else {
@@ -2664,11 +2663,30 @@ bacon_video_widget_set_subtitle (BaconVideoWidget * bvw, int subtitle)
   }
 }
 
+static BvwLangInfo *
+find_next_info_for_id (GList *list,
+                      int    current)
+{
+  GList *l;
+
+  if (list == NULL)
+    return NULL;
+  for (l = list; l != NULL; l = l->next) {
+    BvwLangInfo *info = l->data;
+    if (info->id == current) {
+      if (l->next == NULL)
+        return list->data;
+      return l->next->data;
+    }
+  }
+  return NULL;
+}
+
 /**
  * bacon_video_widget_set_next_subtitle:
  * @bvw: a #BaconVideoWidget
  *
- * Switch to the next text subtitle index for the current video. See
+ * Switch to the next text subtitle for the current video. See
  * bacon_video_widget_set_subtitle().
  *
  * Since: 3.12
@@ -2676,16 +2694,18 @@ bacon_video_widget_set_subtitle (BaconVideoWidget * bvw, int subtitle)
 void
 bacon_video_widget_set_next_subtitle (BaconVideoWidget *bvw)
 {
-  int n_text;
+  BvwLangInfo *info;
   int current_text;
 
-  g_object_get (bvw->play, "current-text", &current_text, "n-text", &n_text, NULL);
-
-  current_text++;
-  if (current_text >= n_text)
-    current_text = -2;
-
-  bacon_video_widget_set_subtitle (bvw, current_text);
+  current_text = bacon_video_widget_get_subtitle (bvw);
+  info = find_next_info_for_id (bvw->subtitles, current_text);
+  if (!info) {
+    GST_DEBUG ("Could not find next subtitle id (current = %d)", current_text);
+    return;
+  }
+  GST_DEBUG ("Switching from subtitle %d to next %d", current_text, info->id);
+  bacon_video_widget_set_subtitle (bvw, info->id);
+  g_signal_emit (bvw, bvw_signals[SIGNAL_SUBTITLES_CHANGED], 0);
 }
 
 static gboolean
@@ -2845,6 +2865,7 @@ get_lang_list_for_type (BaconVideoWidget * bvw, const gchar * type_name)
     g_signal_emit_by_name (G_OBJECT (bvw->play), signal, i, &tags);
 
     info = g_new0 (BvwLangInfo, 1);
+    info->id = i;
 
     if (tags) {
       gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &info->language);
@@ -2867,11 +2888,10 @@ static void
 print_lang_list (GList *list)
 {
   GList *l;
-  guint i;
 
-  for (l = list, i = 0; l != NULL; l = l->next, i++) {
+  for (l = list; l != NULL; l = l->next) {
     BvwLangInfo *info = l->data;
-    GST_DEBUG ("  %d: %s / %s / %s", i,
+    GST_DEBUG ("  %d: %s / %s / %s", info->id,
               GST_STR_NULL (info->title),
               GST_STR_NULL (info->language),
               GST_STR_NULL (info->codec));
@@ -2884,6 +2904,15 @@ update_subtitles_tracks (BaconVideoWidget *bvw)
   g_autolist(BvwLangInfo) list;
 
   list = get_lang_list_for_type (bvw, "TEXT");
+
+  /* Add "none" if there's subs */
+  if (list != NULL || bvw->subtitle_uri != NULL) {
+    BvwLangInfo *info;
+    info = g_new0 (BvwLangInfo, 1);
+    info->id = BVW_TRACK_NONE;
+    info->codec = g_strdup ("none");
+    list = g_list_prepend (list, info);
+  }
   if (bvw_lang_infos_equal (list, bvw->subtitles))
     return FALSE;
   if (bvw->subtitles)
@@ -2900,6 +2929,15 @@ update_languages_tracks (BaconVideoWidget *bvw)
   g_autolist(BvwLangInfo) list;
 
   list = get_lang_list_for_type (bvw, "AUDIO");
+
+  /* Add "auto" if we have a DVD */
+  if (g_str_has_prefix (bvw->mrl, "dvd:")) {
+    BvwLangInfo *info;
+    info = g_new0 (BvwLangInfo, 1);
+    info->id = 0;
+    info->codec = g_strdup ("auto");
+    list = g_list_prepend (list, info);
+  }
   if (bvw_lang_infos_equal (list, bvw->languages))
     return FALSE;
   if (bvw->languages)
@@ -2965,7 +3003,7 @@ bacon_video_widget_get_languages (BaconVideoWidget * bvw)
  * bacon_video_widget_get_language:
  * @bvw: a #BaconVideoWidget
  *
- * Returns the index of the current audio language.
+ * Returns the id of the current audio language.
  *
  * If the widget is not playing, or the default language is in use, <code class="literal">-1</code> will be 
returned.
  *
@@ -2989,8 +3027,7 @@ bacon_video_widget_get_language (BaconVideoWidget * bvw)
  * @bvw: a #BaconVideoWidget
  * @language: an audio language index
  *
- * Sets the audio language index for @bvw. If @language is <code class="literal">-1</code>, the default 
language will
- * be used.
+ * Sets the audio language id for @bvw.
  **/
 void
 bacon_video_widget_set_language (BaconVideoWidget * bvw, int language)
@@ -3005,11 +3042,6 @@ bacon_video_widget_set_language (BaconVideoWidget * bvw, int language)
 
   g_return_if_fail (sublang_is_valid (language, n_lang));
 
-  if (language == -1)
-    language = 0;
-  else if (language == -2)
-    language = -1;
-
   GST_DEBUG ("setting language to %d", language);
 
   g_object_set (bvw->play, "current-audio", language, NULL);
@@ -3030,7 +3062,7 @@ bacon_video_widget_set_language (BaconVideoWidget * bvw, int language)
  * bacon_video_widget_set_next_language:
  * @bvw: a #BaconVideoWidget
  *
- * Switch to the next audio language index for the current video. See
+ * Switch to the next audio language for the current video. See
  * bacon_video_widget_set_language().
  *
  * Since: 3.12
@@ -3038,16 +3070,18 @@ bacon_video_widget_set_language (BaconVideoWidget * bvw, int language)
 void
 bacon_video_widget_set_next_language (BaconVideoWidget *bvw)
 {
-  int n_audio;
+  BvwLangInfo *info;
   int current_audio;
 
-  g_object_get (bvw->play, "current-audio", &current_audio, "n-audio", &n_audio, NULL);
-
-  current_audio++;
-  if (current_audio >= n_audio)
-    current_audio = -2;
-
-  bacon_video_widget_set_language (bvw, current_audio);
+  g_object_get (bvw->play, "current-audio", &current_audio, NULL);
+  info = find_next_info_for_id (bvw->languages, current_audio);
+  if (!info) {
+    GST_DEBUG ("Could not find next language id (current = %d)", current_audio);
+    return;
+  }
+  GST_DEBUG ("Switching from audio track %d to next %d", current_audio, info->id);
+  bacon_video_widget_set_language (bvw, info->id);
+  g_signal_emit (bvw, bvw_signals[SIGNAL_LANGUAGES_CHANGED], 0);
 }
 
 /**
diff --git a/src/backend/bacon-video-widget.h b/src/backend/bacon-video-widget.h
index 19e0a59c1..0e6c77b22 100644
--- a/src/backend/bacon-video-widget.h
+++ b/src/backend/bacon-video-widget.h
@@ -343,6 +343,7 @@ void bacon_video_widget_dvd_event                (BaconVideoWidget *bvw,
  * @language: the ISO-639 language code for the track, or "und" if unknown.
  *   Can never be %NULL.
  * @codec: the codec for the track, or %NULL if unknown or unset.
+ * @index: an opaque track identifier.
  *
  * #BvwLangInfo holds the title, language code and codec for each
  * subtitle or audio track for a media, which would allow the
@@ -352,6 +353,7 @@ typedef struct {
        char *title;
        char *language;
        char *codec;
+       guint id;
 } BvwLangInfo;
 
 void         bacon_video_widget_lang_info_free           (BvwLangInfo *info);
diff --git a/src/test-totem.c b/src/test-totem.c
index 1de005b1b..de4520a22 100644
--- a/src/test-totem.c
+++ b/src/test-totem.c
@@ -23,6 +23,15 @@ bvw_lang_info_new (const char *title,
        return info;
 }
 
+static const char *
+nth_label (GList *list, guint index)
+{
+       MenuItem *item = g_list_nth_data (list, index);
+       if (!item)
+               return NULL;
+       return item->label;
+}
+
 static void
 test_menus_lang_info (void)
 {
@@ -36,8 +45,8 @@ test_menus_lang_info (void)
        ret = bvw_lang_info_to_menu_labels (l, BVW_TRACK_TYPE_AUDIO);
        g_list_free_full (l, (GDestroyNotify) bacon_video_widget_lang_info_free);
 
-       g_assert_cmpstr (g_list_nth_data (ret, 0), ==, "Audio Track #1");
-       g_assert_cmpstr (g_list_nth_data (ret, 1), ==, "Audio Track #2");
+       g_assert_cmpstr (nth_label (ret, 0), ==, "Audio Track #1");
+       g_assert_cmpstr (nth_label (ret, 1), ==, "Audio Track #2");
        g_list_free_full (ret, g_free);
 
        /* Same language, same codecs */
@@ -49,9 +58,9 @@ test_menus_lang_info (void)
        ret = bvw_lang_info_to_menu_labels (l, BVW_TRACK_TYPE_AUDIO);
        g_list_free_full (l, (GDestroyNotify) bacon_video_widget_lang_info_free);
 
-       g_assert_cmpstr (g_list_nth_data (ret, 0), ==, "English #1");
-       g_assert_cmpstr (g_list_nth_data (ret, 1), ==, "English #2");
-       g_assert_cmpstr (g_list_nth_data (ret, 2), ==, "French");
+       g_assert_cmpstr (nth_label (ret, 0), ==, "English #1");
+       g_assert_cmpstr (nth_label (ret, 1), ==, "English #2");
+       g_assert_cmpstr (nth_label (ret, 2), ==, "French");
        g_list_free_full (ret, g_free);
 
        /* Same language, different codecs */
@@ -63,9 +72,9 @@ test_menus_lang_info (void)
        ret = bvw_lang_info_to_menu_labels (l, BVW_TRACK_TYPE_AUDIO);
        g_list_free_full (l, (GDestroyNotify) bacon_video_widget_lang_info_free);
 
-       g_assert_cmpstr (g_list_nth_data (ret, 0), ==, "English — Dolby Pro Racing");
-       g_assert_cmpstr (g_list_nth_data (ret, 1), ==, "English — Dolby Amateur 5.1");
-       g_assert_cmpstr (g_list_nth_data (ret, 2), ==, "French");
+       g_assert_cmpstr (nth_label (ret, 0), ==, "English — Dolby Pro Racing");
+       g_assert_cmpstr (nth_label (ret, 1), ==, "English — Dolby Amateur 5.1");
+       g_assert_cmpstr (nth_label (ret, 2), ==, "French");
        g_list_free_full (ret, g_free);
 
        /* Different languages */
@@ -77,9 +86,9 @@ test_menus_lang_info (void)
        ret = bvw_lang_info_to_menu_labels (l, BVW_TRACK_TYPE_AUDIO);
        g_list_free_full (l, (GDestroyNotify) bacon_video_widget_lang_info_free);
 
-       g_assert_cmpstr (g_list_nth_data (ret, 0), ==, "English");
-       g_assert_cmpstr (g_list_nth_data (ret, 1), ==, "Spanish; Castilian");
-       g_assert_cmpstr (g_list_nth_data (ret, 2), ==, "French");
+       g_assert_cmpstr (nth_label (ret, 0), ==, "English");
+       g_assert_cmpstr (nth_label (ret, 1), ==, "Spanish; Castilian");
+       g_assert_cmpstr (nth_label (ret, 2), ==, "French");
        g_list_free_full (ret, g_free);
 }
 
diff --git a/src/totem-menu.c b/src/totem-menu.c
index 3016ad5fd..d92414d8f 100644
--- a/src/totem-menu.c
+++ b/src/totem-menu.c
@@ -419,6 +419,36 @@ get_language_name_no_und (const char   *lang,
        return NULL;
 }
 
+void
+free_menu_item (MenuItem *item)
+{
+       if (!item)
+               return;
+       g_free (item->label);
+       g_free (item);
+}
+
+static MenuItem *
+create_special_menu_item (BvwLangInfo *info)
+{
+       MenuItem *menu_item;
+       const char *label;
+
+       if (g_strcmp0 (info->codec, "auto") == 0) {
+               /* Translators: an entry in the "Languages" menu, used to choose the audio language of a DVD 
*/
+               label = C_("Language", "Auto");
+       } else if (g_strcmp0 (info->codec, "none") == 0) {
+               /* Translators: an entry in the "Subtitles" menu, used to choose the subtitle language of a 
DVD */
+               label = _("None");
+       } else
+               return NULL;
+
+       menu_item = g_new0 (MenuItem, 1);
+       menu_item->label = g_strdup (_(label));
+       menu_item->id = info->id;
+       return menu_item;
+}
+
 GList *
 bvw_lang_info_to_menu_labels (GList        *langs,
                              BvwTrackType  track_type)
@@ -435,6 +465,9 @@ bvw_lang_info_to_menu_labels (GList        *langs,
                int num;
                char *id;
 
+               if (!info->language)
+                       continue;
+
                num = hash_table_num_instances (lang_table, info->language);
                num++;
                g_hash_table_insert (lang_table,
@@ -453,9 +486,16 @@ bvw_lang_info_to_menu_labels (GList        *langs,
        printed_table = g_hash_table_new (g_str_hash, g_str_equal);
        for (l = langs; l != NULL; l = l->next) {
                BvwLangInfo *info = l->data;
+               MenuItem *menu_item;
                int num;
                char *str;
 
+               menu_item = create_special_menu_item (info);
+               if (menu_item) {
+                       ret = g_list_prepend (ret, menu_item);
+                       continue;
+               }
+
                num = hash_table_num_instances (lang_table, info->language);
                g_assert (num >= 1);
                if (num > 1) {
@@ -483,7 +523,10 @@ bvw_lang_info_to_menu_labels (GList        *langs,
                        str = g_strdup (get_language_name_no_und (info->language, track_type));
                }
 
-               ret = g_list_prepend (ret, str);
+               menu_item = g_new0 (MenuItem, 1);
+               menu_item->label = str;
+               menu_item->id = info->id;
+               ret = g_list_prepend (ret, menu_item);
        }
 
        g_hash_table_destroy (printed_table);
@@ -510,13 +553,12 @@ static void
 add_lang_action (GMenu *menu,
                 const char *action,
                 const char *label,
-                int lang_id)
+                int         id)
 {
-       char *escaped_label;
+       g_autofree char *escaped_label = NULL;
 
        escaped_label = escape_label_for_menu (label);
-       add_lang_item (menu, escaped_label, action, lang_id);
-       g_free (escaped_label);
+       add_lang_item (menu, escaped_label, action, id);
 }
 
 static void
@@ -526,22 +568,15 @@ create_lang_actions (GMenu        *menu,
                     BvwTrackType  track_type)
 {
        GList *ui_list, *l;
-       guint i;
-
-       if (track_type == BVW_TRACK_TYPE_SUBTITLE) {
-               /* Translators: an entry in the "Subtitles" menu, used to choose the subtitle language of a 
DVD */
-               add_lang_action (menu, action, _("None"), -2);
-       }
-
-       /* Translators: an entry in the "Languages" menu, used to choose the audio language of a DVD */
-       add_lang_action (menu, action, C_("Language", "Auto"), -1);
 
        ui_list = bvw_lang_info_to_menu_labels (list, track_type);
 
-       for (l = ui_list, i = 0; l != NULL; l = l->next, i++)
-               add_lang_action (menu, action, l->data, i);
+       for (l = ui_list; l != NULL; l = l->next) {
+               MenuItem *item = l->data;
+               add_lang_action (menu, action, item->label, item->id);
+       }
 
-       g_list_free_full (ui_list, (GDestroyNotify) g_free);
+       g_list_free_full (ui_list, (GDestroyNotify) free_menu_item);
 }
 
 static void
diff --git a/src/totem-menu.h b/src/totem-menu.h
index f826e0219..035535871 100644
--- a/src/totem-menu.h
+++ b/src/totem-menu.h
@@ -35,8 +35,14 @@ void totem_subtitles_menu_update (Totem *totem);
 void totem_languages_menu_update (Totem *totem);
 
 /* For test use only */
+typedef struct {
+       char *label;
+       int id;
+} MenuItem;
+
 GList *bvw_lang_info_to_menu_labels (GList        *langs,
                                     BvwTrackType  track_type);
+void free_menu_item (MenuItem *item);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]