audio: Add a custom SeekScale widget
For handling seeks to the audio player Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
753f6477a7
commit
1c53886152
|
@ -1,5 +1,7 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gst
|
||||
|
||||
class ScalePlus(Gtk.Scale):
|
||||
def __init__(self, min, max, step, page):
|
||||
|
@ -32,3 +34,26 @@ class ScalePlus(Gtk.Scale):
|
|||
|
||||
def format_value(self, scale, value):
|
||||
return str(value)
|
||||
|
||||
|
||||
class SeekScale(ScalePlus):
|
||||
def __init__(self, player):
|
||||
ScalePlus.__init__(self, 0, 0, 5 * Gst.SECOND, 30 * Gst.SECOND)
|
||||
self.set_size_request(200, -1)
|
||||
self.player = player
|
||||
GLib.timeout_add(200, self.update)
|
||||
|
||||
def do_change_value(self, scroll, value):
|
||||
self.player.seek(value)
|
||||
|
||||
def format_value(self, scale, value):
|
||||
position = int(value / Gst.SECOND)
|
||||
duration = int(self.get_adjustment().get_upper() / Gst.SECOND)
|
||||
(p_m, p_s) = divmod(position, 60)
|
||||
(r_m, r_s) = divmod(duration - position, 60)
|
||||
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
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
import unittest
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gst
|
||||
from . import scale
|
||||
|
||||
class FakePlayer(GObject.GObject):
|
||||
def __init__(self, position, duration):
|
||||
GObject.GObject.__init__(self)
|
||||
self.pos = position
|
||||
self.dur = duration
|
||||
|
||||
def position(self): return self.pos
|
||||
def duration(self): return self.dur
|
||||
def seek(self, value): self.seek_val = value
|
||||
|
||||
|
||||
class TestScalePlus(unittest.TestCase):
|
||||
def on_change_value(self, scale, scroll, value):
|
||||
self.change_value = (scroll, value)
|
||||
|
@ -50,3 +63,44 @@ class TestScalePlus(unittest.TestCase):
|
|||
self.change_value = None
|
||||
self.assertIsNone(splus.increment())
|
||||
self.assertIsNone(self.change_value)
|
||||
|
||||
|
||||
class TestSeekScale(unittest.TestCase):
|
||||
def test_seek_scale_init(self):
|
||||
fake = FakePlayer(0, 5 * Gst.SECOND)
|
||||
seek = scale.SeekScale(fake)
|
||||
adj = seek.get_adjustment()
|
||||
|
||||
self.assertIsInstance(seek, scale.ScalePlus)
|
||||
|
||||
self.assertEqual(seek.get_size_request(), (200, -1))
|
||||
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_step_increment(), 5 * Gst.SECOND)
|
||||
self.assertEqual(adj.get_page_increment(), 30 * Gst.SECOND)
|
||||
|
||||
def test_seek_scale_update(self):
|
||||
fake = FakePlayer(3 * Gst.SECOND, 15 * Gst.SECOND)
|
||||
seek = scale.SeekScale(fake)
|
||||
adj = seek.get_adjustment()
|
||||
|
||||
seek.update()
|
||||
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)
|
||||
seek = scale.SeekScale(fake)
|
||||
|
||||
seek.update()
|
||||
seek.increment()
|
||||
self.assertEqual(fake.seek_val, 5 * Gst.SECOND)
|
||||
self.assertEqual(seek.format_value(seek, 5 * Gst.SECOND),
|
||||
"00:05 / 00:10")
|
||||
|
||||
seek.decrement()
|
||||
self.assertEqual(fake.seek_val, 0)
|
||||
|
|
Loading…
Reference in New Issue