Made it possible to name optical clips, and fixed some issues.

This commit is contained in:
Tomas Groth 2014-06-14 23:48:07 +02:00
parent 06825e4aeb
commit 2a1a93d319
4 changed files with 105 additions and 36 deletions

View File

@ -110,6 +110,7 @@ def set_media_players(players_list, overridden_player='auto'):
players = players.replace(overridden_player, '[%s]' % overridden_player)
Settings().setValue('media/players', players)
def parse_optical_path(input):
"""
Split the optical path info.
@ -123,10 +124,24 @@ def parse_optical_path(input):
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
clip_name = clip_info[6]
filename = clip_info[7]
# Windows path usually contains a colon after the drive letter
if len(clip_info) > 8:
filename += clip_info[8]
return filename, title, audio_track, subtitle_track, start, end, clip_name
def format_milliseconds(milliseconds):
"""
Format milliseconds into a human readable time string.
:param milliseconds: Milliseconds to format
:return: Time string in format: hh.mm.ss,ttt
"""
seconds, millis = divmod(milliseconds, 1000)
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
return "%02d:%02d:%02d,%03d" % (hours, minutes, seconds, millis)
from .mediacontroller import MediaController
from .playertab import PlayerTab

View File

@ -373,7 +373,7 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
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) = parse_optical_path(path)
(name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display,
controller)
else:
@ -392,7 +392,7 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
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) = parse_optical_path(path)
(name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display,
controller)
else:
@ -456,6 +456,19 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties):
return True
def media_setup_optical(self, filename, title, audio_track, subtitle_track, start, end, display, controller):
"""
Setup playback of optical media
:param filename: Path of the optical device/drive.
: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 display: The display to play the media.
:param controller: The media contraoller.
:return: True if setup succeded else False.
"""
log.debug('media_setup_optical')
if controller is None:
controller = self.display_controllers[DisplayControllerType.Plugin]

View File

@ -43,6 +43,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.common import translate
from openlp.plugins.media.forms.mediaclipselectordialog import Ui_MediaClipSelector
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media import format_milliseconds
try:
from openlp.core.ui.media.vendor import vlc
except (ImportError, NameError, NotImplementedError):
@ -156,7 +157,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def detect_audio_cd(self, path):
"""
Detects is the given path is an audio CD
:param path: Path to the device to be tested.
:return: True if it was an audio CD else False.
"""
@ -166,7 +167,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.vlc_media_player.play()
# Wait for media to start playing. In this case VLC actually returns an error.
self.media_state_wait(vlc.State.Playing)
self.vlc_media_player.pause()
self.vlc_media_player.set_pause(1)
# If subitems exists, this is a CD
self.audio_cd_tracks = self.vlc_media.subitems()
if not self.audio_cd_tracks or self.audio_cd_tracks.count() < 1:
@ -231,7 +232,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
'VLC player failed playing the media'))
self.toggle_disable_load_media(False)
return
self.vlc_media_player.pause()
self.vlc_media_player.set_pause(1)
self.vlc_media_player.set_time(0)
if not self.audio_cd:
# Get titles, insert in combobox
@ -247,6 +248,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
# Enable audio track combobox if anything is in it
if len(titles) > 0:
self.title_combo_box.setDisabled(False)
self.vlc_media_player.set_pause(1)
self.toggle_disable_load_media(False)
@QtCore.pyqtSlot(bool)
@ -367,7 +369,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
if not self.media_state_wait(vlc.State.Playing):
return
# pause
self.vlc_media_player.pause()
self.vlc_media_player.set_pause(1)
self.vlc_media_player.set_time(0)
self.vlc_media_player.audio_set_mute(False)
self.toggle_disable_player(False)
@ -379,7 +381,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
if not self.media_state_wait(vlc.State.Playing):
return
# pause
self.vlc_media_player.pause()
self.vlc_media_player.set_pause(1)
self.vlc_media_player.set_time(0)
# Get audio tracks, insert in combobox
audio_tracks = self.vlc_media_player.audio_get_track_description()
@ -520,12 +522,38 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
path = self.media_path_combobox.currentText()
optical = ''
if self.audio_cd:
optical = 'optical:' + str(title) + ':-1:-1:' + str(start_time_ms) + ':' + str(end_time_ms) + ':' + path
optical = 'optical:' + str(title) + ':-1:-1:' + str(start_time_ms) + ':' + str(end_time_ms) + ':'
else:
audio_track = self.audio_tracks_combobox.itemData(self.audio_tracks_combobox.currentIndex())
subtitle_track = self.subtitle_tracks_combobox.itemData(self.subtitle_tracks_combobox.currentIndex())
optical = 'optical:' + str(title) + ':' + str(audio_track) + ':' + str(subtitle_track) + ':' + str(
start_time_ms) + ':' + str(end_time_ms) + ':' + path
start_time_ms) + ':' + str(end_time_ms) + ':'
# Ask for an alternative name for the mediaclip
while True:
new_optical_name, ok = QtGui.QInputDialog.getText(self, translate('MediaPlugin.MediaClipSelectorForm',
'Set name of mediaclip'),
translate('MediaPlugin.MediaClipSelectorForm',
'Name of mediaclip:'),
QtGui.QLineEdit.Normal)
# User pressed cancel, don't save the clip
if not ok:
return
# User pressed ok, but the input text is blank
if not new_optical_name:
critical_error_message_box(translate('MediaPlugin.MediaClipSelectorForm',
'Enter a valid name or cancel'),
translate('MediaPlugin.MediaClipSelectorForm',
'Enter a valid name or cancel'))
# The entered new name contains a colon, which we don't allow because colons is used to seperate clip info
elif new_optical_name.find(':') >= 0:
critical_error_message_box(translate('MediaPlugin.MediaClipSelectorForm', 'Invalid character'),
translate('MediaPlugin.MediaClipSelectorForm',
'The name of the mediaclip must not contain the character ":"'))
# New name entered and we use it
else:
break
# Append the new name to the optical string and the path
optical += new_optical_name + ':' + path
self.media_item.add_optical_clip(optical)
def media_state_wait(self, media_state):
@ -585,7 +613,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
log.debug('could not use udisks, will try udisks2')
udev_manager_obj = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2')
udev_manager = dbus.Interface(udev_manager_obj, 'org.freedesktop.DBus.ObjectManager')
for k,v in udev_manager.GetManagedObjects().items():
for k, v in udev_manager.GetManagedObjects().items():
drive_info = v.get('org.freedesktop.UDisks2.Drive', {})
drive_props = drive_info.get('MediaCompatibility')
if drive_props and any('optical' in prop for prop in drive_props):
@ -593,7 +621,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
if dbus.String('org.freedesktop.UDisks2.Block') in device:
if device[dbus.String('org.freedesktop.UDisks2.Block')][dbus.String('Drive')] == k:
block_file = ''
for c in device[dbus.String('org.freedesktop.UDisks2.Block')][dbus.String('PreferredDevice')]:
for c in device[dbus.String('org.freedesktop.UDisks2.Block')][
dbus.String('PreferredDevice')]:
if chr(c) != '\x00':
block_file += chr(c)
self.media_path_combobox.addItem(block_file)
@ -605,5 +634,12 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
if volume.startswith('.'):
continue
dirs = os.listdir('/Volumes/' + volume)
# Detect DVD
if 'VIDEO_TS' in dirs:
self.media_path_combobox.addItem('/Volumes/' + volume)
# Detect audio cd
files = [f for f in dirs if os.path.isfile(f)]
for file in files:
if file.endswith('aiff'):
self.media_path_combobox.addItem('/Volumes/' + volume)
break

View File

@ -39,7 +39,7 @@ from openlp.core.lib import ItemCapabilities, MediaManagerItem, MediaType, Servi
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.ui.media import get_media_players, set_media_players, parse_optical_path
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 VLC_AVAILABLE
if VLC_AVAILABLE:
@ -125,9 +125,20 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
"""
Adds buttons to the start of the header bar.
"""
self.load_optical = self.toolbar.add_toolbar_action('load_optical', icon=OPTICAL_ICON, text='Load CD/DVD',
tooltip='Load CD/DVD', triggers=self.on_load_optical)
if not VLC_AVAILABLE:
print(get_media_players()[0])
if 'vlc' in get_media_players()[0]:
diable_optical_button_text = False
optical_button_text = translate('MediaPlugin.MediaItem', 'Load CD/DVD')
optical_button_tooltip = translate('MediaPlugin.MediaItem', 'Load CD/DVD')
else:
diable_optical_button_text = True
optical_button_text = translate('MediaPlugin.MediaItem', 'Load CD/DVD')
optical_button_tooltip = translate('MediaPlugin.MediaItem',
'Load CD/DVD - only supported when VLC is installed and enabled')
self.load_optical = self.toolbar.add_toolbar_action('load_optical', icon=OPTICAL_ICON, text=optical_button_text,
tooltip=optical_button_tooltip,
triggers=self.on_load_optical)
if diable_optical_button_text:
self.load_optical.setDisabled(True)
def add_end_header_bar(self):
@ -224,7 +235,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
filename = item.data(QtCore.Qt.UserRole)
# Special handling if the filename is a optical clip
if filename.startswith('optical:'):
(name, title, audio_track, subtitle_track, start, end) = parse_optical_path(filename)
(name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(filename)
if not os.path.exists(name):
if not remote:
# Optical disc is no longer present
@ -234,7 +245,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
return False
service_item.processor = self.display_type_combo_box.currentText()
service_item.add_from_command(filename, name, CLAPPERBOARD)
service_item.title = name + '@' + self.format_milliseconds(start) + '-' + self.format_milliseconds(end)
service_item.title = clip_name
# Only set start and end times if going to a service
#if context == ServiceItemContext.Service:
# Set the length
@ -345,12 +356,11 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
track_info = QtCore.QFileInfo(track)
if track.startswith('optical:'):
# Handle optical based item
(file_name, title, audio_track, subtitle_track, start, end) = parse_optical_path(track)
optical = file_name + '@' + self.format_milliseconds(start) + '-' + self.format_milliseconds(end)
item_name = QtGui.QListWidgetItem(optical)
(file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track)
item_name = QtGui.QListWidgetItem(clip_name)
item_name.setIcon(OPTICAL_ICON)
item_name.setData(QtCore.Qt.UserRole, track)
item_name.setToolTip(optical)
item_name.setToolTip(file_name + '@' + format_milliseconds(start) + '-' + format_milliseconds(end))
elif not os.path.exists(track):
# File doesn't exist, mark as error.
file_name = os.path.split(str(track))[1]
@ -417,17 +427,12 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
:param optical: The clip to add.
"""
full_list = self.get_file_list()
# If the clip already is in the media list it isn't added and an error message is displayed.
if optical in full_list:
critical_error_message_box(translate('MediaPlugin.MediaItem', 'Mediaclip already saved'),
translate('MediaPlugin.MediaItem', 'This mediaclip has already been saved'))
return
# Append the optical string to the media list
full_list.append(optical)
self.load_list([optical])
Settings().setValue(self.settings_section + '/media files', self.get_file_list())
def format_milliseconds(self, milliseconds):
"""
Format milliseconds into a human readable time string.
:param milliseconds: Milliseconds to format
:return: Time string in format: hh.mm.ss,ttt
"""
seconds, millis = divmod(milliseconds, 1000)
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
return "%02d:%02d:%02d,%03d" % (hours, minutes, seconds, millis)