Implemented DVD clip selection and playback, still needs a lot of cleanups.

This commit is contained in:
Tomas Groth 2014-03-04 22:33:50 +00:00
parent 6d21a326ed
commit 67acb9d824
6 changed files with 181 additions and 43 deletions

View File

@ -108,6 +108,8 @@ class ItemCapabilities(object):
``CanAutoStartForLive``
The capability to ignore the do not play if display blank flag.
``IsOptical``
.Determines is the service_item is based on an optical device
"""
CanPreview = 1
CanEdit = 2
@ -125,6 +127,7 @@ class ItemCapabilities(object):
CanWordSplit = 14
HasBackgroundAudio = 15
CanAutoStartForLive = 16
IsOptical = 17
class ServiceItem(object):
@ -573,7 +576,7 @@ class ServiceItem(object):
frame = self._raw_frames[row]
except IndexError:
return ''
if self.is_image():
if self.is_image() or self.is_capable(ItemCapabilities.IsOptical):
path_from = frame['path']
else:
path_from = os.path.join(frame['path'], frame['title'])

View File

@ -72,6 +72,9 @@ class MediaInfo(object):
length = 0
start_time = 0
end_time = 0
title_track = 0
audio_track = 0
subtitle_track = 0
media_type = MediaType()

View File

@ -36,7 +36,7 @@ import datetime
from PyQt4 import QtCore, QtGui
from openlp.core.common import Registry, Settings, UiStrings, translate
from openlp.core.lib import OpenLPToolbar
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
from openlp.core.ui.media.mediaplayer import MediaPlayer
@ -387,7 +387,15 @@ class MediaController(object):
controller.media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path())
display = self._define_display(controller)
if controller.is_live:
is_valid = self._check_file_type(controller, display, service_item)
# if this is an optical device use special handling
if service_item.is_capable(ItemCapabilities.IsOptical):
log.debug('video is optical and live')
path = service_item.get_frame_path()
(name, title, audio_track, subtitle_track, start, end) = self.parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller)
else :
log.debug('video is not optical and live')
is_valid = self._check_file_type(controller, display, service_item)
display.override['theme'] = ''
display.override['video'] = True
if controller.media_info.is_background:
@ -398,12 +406,20 @@ class MediaController(object):
controller.media_info.start_time = service_item.start_time
controller.media_info.end_time = service_item.end_time
elif controller.preview_display:
is_valid = self._check_file_type(controller, display, service_item)
if service_item.is_capable(ItemCapabilities.IsOptical):
log.debug('video is optical and preview')
path = service_item.get_frame_path()
(name, title, audio_track, subtitle_track, start, end) = self.parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller)
else :
log.debug('video is not optical and preview')
is_valid = self._check_file_type(controller, display, service_item)
if not is_valid:
# Media could not be loaded correctly
critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
translate('MediaPlugin.MediaItem', 'Unsupported File'))
return False
log.debug('video mediatype: ' +str(controller.media_info.media_type))
# dont care about actual theme, set a black background
if controller.is_live and not controller.media_info.is_background:
display.frame.evaluateJavaScript('show_video( "setBackBoard", null, null, null,"visible");')
@ -456,6 +472,44 @@ class MediaController(object):
log.debug('use %s controller' % self.current_media_players[controller.controller_type])
return True
def media_setup_optical(self, filename, title, audio_track, subtitle_track, start, end, display, controller):
log.debug('media_setup_optical')
if controller is None:
controller = self.display_controllers[DisplayControllerType.Plugin]
# stop running videos
self.media_reset(controller)
# Setup media info
controller.media_info = MediaInfo()
#controller.media_info.volume = 0
controller.media_info.file_info = QtCore.QFileInfo(filename)
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.title_track = title
controller.media_info.audio_track = audio_track
controller.media_info.subtitle_track = subtitle_track
# When called from mediaitem display is None
if display is None:
display = controller.preview_display
# Find vlc player
used_players = get_media_players()[0]
vlc_player = None
for title in used_players:
player = self.media_players[title]
if player.name == 'vlc':
vlc_player = player
if vlc_player is None:
critical_error_message_box(translate('MediaPlugin.MediaItem', 'VLC player required'),
translate('MediaPlugin.MediaItem', 'VLC player required for playback of optical devices'))
return False
vlc_player.load(display)
self.resize(display, vlc_player)
self.current_media_players[controller.controller_type] = vlc_player
controller.media_info.media_type = MediaType.DVD
return True
def _check_file_type(self, controller, display, service_item):
"""
Select the correct media Player type from the prioritized Player list
@ -758,3 +812,17 @@ class MediaController(object):
return self._live_controller
live_controller = property(_get_live_controller)
@staticmethod
def parse_optical_path(input):
# split the clip info
clip_info = input.split(sep=':')
title = int(clip_info[1])
audio_track = int(clip_info[2])
subtitle_track = int(clip_info[3])
start = float(clip_info[4])
end = float(clip_info[5])
filename = clip_info[6]
if len(clip_info) > 7:
filename += clip_info[7]
return filename, title, audio_track, subtitle_track, start, end

View File

@ -39,7 +39,7 @@ from PyQt4 import QtGui
from openlp.core.common import Settings
from openlp.core.lib import translate
from openlp.core.ui.media import MediaState
from openlp.core.ui.media import MediaState, MediaType
from openlp.core.ui.media.mediaplayer import MediaPlayer
log = logging.getLogger(__name__)
@ -205,14 +205,35 @@ class VlcPlayer(MediaPlayer):
"""
controller = display.controller
start_time = 0
if self.state != MediaState.Paused and controller.media_info.start_time > 0:
start_time = controller.media_info.start_time
log.debug('vlc play')
display.vlcMediaPlayer.play()
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')
start_time = controller.media_info.start_time
log.debug('mediatype: ' +str(controller.media_info.media_type))
# Set tracks for the optical device
if controller.media_info.media_type == MediaType.DVD:
log.debug('vlc play, playing started')
if controller.media_info.title_track > 0:
log.debug('vlc play, title_track set: ' + str(controller.media_info.title_track))
display.vlcMediaPlayer.set_title(controller.media_info.title_track)
display.vlcMediaPlayer.play()
if not self.media_state_wait(display, vlc.State.Playing):
return False
if controller.media_info.audio_track > 0:
display.vlcMediaPlayer.audio_set_track(controller.media_info.audio_track)
log.debug('vlc play, audio_track set: ' + str(controller.media_info.audio_track))
if controller.media_info.subtitle_track > 0:
display.vlcMediaPlayer.video_set_spu(controller.media_info.subtitle_track)
log.debug('vlc play, subtitle_track set: ' + str(controller.media_info.subtitle_track))
if controller.media_info.start_time > 0:
log.debug('vlc play, starttime set: ' + str(controller.media_info.start_time))
start_time = controller.media_info.start_time
self.volume(display, controller.media_info.volume)
if start_time > 0:
self.seek(display, controller.media_info.start_time * 1000)
self.seek(display, int(start_time * 1000))
controller.media_info.length = int(display.vlcMediaPlayer.get_media().get_duration() / 1000)
controller.seek_slider.setMaximum(controller.media_info.length * 1000)
self.state = MediaState.Playing
@ -248,6 +269,7 @@ class VlcPlayer(MediaPlayer):
Go to a particular position
"""
if display.vlcMediaPlayer.is_seekable():
log.debug('vlc seek to: ' + str(seek_value))
display.vlcMediaPlayer.set_time(seek_value)
def reset(self, display):

View File

@ -31,6 +31,8 @@ import os
import sys
import logging
import time
from datetime import datetime
from PyQt4 import QtCore, QtGui
@ -132,12 +134,14 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.toggle_disable_load_media(False)
return
self.vlc_media_player.audio_set_mute(True)
while self.vlc_media_player.get_time() == 0:
if self.vlc_media_player.get_state() == vlc.State.Error:
log.debug('player in error state')
self.toggle_disable_load_media(False)
return
time.sleep(0.1)
#while self.vlc_media_player.get_time() == 0:
# if self.vlc_media_player.get_state() == vlc.State.Error:
# log.debug('player in error state')
# self.toggle_disable_load_media(False)
# return
# time.sleep(0.1)
if not self.media_state_wait(vlc.State.Playing):
return
self.vlc_media_player.pause()
self.vlc_media_player.set_time(0)
# Get titles, insert in combobox
@ -223,11 +227,13 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.vlc_media_player.set_time(0)
self.vlc_media_player.play()
self.vlc_media_player.audio_set_mute(True)
while self.vlc_media_player.get_time() == 0:
if self.vlc_media_player.get_state() == vlc.State.Error:
log.debug('player in error state')
return
time.sleep(0.1)
#while self.vlc_media_player.get_time() == 0:
# if self.vlc_media_player.get_state() == vlc.State.Error:
# log.debug('player in error state')
# return
# time.sleep(0.1)
if not self.media_state_wait(vlc.State.Playing):
return
# pause
self.vlc_media_player.pause()
self.vlc_media_player.set_time(0)
@ -358,3 +364,16 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
path = self.media_path_combobox.currentText()
optical = 'optical:' + str(title) + ':' + str(audio_track) + ':' + str(subtitle_track) + ':' + str(start_time_ms) + ':' + str(end_time_ms) + ':' + path
self.media_item.add_optical_clip(optical)
def media_state_wait(self, media_state):
"""
Wait for the video to change its state
Wait no longer than 15 seconds. (loading an iso file needs a long time)
"""
start = datetime.now()
while not media_state == self.vlc_media.get_state():
if self.vlc_media.get_state() == vlc.State.Error:
return False
if (datetime.now() - start).seconds > 15:
return False
return True

View File

@ -33,7 +33,7 @@ import os
from PyQt4 import QtCore, QtGui
from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, UiStrings, translate
from openlp.core.lib import ItemCapabilities, MediaManagerItem,MediaType, ServiceItem, ServiceItemContext, \
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
@ -43,7 +43,6 @@ from openlp.plugins.media.forms.mediaclipselectorform import MediaClipSelectorFo
from openlp.core.ui.media.vlcplayer import VLC_AVAILABLE
log = logging.getLogger(__name__)
@ -193,22 +192,45 @@ class MediaMediaItem(MediaManagerItem):
if item is None:
return False
filename = item.data(QtCore.Qt.UserRole)
if not os.path.exists(filename):
if not remote:
# File is no longer present
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Missing Media File'),
translate('MediaPlugin.MediaItem', 'The file %s no longer exists.') % filename)
return False
(path, name) = os.path.split(filename)
service_item.title = name
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):
log.debug('generate_slide_data, filename: ' + filename)
if filename.startswith('optical:'):
(name, title, audio_track, subtitle_track, start, end) = self.parse_optical_path(filename)
log.debug('generate_slide_data, optical name: ' + name)
if not os.path.exists(name):
if not remote:
# Optical disc is no longer present
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Missing Media File'),
translate('MediaPlugin.MediaItem', 'The optical disc %s is no longer available.') % name)
return False
service_item.title = name
service_item.processor = self.display_type_combo_box.currentText()
service_item.add_from_command(filename, name, OPTICAL_ICON)
# Only set start and end times if going to a service
#if context == ServiceItemContext.Service:
# Set the length
self.media_controller.media_setup_optical(name, title, audio_track, subtitle_track, start, end, None, None)
service_item.set_media_length((end - start)/1000)
service_item.start_time = start/1000
service_item.end_time = end/1000
service_item.add_capability(ItemCapabilities.IsOptical)
else:
if not os.path.exists(filename):
if not remote:
# File is no longer present
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Missing Media File'),
translate('MediaPlugin.MediaItem', 'The file %s no longer exists.') % filename)
return False
(path, name) = os.path.split(filename)
service_item.title = name
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
service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
service_item.add_capability(ItemCapabilities.RequiresMedia)
if Settings().value(self.settings_section + '/media auto start') == QtCore.Qt.Checked:
@ -329,7 +351,14 @@ class MediaMediaItem(MediaManagerItem):
log.debug('in on_load_optical')
self.media_clip_selector_form.exec_()
def parse_optical_path(self, input):
def add_optical_clip(self, optical):
full_list = self.get_file_list()
full_list.append(optical)
self.load_list([optical])
Settings().setValue(self.settings_section + '/media files', self.get_file_list())
@staticmethod
def parse_optical_path(input):
# split the clip info
clip_info = input.split(sep=':')
title = int(clip_info[1])
@ -341,9 +370,3 @@ class MediaMediaItem(MediaManagerItem):
if len(clip_info) > 7:
filename += clip_info[7]
return filename, title, audio_track, subtitle_track, start, end
def add_optical_clip(self, optical):
full_list = self.get_file_list()
full_list.append(optical)
self.load_list([optical])
Settings().setValue(self.settings_section + '/media files', self.get_file_list())