diff --git a/CHANGELOG.md b/CHANGELOG.md index e3f0859..2d36a73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,10 @@ ## Unreleased +### Added + +- When using VLC, the player will properly crash if unexpected instance parameters are given. + ### Changed - The discovery of instrumental file or track is now delegated to the feeder, which means that this data is given by the server. There are no re-discovering processes, but some checks are performed (whether the instrumental file exists, and if the instrumental track exists). diff --git a/src/dakara_player/media_player/vlc.py b/src/dakara_player/media_player/vlc.py index 8cbecff..8f7de0d 100644 --- a/src/dakara_player/media_player/vlc.py +++ b/src/dakara_player/media_player/vlc.py @@ -123,8 +123,10 @@ def init_player(self, config, tempdir): ) # VLC objects - self.instance = vlc.Instance(config_vlc.get("instance_parameters") or []) - self.player = self.instance.media_player_new() + self.instance = get_instance(config_vlc.get("instance_parameters")) + + player = self.instance.media_player_new() + self.player = player self.event_manager = self.player.event_manager() # vlc callbacks @@ -786,6 +788,38 @@ def get_metadata(media): raise ValueError("This media has no set metadata") +def get_instance(instance_parameters=None): + """Get a VLC instance with parameters. + + Args: + instance_parameters (list of str): List of parameters. Must be in the + form "--option=value". + + Returns: + vlc.Instance: New instance. + + Raises: + UnavailableInstanceError: If an instance cannot be obtained without + parameters. + UnexpectedInstanceParameterError: If unexpected parameters are + passed. + """ + # if no parameters are passed, the instance should never be None + if not instance_parameters: + instance = vlc.Instance() + if instance is None: + raise UnavailableInstanceError("Unable to get a VLC instance") + + return instance + + # if parameters are passed, an unexpected parameter makes the instance None + instance = vlc.Instance(instance_parameters) + if instance is None: + raise UnexpectedInstanceParameterError("Unexpected VLC instance parameter") + + return instance + + class Media: """Media object.""" @@ -804,3 +838,11 @@ def __init__(self, *args, track_id_audio=None, **kwargs): class VlcTooOldError(DakaraError): """Error raised if VLC is too old.""" + + +class UnexpectedInstanceParameterError(DakaraError): + """Error raised when passing incorrect parameters to the VLC instance.""" + + +class UnavailableInstanceError(DakaraError): + """Error raised when a VLC instance cannot be obtained.""" diff --git a/tests/integration/test_media_player_vlc.py b/tests/integration/test_media_player_vlc.py index 83d7269..86c73cb 100644 --- a/tests/integration/test_media_player_vlc.py +++ b/tests/integration/test_media_player_vlc.py @@ -16,7 +16,10 @@ from func_timeout import func_set_timeout from dakara_player.media_player.base import IDLE_BG_NAME, TRANSITION_BG_NAME -from dakara_player.media_player.vlc import METADATA_KEYS_COUNT, MediaPlayerVlc +from dakara_player.media_player.vlc import ( + METADATA_KEYS_COUNT, + MediaPlayerVlc, +) from dakara_player.mrl import mrl_to_path from tests.integration.base import TestCasePollerKara diff --git a/tests/unit/test_media_player_vlc.py b/tests/unit/test_media_player_vlc.py index 527d973..3edc5be 100644 --- a/tests/unit/test_media_player_vlc.py +++ b/tests/unit/test_media_player_vlc.py @@ -24,7 +24,10 @@ ) from dakara_player.media_player.vlc import ( MediaPlayerVlc, + UnavailableInstanceError, + UnexpectedInstanceParameterError, VlcTooOldError, + get_instance, get_metadata, set_metadata, ) @@ -1422,3 +1425,29 @@ def test_not_in_list_default_return(self, mocked_is_playing_this): with self.get_instance() as (player, _, _): self.assertEqual(function_decorated(player), 42) + + +@patch("dakara_player.media_player.vlc.vlc", autospec=True) +class GetInstanceTestCase(TestCase): + + def test_parameters_unexpected(self, mocked_vlc): + """Test to pass unexpected parameters.""" + mocked_vlc.Instance.return_value = None + with self.assertRaises(UnexpectedInstanceParameterError): + get_instance(["parameter"]) + + def test_parameters(self, mocked_vlc): + """Test to pass parameters.""" + self.assertIs(mocked_vlc.Instance.return_value, get_instance(["parameter"])) + mocked_vlc.Instance.assert_called_with(["parameter"]) + + def test_no_parameters_unavailable(self, mocked_vlc): + """Test unavailable instance.""" + mocked_vlc.Instance.return_value = None + with self.assertRaises(UnavailableInstanceError): + get_instance() + + def test_no_parameters(self, mocked_vlc): + """Test instance.""" + self.assertIs(mocked_vlc.Instance.return_value, get_instance()) + mocked_vlc.Instance.assert_called_with()