forked from openlp/openlp
Add wrapper for mediainfo
This commit is contained in:
parent
4ecd2085ed
commit
4a0330f126
@ -33,6 +33,7 @@ from openlp.core.lib import OpenLPToolbar, ItemCapabilities
|
|||||||
from openlp.core.lib.ui import critical_error_message_box
|
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,\
|
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players,\
|
||||||
parse_optical_path
|
parse_optical_path
|
||||||
|
from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper
|
||||||
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
||||||
from openlp.core.common import AppLocation
|
from openlp.core.common import AppLocation
|
||||||
from openlp.core.ui import DisplayControllerType
|
from openlp.core.ui import DisplayControllerType
|
||||||
@ -441,12 +442,9 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
|
|||||||
critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
|
critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
|
||||||
translate('MediaPlugin.MediaItem', 'Unsupported File'))
|
translate('MediaPlugin.MediaItem', 'Unsupported File'))
|
||||||
return False
|
return False
|
||||||
if not self.media_play(controller):
|
media_data = MediaInfoWrapper.parse(service_item.get_frame_path())
|
||||||
critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
|
# duration returns in nano seconds
|
||||||
translate('MediaPlugin.MediaItem', 'Unsupported File'))
|
service_item.set_media_length(media_data.tracks[0].duration // 1000)
|
||||||
return False
|
|
||||||
service_item.set_media_length(controller.media_info.length)
|
|
||||||
self.media_stop(controller)
|
|
||||||
log.debug('use %s controller' % self.current_media_players[controller.controller_type])
|
log.debug('use %s controller' % self.current_media_players[controller.controller_type])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
140
openlp/core/ui/media/vendor/mediainfoWrapper.py
vendored
Normal file
140
openlp/core/ui/media/vendor/mediainfoWrapper.py
vendored
Normal file
@ -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 "<Track track_id='{0}', track_type='{1}'>".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())
|
21
tests/interfaces/openlp_core_ul_media_vendor/__init__.py
Normal file
21
tests/interfaces/openlp_core_ul_media_vendor/__init__.py
Normal file
@ -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 #
|
||||||
|
###############################################################################
|
@ -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])
|
BIN
tests/resources/media/avi_file.avi
Normal file
BIN
tests/resources/media/avi_file.avi
Normal file
Binary file not shown.
BIN
tests/resources/media/mp3_file.mp3
Normal file
BIN
tests/resources/media/mp3_file.mp3
Normal file
Binary file not shown.
BIN
tests/resources/media/mp4_file.mp4
Normal file
BIN
tests/resources/media/mp4_file.mp4
Normal file
Binary file not shown.
BIN
tests/resources/media/mpg_file.mpg
Normal file
BIN
tests/resources/media/mpg_file.mpg
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user