[gthumb: 9/13] media viewer: added keyboard shortcuts, actions to skip forward/backward
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 9/13] media viewer: added keyboard shortcuts, actions to skip forward/backward
- Date: Sun, 19 Jul 2020 09:42:55 +0000 (UTC)
commit a7b8142ef4736b63d2ec5b6cbdc0bd80456db6ed
Author: Paolo Bacchilega <paobac src gnome org>
Date: Mon Jul 13 12:49:03 2020 +0200
media viewer: added keyboard shortcuts, actions to skip forward/backward
.../org.gnome.gthumb.gstreamer-tools.gschema.xml | 3 +
extensions/gstreamer_tools/actions.c | 147 +++++++++
extensions/gstreamer_tools/actions.h | 12 +
extensions/gstreamer_tools/callbacks.c | 13 +
extensions/gstreamer_tools/data/ui/mediabar.ui | 220 ++++++++++---
extensions/gstreamer_tools/gth-media-viewer-page.c | 348 +++++++++++++++++----
extensions/gstreamer_tools/gth-media-viewer-page.h | 6 +
extensions/gstreamer_tools/preferences.h | 1 +
8 files changed, 649 insertions(+), 101 deletions(-)
---
diff --git a/data/gschemas/org.gnome.gthumb.gstreamer-tools.gschema.xml
b/data/gschemas/org.gnome.gthumb.gstreamer-tools.gschema.xml
index 91abd78a..30280d5f 100644
--- a/data/gschemas/org.gnome.gthumb.gstreamer-tools.gschema.xml
+++ b/data/gschemas/org.gnome.gthumb.gstreamer-tools.gschema.xml
@@ -25,6 +25,9 @@
<key name="volume" type="i">
<default>100</default>
</key>
+ <key name="mute" type="b">
+ <default>false</default>
+ </key>
<key name="use-hardware-acceleration" type="b">
<default>false</default>
</key>
diff --git a/extensions/gstreamer_tools/actions.c b/extensions/gstreamer_tools/actions.c
index 2b955f91..08e30d1d 100644
--- a/extensions/gstreamer_tools/actions.c
+++ b/extensions/gstreamer_tools/actions.c
@@ -207,6 +207,45 @@ gth_browser_activate_toggle_play (GSimpleAction *action,
}
+void
+gth_browser_activate_toggle_mute (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page;
+
+ page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));
+ gth_media_viewer_page_toggle_mute (page);
+}
+
+
+void
+gth_browser_activate_play_faster (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page;
+
+ page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));
+ gth_media_viewer_page_play_faster (page);
+}
+
+
+void
+gth_browser_activate_play_slower (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page;
+
+ page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));
+ gth_media_viewer_page_play_slower (page);
+}
+
+
void
gth_browser_activate_video_zoom_fit (GSimpleAction *action,
GVariant *state,
@@ -218,3 +257,111 @@ gth_browser_activate_video_zoom_fit (GSimpleAction *action,
g_simple_action_set_state (action, state);
gth_media_viewer_page_set_fit_if_larger (page, g_variant_get_boolean (state));
}
+
+
+void
+gth_browser_activate_next_video_frame (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_next_frame (page);
+}
+
+
+void
+gth_browser_activate_skip_forward_smaller (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, 5);
+}
+
+
+void
+gth_browser_activate_skip_forward_small (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, 10);
+}
+
+
+void
+gth_browser_activate_skip_forward_big (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, 60);
+}
+
+
+void
+gth_browser_activate_skip_forward_bigger (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, 60 * 5);
+}
+
+
+void
+gth_browser_activate_skip_back_smaller (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, -5);
+}
+
+
+void
+gth_browser_activate_skip_back_small (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, -10);
+}
+
+
+void
+gth_browser_activate_skip_back_big (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, -60);
+}
+
+
+void
+gth_browser_activate_skip_back_bigger (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ GthBrowser *browser = GTH_BROWSER (user_data);
+ GthMediaViewerPage *page = GTH_MEDIA_VIEWER_PAGE (gth_browser_get_viewer_page (browser));;
+
+ gth_media_viewer_page_skip (page, -60 * 5);
+}
diff --git a/extensions/gstreamer_tools/actions.h b/extensions/gstreamer_tools/actions.h
index 8b2712b7..aa807c05 100644
--- a/extensions/gstreamer_tools/actions.h
+++ b/extensions/gstreamer_tools/actions.h
@@ -26,6 +26,18 @@
DEF_ACTION_CALLBACK (gth_browser_activate_video_screenshot)
DEF_ACTION_CALLBACK (gth_browser_activate_toggle_play)
+DEF_ACTION_CALLBACK (gth_browser_activate_toggle_mute)
+DEF_ACTION_CALLBACK (gth_browser_activate_play_faster)
+DEF_ACTION_CALLBACK (gth_browser_activate_play_slower)
DEF_ACTION_CALLBACK (gth_browser_activate_video_zoom_fit)
+DEF_ACTION_CALLBACK (gth_browser_activate_next_video_frame)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_forward_smaller)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_forward_small)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_forward_big)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_forward_bigger)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_back_smaller)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_back_small)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_back_big)
+DEF_ACTION_CALLBACK (gth_browser_activate_skip_back_bigger)
#endif /* ACTIONS_H */
diff --git a/extensions/gstreamer_tools/callbacks.c b/extensions/gstreamer_tools/callbacks.c
index bb5e4ebc..38b40017 100644
--- a/extensions/gstreamer_tools/callbacks.c
+++ b/extensions/gstreamer_tools/callbacks.c
@@ -31,6 +31,19 @@
static const GthShortcut shortcuts[] = {
{ "video-screenshot", N_("Screenshot"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Alt>s" },
{ "toggle-play", N_("Play/Pause"), GTH_SHORTCUT_CONTEXT_VIEWER, GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER,
"space" },
+ { "toggle-mute", N_("Mute"), GTH_SHORTCUT_CONTEXT_VIEWER, GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "m" },
+ { "play-faster", N_("Play faster"), GTH_SHORTCUT_CONTEXT_VIEWER, GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER,
"plus" },
+ { "play-slower", N_("Play slower"), GTH_SHORTCUT_CONTEXT_VIEWER, GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER,
"minus" },
+ { "next-frame", N_("Next frame"), GTH_SHORTCUT_CONTEXT_VIEWER, GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER,
"period" },
+ { "skip-forward-smaller", N_("Go forward 5 seconds"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Shift>Right" },
+ { "skip-forward-small", N_("Go forward 10 seconds"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Alt>Right" },
+ { "skip-forward-big", N_("Go forward 1 minute"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Primary>Right" },
+ { "skip-forward-bigger", N_("Go forward 5 minutes"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Primary><Alt>Right" },
+ { "skip-back-smaller", N_("Go back 5 seconds"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Shift>Left" },
+ { "skip-back-small", N_("Go back 10 seconds"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Alt>Left" },
+ { "skip-back-big", N_("Go back 1 minute"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Primary>Left" },
+ { "skip-back-bigger", N_("Go back 5 minutes"), GTH_SHORTCUT_CONTEXT_VIEWER,
GTH_SHORTCUT_CATEGORY_MEDIA_VIEWER, "<Primary><Alt>Left" },
+
};
diff --git a/extensions/gstreamer_tools/data/ui/mediabar.ui b/extensions/gstreamer_tools/data/ui/mediabar.ui
index 42c7c727..036f5a39 100644
--- a/extensions/gstreamer_tools/data/ui/mediabar.ui
+++ b/extensions/gstreamer_tools/data/ui/mediabar.ui
@@ -1,17 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.36.0 -->
<interface>
- <requires lib="gtk+" version="3.0"/>
+ <requires lib="gtk+" version="3.16"/>
<object class="GtkAdjustment" id="position_adjustment">
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="volume_adjustment">
- <property name="upper">1.5</property>
- <property name="value">1</property>
- <property name="step_increment">0.10000000000000001</property>
- <property name="page_increment">0.10000000000000001</property>
+ <property name="upper">100</property>
+ <property name="value">100</property>
+ <property name="page_increment">5</property>
</object>
<object class="GtkBox" id="mediabar">
<property name="visible">True</property>
@@ -159,45 +158,53 @@
</packing>
</child>
<child>
- <object class="GtkBox" id="box1">
+ <object class="GtkToggleButton" id="position_button">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkLabel" id="label_position">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label">--:--</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label">/</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
<child>
- <object class="GtkLabel" id="label_duration">
+ <object class="GtkBox" id="position_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">--∶--</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkLabel" id="label_position">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">--:--</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">/</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_duration">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">--∶--</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
</child>
</object>
<packing>
@@ -266,4 +273,137 @@ audio-volume-medium-symbolic</property>
<class name="osd"/>
</style>
</object>
+ <object class="GtkPopover" id="position_popover">
+ <property name="can_focus">False</property>
+ <property name="relative_to">position_button</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_back_smaller_button">
+ <property name="label" translatable="yes" comments="minus 5 seconds">-5s</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go back 5 seconds</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_back_small_button">
+ <property name="label" translatable="yes" comments="minus 10 seconds">-10s</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go back 10 seconds</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_back_big_button">
+ <property name="label" translatable="yes" comments="minus 1 minute">-1m</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go back 1 minute</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_back_bigger_button">
+ <property name="label" translatable="yes" comments="minus 5 minutes">-5m</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go back 5 minutes</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_forward_smaller_button">
+ <property name="label" translatable="yes" comments="plus 5 seconds">+5s</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go forward 5 seconds</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_forward_small_button">
+ <property name="label" translatable="yes" comments="plus 10 seconds">+10s</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go forward 10 seconds</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_forward_big_button">
+ <property name="label" translatable="yes" comments="plus 1 minute">+1m</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go forward 1 minute</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="skip_forward_bigger_button">
+ <property name="label" translatable="yes" comments="plus 5 minutes">+5m</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Go forward 5 minutes</property>
+ <property name="relief">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
</interface>
diff --git a/extensions/gstreamer_tools/gth-media-viewer-page.c
b/extensions/gstreamer_tools/gth-media-viewer-page.c
index 316476d6..43b60a07 100644
--- a/extensions/gstreamer_tools/gth-media-viewer-page.c
+++ b/extensions/gstreamer_tools/gth-media-viewer-page.c
@@ -92,6 +92,18 @@ static double default_rates[] = { 0.03, 0.06, 0.12, 0.25, 0.33, 0.50, 0.66, 1.0,
static const GActionEntry actions[] = {
{ "video-screenshot", gth_browser_activate_video_screenshot },
{ "toggle-play", gth_browser_activate_toggle_play },
+ { "toggle-mute", gth_browser_activate_toggle_mute },
+ { "play-faster", gth_browser_activate_play_faster },
+ { "play-slower", gth_browser_activate_play_slower },
+ { "next-frame", gth_browser_activate_next_video_frame },
+ { "skip-forward-smaller", gth_browser_activate_skip_forward_smaller },
+ { "skip-forward-small", gth_browser_activate_skip_forward_small },
+ { "skip-forward-big", gth_browser_activate_skip_forward_big },
+ { "skip-forward-bigger", gth_browser_activate_skip_forward_bigger },
+ { "skip-back-smaller", gth_browser_activate_skip_back_smaller },
+ { "skip-back-small", gth_browser_activate_skip_back_small },
+ { "skip-back-big", gth_browser_activate_skip_back_big },
+ { "skip-back-bigger", gth_browser_activate_skip_back_bigger },
{ "video-zoom-fit", toggle_action_activated, NULL, "true", gth_browser_activate_video_zoom_fit },
};
@@ -341,13 +353,13 @@ volume_value_changed_cb (GtkAdjustment *adjustment,
return;
/* cubic in [0,1], linear in [1,2] */
- v = gtk_adjustment_get_value (adjustment);
+ v = gtk_adjustment_get_value (adjustment) / 100.0;
if (v <= 1.0)
v = (v * v * v);
- g_object_set (self->priv->playbin,
- "volume", v,
- NULL);
+ g_object_set (self->priv->playbin, "volume", v, NULL);
+ if (v > 0)
+ g_object_set (self->priv->playbin, "mute", FALSE, NULL);
}
@@ -358,15 +370,13 @@ static void position_value_changed_cb (GtkAdjustment *adjustment,
static void
update_current_position_bar (GthMediaViewerPage *self)
{
- GstFormat format;
- gint64 current_value = 0;
+ gint64 current_value = 0;
- format = GST_FORMAT_TIME;
- if (gst_element_query_position (self->priv->playbin, format, ¤t_value)) {
- char *s;
+ if (gst_element_query_position (self->priv->playbin, GST_FORMAT_TIME, ¤t_value)) {
+ char *s;
if (self->priv->duration <= 0) {
- gst_element_query_duration (self->priv->playbin, format, &self->priv->duration);
+ gst_element_query_duration (self->priv->playbin, GST_FORMAT_TIME,
&self->priv->duration);
s = _g_format_duration_for_display (GST_TIME_AS_MSECONDS (self->priv->duration));
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("label_duration")), s);
@@ -386,9 +396,8 @@ update_current_position_bar (GthMediaViewerPage *self)
s = _g_format_duration_for_display (GST_TIME_AS_MSECONDS (current_value));
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("label_position")), s);
-
g_free (s);
- }
+ }
}
@@ -473,74 +482,60 @@ play_button_clicked_cb (GtkButton *button,
}
-static int
-get_nearest_rate (double rate)
+static void
+play_slower_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
{
- int min_idx = -1;
- double min_delta = 0;
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (default_rates); i++) {
- double delta;
-
- delta = fabs (default_rates[i] - rate);
- if ((i == 0) || (delta < min_delta)) {
- min_delta = delta;
- min_idx = i;
- }
- }
-
- return min_idx;
+ gth_media_viewer_page_play_slower (GTH_MEDIA_VIEWER_PAGE (user_data));
}
static void
-play_slower_button_clicked_cb (GtkButton *button,
+play_faster_button_clicked_cb (GtkButton *button,
gpointer user_data)
{
- GthMediaViewerPage *self = user_data;
- int i;
+ gth_media_viewer_page_play_faster (GTH_MEDIA_VIEWER_PAGE (user_data));
+}
- i = get_nearest_rate (self->priv->rate);
- if (i > 0)
- self->priv->rate = default_rates[i - 1];
- else
- self->priv->rate = default_rates[0];
- update_player_rate (self);
+static void
+loop_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ GthMediaViewerPage *self = user_data;
+ self->priv->loop = ! self->priv->loop;
}
static void
-play_faster_button_clicked_cb (GtkButton *button,
- gpointer user_data)
+position_button_toggled_cb (GtkButton *button,
+ gpointer user_data)
{
GthMediaViewerPage *self = user_data;
- int i;
- i = get_nearest_rate (self->priv->rate);
- if (i < G_N_ELEMENTS (default_rates) - 1)
- self->priv->rate = default_rates[i + 1];
- else
- self->priv->rate = default_rates[G_N_ELEMENTS (default_rates) - 1];
-
- update_player_rate (self);
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("position_button")))) {
+ gtk_popover_popup (GTK_POPOVER (GET_WIDGET ("position_popover")));
+ gth_browser_keep_mouse_visible (self->priv->browser, TRUE);
+ }
}
static void
-loop_button_clicked_cb (GtkButton *button,
- gpointer user_data)
+position_popover_closed_cb (GtkPopover *popover,
+ gpointer user_data)
{
GthMediaViewerPage *self = user_data;
- self->priv->loop = ! self->priv->loop;
+
+ gth_browser_keep_mouse_visible (self->priv->browser, FALSE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("position_button")), FALSE);
}
static gboolean
update_volume_from_playbin (GthMediaViewerPage *self)
{
- double volume, v;
+ double volume, v;
+ gboolean mute;
if (self->priv->update_volume_id != 0) {
g_source_remove (self->priv->update_volume_id);
@@ -550,7 +545,9 @@ update_volume_from_playbin (GthMediaViewerPage *self)
if ((self->priv->builder == NULL) || (self->priv->playbin == NULL))
return FALSE;
- g_object_get (self->priv->playbin, "volume", &volume, NULL);
+ g_object_get (self->priv->playbin, "volume", &volume, "mute", &mute, NULL);
+ if (mute)
+ volume = 0;
/* cubic in [0,1], linear in [1,2] */
if (volume <= 1.0)
@@ -559,7 +556,7 @@ update_volume_from_playbin (GthMediaViewerPage *self)
v = volume;
g_signal_handlers_block_by_func (GET_WIDGET ("volume_adjustment"), volume_value_changed_cb, self);
- gtk_adjustment_set_value (GTK_ADJUSTMENT (GET_WIDGET ("volume_adjustment")), v);
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (GET_WIDGET ("volume_adjustment")), v * 100.0);
g_signal_handlers_unblock_by_func (GET_WIDGET ("volume_adjustment"), volume_value_changed_cb, self);
return FALSE;
@@ -739,6 +736,11 @@ bus_message_cb (GstBus *bus,
return;
switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ASYNC_DONE: {
+ update_current_position_bar (self);
+ break;
+ }
+
case GST_MESSAGE_STATE_CHANGED: {
GstState old_state;
GstState new_state;
@@ -820,7 +822,7 @@ playbin_notify_volume_cb (GObject *playbin,
GthMediaViewerPage *self = user_data;
if (self->priv->update_volume_id == 0)
- self->priv->update_volume_id = g_idle_add ((GSourceFunc) update_volume_from_playbin,
user_data);
+ self->priv->update_volume_id = g_idle_add ((GSourceFunc) update_volume_from_playbin, self);
}
@@ -896,6 +898,7 @@ create_playbin (GthMediaViewerPage *self)
g_object_set (self->priv->playbin,
"volume", (double) g_settings_get_int (self->priv->settings,
PREF_GSTREAMER_TOOLS_VOLUME) / 100.0,
+ "mute", g_settings_get_boolean (self->priv->settings, PREF_GSTREAMER_TOOLS_MUTE),
"force-aspect-ratio", TRUE,
NULL);
@@ -906,6 +909,10 @@ create_playbin (GthMediaViewerPage *self)
"notify::volume",
G_CALLBACK (playbin_notify_volume_cb),
self);
+ g_signal_connect (self->priv->playbin,
+ "notify::mute",
+ G_CALLBACK (playbin_notify_volume_cb),
+ self);
g_signal_connect (bus,
"message",
G_CALLBACK (bus_message_cb),
@@ -913,6 +920,69 @@ create_playbin (GthMediaViewerPage *self)
}
+static void
+skip_back_bigger_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), -60 * 5);
+}
+
+
+static void
+skip_back_big_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), -60);
+}
+
+
+static void
+skip_back_small_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), -10);
+}
+
+
+static void
+skip_back_smaller_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), -5);
+}
+
+
+static void
+skip_forward_smaller_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), 5);
+}
+
+static void
+skip_forward_small_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), 10);
+}
+
+
+static void
+skip_forward_big_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), 60);
+}
+
+
+static void
+skip_forward_bigger_button_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ gth_media_viewer_page_skip (GTH_MEDIA_VIEWER_PAGE (user_data), 60 * 5);
+}
+
+
static void
gth_media_viewer_page_real_activate (GthViewerPage *base,
GthBrowser *browser)
@@ -1004,6 +1074,46 @@ gth_media_viewer_page_real_activate (GthViewerPage *base,
"clicked",
G_CALLBACK (loop_button_clicked_cb),
self);
+ g_signal_connect (GET_WIDGET ("position_button"),
+ "toggled",
+ G_CALLBACK (position_button_toggled_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("position_popover"),
+ "closed",
+ G_CALLBACK (position_popover_closed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_back_bigger_button"),
+ "clicked",
+ G_CALLBACK (skip_back_bigger_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_back_big_button"),
+ "clicked",
+ G_CALLBACK (skip_back_big_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_back_small_button"),
+ "clicked",
+ G_CALLBACK (skip_back_small_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_back_smaller_button"),
+ "clicked",
+ G_CALLBACK (skip_back_smaller_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_forward_smaller_button"),
+ "clicked",
+ G_CALLBACK (skip_forward_smaller_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_forward_small_button"),
+ "clicked",
+ G_CALLBACK (skip_forward_small_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_forward_big_button"),
+ "clicked",
+ G_CALLBACK (skip_forward_big_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("skip_forward_bigger_button"),
+ "clicked",
+ G_CALLBACK (skip_forward_bigger_button_clicked_cb),
+ self);
self->priv->mediabar_revealer = gtk_revealer_new ();
gtk_revealer_set_transition_type (GTK_REVEALER (self->priv->mediabar_revealer),
GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
@@ -1085,10 +1195,12 @@ gth_media_viewer_page_real_deactivate (GthViewerPage *base)
}
if (self->priv->playbin != NULL) {
- double volume;
+ double volume;
+ gboolean mute;
- g_object_get (self->priv->playbin, "volume", &volume, NULL);
+ g_object_get (self->priv->playbin, "volume", &volume, "mute", &mute, NULL);
g_settings_set_int (self->priv->settings, PREF_GSTREAMER_TOOLS_VOLUME, (int) (volume *
100.0));
+ g_settings_set_boolean (self->priv->settings, PREF_GSTREAMER_TOOLS_MUTE, mute);
g_settings_set_boolean (self->priv->settings, PREF_GSTREAMER_ZOOM_TO_FIT,
self->priv->fit_if_larger);
@@ -1475,6 +1587,13 @@ gth_media_viewer_page_get_file_data (GthMediaViewerPage *self)
}
+static gint64
+_gth_media_viewer_page_get_current_time (GthMediaViewerPage *self)
+{
+ return (gint64) (gtk_adjustment_get_value (GTK_ADJUSTMENT (GET_WIDGET ("position_adjustment"))) /
100.0 * self->priv->duration);
+}
+
+
void
gth_media_viewer_page_toggle_play (GthMediaViewerPage *self)
{
@@ -1494,15 +1613,12 @@ gth_media_viewer_page_toggle_play (GthMediaViewerPage *self)
0.0);
}
else {
- gint64 current_value;
-
- current_value = (gint64) (gtk_adjustment_get_value (GTK_ADJUSTMENT (GET_WIDGET
("position_adjustment"))) / 100.0 * self->priv->duration);
gst_element_seek (self->priv->playbin,
self->priv->rate,
GST_FORMAT_TIME,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
GST_SEEK_TYPE_SET,
- current_value,
+ _gth_media_viewer_page_get_current_time (self),
GST_SEEK_TYPE_NONE,
0.0);
}
@@ -1528,3 +1644,113 @@ gth_media_viewer_page_set_fit_if_larger (GthMediaViewerPage *self,
gth_window_change_action_state (GTH_WINDOW (self->priv->browser), "video-zoom-fit",
self->priv->fit_if_larger);
}
}
+
+
+void
+gth_media_viewer_page_skip (GthMediaViewerPage *self,
+ int seconds)
+{
+ GstSeekFlags seek_flags;
+ GstSeekType start_type;
+ gint64 start;
+
+ if (self->priv->playbin == NULL)
+ return;
+
+ seek_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE;
+ start_type = GST_SEEK_TYPE_SET;
+ start = _gth_media_viewer_page_get_current_time (self) + (seconds * GST_SECOND);
+ if (start < 0)
+ start = 0;
+ if (start >= self->priv->duration) {
+ seek_flags |= GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE | GST_SEEK_FLAG_TRICKMODE;
+ start_type = GST_SEEK_TYPE_END;
+ start = 0;
+ }
+
+ gst_element_seek (self->priv->playbin,
+ self->priv->rate,
+ GST_FORMAT_TIME,
+ seek_flags,
+ start_type,
+ start,
+ GST_SEEK_TYPE_NONE,
+ 0.0);
+}
+
+
+void
+gth_media_viewer_page_next_frame (GthMediaViewerPage *self)
+{
+ if (self->priv->playbin == NULL)
+ return;
+
+ if (! self->priv->has_video)
+ return;
+
+ gst_element_send_event (self->priv->playbin, gst_event_new_step (GST_FORMAT_BUFFERS, 1, ABS
(self->priv->rate), TRUE, FALSE));
+}
+
+
+void
+gth_media_viewer_page_toggle_mute (GthMediaViewerPage *self)
+{
+ gboolean mute;
+
+ if (self->priv->playbin == NULL)
+ return;
+
+ g_object_get (self->priv->playbin, "mute", &mute, NULL);
+ g_object_set (self->priv->playbin, "mute", ! mute, NULL);
+}
+
+
+static int
+get_nearest_rate (double rate)
+{
+ int min_idx = -1;
+ double min_delta = 0;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (default_rates); i++) {
+ double delta;
+
+ delta = fabs (default_rates[i] - rate);
+ if ((i == 0) || (delta < min_delta)) {
+ min_delta = delta;
+ min_idx = i;
+ }
+ }
+
+ return min_idx;
+}
+
+
+void
+gth_media_viewer_page_play_faster (GthMediaViewerPage *self)
+{
+ int i;
+
+ i = get_nearest_rate (self->priv->rate);
+ if (i < G_N_ELEMENTS (default_rates) - 1)
+ self->priv->rate = default_rates[i + 1];
+ else
+ self->priv->rate = default_rates[G_N_ELEMENTS (default_rates) - 1];
+
+ update_player_rate (self);
+}
+
+
+void
+gth_media_viewer_page_play_slower (GthMediaViewerPage *self)
+{
+ int i;
+
+ i = get_nearest_rate (self->priv->rate);
+ if (i > 0)
+ self->priv->rate = default_rates[i - 1];
+ else
+ self->priv->rate = default_rates[0];
+
+ update_player_rate (self);
+}
diff --git a/extensions/gstreamer_tools/gth-media-viewer-page.h
b/extensions/gstreamer_tools/gth-media-viewer-page.h
index 9b8e6c4d..6c8b2b32 100644
--- a/extensions/gstreamer_tools/gth-media-viewer-page.h
+++ b/extensions/gstreamer_tools/gth-media-viewer-page.h
@@ -59,6 +59,12 @@ void gth_media_viewer_page_toggle_play (GthMediaViewerPage *self);
void gth_media_viewer_page_set_fit_if_larger
(GthMediaViewerPage *self,
gboolean fit_if_larger);
+void gth_media_viewer_page_skip (GthMediaViewerPage *self,
+ int seconds);
+void gth_media_viewer_page_next_frame (GthMediaViewerPage *self);
+void gth_media_viewer_page_toggle_mute (GthMediaViewerPage *self);
+void gth_media_viewer_page_play_faster (GthMediaViewerPage *self);
+void gth_media_viewer_page_play_slower (GthMediaViewerPage *self);
G_END_DECLS
diff --git a/extensions/gstreamer_tools/preferences.h b/extensions/gstreamer_tools/preferences.h
index 68b517c2..86f39a8c 100644
--- a/extensions/gstreamer_tools/preferences.h
+++ b/extensions/gstreamer_tools/preferences.h
@@ -30,6 +30,7 @@
#define PREF_GSTREAMER_TOOLS_SCREESHOT_LOCATION "screenshot-location"
#define PREF_GSTREAMER_TOOLS_VOLUME "volume"
+#define PREF_GSTREAMER_TOOLS_MUTE "mute"
#define PREF_GSTREAMER_USE_HARDWARE_ACCEL "use-hardware-acceleration"
#define PREF_GSTREAMER_ZOOM_TO_FIT "zoom-to-fit"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]