1e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block/*
2e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  Copyright (C) 2010 Igalia S.L
3e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *
4e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  This library is free software; you can redistribute it and/or
5e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  modify it under the terms of the GNU Library General Public
6e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  License as published by the Free Software Foundation; either
7e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  version 2 of the License, or (at your option) any later version.
8e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *
9e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  This library is distributed in the hope that it will be useful,
10e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  Library General Public License for more details.
13e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *
14e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  You should have received a copy of the GNU Library General Public License
15e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  along with this library; see the file COPYING.LIB.  If not, write to
16e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *  Boston, MA 02110-1301, USA.
18e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block */
19e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
20e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "config.h"
21e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
22e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#if ENABLE(VIDEO)
23e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
24e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "FullscreenVideoController.h"
25e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
2665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "GRefPtrGtk.h"
2768513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "GtkVersioning.h"
28e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "MediaPlayer.h"
29e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
30e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include <gdk/gdk.h>
31e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include <gdk/gdkkeysyms.h>
32e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include <glib/gi18n-lib.h>
33e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include <gst/gst.h>
34e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include <gtk/gtk.h>
35e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
36e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockusing namespace std;
37e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockusing namespace WebCore;
38e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
39e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define HUD_AUTO_HIDE_INTERVAL 3000 // 3 seconds
40e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define PROGRESS_BAR_UPDATE_INTERVAL 150 // 150ms
41e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define VOLUME_UP_OFFSET 0.05 // 5%
42e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define VOLUME_DOWN_OFFSET 0.05 // 5%
43e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
44e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block// Use symbolic icons only if we build with GTK+-3 support. They could
45e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block// be enabled for the GTK+2 build but we'd need to bump the required
46e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block// version to at least 2.22.
47e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#if GTK_MAJOR_VERSION < 3
48e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define PLAY_ICON_NAME "media-playback-start"
49e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define PAUSE_ICON_NAME "media-playback-pause"
50e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define EXIT_FULLSCREEN_ICON_NAME "view-restore"
51e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#else
52e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define PLAY_ICON_NAME "media-playback-start-symbolic"
53e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define PAUSE_ICON_NAME "media-playback-pause-symbolic"
54e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#define EXIT_FULLSCREEN_ICON_NAME "view-restore-symbolic"
55e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#endif
56e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
57e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic gboolean hideHudCallback(FullscreenVideoController* controller)
58e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
59e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->hideHud();
60e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return FALSE;
61e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
62e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
63e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic gboolean onFullscreenGtkMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event,  FullscreenVideoController* controller)
64e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
65e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->showHud(true);
66e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return TRUE;
67e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
68e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
69e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic void onFullscreenGtkActiveNotification(GtkWidget* widget, GParamSpec* property, FullscreenVideoController* controller)
70e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
71e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!gtk_window_is_active(GTK_WINDOW(widget)))
72e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        controller->hideHud();
73e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
74e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
75e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic gboolean onFullscreenGtkConfigureEvent(GtkWidget* widget, GdkEventConfigure* event, FullscreenVideoController* controller)
76e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
77e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->gtkConfigure(event);
78e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return TRUE;
79e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
80e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
81e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic void onFullscreenGtkDestroy(GtkWidget* widget, FullscreenVideoController* controller)
82e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
83e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->exitFullscreen();
84e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
85e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
86e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic void togglePlayPauseActivated(GtkAction* action, FullscreenVideoController* controller)
87e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
88e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->togglePlay();
89e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
90e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
91e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic void exitFullscreenActivated(GtkAction* action, FullscreenVideoController* controller)
92e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
93e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->exitOnUserRequest();
94e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
95e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
96e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic gboolean progressBarUpdateCallback(FullscreenVideoController* controller)
97e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
98e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return controller->updateHudProgressBar();
99e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
100e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
101e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic gboolean timeScaleButtonPressed(GtkWidget* widget, GdkEventButton* event, FullscreenVideoController* controller)
102e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
103e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (event->type != GDK_BUTTON_PRESS)
104e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return FALSE;
105e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
106e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->beginSeek();
107e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return FALSE;
108e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
109e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
110e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic gboolean timeScaleButtonReleased(GtkWidget* widget, GdkEventButton* event, FullscreenVideoController* controller)
111e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
112e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->endSeek();
113e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return FALSE;
114e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
115e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
116e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic void timeScaleValueChanged(GtkWidget* widget, FullscreenVideoController* controller)
117e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
118e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->doSeek();
119e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
120e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
121e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic void volumeValueChanged(GtkScaleButton *button, gdouble value, FullscreenVideoController* controller)
122e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
123e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->setVolume(static_cast<float>(value));
124e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
125e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
126e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid playerVolumeChangedCallback(GObject *element, GParamSpec *pspec, FullscreenVideoController* controller)
127e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
128e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->volumeChanged();
129e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
130e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
131e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid playerMuteChangedCallback(GObject *element, GParamSpec *pspec, FullscreenVideoController* controller)
132e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
133e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    controller->muteChanged();
134e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
135e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
136e8b154fd68f9b33be40a3590e58347f353835f5cSteve BlockFullscreenVideoController::FullscreenVideoController()
137e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    : m_hudTimeoutId(0)
138e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_progressBarUpdateId(0)
139e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_seekLock(false)
140e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_window(0)
141e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_hudWindow(0)
142e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
143e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
144e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
145e8b154fd68f9b33be40a3590e58347f353835f5cSteve BlockFullscreenVideoController::~FullscreenVideoController()
146e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
147e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    exitFullscreen();
148e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
149e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
150e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::setMediaElement(HTMLMediaElement* mediaElement)
151e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
152e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (mediaElement == m_mediaElement)
153e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
154e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
155e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_mediaElement = mediaElement;
156e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_mediaElement) {
157e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        // Can't do full-screen, just get out
158e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        exitFullscreen();
159e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
160e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
161e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
162e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::gtkConfigure(GdkEventConfigure* event)
163e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
164e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    updateHudPosition();
165e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
166e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
167e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::showHud(bool autoHide)
168e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
169e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_hudWindow)
170e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
171e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
172e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_hudTimeoutId) {
173e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        g_source_remove(m_hudTimeoutId);
174e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_hudTimeoutId = 0;
175e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
176e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
177e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Show the cursor.
178e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GdkWindow* window = gtk_widget_get_window(m_window);
179bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    gdk_window_set_cursor(window, 0);
180e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
181e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Update the progress bar immediately before showing the window.
182e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    updateHudProgressBar();
183e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_widget_show_all(m_hudWindow);
184e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    updateHudPosition();
185e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
186e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Start periodic updates of the progress bar.
187e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_progressBarUpdateId)
188e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_progressBarUpdateId = g_timeout_add(PROGRESS_BAR_UPDATE_INTERVAL, reinterpret_cast<GSourceFunc>(progressBarUpdateCallback), this);
189e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
190e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Hide the hud in few seconds, if requested.
191e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (autoHide)
192e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_hudTimeoutId = g_timeout_add(HUD_AUTO_HIDE_INTERVAL, reinterpret_cast<GSourceFunc>(hideHudCallback), this);
193e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
194e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
195e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::hideHud()
196e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
197e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_hudTimeoutId) {
198e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        g_source_remove(m_hudTimeoutId);
199e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_hudTimeoutId = 0;
200e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
201e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
202e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_hudWindow)
203e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
204e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
205e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Keep the hud visible if a seek is in progress or if the volume
206e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // popup is visible.
207e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GtkWidget* volumePopup = gtk_scale_button_get_popup(GTK_SCALE_BUTTON(m_volumeButton));
208e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_seekLock || gtk_widget_get_visible(volumePopup)) {
209e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        showHud(true);
210e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
211e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
212e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
213e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GdkWindow* window = gtk_widget_get_window(m_window);
214bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    GdkCursor* cursor = blankCursor();
215e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gdk_window_set_cursor(window, cursor);
216e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
217a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    gtk_widget_hide(m_hudWindow);
218e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
219e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_progressBarUpdateId) {
220e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        g_source_remove(m_progressBarUpdateId);
221e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_progressBarUpdateId = 0;
222e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
223e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
224e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
225e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic gboolean onFullscreenGtkKeyPressEvent(GtkWidget* widget, GdkEventKey* event, FullscreenVideoController* controller)
226e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
227e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    switch (event->keyval) {
228e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    case GDK_Escape:
229e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    case 'f':
230e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    case 'F':
231e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        controller->exitOnUserRequest();
232e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        break;
233e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    case GDK_space:
234e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    case GDK_Return:
235e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        controller->togglePlay();
236e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        break;
237e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    case GDK_Up:
238e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        // volume up
239e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        controller->setVolume(controller->volume() + VOLUME_UP_OFFSET);
240e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        break;
241e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    case GDK_Down:
242e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        // volume down
243e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        controller->setVolume(controller->volume() - VOLUME_DOWN_OFFSET);
244e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        break;
245e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    default:
246e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        break;
247e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
248e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
249e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return TRUE;
250e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
251e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
252e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
253e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::enterFullscreen()
254e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
255e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_mediaElement)
256e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
257e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
258e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement->platformMedia().type != WebCore::PlatformMedia::GStreamerGWorldType)
259e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
260e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
261e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_gstreamerGWorld = m_mediaElement->platformMedia().media.gstreamerGWorld;
262e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_gstreamerGWorld->enterFullscreen())
263e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
264e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
265e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_window = reinterpret_cast<GtkWidget*>(m_gstreamerGWorld->platformVideoWindow()->window());
266e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
267e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GstElement* pipeline = m_gstreamerGWorld->pipeline();
268e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(pipeline, "notify::volume", G_CALLBACK(playerVolumeChangedCallback), this);
269e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(pipeline, "notify::mute", G_CALLBACK(playerMuteChangedCallback), this);
270e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
271e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_hudWindow)
272e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        createHud();
273e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
274e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Ensure black background.
27565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#ifdef GTK_API_VERSION_2
27665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    GdkColor color = { 1, 0, 0, 0 };
277e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_widget_modify_bg(m_window, GTK_STATE_NORMAL, &color);
27865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#else
27965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    GdkRGBA color = { 0, 0, 0, 1};
28065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    gtk_widget_override_background_color(m_window, GTK_STATE_FLAG_NORMAL, &color);
28165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#endif
282e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_widget_set_double_buffered(m_window, FALSE);
283e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
284e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_window, "key-press-event", G_CALLBACK(onFullscreenGtkKeyPressEvent), this);
285e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_window, "destroy", G_CALLBACK(onFullscreenGtkDestroy), this);
286e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_window, "notify::is-active", G_CALLBACK(onFullscreenGtkActiveNotification), this);
287e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
288e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_widget_show_all(m_window);
289e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
290e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GdkWindow* window = gtk_widget_get_window(m_window);
29165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    GRefPtr<GdkCursor> cursor(adoptGRef(blankCursor()));
29265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    gdk_window_set_cursor(window, cursor.get());
293e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
294e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_window, "motion-notify-event", G_CALLBACK(onFullscreenGtkMotionNotifyEvent), this);
295e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_window, "configure-event", G_CALLBACK(onFullscreenGtkConfigureEvent), this);
296e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
297e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_window_fullscreen(GTK_WINDOW(m_window));
298e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    showHud(true);
299e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
300e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
301e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::updateHudPosition()
302e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
303e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_hudWindow)
304e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
305e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
306e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Get the screen rectangle.
307e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(m_window));
308e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GdkWindow* window = gtk_widget_get_window(m_window);
309e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GdkRectangle fullscreenRectangle;
310e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gdk_screen_get_monitor_geometry(screen, gdk_screen_get_monitor_at_window(screen, window),
311e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block                                    &fullscreenRectangle);
312e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
313e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Get the popup window size.
314e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    int hudWidth, hudHeight;
315e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_window_get_size(GTK_WINDOW(m_hudWindow), &hudWidth, &hudHeight);
316e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
317e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Resize the hud to the full width of the screen.
318e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_window_resize(GTK_WINDOW(m_hudWindow), fullscreenRectangle.width, hudHeight);
319e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
320e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Move the hud to the bottom of the screen.
321e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_window_move(GTK_WINDOW(m_hudWindow), fullscreenRectangle.x,
322e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block                    fullscreenRectangle.height + fullscreenRectangle.y - hudHeight);
323e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
324e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
325e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::exitOnUserRequest()
326e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
327e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_mediaElement->exitFullscreen();
328e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
329e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
330e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::exitFullscreen()
331e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
332e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_hudWindow)
333e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
334e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
335e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkKeyPressEvent), this);
336e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkDestroy), this);
337e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkMotionNotifyEvent), this);
338e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handlers_disconnect_by_func(m_window, reinterpret_cast<void*>(onFullscreenGtkConfigureEvent), this);
339e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
340e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GstElement* pipeline = m_mediaElement->platformMedia().media.gstreamerGWorld->pipeline();
341e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handlers_disconnect_by_func(pipeline, reinterpret_cast<void*>(playerVolumeChangedCallback), this);
342e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handlers_disconnect_by_func(pipeline, reinterpret_cast<void*>(playerMuteChangedCallback), this);
343e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
344e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_hudTimeoutId) {
345e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        g_source_remove(m_hudTimeoutId);
346e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_hudTimeoutId = 0;
347e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
348e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
349e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_progressBarUpdateId) {
350e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        g_source_remove(m_progressBarUpdateId);
351e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_progressBarUpdateId = 0;
352e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
353e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
354e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement->platformMedia().type == WebCore::PlatformMedia::GStreamerGWorldType)
355e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_mediaElement->platformMedia().media.gstreamerGWorld->exitFullscreen();
356e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
357a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    gtk_widget_hide(m_window);
358e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
359e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_widget_destroy(m_hudWindow);
360e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_hudWindow = 0;
361e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
362e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
363e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockbool FullscreenVideoController::canPlay() const
364e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
365e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return m_mediaElement && m_mediaElement->canPlay();
366e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
367e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
368e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::play()
369e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
370e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement)
371e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_mediaElement->play(m_mediaElement->processingUserGesture());
372e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
373e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    playStateChanged();
374e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    showHud(true);
375e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
376e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
377e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::pause()
378e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
379e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement)
380e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_mediaElement->pause(m_mediaElement->processingUserGesture());
381e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
382e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    playStateChanged();
383e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    showHud(false);
384e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
385e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
386e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::playStateChanged()
387e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
388e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (canPlay())
389e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        g_object_set(m_playPauseAction, "tooltip", _("Play"), "icon-name", PLAY_ICON_NAME, NULL);
390e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    else
391e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        g_object_set(m_playPauseAction, "tooltip", _("Pause"), "icon-name", PAUSE_ICON_NAME, NULL);
392e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
393e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
394e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::togglePlay()
395e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
396e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (canPlay())
397e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        play();
398e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    else
399e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        pause();
400e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
401e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
402e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockfloat FullscreenVideoController::volume() const
403e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
404e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return m_mediaElement ? m_mediaElement->volume() : 0;
405e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
406e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
407e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockbool FullscreenVideoController::muted() const
408e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
409e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return m_mediaElement ? m_mediaElement->muted() : false;
410e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
411e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
412e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::setVolume(float volume)
413e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
414e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (volume < 0.0 || volume > 1.0)
415e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
416e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
417e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement) {
418e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        ExceptionCode ec;
419e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_mediaElement->setVolume(volume, ec);
420e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
421e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
422e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
423e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::volumeChanged()
424e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
425e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handler_block(m_volumeButton, m_volumeUpdateId);
426e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_scale_button_set_value(GTK_SCALE_BUTTON(m_volumeButton), volume());
427e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handler_unblock(m_volumeButton, m_volumeUpdateId);
428e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
429e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
430e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::muteChanged()
431e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
432e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handler_block(m_volumeButton, m_volumeUpdateId);
433e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_scale_button_set_value(GTK_SCALE_BUTTON(m_volumeButton), muted() ? 0 : volume());
434e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_handler_unblock(m_volumeButton, m_volumeUpdateId);
435e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
436e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
437e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockfloat FullscreenVideoController::currentTime() const
438e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
439e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return m_mediaElement ? m_mediaElement->currentTime() : 0;
440e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
441e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
442e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::setCurrentTime(float value)
443e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
444e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement) {
445e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        ExceptionCode ec;
446e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_mediaElement->setCurrentTime(value, ec);
447e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
448e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
449e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
450e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockfloat FullscreenVideoController::duration() const
451e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
452e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return m_mediaElement ? m_mediaElement->duration() : 0;
453e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
454e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
455e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockfloat FullscreenVideoController::percentLoaded() const
456e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
457e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return m_mediaElement ? m_mediaElement->percentLoaded() : 0;
458e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
459e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
460e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::beginSeek()
461e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
462e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_seekLock = true;
463e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
464e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement)
465e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_mediaElement->beginScrubbing();
466e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
467e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
468e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::doSeek()
469e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
470e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_seekLock)
471e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block         return;
472e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
473e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    setCurrentTime(gtk_range_get_value(GTK_RANGE(m_timeHScale))*duration() / 100);
474e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
475e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
476e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::endSeek()
477e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
478e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_mediaElement)
479e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_mediaElement->endScrubbing();
480e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
481e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_seekLock = false;
482e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
483e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
484e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic String timeToString(float time)
485e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
486e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!isfinite(time))
487e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        time = 0;
488e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    int seconds = fabsf(time);
489e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    int hours = seconds / (60 * 60);
490e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    int minutes = (seconds / 60) % 60;
491e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    seconds %= 60;
492e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
493e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (hours) {
494e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        if (hours > 9)
495e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block            return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
496e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
497e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
498e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
499e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
500e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
501e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
502e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockgboolean FullscreenVideoController::updateHudProgressBar()
503e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
504e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    float mediaDuration(duration());
505e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    float mediaPosition(currentTime());
506e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
507e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_seekLock) {
508e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        gdouble value = 0.0;
509e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
510e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        if (mediaPosition && mediaDuration)
511e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block            value = (mediaPosition * 100.0) / mediaDuration;
512e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
513e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(m_timeHScale));
514e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        gtk_adjustment_set_value(adjustment, value);
515e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
516e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
517e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_range_set_fill_level(GTK_RANGE(m_timeHScale), percentLoaded()* 100);
518e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
519e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gchar* label = g_strdup_printf("%s / %s", timeToString(mediaPosition).utf8().data(),
520e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block                                   timeToString(mediaDuration).utf8().data());
521e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_label_set_text(GTK_LABEL(m_timeLabel), label);
522e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_free(label);
523e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return TRUE;
524e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
525e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
526e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid FullscreenVideoController::createHud()
527e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
528e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_hudWindow = gtk_window_new(GTK_WINDOW_POPUP);
529e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_window_set_gravity(GTK_WINDOW(m_hudWindow), GDK_GRAVITY_SOUTH_WEST);
530e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_window_set_type_hint(GTK_WINDOW(m_hudWindow), GDK_WINDOW_TYPE_HINT_NORMAL);
531e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
532e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_hudWindow, "motion-notify-event", G_CALLBACK(onFullscreenGtkMotionNotifyEvent), this);
533e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
534e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GtkWidget* hbox = gtk_hbox_new(FALSE, 4);
535e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_container_add(GTK_CONTAINER(m_hudWindow), hbox);
536e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
537e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_playPauseAction = gtk_action_new("play", _("Play / Pause"), _("Play or pause the media"), PAUSE_ICON_NAME);
538e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_playPauseAction, "activate", G_CALLBACK(togglePlayPauseActivated), this);
539e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
540e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    playStateChanged();
541e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
542e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GtkWidget* item = gtk_action_create_tool_item(m_playPauseAction);
543e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_box_pack_start(GTK_BOX(hbox), item, FALSE, TRUE, 0);
544e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
545e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    GtkWidget* label = gtk_label_new(_("Time:"));
546e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
547e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
548a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GtkAdjustment* adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 100.0, 0.1, 1.0, 1.0));
549a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    m_timeHScale = gtk_hscale_new(adjustment);
550e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_scale_set_draw_value(GTK_SCALE(m_timeHScale), FALSE);
551e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_range_set_show_fill_level(GTK_RANGE(m_timeHScale), TRUE);
552e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_timeHScale, "button-press-event", G_CALLBACK(timeScaleButtonPressed), this);
553e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_timeHScale, "button-release-event", G_CALLBACK(timeScaleButtonReleased), this);
554e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_hscaleUpdateId = g_signal_connect(m_timeHScale, "value-changed", G_CALLBACK(timeScaleValueChanged), this);
555e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
556e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_box_pack_start(GTK_BOX(hbox), m_timeHScale, TRUE, TRUE, 0);
557e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
558e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_timeLabel = gtk_label_new("");
559e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_box_pack_start(GTK_BOX(hbox), m_timeLabel, FALSE, TRUE, 0);
560e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
561e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Volume button.
562e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_volumeButton = gtk_volume_button_new();
563e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_box_pack_start(GTK_BOX(hbox), m_volumeButton, FALSE, TRUE, 0);
564e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_scale_button_set_value(GTK_SCALE_BUTTON(m_volumeButton), volume());
565e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_volumeUpdateId = g_signal_connect(m_volumeButton, "value-changed", G_CALLBACK(volumeValueChanged), this);
566e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
567e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
568e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_exitFullscreenAction = gtk_action_new("exit", _("Exit Fullscreen"), _("Exit from fullscreen mode"), EXIT_FULLSCREEN_ICON_NAME);
569e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_signal_connect(m_exitFullscreenAction, "activate", G_CALLBACK(exitFullscreenActivated), this);
570e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    g_object_set(m_exitFullscreenAction, "icon-name", EXIT_FULLSCREEN_ICON_NAME, NULL);
571e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    item = gtk_action_create_tool_item(m_exitFullscreenAction);
572e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    gtk_box_pack_start(GTK_BOX(hbox), item, FALSE, TRUE, 0);
573e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
574e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
575e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_progressBarUpdateId = g_timeout_add(PROGRESS_BAR_UPDATE_INTERVAL, reinterpret_cast<GSourceFunc>(progressBarUpdateCallback), this);
576e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
577e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
578e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#endif
579