mirror of
https://github.com/beetbox/beets.git
synced 2026-01-03 06:22:48 +01:00
bpg: Converted gstplayer.py to GStreamer 1.0
This commit is contained in:
parent
2669b35945
commit
0917e675d7
1 changed files with 36 additions and 25 deletions
|
|
@ -21,16 +21,17 @@ from __future__ import division, absolute_import, print_function
|
|||
|
||||
import sys
|
||||
import time
|
||||
import gobject
|
||||
import thread
|
||||
import os
|
||||
import copy
|
||||
import urllib
|
||||
|
||||
import pygst
|
||||
pygst.require('0.10')
|
||||
import gst # noqa
|
||||
import gi
|
||||
gi.require_version('Gst', '1.0')
|
||||
from gi.repository import GObject, Gst
|
||||
|
||||
GObject.threads_init()
|
||||
Gst.init(None)
|
||||
|
||||
class GstPlayer(object):
|
||||
"""A music player abstracting GStreamer's Playbin element.
|
||||
|
|
@ -57,8 +58,19 @@ class GstPlayer(object):
|
|||
|
||||
# Set up the Gstreamer player. From the pygst tutorial:
|
||||
# http://pygstdocs.berlios.de/pygst-tutorial/playbin.html
|
||||
self.player = gst.element_factory_make("playbin2", "player")
|
||||
fakesink = gst.element_factory_make("fakesink", "fakesink")
|
||||
####
|
||||
# Updated to GStreamer 1.0 with:
|
||||
# https://wiki.ubuntu.com/Novacut/GStreamer1.0
|
||||
self.player = Gst.ElementFactory.make("playbin", "player")
|
||||
|
||||
if self.player == None:
|
||||
raise RuntimeError("Could not create playbin")
|
||||
|
||||
fakesink = Gst.ElementFactory.make("fakesink", "fakesink")
|
||||
|
||||
if fakesink == None:
|
||||
raise RuntimeError("Could not create fakesink")
|
||||
|
||||
self.player.set_property("video-sink", fakesink)
|
||||
bus = self.player.get_bus()
|
||||
bus.add_signal_watch()
|
||||
|
|
@ -74,21 +86,21 @@ class GstPlayer(object):
|
|||
"""Returns the current state flag of the playbin."""
|
||||
# gst's get_state function returns a 3-tuple; we just want the
|
||||
# status flag in position 1.
|
||||
return self.player.get_state()[1]
|
||||
return self.player.get_state(Gst.CLOCK_TIME_NONE)[1]
|
||||
|
||||
def _handle_message(self, bus, message):
|
||||
"""Callback for status updates from GStreamer."""
|
||||
if message.type == gst.MESSAGE_EOS:
|
||||
if message.type == Gst.MessageType.EOS:
|
||||
# file finished playing
|
||||
self.player.set_state(gst.STATE_NULL)
|
||||
self.player.set_state(Gst.State.NULL)
|
||||
self.playing = False
|
||||
self.cached_time = None
|
||||
if self.finished_callback:
|
||||
self.finished_callback()
|
||||
|
||||
elif message.type == gst.MESSAGE_ERROR:
|
||||
elif message.type == Gst.MessageType.ERROR:
|
||||
# error
|
||||
self.player.set_state(gst.STATE_NULL)
|
||||
self.player.set_state(Gst.State.NULL)
|
||||
err, debug = message.parse_error()
|
||||
print(u"Error: {0}".format(err))
|
||||
self.playing = False
|
||||
|
|
@ -109,27 +121,27 @@ class GstPlayer(object):
|
|||
"""Immediately begin playing the audio file at the given
|
||||
path.
|
||||
"""
|
||||
self.player.set_state(gst.STATE_NULL)
|
||||
self.player.set_state(Gst.State.NULL)
|
||||
if isinstance(path, unicode):
|
||||
path = path.encode('utf8')
|
||||
uri = 'file://' + urllib.quote(path)
|
||||
self.player.set_property("uri", uri)
|
||||
self.player.set_state(gst.STATE_PLAYING)
|
||||
self.player.set_state(Gst.State.PLAYING)
|
||||
self.playing = True
|
||||
|
||||
def play(self):
|
||||
"""If paused, resume playback."""
|
||||
if self._get_state() == gst.STATE_PAUSED:
|
||||
self.player.set_state(gst.STATE_PLAYING)
|
||||
if self._get_state() == Gst.State.PAUSED:
|
||||
self.player.set_state(Gst.State.PLAYING)
|
||||
self.playing = True
|
||||
|
||||
def pause(self):
|
||||
"""Pause playback."""
|
||||
self.player.set_state(gst.STATE_PAUSED)
|
||||
self.player.set_state(Gst.State.PAUSED)
|
||||
|
||||
def stop(self):
|
||||
"""Halt playback."""
|
||||
self.player.set_state(gst.STATE_NULL)
|
||||
self.player.set_state(Gst.State.NULL)
|
||||
self.playing = False
|
||||
self.cached_time = None
|
||||
|
||||
|
|
@ -140,10 +152,9 @@ class GstPlayer(object):
|
|||
play_file() or play().
|
||||
"""
|
||||
# If we don't use the MainLoop, messages are never sent.
|
||||
gobject.threads_init()
|
||||
|
||||
def start():
|
||||
loop = gobject.MainLoop()
|
||||
loop = GObject.MainLoop()
|
||||
loop.run()
|
||||
thread.start_new_thread(start, ())
|
||||
|
||||
|
|
@ -152,14 +163,14 @@ class GstPlayer(object):
|
|||
values are integers in seconds. If no stream is available,
|
||||
returns (0, 0).
|
||||
"""
|
||||
fmt = gst.Format(gst.FORMAT_TIME)
|
||||
fmt = Gst.Format(Gst.Format.TIME)
|
||||
try:
|
||||
pos = self.player.query_position(fmt, None)[0] / (10 ** 9)
|
||||
length = self.player.query_duration(fmt, None)[0] / (10 ** 9)
|
||||
pos = self.player.query_position(fmt)[1] / (10 ** 9)
|
||||
length = self.player.query_duration(fmt)[1] / (10 ** 9)
|
||||
self.cached_time = (pos, length)
|
||||
return (pos, length)
|
||||
|
||||
except gst.QueryError:
|
||||
except Exception:
|
||||
# Stream not ready. For small gaps of time, for instance
|
||||
# after seeking, the time values are unavailable. For this
|
||||
# reason, we cache recent.
|
||||
|
|
@ -175,9 +186,9 @@ class GstPlayer(object):
|
|||
self.stop()
|
||||
return
|
||||
|
||||
fmt = gst.Format(gst.FORMAT_TIME)
|
||||
fmt = Gst.Format(Gst.Format.TIME)
|
||||
ns = position * 10 ** 9 # convert to nanoseconds
|
||||
self.player.seek_simple(fmt, gst.SEEK_FLAG_FLUSH, ns)
|
||||
self.player.seek_simple(fmt, Gst.SeekFlags.FLUSH, ns)
|
||||
|
||||
# save new cached time
|
||||
self.cached_time = (position, cur_len)
|
||||
|
|
|
|||
Loading…
Reference in a new issue