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.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
|
||||
|
||||
|
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