summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2022-02-11 14:54:17 +0100
committerBastien Nocera <hadess@hadess.net>2022-02-11 18:33:04 +0100
commit252354b8ab99a9e934381714dfae050b3070764f (patch)
tree993b57ee019d1a7df8cf8d48787d5dac262182af
parentc16df464d1c47f6419054e9eaac804d6d32b5395 (diff)
downloadtotem-252354b8ab99a9e934381714dfae050b3070764f.tar.gz
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.
-rw-r--r--src/backend/bacon-video-widget.c120
-rw-r--r--src/backend/bacon-video-widget.h2
-rw-r--r--src/test-totem.c31
-rw-r--r--src/totem-menu.c69
-rw-r--r--src/totem-menu.h6
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