openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #28686
[Merge] lp:~trb143/openlp/media_timer2 into lp:openlp
Tim Bentley has proposed merging lp:~trb143/openlp/media_timer2 into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
Related bugs:
Bug #1022053 in OpenLP: "Previewing media item interferes with live media item"
https://bugs.launchpad.net/openlp/+bug/1022053
Bug #1079874 in OpenLP: "Time of playing viedeo and video length"
https://bugs.launchpad.net/openlp/+bug/1079874
Bug #1414563 in OpenLP: "Volume slider shows in preview controller"
https://bugs.launchpad.net/openlp/+bug/1414563
Bug #1458347 in OpenLP: "Expose more playback options for VLC"
https://bugs.launchpad.net/openlp/+bug/1458347
Bug #1463286 in OpenLP: "Live media restarts when adding media to servicemanager"
https://bugs.launchpad.net/openlp/+bug/1463286
For more details, see:
https://code.launchpad.net/~trb143/openlp/media_timer2/+merge/285995
Test proposal to check changes.
--
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/media_timer2 into lp:openlp.
=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py 2015-12-31 22:46:06 +0000
+++ openlp/core/lib/serviceitem.py 2016-02-14 17:55:52 +0000
@@ -610,7 +610,7 @@
str(datetime.timedelta(seconds=self.start_time))
if self.media_length != 0:
end = translate('OpenLP.ServiceItem', '<strong>Length</strong>: %s') % \
- str(datetime.timedelta(seconds=self.media_length))
+ str(datetime.timedelta(seconds=self.media_length // 1000))
if not start and not end:
return ''
elif start and not end:
=== modified file 'openlp/core/ui/media/__init__.py'
--- openlp/core/ui/media/__init__.py 2015-12-31 22:46:06 +0000
+++ openlp/core/ui/media/__init__.py 2016-02-14 17:55:52 +0000
@@ -60,12 +60,14 @@
"""
file_info = None
volume = 100
- is_flash = False
is_background = False
+ loop_playback = False
length = 0
start_time = 0
end_time = 0
title_track = 0
+ playing = False
+ timer = 1000
audio_track = 0
subtitle_track = 0
media_type = MediaType()
@@ -104,15 +106,15 @@
Settings().setValue('media/players', players)
-def parse_optical_path(input):
+def parse_optical_path(input_string):
"""
Split the optical path info.
- :param input: The string to parse
+ :param input_string: The string to parse
:return: The elements extracted from the string: filename, title, audio_track, subtitle_track, start, end
"""
- log.debug('parse_optical_path, about to parse: "%s"' % input)
- clip_info = input.split(sep=':')
+ log.debug('parse_optical_path, about to parse: "%s"' % input_string)
+ clip_info = input_string.split(sep=':')
title = int(clip_info[1])
audio_track = int(clip_info[2])
subtitle_track = int(clip_info[3])
=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py 2015-12-31 22:46:06 +0000
+++ openlp/core/ui/media/mediacontroller.py 2016-02-14 17:55:52 +0000
@@ -33,12 +33,15 @@
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
log = logging.getLogger(__name__)
+TICK_TIME = 200
+
class MediaSlider(QtWidgets.QSlider):
"""
@@ -51,10 +54,13 @@
super(MediaSlider, self).__init__(direction)
self.manager = manager
self.controller = controller
+ self.no_matching_player = translate('MediaPlugin.MediaItem', 'File %s not supported using player %s')
def mouseMoveEvent(self, event):
"""
Override event to allow hover time to be displayed.
+
+ :param event: The triggering event
"""
time_value = QtWidgets.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width())
self.setToolTip('%s' % datetime.timedelta(seconds=int(time_value / 1000)))
@@ -63,12 +69,16 @@
def mousePressEvent(self, event):
"""
Mouse Press event no new functionality
+
+ :param event: The triggering event
"""
QtWidgets.QSlider.mousePressEvent(self, event)
def mouseReleaseEvent(self, event):
"""
Set the slider position when the mouse is clicked and released on the slider.
+
+ :param event: The triggering event
"""
self.setValue(QtWidgets.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width()))
QtWidgets.QSlider.mouseReleaseEvent(self, event)
@@ -97,12 +107,13 @@
self.current_media_players = {}
# Timer for video state
self.timer = QtCore.QTimer()
- self.timer.setInterval(200)
+ self.timer.setInterval(TICK_TIME)
# Signals
self.timer.timeout.connect(self.media_state)
Registry().register_function('playbackPlay', self.media_play_msg)
Registry().register_function('playbackPause', self.media_pause_msg)
Registry().register_function('playbackStop', self.media_stop_msg)
+ Registry().register_function('playbackLoop', self.media_loop_msg)
Registry().register_function('seek_slider', self.media_seek_msg)
Registry().register_function('volume_slider', self.media_volume_msg)
Registry().register_function('media_hide', self.media_hide)
@@ -202,6 +213,7 @@
self.current_media_players[source].update_ui(display)
if self.current_media_players[source].state == MediaState.Playing:
any_active = True
+ self.tick(self.display_controllers[source])
# There are still any active players - no need to stop timer.
if any_active:
return
@@ -274,6 +286,15 @@
icon=':/slides/media_playback_stop.png',
tooltip=translate('OpenLP.SlideController', 'Stop playing media.'),
triggers=controller.send_to_plugins)
+ controller.mediabar.add_toolbar_action('playbackLoop', text='media_playback_loop',
+ icon=':/slides/media_playback_stop.png', checked=False,
+ tooltip=translate('OpenLP.SlideController', 'Loop playing media.'),
+ triggers=controller.send_to_plugins)
+ controller.position_label = QtWidgets.QLabel()
+ controller.position_label.setText(' 00:00 / 00:00')
+ controller.position_label.setToolTip(translate('OpenLP.SlideController', 'Video timer.'))
+ controller.position_label.setObjectName('position_label')
+ controller.mediabar.add_toolbar_widget(controller.position_label)
# Build the seek_slider.
controller.seek_slider = MediaSlider(QtCore.Qt.Horizontal, self, controller)
controller.seek_slider.setMaximum(1000)
@@ -297,6 +318,8 @@
controller.mediabar.add_toolbar_widget(controller.volume_slider)
controller.controller_layout.addWidget(controller.mediabar)
controller.mediabar.setVisible(False)
+ if not controller.is_live:
+ controller.volume_slider.setEnabled(False)
# Signals
controller.seek_slider.valueChanged.connect(controller.send_to_plugins)
controller.volume_slider.valueChanged.connect(controller.send_to_plugins)
@@ -335,7 +358,8 @@
if self.current_media_players[controller.controller_type] != self.media_players['webkit']:
controller.display.set_transparency(False)
- def resize(self, display, player):
+ @staticmethod
+ def resize(display, player):
"""
After Mainwindow changes or Splitter moved all related media widgets have to be resized
@@ -353,7 +377,6 @@
:param hidden: The player which is doing the playing
:param video_behind_text: Is the video to be played behind text.
"""
- log.debug('video')
is_valid = False
controller = self.display_controllers[source]
# stop running videos
@@ -361,6 +384,8 @@
controller.media_info = MediaInfo()
controller.media_info.volume = controller.volume_slider.value()
controller.media_info.is_background = video_behind_text
+ # background will always loop video.
+ controller.media_info.loop_playback = video_behind_text
controller.media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path())
display = self._define_display(controller)
if controller.is_live:
@@ -373,6 +398,7 @@
controller)
else:
log.debug('video is not optical and live')
+ controller.media_info.length = service_item.media_length
is_valid = self._check_file_type(controller, display, service_item)
display.override['theme'] = ''
display.override['video'] = True
@@ -392,6 +418,7 @@
controller)
else:
log.debug('video is not optical and preview')
+ controller.media_info.length = service_item.media_length
is_valid = self._check_file_type(controller, display, service_item)
if not is_valid:
# Media could not be loaded correctly
@@ -428,26 +455,22 @@
:param service_item: The ServiceItem containing the details to be played.
"""
- controller = self.display_controllers[DisplayControllerType.Plugin]
- log.debug('media_length')
- # stop running videos
- self.media_reset(controller)
- controller.media_info = MediaInfo()
- controller.media_info.volume = 0
- controller.media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path())
- display = controller.preview_display
- if not self._check_file_type(controller, display, service_item):
+ media_info = MediaInfo()
+ media_info.volume = 0
+ media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path())
+ # display = controller.preview_display
+ suffix = '*.%s' % media_info.file_info.suffix().lower()
+ used_players = get_media_players()[0]
+ player = self.media_players[used_players[0]]
+ if suffix not in player.video_extensions_list and suffix not in player.audio_extensions_list:
# Media could not be loaded correctly
- 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)
- log.debug('use %s controller' % self.current_media_players[controller.controller_type])
+ critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported Media File'),
+ translate('MediaPlugin.MediaItem', 'File %s not supported using player %s') %
+ (service_item.get_frame_path(), used_players[0]))
+ return False
+ media_data = MediaInfoWrapper.parse(service_item.get_frame_path())
+ # duration returns in milli seconds
+ service_item.set_media_length(media_data.tracks[0].duration)
return True
def media_setup_optical(self, filename, title, audio_track, subtitle_track, start, end, display, controller):
@@ -458,13 +481,12 @@
:param title: The main/title track to play.
:param audio_track: The audio track to play.
:param subtitle_track: The subtitle track to play.
- :param start: Start position in miliseconds.
- :param end: End position in miliseconds.
+ :param start: Start position in milliseconds.
+ :param end: End position in milliseconds.
:param display: The display to play the media.
- :param controller: The media contraoller.
- :return: True if setup succeded else False.
+ :param controller: The media controller.
+ :return: True if setup succeeded else False.
"""
- log.debug('media_setup_optical')
if controller is None:
controller = self.display_controllers[DisplayControllerType.Plugin]
# stop running videos
@@ -476,9 +498,9 @@
controller.media_info.media_type = MediaType.CD
else:
controller.media_info.media_type = MediaType.DVD
- controller.media_info.start_time = start / 1000
- controller.media_info.end_time = end / 1000
- controller.media_info.length = (end - start) / 1000
+ controller.media_info.start_time = start // 1000
+ controller.media_info.end_time = end // 1000
+ controller.media_info.length = (end - start) // 1000
controller.media_info.title_track = title
controller.media_info.audio_track = audio_track
controller.media_info.subtitle_track = subtitle_track
@@ -506,13 +528,13 @@
controller.media_info.media_type = MediaType.DVD
return True
- def _check_file_type(self, controller, display, service_item):
+ @staticmethod
+ def _get_used_players(service_item):
"""
- Select the correct media Player type from the prioritized Player list
+ Find the player for a given service item
- :param controller: First element is the controller which should be used
- :param display: Which display to use
- :param service_item: The ServiceItem containing the details to be played.
+ :param service_item: where the information is about the media and required player
+ :return: player description
"""
used_players = get_media_players()[0]
# If no player, we can't play
@@ -525,6 +547,17 @@
used_players = default_player
else:
used_players = [service_item.processor.lower()]
+ return used_players
+
+ def _check_file_type(self, controller, display, service_item):
+ """
+ Select the correct media Player type from the prioritized Player list
+
+ :param controller: First element is the controller which should be used
+ :param display: Which display to use
+ :param service_item: The ServiceItem containing the details to be played.
+ """
+ used_players = self._get_used_players(service_item)
if controller.media_info.file_info.isFile():
suffix = '*.%s' % controller.media_info.file_info.suffix().lower()
for title in used_players:
@@ -573,17 +606,15 @@
:param msg: First element is the controller which should be used
:param status:
"""
- log.debug('media_play_msg')
self.media_play(msg[0], status)
- def media_play(self, controller, status=True):
+ def media_play(self, controller, first_time=True):
"""
Responds to the request to play a loaded video
:param controller: The controller to be played
- :param status:
+ :param first_time:
"""
- log.debug('media_play')
controller.seek_slider.blockSignals(True)
controller.volume_slider.blockSignals(True)
display = self._define_display(controller)
@@ -595,26 +626,25 @@
self.media_volume(controller, 0)
else:
self.media_volume(controller, controller.media_info.volume)
- if status:
+ if first_time:
if not controller.media_info.is_background:
display.frame.evaluateJavaScript('show_blank("desktop");')
- self.current_media_players[controller.controller_type].set_visible(display, True)
- # Flash needs to be played and will not AutoPlay
- if controller.media_info.is_flash:
- controller.mediabar.actions['playbackPlay'].setVisible(True)
- controller.mediabar.actions['playbackPause'].setVisible(False)
- else:
- controller.mediabar.actions['playbackPlay'].setVisible(False)
- controller.mediabar.actions['playbackPause'].setVisible(True)
- controller.mediabar.actions['playbackStop'].setDisabled(False)
- if controller.is_live:
- if controller.hide_menu.defaultAction().isChecked() and not controller.media_info.is_background:
- controller.hide_menu.defaultAction().trigger()
+ else:
+ if controller.media_info.is_background:
+ display.frame.evaluateJavaScript('show_blank("desktop");')
+ self.current_media_players[controller.controller_type].set_visible(display, True)
+ controller.mediabar.actions['playbackPlay'].setVisible(False)
+ controller.mediabar.actions['playbackPause'].setVisible(True)
+ controller.mediabar.actions['playbackStop'].setDisabled(False)
+ if controller.is_live:
+ if controller.hide_menu.defaultAction().isChecked() and not controller.media_info.is_background:
+ controller.hide_menu.defaultAction().trigger()
# Start Timer for ui updates
if not self.timer.isActive():
self.timer.start()
controller.seek_slider.blockSignals(False)
controller.volume_slider.blockSignals(False)
+ controller.media_info.playing = True
return True
def media_pause_msg(self, msg):
@@ -623,21 +653,62 @@
:param msg: First element is the controller which should be used
"""
- log.debug('media_pause_msg')
self.media_pause(msg[0])
+ def tick(self, controller):
+ """
+ Add a tick while the media is playing but only count if not paused
+
+ :param controller: The Controller to be processed
+ """
+ start_again = False
+ if controller.media_info.playing and controller.media_info.length > 0:
+ if controller.media_info.timer > controller.media_info.length:
+ self.media_stop(controller)
+ if controller.media_info.loop_playback:
+ start_again = True
+ controller.media_info.timer += TICK_TIME
+ seconds = controller.media_info.timer // 1000
+ minutes = seconds // 60
+ seconds %= 60
+ total_seconds = controller.media_info.length // 1000
+ total_minutes = total_seconds // 60
+ total_seconds %= 60
+ controller.position_label.setText(' %02d:%02d / %02d:%02d' %
+ (minutes, seconds, total_minutes, total_seconds))
+ if start_again:
+ self.media_play(controller, False)
+
def media_pause(self, controller):
"""
Responds to the request to pause a loaded video
:param controller: The Controller to be paused
"""
- log.debug('media_pause')
display = self._define_display(controller)
self.current_media_players[controller.controller_type].pause(display)
controller.mediabar.actions['playbackPlay'].setVisible(True)
controller.mediabar.actions['playbackStop'].setDisabled(False)
controller.mediabar.actions['playbackPause'].setVisible(False)
+ controller.media_info.playing = False
+
+ def media_loop_msg(self, msg):
+ """
+ Responds to the request to loop a loaded video
+
+ :param msg: First element is the controller which should be used
+ """
+ self.media_loop(msg[0])
+
+ @staticmethod
+ def media_loop(controller):
+ """
+ Responds to the request to loop a loaded video
+
+ :param controller: The controller that needs to be stopped
+ """
+ controller.media_info.loop_playback = not controller.media_info.loop_playback
+ controller.mediabar.actions['playbackLoop'].setChecked(controller.media_info.loop_playback)
def media_stop_msg(self, msg):
"""
@@ -645,7 +716,6 @@
:param msg: First element is the controller which should be used
"""
- log.debug('media_stop_msg')
self.media_stop(msg[0])
def media_stop(self, controller):
@@ -654,7 +724,6 @@
:param controller: The controller that needs to be stopped
"""
- log.debug('media_stop')
display = self._define_display(controller)
if controller.controller_type in self.current_media_players:
display.frame.evaluateJavaScript('show_blank("black");')
@@ -664,6 +733,9 @@
controller.mediabar.actions['playbackPlay'].setVisible(True)
controller.mediabar.actions['playbackStop'].setDisabled(True)
controller.mediabar.actions['playbackPause'].setVisible(False)
+ controller.media_info.playing = False
+ controller.media_info.timer = 1000
+ controller.media_timer = 0
def media_volume_msg(self, msg):
"""
@@ -694,7 +766,6 @@
:param msg: First element is the controller which should be used
Second element is a list with the seek value as first element
"""
- log.debug('media_seek')
controller = msg[0]
seek_value = msg[1][0]
self.media_seek(controller, seek_value)
@@ -706,15 +777,15 @@
:param controller: The controller to use.
:param seek_value: The value to set.
"""
- log.debug('media_seek')
display = self._define_display(controller)
self.current_media_players[controller.controller_type].seek(display, seek_value)
+ controller.media_info.timer = seek_value
def media_reset(self, controller):
"""
Responds to the request to reset a loaded video
+ :param controller: The controller to use.
"""
- log.debug('media_reset')
self.set_controls_visible(controller, False)
display = self._define_display(controller)
if controller.controller_type in self.current_media_players:
@@ -785,7 +856,8 @@
for controller in self.display_controllers:
self.media_reset(self.display_controllers[controller])
- def _define_display(self, controller):
+ @staticmethod
+ def _define_display(controller):
"""
Extract the correct display for a given controller
=== modified file 'openlp/core/ui/media/mediaplayer.py'
--- openlp/core/ui/media/mediaplayer.py 2015-12-31 22:46:06 +0000
+++ openlp/core/ui/media/mediaplayer.py 2016-02-14 17:55:52 +0000
@@ -55,12 +55,16 @@
def setup(self, display):
"""
Create the related widgets for the current display
+
+ :param display: The display to be updated.
"""
pass
def load(self, display):
"""
Load a new media file and check if it is valid
+
+ :param display: The display to be updated.
"""
return True
@@ -68,54 +72,75 @@
"""
If the main display size or position is changed, the media widgets
should also resized
+
+ :param display: The display to be updated.
"""
pass
def play(self, display):
"""
Starts playing of current Media File
+
+ :param display: The display to be updated.
"""
pass
def pause(self, display):
"""
Pause of current Media File
+
+ :param display: The display to be updated.
"""
pass
def stop(self, display):
"""
Stop playing of current Media File
+
+ :param display: The display to be updated.
"""
pass
- def volume(self, display, vol):
+ def volume(self, display, volume):
"""
Change volume of current Media File
+
+ :param display: The display to be updated.
+ :param volume: The volume to set.
"""
pass
def seek(self, display, seek_value):
"""
Change playing position of current Media File
+
+ :param display: The display to be updated.
+ :param seek_value: The where to seek to.
"""
pass
def reset(self, display):
"""
Remove the current loaded video
+
+ :param display: The display to be updated.
"""
pass
def set_visible(self, display, status):
"""
Show/Hide the media widgets
+
+ :param display: The display to be updated.
+ :param status: The status to be set.
"""
pass
def update_ui(self, display):
"""
Do some ui related stuff (e.g. update the seek slider)
+
+ :param display: The display to be updated.
"""
pass
=== modified file 'openlp/core/ui/media/playertab.py'
--- openlp/core/ui/media/playertab.py 2015-12-31 22:46:06 +0000
+++ openlp/core/ui/media/playertab.py 2016-02-14 17:55:52 +0000
@@ -133,12 +133,16 @@
def on_background_color_changed(self, color):
"""
Set the background color
+
+ :param color: The color to be set.
"""
self.background_color = color
def on_player_check_box_changed(self, check_state):
"""
Add or remove players depending on their status
+
+ :param check_state: The requested status.
"""
player = self.sender().player_name
if check_state == QtCore.Qt.Checked:
=== modified file 'openlp/core/ui/media/systemplayer.py'
--- openlp/core/ui/media/systemplayer.py 2015-12-10 19:03:57 +0000
+++ openlp/core/ui/media/systemplayer.py 2016-02-14 17:55:52 +0000
@@ -4,14 +4,7 @@
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2014 Raoul Snyman #
-# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
-# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
-# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
-# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
-# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
-# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# 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 #
@@ -124,7 +117,8 @@
def load(self, display):
"""
Load a video into the display
- :param display:
+
+ :param display: The display where the media is
"""
log.debug('load vid in System Controller')
controller = display.controller
@@ -141,14 +135,16 @@
def resize(self, display):
"""
Resize the display
- :param display:
+
+ :param display: The display where the media is
"""
display.video_widget.resize(display.size())
def play(self, display):
"""
Play the current media item
- :param display:
+
+ :param display: The display where the media is
"""
log.info('Play the current item')
controller = display.controller
@@ -168,6 +164,8 @@
def pause(self, display):
"""
Pause the current media item
+
+ :param display: The display where the media is
"""
display.media_player.pause()
if display.media_player.state() == QtMultimedia.QMediaPlayer.PausedState:
@@ -176,6 +174,8 @@
def stop(self, display):
"""
Stop the current media item
+
+ :param display: The display where the media is
"""
display.media_player.blockSignals(True)
display.media_player.durationChanged.disconnect()
@@ -184,22 +184,29 @@
self.set_visible(display, False)
self.state = MediaState.Stopped
- def volume(self, display, vol):
+ def volume(self, display, volume):
"""
Set the volume
+
+ :param display: The display where the media is
+ :param volume: The volume to be set
"""
if display.has_audio:
- display.media_player.setVolume(vol)
+ display.media_player.setVolume(volume)
def seek(self, display, seek_value):
"""
Go to a particular point in the current media item
+
+ :param display: The display where the media is
"""
display.media_player.setPosition(seek_value)
def reset(self, display):
"""
Reset the media player
+
+ :param display: The display where the media is
"""
display.media_player.stop()
display.media_player.setMedia(QtMultimedia.QMediaContent())
@@ -210,24 +217,34 @@
def set_visible(self, display, status):
"""
Set the visibility of the widget
+
+ :param display: The display where the media is
+ :param status: The visibility status to be set
"""
if self.has_own_widget:
display.video_widget.setVisible(status)
@staticmethod
def set_duration(controller, duration):
- controller.media_info.length = int(duration / 1000)
- controller.seek_slider.setMaximum(controller.media_info.length * 1000)
+ """
+
+ :param controller: the controller displaying the media
+ :param duration: how long is the media
+ :return:
+ """
+ controller.seek_slider.setMaximum(controller.media_info.length)
def update_ui(self, display):
"""
Update the UI
+
+ :param display: The display where the media is
"""
if display.media_player.state() == QtMultimedia.QMediaPlayer.PausedState and self.state != MediaState.Paused:
self.stop(display)
controller = display.controller
if controller.media_info.end_time > 0:
- if display.media_player.position() > controller.media_info.end_time * 1000:
+ if display.media_player.position() > controller.media_info.end_time:
self.stop(display)
self.set_visible(display, False)
if not controller.seek_slider.isSliderDown():
=== added file 'openlp/core/ui/media/vendor/mediainfoWrapper.py'
--- openlp/core/ui/media/vendor/mediainfoWrapper.py 1970-01-01 00:00:00 +0000
+++ openlp/core/ui/media/vendor/mediainfoWrapper.py 2016-02-14 17:55:52 +0000
@@ -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())
\ No newline at end of file
=== modified file 'openlp/core/ui/media/vlcplayer.py'
--- openlp/core/ui/media/vlcplayer.py 2015-12-31 22:46:06 +0000
+++ openlp/core/ui/media/vlcplayer.py 2016-02-14 17:55:52 +0000
@@ -144,6 +144,9 @@
def setup(self, display):
"""
Set up the media player
+
+ :param display: The display where the media is
+ :return:
"""
vlc = get_vlc()
display.vlc_widget = QtWidgets.QFrame(display)
@@ -186,6 +189,9 @@
def load(self, display):
"""
Load a video into VLC
+
+ :param display: The display where the media is
+ :return:
"""
vlc = get_vlc()
log.debug('load vid in Vlc Controller')
@@ -214,18 +220,16 @@
# parse the metadata of the file
display.vlc_media.parse()
self.volume(display, volume)
- # We need to set media_info.length during load because we want
- # to avoid start and stop the video twice. Once for real playback
- # and once to just get media length.
- #
- # Media plugin depends on knowing media length before playback.
- controller.media_info.length = int(display.vlc_media_player.get_media().get_duration() / 1000)
return True
def media_state_wait(self, display, media_state):
"""
Wait for the video to change its state
Wait no longer than 60 seconds. (loading an iso file needs a long time)
+
+ :param media_state: The state of the playing media
+ :param display: The display where the media is
+ :return:
"""
vlc = get_vlc()
start = datetime.now()
@@ -240,12 +244,18 @@
def resize(self, display):
"""
Resize the player
+
+ :param display: The display where the media is
+ :return:
"""
display.vlc_widget.resize(display.size())
def play(self, display):
"""
Play the current item
+
+ :param display: The display where the media is
+ :return:
"""
vlc = get_vlc()
controller = display.controller
@@ -257,7 +267,7 @@
if not self.media_state_wait(display, vlc.State.Playing):
return False
if self.state != MediaState.Paused and controller.media_info.start_time > 0:
- log.debug('vlc play, starttime set')
+ log.debug('vlc play, start time set')
start_time = controller.media_info.start_time
log.debug('mediatype: ' + str(controller.media_info.media_type))
# Set tracks for the optical device
@@ -279,12 +289,10 @@
log.debug('vlc play, starttime set: ' + str(controller.media_info.start_time))
start_time = controller.media_info.start_time
controller.media_info.length = controller.media_info.end_time - controller.media_info.start_time
- else:
- controller.media_info.length = int(display.vlc_media_player.get_media().get_duration() / 1000)
self.volume(display, controller.media_info.volume)
if start_time > 0 and display.vlc_media_player.is_seekable():
- display.vlc_media_player.set_time(int(start_time * 1000))
- controller.seek_slider.setMaximum(controller.media_info.length * 1000)
+ display.vlc_media_player.set_time(int(start_time))
+ controller.seek_slider.setMaximum(controller.media_info.length)
self.state = MediaState.Playing
display.vlc_widget.raise_()
return True
@@ -292,6 +300,9 @@
def pause(self, display):
"""
Pause the current item
+
+ :param display: The display where the media is
+ :return:
"""
vlc = get_vlc()
if display.vlc_media.get_state() != vlc.State.Playing:
@@ -303,6 +314,9 @@
def stop(self, display):
"""
Stop the current item
+
+ :param display: The display where the media is
+ :return:
"""
threading.Thread(target=display.vlc_media_player.stop).start()
self.state = MediaState.Stopped
@@ -310,6 +324,10 @@
def volume(self, display, vol):
"""
Set the volume
+
+ :param vol: The volume to be sets
+ :param display: The display where the media is
+ :return:
"""
if display.has_audio:
display.vlc_media_player.audio_set_volume(vol)
@@ -317,6 +335,9 @@
def seek(self, display, seek_value):
"""
Go to a particular position
+
+ :param seek_value: The position of where a seek goes to
+ :param display: The display where the media is
"""
if display.controller.media_info.media_type == MediaType.CD \
or display.controller.media_info.media_type == MediaType.DVD:
@@ -327,6 +348,8 @@
def reset(self, display):
"""
Reset the player
+
+ :param display: The display where the media is
"""
display.vlc_media_player.stop()
display.vlc_widget.setVisible(False)
@@ -335,6 +358,9 @@
def set_visible(self, display, status):
"""
Set the visibility
+
+ :param display: The display where the media is
+ :param status: The visibility status
"""
if self.has_own_widget:
display.vlc_widget.setVisible(status)
@@ -342,6 +368,8 @@
def update_ui(self, display):
"""
Update the UI
+
+ :param display: The display where the media is
"""
vlc = get_vlc()
# Stop video if playback is finished.
=== modified file 'openlp/core/ui/media/webkitplayer.py'
--- openlp/core/ui/media/webkitplayer.py 2016-01-09 16:26:14 +0000
+++ openlp/core/ui/media/webkitplayer.py 2016-02-14 17:55:52 +0000
@@ -99,74 +99,6 @@
<video id="video" class="size" style="visibility:hidden" autobuffer preload></video>
"""
-FLASH_CSS = """
-#flash {
- z-index:5;
-}
-"""
-
-FLASH_JS = """
- function getFlashMovieObject(movieName)
- {
- if (window.document[movieName]){
- return window.document[movieName];
- }
- if (document.embeds && document.embeds[movieName]){
- return document.embeds[movieName];
- }
- }
-
- function show_flash(state, path, volume, variable_value){
- var text = document.getElementById('flash');
- var flashMovie = getFlashMovieObject("OpenLPFlashMovie");
- var src = "src = 'file:///" + path + "'";
- var view_parm = " wmode='opaque'" + " width='100%%'" + " height='100%%'";
- var swf_parm = " name='OpenLPFlashMovie'" + " autostart='true' loop='false' play='true'" +
- " hidden='false' swliveconnect='true' allowscriptaccess='always'" + " volume='" + volume + "'";
-
- switch(state){
- case 'load':
- text.innerHTML = "<embed " + src + view_parm + swf_parm + "/>";
- flashMovie = getFlashMovieObject("OpenLPFlashMovie");
- flashMovie.Play();
- break;
- case 'play':
- flashMovie.Play();
- break;
- case 'pause':
- flashMovie.StopPlay();
- break;
- case 'stop':
- flashMovie.StopPlay();
- tempHtml = text.innerHTML;
- text.innerHTML = '';
- text.innerHTML = tempHtml;
- break;
- case 'close':
- flashMovie.StopPlay();
- text.innerHTML = '';
- break;
- case 'length':
- return flashMovie.TotalFrames();
- case 'current_time':
- return flashMovie.CurrentFrame();
- case 'seek':
-// flashMovie.GotoFrame(variable_value);
- break;
- case 'isEnded':
- //TODO check flash end
- return false;
- case 'setVisible':
- text.style.visibility = variable_value;
- break;
- }
- }
-"""
-
-FLASH_HTML = """
-<div id="flash" class="size" style="visibility:hidden"></div>
-"""
-
VIDEO_EXT = ['*.3gp', '*.3gpp', '*.3g2', '*.3gpp2', '*.aac', '*.flv', '*.f4a', '*.f4b', '*.f4p', '*.f4v', '*.mov',
'*.m4a', '*.m4b', '*.m4p', '*.m4v', '*.mkv', '*.mp4', '*.ogv', '*.webm', '*.mpg', '*.wmv', '*.mpeg',
'*.avi', '*.swf']
@@ -198,23 +130,25 @@
"""
background = QtGui.QColor(Settings().value('players/background color')).name()
css = VIDEO_CSS % {'bgcolor': background}
- return css + FLASH_CSS
+ return css
def get_media_display_javascript(self):
"""
Add javascript functions to htmlbuilder
"""
- return VIDEO_JS + FLASH_JS
+ return VIDEO_JS
def get_media_display_html(self):
"""
Add html code to htmlbuilder
"""
- return VIDEO_HTML + FLASH_HTML
+ return VIDEO_HTML
def setup(self, display):
"""
Set up the player
+
+ :param display: The display to be updated.
"""
display.web_view.resize(display.size())
display.web_view.raise_()
@@ -235,6 +169,8 @@
def load(self, display):
"""
Load a video
+
+ :param display: The display to be updated.
"""
log.debug('load vid in Webkit Controller')
controller = display.controller
@@ -249,23 +185,23 @@
else:
loop = 'false'
display.web_view.setVisible(True)
- if controller.media_info.file_info.suffix() == 'swf':
- controller.media_info.is_flash = True
- js = 'show_flash("load","%s");' % (path.replace('\\', '\\\\'))
- else:
- js = 'show_video("load", "%s", %s, %s);' % (path.replace('\\', '\\\\'), str(vol), loop)
+ js = 'show_video("load", "%s", %s, %s);' % (path.replace('\\', '\\\\'), str(vol), loop)
display.frame.evaluateJavaScript(js)
return True
def resize(self, display):
"""
Resize the player
+
+ :param display: The display to be updated.
"""
display.web_view.resize(display.size())
def play(self, display):
"""
Play a video
+
+ :param display: The display to be updated.
"""
controller = display.controller
display.web_loaded = True
@@ -274,14 +210,9 @@
if self.state != MediaState.Paused and controller.media_info.start_time > 0:
start_time = controller.media_info.start_time
self.set_visible(display, True)
- if controller.media_info.is_flash:
- display.frame.evaluateJavaScript('show_flash("play");')
- else:
- display.frame.evaluateJavaScript('show_video("play");')
+ display.frame.evaluateJavaScript('show_video("play");')
if start_time > 0:
self.seek(display, controller.media_info.start_time * 1000)
- # TODO add playing check and get the correct media length
- controller.media_info.length = length
self.state = MediaState.Playing
display.web_view.raise_()
return True
@@ -289,92 +220,82 @@
def pause(self, display):
"""
Pause a video
+
+ :param display: The display to be updated.
"""
- controller = display.controller
- if controller.media_info.is_flash:
- display.frame.evaluateJavaScript('show_flash("pause");')
- else:
- display.frame.evaluateJavaScript('show_video("pause");')
+ display.frame.evaluateJavaScript('show_video("pause");')
self.state = MediaState.Paused
def stop(self, display):
"""
Stop a video
+
+ :param display: The display to be updated.
"""
- controller = display.controller
- if controller.media_info.is_flash:
- display.frame.evaluateJavaScript('show_flash("stop");')
- else:
- display.frame.evaluateJavaScript('show_video("stop");')
+ display.frame.evaluateJavaScript('show_video("stop");')
self.state = MediaState.Stopped
def volume(self, display, volume):
"""
Set the volume
+
+ :param display: The display to be updated.
+ :param volume: The volume to be set.
"""
- controller = display.controller
# 1.0 is the highest value
if display.has_audio:
vol = float(volume) / float(100)
- if not controller.media_info.is_flash:
- display.frame.evaluateJavaScript('show_video(null, null, %s);' % str(vol))
+ display.frame.evaluateJavaScript('show_video(null, null, %s);' % str(vol))
def seek(self, display, seek_value):
"""
Go to a position in the video
+
+ :param display: The display to be updated.
+ :param seek_value: The value to be set.
"""
- controller = display.controller
- if controller.media_info.is_flash:
- seek = seek_value
- display.frame.evaluateJavaScript('show_flash("seek", null, null, "%s");' % seek)
- else:
- seek = float(seek_value) / 1000
- display.frame.evaluateJavaScript('show_video("seek", null, null, null, "%f");' % seek)
+ seek = float(seek_value) / 1000
+ display.frame.evaluateJavaScript('show_video("seek", null, null, null, "%f");' % seek)
def reset(self, display):
"""
Reset the player
+
+ :param display: The display to be updated.
"""
- controller = display.controller
- if controller.media_info.is_flash:
- display.frame.evaluateJavaScript('show_flash("close");')
- else:
- display.frame.evaluateJavaScript('show_video("close");')
+ display.frame.evaluateJavaScript('show_video("close");')
self.state = MediaState.Off
- def set_visible(self, display, status):
+ def set_visible(self, display, visibility):
"""
Set the visibility
+
+ :param display: The display to be updated.
+ :param visibility: The visibility to be set.
"""
- controller = display.controller
- if status:
+ if visibility:
is_visible = "visible"
else:
is_visible = "hidden"
- if controller.media_info.is_flash:
- display.frame.evaluateJavaScript('show_flash("setVisible", null, null, "%s");' % is_visible)
- else:
- display.frame.evaluateJavaScript('show_video("setVisible", null, null, null, "%s");' % is_visible)
+ display.frame.evaluateJavaScript('show_video("setVisible", null, null, null, "%s");' % is_visible)
def update_ui(self, display):
"""
Update the UI
+
+ :param display: The display to be updated.
"""
controller = display.controller
- if controller.media_info.is_flash:
- current_time = display.frame.evaluateJavaScript('show_flash("current_time");')
- length = display.frame.evaluateJavaScript('show_flash("length");')
- else:
- if display.frame.evaluateJavaScript('show_video("isEnded");'):
- self.stop(display)
- current_time = display.frame.evaluateJavaScript('show_video("current_time");')
- # check if conversion was ok and value is not 'NaN'
- if current_time and current_time != float('inf'):
- current_time = int(current_time * 1000)
- length = display.frame.evaluateJavaScript('show_video("length");')
- # check if conversion was ok and value is not 'NaN'
- if length and length != float('inf'):
- length = int(length * 1000)
+ if display.frame.evaluateJavaScript('show_video("isEnded");'):
+ self.stop(display)
+ current_time = display.frame.evaluateJavaScript('show_video("current_time");')
+ # check if conversion was ok and value is not 'NaN'
+ if current_time and current_time != float('inf'):
+ current_time = int(current_time * 1000)
+ length = display.frame.evaluateJavaScript('show_video("length");')
+ # check if conversion was ok and value is not 'NaN'
+ if length and length != float('inf'):
+ length = int(length * 1000)
if current_time and length:
controller.media_info.length = length
controller.seek_slider.setMaximum(length)
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/media/lib/mediaitem.py 2016-02-14 17:55:52 +0000
@@ -29,8 +29,8 @@
translate
from openlp.core.lib import ItemCapabilities, MediaManagerItem, MediaType, ServiceItem, ServiceItemContext, \
build_icon, check_item_selected
-from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
-from openlp.core.ui import DisplayController, Display, DisplayControllerType
+from openlp.core.lib.ui import create_widget_action, critical_error_message_box, create_horizontal_adjusting_combo_box
+from openlp.core.ui import DisplayController, DisplayControllerType
from openlp.core.ui.media import get_media_players, set_media_players, parse_optical_path, format_milliseconds
from openlp.core.utils import get_locale_key
from openlp.core.ui.media.vlcplayer import get_vlc
@@ -79,15 +79,6 @@
self.has_search = True
self.media_object = None
self.display_controller = DisplayController(self.parent())
- self.display_controller.controller_layout = QtWidgets.QVBoxLayout()
- self.media_controller.register_controller(self.display_controller)
- self.media_controller.set_controls_visible(self.display_controller, False)
- self.display_controller.preview_display = Display(self.display_controller)
- self.display_controller.preview_display.hide()
- self.display_controller.preview_display.setGeometry(QtCore.QRect(0, 0, 300, 300))
- self.display_controller.preview_display.screen = {'size': self.display_controller.preview_display.geometry()}
- self.display_controller.preview_display.setup()
- self.media_controller.setup_display(self.display_controller.preview_display, False)
Registry().register_function('video_background_replaced', self.video_background_replaced)
Registry().register_function('mediaitem_media_rebuild', self.rebuild_players)
Registry().register_function('config_screen_changed', self.display_setup)
@@ -101,12 +92,17 @@
"""
self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
self.replace_action.setText(UiStrings().ReplaceBG)
+ self.replace_action_context.setText(UiStrings().ReplaceBG)
if 'webkit' in get_media_players()[0]:
self.replace_action.setToolTip(UiStrings().ReplaceLiveBG)
+ self.replace_action_context.setToolTip(UiStrings().ReplaceLiveBG)
else:
self.replace_action.setToolTip(UiStrings().ReplaceLiveBGDisabled)
+ self.replace_action_context.setToolTip(UiStrings().ReplaceLiveBGDisabled)
self.reset_action.setText(UiStrings().ResetBG)
self.reset_action.setToolTip(UiStrings().ResetLiveBG)
+ self.reset_action_context.setText(UiStrings().ResetBG)
+ self.reset_action_context.setToolTip(UiStrings().ResetLiveBG)
self.automatic = UiStrings().Automatic
self.display_type_label.setText(translate('MediaPlugin.MediaItem', 'Use Player:'))
@@ -155,6 +151,7 @@
triggers=self.on_replace_click)
if 'webkit' not in get_media_players()[0]:
self.replace_action.setDisabled(True)
+ self.replace_action_context.setDisabled(True)
self.reset_action = self.toolbar.add_toolbar_action('reset_action', icon=':/system/system_close.png',
visible=False, triggers=self.on_reset_click)
self.media_widget = QtWidgets.QWidget(self)
@@ -173,7 +170,17 @@
self.page_layout.addWidget(self.media_widget)
self.display_type_combo_box.currentIndexChanged.connect(self.override_player_changed)
- def override_player_changed(self, index):
+ def add_custom_context_actions(self):
+ create_widget_action(self.list_view, separator=True)
+ self.replace_action_context = create_widget_action(
+ self.list_view, text=UiStrings().ReplaceBG, icon=':/slides/slide_blank.png',
+ triggers=self.on_replace_click)
+ self.reset_action_context = create_widget_action(
+ self.list_view, text=UiStrings().ReplaceLiveBG, icon=':/system/system_close.png',
+ visible=False, triggers=self.on_reset_click)
+
+ @staticmethod
+ def override_player_changed(index):
"""
The Player has been overridden
@@ -191,12 +198,14 @@
"""
self.media_controller.media_reset(self.live_controller)
self.reset_action.setVisible(False)
+ self.reset_action_context.setVisible(False)
def video_background_replaced(self):
"""
Triggered by main display on change of serviceitem.
"""
self.reset_action.setVisible(False)
+ self.reset_action_context.setVisible(False)
def on_replace_click(self):
"""
@@ -215,6 +224,7 @@
service_item.add_from_command(path, name, CLAPPERBOARD)
if self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True):
self.reset_action.setVisible(True)
+ self.reset_action_context.setVisible(True)
else:
critical_error_message_box(UiStrings().LiveBGError,
translate('MediaPlugin.MediaItem',
@@ -273,10 +283,8 @@
service_item.processor = self.display_type_combo_box.currentText()
service_item.add_from_command(path, name, CLAPPERBOARD)
# Only get start and end times if going to a service
- if context == ServiceItemContext.Service:
- # Start media and obtain the length
- if not self.media_controller.media_length(service_item):
- return False
+ if not self.media_controller.media_length(service_item):
+ return False
service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
service_item.add_capability(ItemCapabilities.CanEditTitle)
service_item.add_capability(ItemCapabilities.RequiresMedia)
=== added directory 'tests/interfaces/openlp_core_ul_media_vendor'
=== added file 'tests/interfaces/openlp_core_ul_media_vendor/__init__.py'
--- tests/interfaces/openlp_core_ul_media_vendor/__init__.py 1970-01-01 00:00:00 +0000
+++ tests/interfaces/openlp_core_ul_media_vendor/__init__.py 2016-02-14 17:55:52 +0000
@@ -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 #
+###############################################################################
=== added file 'tests/interfaces/openlp_core_ul_media_vendor/test_mediainfoWrapper.py'
--- tests/interfaces/openlp_core_ul_media_vendor/test_mediainfoWrapper.py 1970-01-01 00:00:00 +0000
+++ tests/interfaces/openlp_core_ul_media_vendor/test_mediainfoWrapper.py 2016-02-14 17:55:52 +0000
@@ -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])
=== added directory 'tests/resources/media'
=== added file 'tests/resources/media/avi_file.avi'
Binary files tests/resources/media/avi_file.avi 1970-01-01 00:00:00 +0000 and tests/resources/media/avi_file.avi 2016-02-14 17:55:52 +0000 differ
=== added file 'tests/resources/media/mp3_file.mp3'
Binary files tests/resources/media/mp3_file.mp3 1970-01-01 00:00:00 +0000 and tests/resources/media/mp3_file.mp3 2016-02-14 17:55:52 +0000 differ
=== added file 'tests/resources/media/mp4_file.mp4'
Binary files tests/resources/media/mp4_file.mp4 1970-01-01 00:00:00 +0000 and tests/resources/media/mp4_file.mp4 2016-02-14 17:55:52 +0000 differ
=== added file 'tests/resources/media/mpg_file.mpg'
Binary files tests/resources/media/mpg_file.mpg 1970-01-01 00:00:00 +0000 and tests/resources/media/mpg_file.mpg 2016-02-14 17:55:52 +0000 differ
Follow ups