diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index 343ce0dd4..d043a9edd 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -33,6 +33,7 @@ from openlp.core.lib import OpenLPToolbar, ItemCapabilities from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players,\ parse_optical_path +from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper from openlp.core.ui.media.mediaplayer import MediaPlayer from openlp.core.common import AppLocation from openlp.core.ui import DisplayControllerType @@ -441,12 +442,9 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties): critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) return False - if not self.media_play(controller): - critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), - translate('MediaPlugin.MediaItem', 'Unsupported File')) - return False - service_item.set_media_length(controller.media_info.length) - self.media_stop(controller) + media_data = MediaInfoWrapper.parse(service_item.get_frame_path()) + # duration returns in nano seconds + service_item.set_media_length(media_data.tracks[0].duration // 1000) log.debug('use %s controller' % self.current_media_players[controller.controller_type]) return True diff --git a/openlp/core/ui/media/vendor/mediainfoWrapper.py b/openlp/core/ui/media/vendor/mediainfoWrapper.py new file mode 100644 index 000000000..c77b47912 --- /dev/null +++ b/openlp/core/ui/media/vendor/mediainfoWrapper.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2016 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`~openlp.core.ui.media.mediainfo` module contains code to run mediainfo on a media file and obtain +information related to the rwquested media. +""" +import json +import os +from subprocess import Popen +from tempfile import mkstemp + +import six +from bs4 import BeautifulSoup, NavigableString + +ENV_DICT = os.environ + + +class Track(object): + + def __getattribute__(self, name): + try: + return object.__getattribute__(self, name) + except: + pass + return None + + def __init__(self, xml_dom_fragment): + self.xml_dom_fragment = xml_dom_fragment + self.track_type = xml_dom_fragment.attrs['type'] + for el in self.xml_dom_fragment.children: + if not isinstance(el, NavigableString): + node_name = el.name.lower().strip().strip('_') + if node_name == 'id': + node_name = 'track_id' + node_value = el.string + other_node_name = "other_%s" % node_name + if getattr(self, node_name) is None: + setattr(self, node_name, node_value) + else: + if getattr(self, other_node_name) is None: + setattr(self, other_node_name, [node_value, ]) + else: + getattr(self, other_node_name).append(node_value) + + for o in [d for d in self.__dict__.keys() if d.startswith('other_')]: + try: + primary = o.replace('other_', '') + setattr(self, primary, int(getattr(self, primary))) + except: + for v in getattr(self, o): + try: + current = getattr(self, primary) + setattr(self, primary, int(v)) + getattr(self, o).append(current) + break + except: + pass + + def __repr__(self): + return "".format(self.track_id, self.track_type) + + def to_data(self): + data = {} + for k, v in six.iteritems(self.__dict__): + if k != 'xml_dom_fragment': + data[k] = v + return data + + +class MediaInfoWrapper(object): + + def __init__(self, xml): + self.xml_dom = xml + xml_types = (str,) # no unicode type in python3 + if isinstance(xml, xml_types): + self.xml_dom = MediaInfoWrapper.parse_xml_data_into_dom(xml) + + @staticmethod + def parse_xml_data_into_dom(xml_data): + return BeautifulSoup(xml_data, "xml") + + @staticmethod + def parse(filename, environment=ENV_DICT): + command = ["mediainfo", "-f", "--Output=XML", filename] + fileno_out, fname_out = mkstemp(suffix=".xml", prefix="media-") + fileno_err, fname_err = mkstemp(suffix=".err", prefix="media-") + fp_out = os.fdopen(fileno_out, 'r+b') + fp_err = os.fdopen(fileno_err, 'r+b') + p = Popen(command, stdout=fp_out, stderr=fp_err, env=environment) + p.wait() + fp_out.seek(0) + + xml_dom = MediaInfoWrapper.parse_xml_data_into_dom(fp_out.read()) + fp_out.close() + fp_err.close() + os.unlink(fname_out) + os.unlink(fname_err) + return MediaInfoWrapper(xml_dom) + + def _populate_tracks(self): + if self.xml_dom is None: + return + for xml_track in self.xml_dom.Mediainfo.File.find_all("track"): + self._tracks.append(Track(xml_track)) + + @property + def tracks(self): + if not hasattr(self, "_tracks"): + self._tracks = [] + if len(self._tracks) == 0: + self._populate_tracks() + return self._tracks + + def to_data(self): + data = {'tracks': []} + for track in self.tracks: + data['tracks'].append(track.to_data()) + return data + + def to_json(self): + return json.dumps(self.to_data()) \ No newline at end of file diff --git a/tests/interfaces/openlp_core_ul_media_vendor/__init__.py b/tests/interfaces/openlp_core_ul_media_vendor/__init__.py new file mode 100644 index 000000000..02bded5b0 --- /dev/null +++ b/tests/interfaces/openlp_core_ul_media_vendor/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2016 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### diff --git a/tests/interfaces/openlp_core_ul_media_vendor/test_mediainfoWrapper.py b/tests/interfaces/openlp_core_ul_media_vendor/test_mediainfoWrapper.py new file mode 100644 index 000000000..acf17f581 --- /dev/null +++ b/tests/interfaces/openlp_core_ul_media_vendor/test_mediainfoWrapper.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2016 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +Package to test the openlp.core.ui.media package. +""" + +import os +from unittest import TestCase + +from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper + +TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'resources', 'media')) + +TEST_MEDIA = [['avi_file.avi', 61495], ['mp3_file.mp3', 134426], ['mpg_file.mpg', 9404], ['mp4_file.mp4', 188336]] + + +class TestMediainfoWrapper(TestCase): + + def media_length_test(self): + """ + Test the Media Info basic functionality + """ + for test_data in TEST_MEDIA: + # GIVEN: a media file + full_path = os.path.normpath(os.path.join(TEST_PATH, test_data[0])) + + # WHEN the media data is retrieved + results = MediaInfoWrapper.parse(full_path) + + # THEN you can determine the run time + self.assertEqual(results.tracks[0].duration, test_data[1], 'The correct duration is returned for ' + + test_data[0]) diff --git a/tests/resources/media/avi_file.avi b/tests/resources/media/avi_file.avi new file mode 100644 index 000000000..9a89932fe Binary files /dev/null and b/tests/resources/media/avi_file.avi differ diff --git a/tests/resources/media/mp3_file.mp3 b/tests/resources/media/mp3_file.mp3 new file mode 100644 index 000000000..2b5cc44f7 Binary files /dev/null and b/tests/resources/media/mp3_file.mp3 differ diff --git a/tests/resources/media/mp4_file.mp4 b/tests/resources/media/mp4_file.mp4 new file mode 100644 index 000000000..73abf10a0 Binary files /dev/null and b/tests/resources/media/mp4_file.mp4 differ diff --git a/tests/resources/media/mpg_file.mpg b/tests/resources/media/mpg_file.mpg new file mode 100644 index 000000000..af768c542 Binary files /dev/null and b/tests/resources/media/mpg_file.mpg differ