audio: Give the BassPlayer a duration property
I also add a duration-changed signal so the seek scale can update its range. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
a4464cd7d9
commit
a4595eab93
|
@ -12,11 +12,17 @@ class BassPlayer(GObject.GObject):
|
|||
|
||||
self.bus.add_signal_watch()
|
||||
self.bus.connect("message::state-changed", self.state_changed)
|
||||
self.bus.connect("message::stream-start", self.stream_start)
|
||||
|
||||
@GObject.Property
|
||||
def bus(self):
|
||||
return self.playbin.get_bus()
|
||||
|
||||
@GObject.Property
|
||||
def duration(self):
|
||||
(res, dur) = self.playbin.query_duration(Gst.Format.TIME)
|
||||
return dur if res == True else 0
|
||||
|
||||
@GObject.Property
|
||||
def playing(self):
|
||||
(ret, state, pending) = self.playbin.get_state(Gst.CLOCK_TIME_NONE)
|
||||
|
@ -46,6 +52,13 @@ class BassPlayer(GObject.GObject):
|
|||
else:
|
||||
self.emit("playback-paused")
|
||||
|
||||
def stream_start(self, bus, message):
|
||||
self.emit("duration-changed")
|
||||
|
||||
@GObject.Signal
|
||||
def duration_changed(self):
|
||||
pass
|
||||
|
||||
@GObject.Signal
|
||||
def playback_start(self):
|
||||
pass
|
||||
|
|
|
@ -25,10 +25,6 @@ class Player(bass.BassPlayer):
|
|||
if self.track:
|
||||
self.track.add_to_playlist("Previous")
|
||||
|
||||
def duration(self):
|
||||
(res, dur) = self.playbin.query_duration(Gst.Format.TIME)
|
||||
return dur if res == True else 0
|
||||
|
||||
def get_state(self):
|
||||
(ret, state, pending) = self.playbin.get_state(Gst.CLOCK_TIME_NONE)
|
||||
if ret == Gst.StateChangeReturn.SUCCESS:
|
||||
|
@ -53,7 +49,7 @@ class Player(bass.BassPlayer):
|
|||
self.playbin.set_state(state)
|
||||
|
||||
def next(self, *args):
|
||||
duration = self.duration()
|
||||
duration = self.duration
|
||||
if duration > 0 and (self.runtime() / duration) > (2 / 3):
|
||||
self.track.played()
|
||||
|
||||
|
|
|
@ -38,14 +38,19 @@ class ScalePlus(Gtk.Scale):
|
|||
|
||||
class SeekScale(ScalePlus):
|
||||
def __init__(self, player):
|
||||
ScalePlus.__init__(self, 0, 0, 5 * Gst.SECOND, 30 * Gst.SECOND)
|
||||
ScalePlus.__init__(self, 0, player.duration,
|
||||
5 * Gst.SECOND, 30 * Gst.SECOND)
|
||||
self.set_size_request(200, -1)
|
||||
self.player = player
|
||||
self.player.connect("duration-changed", self.duration_changed)
|
||||
GLib.timeout_add(200, self.update)
|
||||
|
||||
def do_change_value(self, scroll, value):
|
||||
self.player.seek(value)
|
||||
|
||||
def duration_changed(self, player):
|
||||
self.set_range(0, player.duration)
|
||||
|
||||
def format_value(self, scale, value):
|
||||
position = int(value / Gst.SECOND)
|
||||
duration = int(self.get_adjustment().get_upper() / Gst.SECOND)
|
||||
|
@ -54,7 +59,6 @@ class SeekScale(ScalePlus):
|
|||
return f"{p_m:02}:{p_s:02} / {r_m:02}:{r_s:02}"
|
||||
|
||||
def update(self):
|
||||
self.set_range(0, self.player.duration())
|
||||
self.set_value(self.player.position())
|
||||
return GLib.SOURCE_CONTINUE
|
||||
|
||||
|
|
|
@ -2,14 +2,20 @@
|
|||
import pathlib
|
||||
import unittest
|
||||
from gi.repository import GObject
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Gst
|
||||
from . import bass
|
||||
|
||||
main_context = GLib.main_context_default()
|
||||
test_album = pathlib.Path("./data/Test Album/")
|
||||
test_track = test_album / "01 - Test Track.ogg"
|
||||
test_uri = test_track.absolute().as_uri()
|
||||
|
||||
class TestBassPlayer(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.duration_changed = None
|
||||
|
||||
def on_duration_changed(self, player): self.duration_changed = player.duration
|
||||
def on_playback_start(self, player): self.playing = True
|
||||
def on_playback_paused(self, player): self.playing = False
|
||||
|
||||
|
@ -26,6 +32,23 @@ class TestBassPlayer(unittest.TestCase):
|
|||
base = bass.BassPlayer()
|
||||
self.assertIsInstance(base.bus, Gst.Bus)
|
||||
|
||||
def test_bass_player_duration(self):
|
||||
base = bass.BassPlayer()
|
||||
base.connect("duration-changed", self.on_duration_changed)
|
||||
self.assertEqual(base.get_property("duration"), 0)
|
||||
|
||||
base.set_property("uri", test_uri)
|
||||
base.set_property("playing", False)
|
||||
|
||||
iterations = 0
|
||||
while self.duration_changed == None:
|
||||
main_context.iteration(may_block=False)
|
||||
if (iterations := iterations +1) == 100000:
|
||||
break
|
||||
|
||||
self.assertEqual(base.get_property("duration"), 10 * Gst.SECOND)
|
||||
self.assertEqual(self.duration_changed, 10 * Gst.SECOND)
|
||||
|
||||
def test_bass_player_playing(self):
|
||||
base = bass.BassPlayer()
|
||||
base.connect("playback-start", self.on_playback_start)
|
||||
|
|
|
@ -12,6 +12,7 @@ from gi.repository import GLib
|
|||
from gi.repository import Gst
|
||||
import pathlib
|
||||
import tagdb
|
||||
import time
|
||||
import unittest
|
||||
|
||||
main_context = GLib.main_context_default()
|
||||
|
|
|
@ -13,7 +13,12 @@ class FakePlayer(GObject.GObject):
|
|||
self.vol = volume
|
||||
|
||||
def position(self): return self.pos
|
||||
|
||||
@GObject.Property
|
||||
def duration(self): return self.dur
|
||||
@GObject.Signal
|
||||
def duration_changed(self): pass
|
||||
|
||||
def seek(self, value): self.seek_val = value
|
||||
def set_volume(self, volume): self.vol = volume
|
||||
def get_volume(self): return self.vol
|
||||
|
@ -80,10 +85,20 @@ class TestSeekScale(unittest.TestCase):
|
|||
self.assertEqual(seek.player, fake)
|
||||
self.assertEqual(adj.get_value(), 0)
|
||||
self.assertEqual(adj.get_lower(), 0)
|
||||
self.assertEqual(adj.get_upper(), 0)
|
||||
self.assertEqual(adj.get_upper(), 5 * Gst.SECOND)
|
||||
self.assertEqual(adj.get_step_increment(), 5 * Gst.SECOND)
|
||||
self.assertEqual(adj.get_page_increment(), 30 * Gst.SECOND)
|
||||
|
||||
def test_seek_scale_duration(self):
|
||||
fake = FakePlayer(0, 2 * Gst.SECOND, 1)
|
||||
seek = scale.SeekScale(fake)
|
||||
adj = seek.get_adjustment()
|
||||
|
||||
self.assertEqual(adj.get_upper(), 2 * Gst.SECOND)
|
||||
fake.dur = 3 * Gst.SECOND
|
||||
fake.emit("duration-changed")
|
||||
self.assertEqual(adj.get_upper(), 3 * Gst.SECOND)
|
||||
|
||||
def test_seek_scale_update(self):
|
||||
fake = FakePlayer(3 * Gst.SECOND, 15 * Gst.SECOND, 1)
|
||||
seek = scale.SeekScale(fake)
|
||||
|
@ -93,7 +108,6 @@ class TestSeekScale(unittest.TestCase):
|
|||
self.assertEqual(seek.player, fake)
|
||||
self.assertEqual(adj.get_value(), 3 * Gst.SECOND)
|
||||
self.assertEqual(adj.get_lower(), 0)
|
||||
self.assertEqual(adj.get_upper(), 15 * Gst.SECOND)
|
||||
|
||||
def test_seek_scale_values(self):
|
||||
fake = FakePlayer(0, 15 * Gst.SECOND, 1)
|
||||
|
|
Loading…
Reference in New Issue