|
9 | 9 |
|
10 | 10 | _logger = logging.getLogger(__name__) |
11 | 11 |
|
12 | | - |
13 | | -# Gstreamer |
| 12 | +# Gstreamer 1.0 |
| 13 | +try: |
| 14 | + import gi |
| 15 | + gi.require_version('Gst', '1.0') |
| 16 | + from gi.repository import GObject, Gst |
| 17 | + GObject.threads_init() |
| 18 | + Gst.init(None) |
| 19 | +except (ImportError, ValueError): |
| 20 | + Gst = None |
| 21 | + GObject = None |
| 22 | + |
| 23 | +# Gstreamer 0.10 |
14 | 24 | try: |
| 25 | + if Gst is not None: |
| 26 | + raise ImportError() |
15 | 27 | import gst |
16 | 28 | import gobject |
17 | 29 | gobject.threads_init() |
18 | 30 | except ImportError: |
19 | 31 | gst = None |
20 | 32 | gobject = None |
21 | 33 |
|
22 | | - |
23 | 34 | # Cocoa via PyObjC |
24 | 35 | try: |
25 | 36 | import AppKit |
@@ -66,6 +77,54 @@ def close(self): |
66 | 77 |
|
67 | 78 |
|
68 | 79 | class GstreamerBackend(Backend): |
| 80 | + """Backend for Gstreamer 1.0""" |
| 81 | + |
| 82 | + def __init__(self, parent, temp_dir): |
| 83 | + self._player = None |
| 84 | + self._data = None |
| 85 | + |
| 86 | + def play(self, data): |
| 87 | + if self._player: |
| 88 | + self._player.set_state(Gst.State.NULL) |
| 89 | + |
| 90 | + try: |
| 91 | + self._player = Gst.parse_launch( |
| 92 | + 'appsrc name=src ! decodebin ! autoaudiosink') |
| 93 | + except: |
| 94 | + _logger.error( |
| 95 | + "Gstreamer's good-plugins package is needed to play sound") |
| 96 | + return |
| 97 | + |
| 98 | + self._player.set_state(Gst.State.NULL) |
| 99 | + bus = self._player.get_bus() |
| 100 | + bus.add_signal_watch() |
| 101 | + bus.connect("message", self._on_message) |
| 102 | + |
| 103 | + def need_data(appsrc, size): |
| 104 | + if not self._data: |
| 105 | + appsrc.emit('end-of-stream') |
| 106 | + return |
| 107 | + appsrc.emit('push-buffer', Gst.Buffer.new_wrapped(self._data[:size])) |
| 108 | + self._data = self._data[size:] |
| 109 | + |
| 110 | + self._data = data |
| 111 | + self._player.get_by_name('src').connect('need-data', need_data) |
| 112 | + self._player.set_state(Gst.State.PLAYING) |
| 113 | + |
| 114 | + def _on_message(self, bus, message): |
| 115 | + if message.type == Gst.MessageType.EOS: |
| 116 | + self._player.set_state(Gst.State.NULL) |
| 117 | + self._player = None |
| 118 | + |
| 119 | + def close(self): |
| 120 | + if self._player: |
| 121 | + self._player.set_state(Gst.State.NULL) |
| 122 | + self._player = None |
| 123 | + |
| 124 | + |
| 125 | +class GstreamerOldBackend(Backend): |
| 126 | + """Backend for Gstreamer 0.10""" |
| 127 | + |
69 | 128 | def __init__(self, parent, temp_dir): |
70 | 129 | self._player = None |
71 | 130 | self._data = None |
@@ -222,8 +281,10 @@ def create_soundplayer(parent, temp_dir): |
222 | 281 | backends.append(WinMCIBackend) |
223 | 282 | if Phonon: |
224 | 283 | backends.append(PhononBackend) |
225 | | - if gst: |
| 284 | + if Gst: |
226 | 285 | backends.append(GstreamerBackend) |
| 286 | + if gst: |
| 287 | + backends.append(GstreamerOldBackend) |
227 | 288 | backends.append(NullBackend) |
228 | 289 |
|
229 | 290 | return backends[0](parent, temp_dir) |
|
0 commit comments