~nataliabidart/software-center/winged-migration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# Copyright (C) 2011 Canonical
#
# Authors:
#  Michael Vogt
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 3.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

import logging
import subprocess

from gettext import gettext as _
from gi.repository import Gdk

# FIXME: remove this try/except and add a dependency on gir1.2-gstreamer-0.10
#        if we (ever) start using VideoPlayerGtk3
try:
    from gi.repository import Gst
except ImportError:
    pass

from gi.repository import Gtk
from gi.repository import WebKit

LOG = logging.getLogger(__name__)


class VideoPlayer(Gtk.VBox):
    def __init__(self):
        super(VideoPlayer, self).__init__()
        self.set_size_request(400, 255)
        self.webkit = WebKit.WebView()
        settings = self.webkit.get_settings()
        # this disables the flash and other plugins so that we force html5
        # video on the system. This is works currently (11/2011) fine with
        # dailymotion and vimeo but youtube is opt-in only so we need
        # to monitor the situation
        settings.set_property("enable-plugins", False)
        # on navigation/new window etc, just use the proper browser
        self.webkit.connect(
            "new-window-policy-decision-requested", self._on_new_window)
        self.webkit.connect("create-web-view", self._on_create_web_view)
        self.pack_start(self.webkit, True, True, 0)
        self._uri = ""

    # helper required to follow ToS about the "back" link (flash version)
    def _on_new_window(self, view, frame, request, action, policy):
        subprocess.Popen(['xdg-open', request.get_uri()])
        return True

    # helper for the embedded html5 viewer
    def _on_create_web_view(self, view, frame):
        # mvo: this is not ideal, the trouble is that we do not get the
        #      url that the new view points to until after the view was
        #      created. But we don't want to be a full blow internal
        #      webbrowser so we simply go back to the youtube url here
        #      and the user needs to click "youtube" there again :/
        uri = frame.get_uri()
        subprocess.Popen(['xdg-open', uri])

    # uri property
    def _set_uri(self, v):
        self._uri = v or ""
        if self._uri:
            # only load the uri if it's defined, otherwise we may get:
            # Program received signal SIGSEGV, Segmentation fault.
            # webkit_web_frame_load_uri () from /usr/lib/libwebkitgtk-3.0.so.0
            self.webkit.load_uri(self._uri)

    def _get_uri(self):
        return self._uri
    uri = property(_get_uri, _set_uri, None, "uri property")

    def load_html_string(self, html):
        """ Instead of a video URI use a html embedded video like e.g.
            youtube or vimeo. Note that on a default install not all
            video codecs will play (no flash!), so be careful!
        """
        # FIXME: add something more useful here
        base_uri = "http://www.ubuntu.com"
        self.webkit.load_html_string(html, base_uri)


# AKA the-segfault-edition-with-no-documentation
class VideoPlayerGtk3(Gtk.VBox):

    def __init__(self):
        super(VideoPlayerGtk3, self).__init__()
        self.uri = ""
        # gtk ui
        self.movie_window = Gtk.DrawingArea()
        self.pack_start(self.movie_window, True, True, 0)
        self.button = Gtk.Button(_("Play"))
        self.pack_start(self.button, False, True, 0)
        self.button.connect("clicked", self.on_play_clicked)
        # player
        self.player = Gst.ElementFactory.make("playbin2", "player")
        # bus stuff
        bus = self.player.get_bus()
        bus.add_signal_watch()
        bus.enable_sync_message_emission()
        bus.connect("message", self.on_message)
        # FIXME: no sync messages currently so no playing in the widget :/
        # the former appears to be not working anymore with GIR, the
        # later is not exported (introspectable=0 in the GIR)
        bus.connect("sync-message", self.on_sync_message)
        #bus.set_sync_handler(self.on_sync_message)

    def on_play_clicked(self, button):
        if self.button.get_label() == _("Play"):
            self.button.set_label("Stop")
            print(self.uri)
            self.player.set_property("uri", self.uri)
            self.player.set_state(Gst.State.PLAYING)
        else:
            self.player.set_state(Gst.State.NULL)
            self.button.set_label(_("Play"))

    def on_message(self, bus, message):
        print("message: %s" % bus, message)
        if message is None:
            return
        t = message.type
        print(t)
        if t == Gst.MessageType.EOS:
            self.player.set_state(Gst.State.NULL)
            self.button.set_label(_("Play"))
        elif t == Gst.MessageType.ERROR:
            self.player.set_state(Gst.State.NULL)
            err, debug = message.parse_error()
            LOG.error("Error playing video: %s (%s)" % (err, debug))
            self.button.set_label(_("Play"))

    def on_sync_message(self, bus, message):
        print("sync: %s" % bus, message)
        if message is None or message.structure is None:
            return
        message_name = message.structure.get_name()
        if message_name == "prepare-xwindow-id":
            imagesink = message.src
            imagesink.set_property("force-aspect-ratio", True)
            Gdk.threads_enter()
            # FIXME: this is the way to do it, *but* get_xid() is not
            #        exported in the GIR
            xid = self.player.movie_window.get_window().get_xid()
            imagesink.set_xwindow_id(xid)
            Gdk.threads_leave()