rind: Begin audio code
I don't yet have UI widgets, but this should cover the basics of audio playback. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
e9e056e925
commit
b42c654c2c
|
@ -0,0 +1,55 @@
|
|||
# Copyright 2019 (c) Anna Schumaker.
|
||||
import curds
|
||||
import gi
|
||||
import sys
|
||||
gi.require_version("Gst", "1.0")
|
||||
from gi.repository import Gst, GLib
|
||||
|
||||
class EmmentalAudio:
|
||||
def __init__(self):
|
||||
self.playbin = Gst.ElementFactory.make("playbin")
|
||||
self.bus = self.playbin.get_bus()
|
||||
self.bus.add_signal_watch()
|
||||
self.bus.connect("message", self.on_message)
|
||||
|
||||
def duration(self):
|
||||
(res, cur) = self.playbin.query_duration(Gst.Format.TIME)
|
||||
return cur / Gst.SECOND if res == True else 0.0
|
||||
|
||||
def load(self, track, play=True):
|
||||
if track:
|
||||
self.playbin.set_property("uri", f"file://{track.path}")
|
||||
self.playbin.set_state(Gst.State.PLAYING if play else Gst.State.PAUSED)
|
||||
|
||||
def next(self):
|
||||
track = curds.PlaylistManager.next()
|
||||
if track != None:
|
||||
self.load(track)
|
||||
|
||||
def on_message(self, bus, message):
|
||||
if message.type == Gst.MessageType.STATE_CHANGED:
|
||||
(old, new, pending) = message.parse_state_changed()
|
||||
curds.Notify.notify("state-changed", new)
|
||||
elif message.type == Gst.MessageType.STREAM_START:
|
||||
curds.Notify.notify("duration-changed", self.duration())
|
||||
return True
|
||||
|
||||
def pause(self):
|
||||
self.playbin.set_state(Gst.State.PAUSED)
|
||||
|
||||
def play(self):
|
||||
self.playbin.set_state(Gst.State.PLAYING)
|
||||
|
||||
def position(self):
|
||||
(res, cur) = self.playbin.query_position(Gst.Format.TIME)
|
||||
return cur if res == True else 0
|
||||
|
||||
def progress(self):
|
||||
pos = self.position()
|
||||
dur = self.duration()
|
||||
return (pos / dur) if dur > 0 else 0
|
||||
|
||||
def state(self):
|
||||
return self.playbin.get_state(Gst.CLOCK_TIME_NONE)[1]
|
||||
|
||||
Gst.init(sys.argv)
|
|
@ -0,0 +1,90 @@
|
|||
# Copyright 2019 (c) Anna Schumaker.
|
||||
from . import gst
|
||||
import curds
|
||||
import os
|
||||
import time
|
||||
import unittest
|
||||
from gi.repository import Gst, GLib
|
||||
|
||||
test_album = os.path.abspath("./trier/Test Library/Test Artist 01/Test Album 1")
|
||||
|
||||
class TestGst(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.state = None
|
||||
self.duration = None
|
||||
curds.PlaylistManager["Collection"].list.clear()
|
||||
curds.PlaylistManager["Library"].clear()
|
||||
curds.Notify.notify_me("new-track", curds.PlaylistManager["Collection"].add)
|
||||
if not curds.playlist.library.library_thread.is_alive():
|
||||
curds.playlist.library.library_thread = curds.ThreadQueue()
|
||||
curds.Notify.notify_me("state-changed", self.on_state_changed)
|
||||
curds.Notify.notify_me("duration-changed", self.on_duration_changed)
|
||||
|
||||
def tearDown(self):
|
||||
curds.playlist.library.library_thread.stop()
|
||||
|
||||
def main_loop(self):
|
||||
events = GLib.main_context_default().iteration()
|
||||
while events == True:
|
||||
events = GLib.main_context_default().iteration(may_block=False)
|
||||
|
||||
def test_gst_init(self):
|
||||
audio = gst.EmmentalAudio()
|
||||
self.assertIsInstance(audio.playbin, Gst.Element)
|
||||
self.assertIsInstance(audio.bus, Gst.Bus)
|
||||
|
||||
self.assertEqual(audio.state(), Gst.State.NULL)
|
||||
audio.load(None)
|
||||
self.assertEqual(audio.state(), Gst.State.NULL)
|
||||
audio.play()
|
||||
self.assertEqual(audio.state(), Gst.State.READY)
|
||||
audio.pause()
|
||||
self.assertEqual(audio.state(), Gst.State.READY)
|
||||
self.assertEqual(audio.position(), 0)
|
||||
self.assertEqual(audio.duration(), 0)
|
||||
self.assertEqual(audio.progress(), 0)
|
||||
|
||||
def on_state_changed(self, state):
|
||||
self.state = state
|
||||
|
||||
def on_duration_changed(self, duration):
|
||||
self.duration = duration
|
||||
|
||||
def test_gst_load(self):
|
||||
audio = gst.EmmentalAudio()
|
||||
track = curds.Track.lookup(os.path.join(test_album, "10 - Test Track 10.ogg"))
|
||||
|
||||
self.main_loop()
|
||||
self.state = None
|
||||
self.duration = None
|
||||
audio.load(track)
|
||||
while self.state == None or self.duration == None:
|
||||
self.main_loop()
|
||||
|
||||
self.assertEqual(self.state, Gst.State.PAUSED)
|
||||
self.assertEqual(audio.position(), 0)
|
||||
self.assertEqual(audio.duration(), 10.0)
|
||||
self.assertEqual(audio.progress(), 0)
|
||||
|
||||
while self.state != Gst.State.PLAYING:
|
||||
self.main_loop()
|
||||
|
||||
def test_gst_controls(self):
|
||||
audio = gst.EmmentalAudio()
|
||||
self.assertEqual(audio.state(), Gst.State.NULL)
|
||||
audio.next()
|
||||
self.assertEqual(audio.state(), Gst.State.NULL)
|
||||
self.assertIsNone(curds.PlaylistManager.track)
|
||||
|
||||
curds.PlaylistManager["Library"].add(test_album)
|
||||
curds.playlist.library.library_thread.join()
|
||||
|
||||
self.state == None
|
||||
audio.next()
|
||||
self.assertIsNotNone(curds.PlaylistManager.track)
|
||||
while self.state != Gst.State.PLAYING:
|
||||
self.main_loop()
|
||||
|
||||
audio.pause()
|
||||
while self.state != Gst.State.PAUSED:
|
||||
self.main_loop()
|
Loading…
Reference in New Issue