# Copyright 2022 (c) Anna Schumaker. """Tests our GObject audio player wrapping a GStreamer Playbin element.""" import io import unittest import unittest.mock import emmental.audio import tests.util from gi.repository import GObject from gi.repository import GLib from gi.repository import Gst class TestAudio(unittest.TestCase): """Our audio player test case.""" def setUp(self): """Set up common variables.""" self.player = emmental.audio.Player() def tearDown(self): """Clean up the playbin.""" self.player.shutdown() def main_loop(self) -> None: """Run a GLib main loop.""" while GLib.main_context_default().iteration(): pass def test_player(self): """Test that the audio player was set up correctly.""" self.assertIsInstance(self.player, GObject.GObject) self.assertEqual(self.player.get_state(), Gst.State.READY) self.assertIsNone(self.player.file) self.assertFalse(self.player.have_track) def test_playbin(self): """Test that the playbin was configured correctly.""" self.assertIsInstance(self.player._playbin, Gst.Element) self.assertIsInstance(self.player._playbin.get_property("video-sink"), Gst.Element) self.assertRegex(self.player._playbin.name, r"playbin\d+") self.assertRegex(self.player._playbin.get_property("video-sink").name, r"fakesink\d+") @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_eos(self, mock_stdout: io.StringIO): """Test handling an EOS message.""" self.player.file = tests.util.TRACK_OGG eos = Gst.Message.new_eos(self.player._playbin) self.player._playbin.get_bus().post(eos) self.main_loop() self.assertRegex(mock_stdout.getvalue(), "audio: end of stream") self.assertEqual(self.player.get_state(), Gst.State.READY) self.assertFalse(self.player.have_track) self.assertIsNone(self.player.file) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_file(self, mock_stdout: io.StringIO): """Test that the file property works as expected.""" self.player.file = tests.util.TRACK_OGG self.assertEqual(self.player._playbin.get_property("uri"), tests.util.TRACK_OGG.as_uri()) started = unittest.mock.Mock() self.player.connect("file-loaded", started) self.player.set_state_sync(Gst.State.PAUSED) self.main_loop() started.assert_called_with(self.player, tests.util.TRACK_OGG) self.assertTrue(self.player.have_track) self.assertEqual(mock_stdout.getvalue(), f"audio: loading {tests.util.TRACK_OGG.as_uri()}\n" "audio: file loaded\n") def test_volume(self): """Test that the volume property works as expected.""" self.assertEqual(self.player.volume, 1.0) self.assertEqual(self.player._playbin.get_property("volume"), 1.0) self.player.volume = 0.5 self.assertEqual(self.player.volume, 0.5) self.assertEqual(self.player._playbin.get_property("volume"), 0.5) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_replaygain(self, mock_stdout: io.StringIO): """Test that ReplayGain functions work as expected.""" self.assertIsInstance(self.player._replaygain, emmental.audio.replaygain.Filter) self.assertEqual(self.player._playbin.get_property("audio-filter"), self.player._replaygain) self.assertEqual(self.player._replaygain.mode, "disabled") self.assertEqual(self.player.get_replaygain(), (False, None)) self.player.set_replaygain(True, "album") self.assertEqual(self.player._replaygain.mode, "album") self.assertEqual(self.player.get_replaygain(), (True, "album")) self.assertRegex(mock_stdout.getvalue(), r"audio: setting ReplayGain mode to 'album'") self.player.set_replaygain(False, "track") self.assertEqual(self.player._replaygain.mode, "disabled") self.assertEqual(self.player.get_replaygain(), (False, None)) self.assertRegex(mock_stdout.getvalue(), r"audio: setting ReplayGain mode to 'disabled'") def test_shutdown(self): """Test that the shutdown function works as expected.""" self.player.shutdown() self.assertEqual(self.player.get_state(), Gst.State.NULL)