audio: Add a custom ReplayGainSink
I use output-switcher and funnel elements so we can disable the replaygain plugins by routing the stream around them if necessary. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
d6a442277f
commit
6792971ef7
|
@ -0,0 +1,52 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gst
|
||||
|
||||
|
||||
class ReplayGainSink(Gst.Bin):
|
||||
def __init__(self):
|
||||
Gst.Bin.__init__(self)
|
||||
self.selector = Gst.ElementFactory.make("output-selector")
|
||||
self.funnel = Gst.ElementFactory.make("funnel")
|
||||
self.audiosink = Gst.ElementFactory.make("autoaudiosink")
|
||||
self.rgvolume = Gst.ElementFactory.make("rgvolume")
|
||||
self.rglimiter = Gst.ElementFactory.make("rglimiter")
|
||||
|
||||
for element in [ self.selector, self.funnel, self.audiosink,
|
||||
self.rgvolume, self.rglimiter ]:
|
||||
self.add(element)
|
||||
|
||||
# No ReplayGain: selector -> funnel -> audiosink
|
||||
self.shortcut = self.selector.get_request_pad("src_%u")
|
||||
self.shortcut.link(self.funnel.get_request_pad("sink_%u"))
|
||||
self.funnel.link(self.audiosink)
|
||||
|
||||
# Replaygain: selector -> rgvolume -> rglimiter -> funnel -> audiosink
|
||||
self.replaygain = self.selector.get_request_pad("src_%u")
|
||||
self.replaygain.link(self.rgvolume.get_static_pad("sink"))
|
||||
self.rgvolume.link(self.rglimiter)
|
||||
self.rglimiter.get_static_pad("src").link(
|
||||
self.funnel.get_request_pad("sink_%u"))
|
||||
|
||||
self.selector.set_property("pad-negotiation-mode", 2)
|
||||
self.selector.set_property("active-pad", self.shortcut)
|
||||
|
||||
pad = self.selector.get_static_pad("sink")
|
||||
ghost = Gst.GhostPad.new("sink", pad)
|
||||
ghost.set_active(True)
|
||||
self.add_pad(ghost)
|
||||
|
||||
@GObject.Property
|
||||
def mode(self):
|
||||
if self.selector.get_property("active-pad") == self.shortcut:
|
||||
return "disabled"
|
||||
album_mode = self.rgvolume.get_property("album-mode")
|
||||
return "album" if album_mode else "track"
|
||||
|
||||
@mode.setter
|
||||
def mode(self, mode):
|
||||
if mode == "disabled":
|
||||
self.selector.set_property("active-pad", self.shortcut)
|
||||
else:
|
||||
self.rgvolume.set_property("album-mode", mode == "album")
|
||||
self.selector.set_property("active-pad", self.replaygain)
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
import unittest
|
||||
from gi.repository import Gst
|
||||
from . import replaygain
|
||||
|
||||
class TestReplayGainSink(unittest.TestCase):
|
||||
def test_replay_gain_sink_init(self):
|
||||
rgsink = replaygain.ReplayGainSink()
|
||||
|
||||
self.assertIsInstance(rgsink, Gst.Bin)
|
||||
self.assertIsInstance(rgsink.selector, Gst.Element)
|
||||
self.assertIsInstance(rgsink.funnel, Gst.Element)
|
||||
self.assertIsInstance(rgsink.audiosink, Gst.Element)
|
||||
self.assertIsInstance(rgsink.rgvolume, Gst.Element)
|
||||
self.assertIsInstance(rgsink.rglimiter, Gst.Element)
|
||||
|
||||
self.assertIsInstance(rgsink.shortcut, Gst.Pad)
|
||||
self.assertIsInstance(rgsink.replaygain, Gst.Pad)
|
||||
self.assertIsInstance(rgsink.get_static_pad("sink"), Gst.GhostPad)
|
||||
|
||||
def test_replay_gain_sink_mode(self):
|
||||
rgsink = replaygain.ReplayGainSink()
|
||||
self.assertEqual(rgsink.get_property("mode"), "disabled")
|
||||
|
||||
rgsink.set_property("mode", "album")
|
||||
self.assertEqual(rgsink.get_property("mode"), "album")
|
||||
self.assertEqual(rgsink.selector.get_property("active-pad"),
|
||||
rgsink.replaygain)
|
||||
|
||||
rgsink.set_property("mode", "track")
|
||||
self.assertEqual(rgsink.get_property("mode"), "track")
|
||||
self.assertEqual(rgsink.selector.get_property("active-pad"),
|
||||
rgsink.replaygain)
|
||||
|
||||
rgsink.set_property("mode", "disabled")
|
||||
self.assertEqual(rgsink.get_property("mode"), "disabled")
|
||||
self.assertEqual(rgsink.selector.get_property("active-pad"),
|
||||
rgsink.shortcut)
|
Loading…
Reference in New Issue