diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index de9f65f3e..344a31f21 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -25,10 +25,11 @@ import logging from pathlib import Path try: - from pymediainfo import MediaInfo + from pymediainfo import MediaInfo, __version__ as pymediainfo_version pymediainfo_available = True except ImportError: pymediainfo_available = False + pymediainfo_version = '0.0' from PyQt5 import QtCore @@ -350,11 +351,16 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): :param media_path: The file path to be checked.. """ if MediaInfo.can_parse(): - # pymediainfo has an issue opening non-ascii file names, so pass it a file object instead - # See https://gitlab.com/openlp/openlp/-/issues/1041 - with Path(media_path).open('rb') as media_file: - media_data = MediaInfo.parse(media_file) - # duration returns in milli seconds + if pymediainfo_version < '4.3': + # pymediainfo only introduced file objects in 4.3, so if this is an older version, we'll have to use + # the old method. See https://gitlab.com/openlp/openlp/-/issues/1187 + media_data = MediaInfo.parse(str(media_path)) + else: + # pymediainfo has an issue opening non-ascii file names, so pass it a file object instead + # See https://gitlab.com/openlp/openlp/-/issues/1041 + with Path(media_path).open('rb') as media_file: + media_data = MediaInfo.parse(media_file) + # duration returns in milli seconds return media_data.tracks[0].duration or 0 return 0 diff --git a/tests/openlp_core/ui/media/test_mediacontroller.py b/tests/openlp_core/ui/media/test_mediacontroller.py index 06e46e83d..5fa62c71c 100644 --- a/tests/openlp_core/ui/media/test_mediacontroller.py +++ b/tests/openlp_core/ui/media/test_mediacontroller.py @@ -357,6 +357,47 @@ def test_media_length_duration_none(MockPath, mocked_parse, media_env): assert duration == 0, 'The duration should be 0' +@patch('openlp.core.ui.media.mediacontroller.MediaInfo.parse') +def test_media_length_duration_old_version(mocked_parse, media_env): + """ + Test that when a version of MediaInfo < 4.3 is installed, a file name is passed directly to the parse method + """ + # GIVEN: A fake media file and a mocked MediaInfo.parse() function + from openlp.core.ui.media import mediacontroller + mediacontroller.pymediainfo_version = '4.0.1' + mocked_parse.return_value = MagicMock(tracks=[MagicMock(duration=10)]) + file_path = 'path/to/fake/video.mkv' + + # WHEN the media data is retrieved + duration = media_env.media_controller.media_length(file_path) + + # THEN you can determine the run time + mocked_parse.assert_called_once_with('path/to/fake/video.mkv') + assert duration == 10, 'The duration should be 10' + + +@patch('openlp.core.ui.media.mediacontroller.Path') +@patch('openlp.core.ui.media.mediacontroller.MediaInfo.parse') +def test_media_length_duration_new_version(mocked_parse, MockPath, media_env): + """ + Test that when a version of MediaInfo > 4.3 is installed, a file OBJECT is passed to the parse method + """ + # GIVEN: A fake media file and a mocked MediaInfo.parse() function + from openlp.core.ui.media import mediacontroller + mediacontroller.pymediainfo_version = '5.0.3' + mocked_file = MagicMock() + MockPath.return_value.open.return_value.__enter__.return_value = mocked_file + mocked_parse.return_value = MagicMock(tracks=[MagicMock(duration=8)]) + file_path = 'path/to/fake/video.mkv' + + # WHEN the media data is retrieved + duration = media_env.media_controller.media_length(file_path) + + # THEN you can determine the run time + mocked_parse.assert_called_once_with(mocked_file) + assert duration == 8, 'The duration should be 8' + + @patch('openlp.core.ui.media.mediacontroller.MediaInfo.can_parse') def test_media_length_no_can_parse(mocked_can_parse, media_env): """