Made it possible to save and load optical clip to servicefile. Also some pep8 and general cleanup.

This commit is contained in:
Tomas Groth 2014-03-08 21:14:04 +00:00
parent e6f23324ba
commit 3988aacfbd
5 changed files with 167 additions and 82 deletions

View File

@ -435,7 +435,10 @@ class ServiceItem(object):
for text_image in serviceitem['serviceitem']['data']: for text_image in serviceitem['serviceitem']['data']:
if not self.title: if not self.title:
self.title = text_image['title'] self.title = text_image['title']
if path: if self.is_capable(ItemCapabilities.IsOptical):
self.has_original_files = False
self.add_from_command(text_image['path'], text_image['title'], text_image['image'])
elif path:
self.has_original_files = False self.has_original_files = False
self.add_from_command(path, text_image['title'], text_image['image']) self.add_from_command(path, text_image['title'], text_image['image'])
else: else:
@ -446,7 +449,7 @@ class ServiceItem(object):
""" """
Returns the title of the service item. Returns the title of the service item.
""" """
if self.is_text(): if self.is_text() or self.is_capable(ItemCapabilities.IsOptical):
return self.title return self.title
else: else:
if len(self._raw_frames) > 1: if len(self._raw_frames) > 1:
@ -516,7 +519,8 @@ class ServiceItem(object):
""" """
Confirms if the ServiceItem uses a file Confirms if the ServiceItem uses a file
""" """
return self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command return self.service_item_type == ServiceItemType.Image or \
(self.service_item_type == ServiceItemType.Command and not self.is_capable(ItemCapabilities.IsOptical))
def is_text(self): def is_text(self):
""" """
@ -646,15 +650,20 @@ class ServiceItem(object):
self.is_valid = False self.is_valid = False
break break
elif self.is_command(): elif self.is_command():
file_name = os.path.join(frame['path'], frame['title']) if self.is_capable(ItemCapabilities.IsOptical):
if not os.path.exists(file_name): if not os.path.exists(frame['title']):
self.is_valid = False
break
if suffix_list and not self.is_text():
file_suffix = frame['title'].split('.')[-1]
if file_suffix.lower() not in suffix_list:
self.is_valid = False self.is_valid = False
break break
else:
file_name = os.path.join(frame['path'], frame['title'])
if not os.path.exists(file_name):
self.is_valid = False
break
if suffix_list and not self.is_text():
file_suffix = frame['title'].split('.')[-1]
if file_suffix.lower() not in suffix_list:
self.is_valid = False
break
def _get_renderer(self): def _get_renderer(self):
""" """

View File

@ -102,11 +102,8 @@ def set_media_players(players_list, overridden_player='auto'):
This method saves the configured media players and overridden player to the This method saves the configured media players and overridden player to the
settings settings
``players_list`` :param players_list: A list with all active media players.
A list with all active media players. :param overridden_player: Here an special media player is chosen for all media actions.
``overridden_player``
Here an special media player is chosen for all media actions.
""" """
log.debug('set_media_players') log.debug('set_media_players')
players = ','.join(players_list) players = ','.join(players_list)
@ -114,6 +111,24 @@ def set_media_players(players_list, overridden_player='auto'):
players = players.replace(overridden_player, '[%s]' % overridden_player) players = players.replace(overridden_player, '[%s]' % overridden_player)
Settings().setValue('media/players', players) Settings().setValue('media/players', players)
def parse_optical_path(input):
"""
Split the optical path info.
:param input: The string to parse
:return: The elements extracted from the string: filename, title, audio_track, subtitle_track, start, end
"""
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
from .mediacontroller import MediaController from .mediacontroller import MediaController
from .playertab import PlayerTab from .playertab import PlayerTab

View File

@ -38,7 +38,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.common import Registry, RegistryMixin, Settings, UiStrings, translate from openlp.core.common import Registry, RegistryMixin, Settings, UiStrings, translate
from openlp.core.lib import OpenLPToolbar, ItemCapabilities from openlp.core.lib import OpenLPToolbar, ItemCapabilities
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players, parse_optical_path
from openlp.core.ui.media.mediaplayer import MediaPlayer from openlp.core.ui.media.mediaplayer import MediaPlayer
from openlp.core.common import AppLocation from openlp.core.common import AppLocation
from openlp.core.ui import DisplayControllerType from openlp.core.ui import DisplayControllerType
@ -397,7 +397,7 @@ class MediaController(object):
if service_item.is_capable(ItemCapabilities.IsOptical): if service_item.is_capable(ItemCapabilities.IsOptical):
log.debug('video is optical and live') log.debug('video is optical and live')
path = service_item.get_frame_path() path = service_item.get_frame_path()
(name, title, audio_track, subtitle_track, start, end) = self.parse_optical_path(path) (name, title, audio_track, subtitle_track, start, end) = parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller)
else : else :
log.debug('video is not optical and live') log.debug('video is not optical and live')
@ -415,7 +415,7 @@ class MediaController(object):
if service_item.is_capable(ItemCapabilities.IsOptical): if service_item.is_capable(ItemCapabilities.IsOptical):
log.debug('video is optical and preview') log.debug('video is optical and preview')
path = service_item.get_frame_path() path = service_item.get_frame_path()
(name, title, audio_track, subtitle_track, start, end) = self.parse_optical_path(path) (name, title, audio_track, subtitle_track, start, end) = parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller)
else : else :
log.debug('video is not optical and preview') log.debug('video is not optical and preview')
@ -819,16 +819,3 @@ class MediaController(object):
live_controller = property(_get_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

@ -67,7 +67,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
""" """
Exit Dialog and do not save Exit Dialog and do not save
""" """
log.debug ('MediaClipSelectorForm.reject') log.debug('MediaClipSelectorForm.reject')
self.vlc_media_player.stop() self.vlc_media_player.stop()
QtGui.QDialog.reject(self) QtGui.QDialog.reject(self)
@ -110,6 +110,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_load_disc_pushbutton_clicked(self, clicked): def on_load_disc_pushbutton_clicked(self, clicked):
""" """
Load the media when the load-button has been clicked Load the media when the load-button has been clicked
:param clicked: Given from signal, not used.
""" """
self.disable_all() self.disable_all()
path = self.media_path_combobox.currentText() path = self.media_path_combobox.currentText()
@ -134,12 +136,6 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.toggle_disable_load_media(False) self.toggle_disable_load_media(False)
return return
self.vlc_media_player.audio_set_mute(True) 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)
if not self.media_state_wait(vlc.State.Playing): if not self.media_state_wait(vlc.State.Playing):
return return
self.vlc_media_player.pause() self.vlc_media_player.pause()
@ -163,6 +159,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_pause_pushbutton_clicked(self, clicked): def on_pause_pushbutton_clicked(self, clicked):
""" """
Pause the playback Pause the playback
:param clicked: Given from signal, not used.
""" """
self.vlc_media_player.pause() self.vlc_media_player.pause()
@ -170,6 +168,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_play_pushbutton_clicked(self, clicked): def on_play_pushbutton_clicked(self, clicked):
""" """
Start the playback Start the playback
:param clicked: Given from signal, not used.
""" """
self.vlc_media_player.play() self.vlc_media_player.play()
@ -177,26 +177,40 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_set_start_pushbutton_clicked(self, clicked): def on_set_start_pushbutton_clicked(self, clicked):
""" """
Copy the current player position to start_timeedit Copy the current player position to start_timeedit
:param clicked: Given from signal, not used.
""" """
vlc_ms_pos = self.vlc_media_player.get_time() vlc_ms_pos = self.vlc_media_player.get_time()
time = QtCore.QTime() time = QtCore.QTime()
new_pos_time = time.addMSecs(vlc_ms_pos) new_pos_time = time.addMSecs(vlc_ms_pos)
self.start_timeedit.setTime(new_pos_time) self.start_timeedit.setTime(new_pos_time)
# If start time is after end time, update end time.
end_time = self.end_timeedit.time()
if end_time < new_pos_time:
self.end_timeedit.setTime(new_pos_time)
@QtCore.pyqtSlot(bool) @QtCore.pyqtSlot(bool)
def on_set_end_pushbutton_clicked(self, clicked): def on_set_end_pushbutton_clicked(self, clicked):
""" """
Copy the current player position to end_timeedit Copy the current player position to end_timeedit
:param clicked: Given from signal, not used.
""" """
vlc_ms_pos = self.vlc_media_player.get_time() vlc_ms_pos = self.vlc_media_player.get_time()
time = QtCore.QTime() time = QtCore.QTime()
new_pos_time = time.addMSecs(vlc_ms_pos) new_pos_time = time.addMSecs(vlc_ms_pos)
self.end_timeedit.setTime(new_pos_time) self.end_timeedit.setTime(new_pos_time)
# If start time is after end time, update end time.
start_time = self.start_timeedit.time()
if start_time > new_pos_time:
self.start_timeedit.setTime(new_pos_time)
@QtCore.pyqtSlot(bool) @QtCore.pyqtSlot(bool)
def on_jump_end_pushbutton_clicked(self, clicked): def on_jump_end_pushbutton_clicked(self, clicked):
""" """
Set the player position to the position stored in end_timeedit Set the player position to the position stored in end_timeedit
:param clicked: Given from signal, not used.
""" """
end_time = self.end_timeedit.time() end_time = self.end_timeedit.time()
end_time_ms = end_time.hour() * 60 * 60 * 1000 + \ end_time_ms = end_time.hour() * 60 * 60 * 1000 + \
@ -209,6 +223,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_jump_start_pushbutton_clicked(self, clicked): def on_jump_start_pushbutton_clicked(self, clicked):
""" """
Set the player position to the position stored in start_timeedit Set the player position to the position stored in start_timeedit
:param clicked: Given from signal, not used.
""" """
start_time = self.start_timeedit.time() start_time = self.start_timeedit.time()
start_time_ms = start_time.hour() * 60 * 60 * 1000 + \ start_time_ms = start_time.hour() * 60 * 60 * 1000 + \
@ -221,17 +237,14 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_title_combo_box_currentIndexChanged(self, index): def on_title_combo_box_currentIndexChanged(self, index):
""" """
When a new title is chosen, it is loaded by VLC and info about audio and subtitle tracks is reloaded When a new title is chosen, it is loaded by VLC and info about audio and subtitle tracks is reloaded
:param index: The index of the newly chosen title track.
""" """
log.debug('in on_title_combo_box_changed, index: ', str(index)) log.debug('in on_title_combo_box_changed, index: ', str(index))
self.vlc_media_player.set_title(index) self.vlc_media_player.set_title(index)
self.vlc_media_player.set_time(0) self.vlc_media_player.set_time(0)
self.vlc_media_player.play() self.vlc_media_player.play()
self.vlc_media_player.audio_set_mute(True) 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)
if not self.media_state_wait(vlc.State.Playing): if not self.media_state_wait(vlc.State.Playing):
return return
# pause # pause
@ -241,7 +254,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
audio_tracks = self.vlc_media_player.audio_get_track_description() audio_tracks = self.vlc_media_player.audio_get_track_description()
self.audio_tracks_combobox.clear() self.audio_tracks_combobox.clear()
for audio_track in audio_tracks: for audio_track in audio_tracks:
self.audio_tracks_combobox.addItem(audio_track[1].decode(),audio_track[0]) self.audio_tracks_combobox.addItem(audio_track[1].decode(), audio_track[0])
# Enable audio track combobox if anything is in it # Enable audio track combobox if anything is in it
if len(audio_tracks) > 0: if len(audio_tracks) > 0:
self.audio_tracks_combobox.setDisabled(False) self.audio_tracks_combobox.setDisabled(False)
@ -270,6 +283,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_audio_tracks_combobox_currentIndexChanged(self, index): def on_audio_tracks_combobox_currentIndexChanged(self, index):
""" """
When a new audio track is chosen update audio track bing played by VLC When a new audio track is chosen update audio track bing played by VLC
:param index: The index of the newly chosen audio track.
""" """
audio_track = self.audio_tracks_combobox.itemData(index) audio_track = self.audio_tracks_combobox.itemData(index)
log.debug('in on_audio_tracks_combobox_currentIndexChanged, index: ', str(index), ' audio_track: ', audio_track) log.debug('in on_audio_tracks_combobox_currentIndexChanged, index: ', str(index), ' audio_track: ', audio_track)
@ -280,15 +295,18 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
def on_subtitle_tracks_combobox_currentIndexChanged(self, index): def on_subtitle_tracks_combobox_currentIndexChanged(self, index):
""" """
When a new subtitle track is chosen update subtitle track bing played by VLC When a new subtitle track is chosen update subtitle track bing played by VLC
:param index: The index of the newly chosen subtitle.
""" """
subtitle_track = self.subtitle_tracks_combobox.itemData(index) subtitle_track = self.subtitle_tracks_combobox.itemData(index)
log.debug('in on_subtitle_tracks_combobox_currentIndexChanged, index: ', str(index), ' subtitle_track: ', subtitle_track)
if subtitle_track: if subtitle_track:
self.vlc_media_player.video_set_spu(int(subtitle_track)) self.vlc_media_player.video_set_spu(int(subtitle_track))
def on_position_horizontalslider_sliderMoved(self, position): def on_position_horizontalslider_sliderMoved(self, position):
""" """
Set player position according to new slider position. Set player position according to new slider position.
:param position: Position to seek to.
""" """
self.vlc_media_player.set_time(position) self.vlc_media_player.set_time(position)
@ -318,16 +336,16 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
""" """
Enable/disable load media combobox and button. Enable/disable load media combobox and button.
@param action: If True elements are disabled, if False they are enabled. :param action: If True elements are disabled, if False they are enabled.
""" """
self.media_path_combobox.setDisabled(action) self.media_path_combobox.setDisabled(action)
self.load_disc_pushbutton.setDisabled(action) self.load_disc_pushbutton.setDisabled(action)
def toggle_disable_player(self, action): def toggle_disable_player(self, action):
""" """
Enable/disable player elementa. Enable/disable player elements.
@param action: If True elements are disabled, if False they are enabled. :param action: If True elements are disabled, if False they are enabled.
""" """
self.play_pushbutton.setDisabled(action) self.play_pushbutton.setDisabled(action)
self.pause_pushbutton.setDisabled(action) self.pause_pushbutton.setDisabled(action)
@ -343,9 +361,11 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.save_pushbutton.setDisabled(action) self.save_pushbutton.setDisabled(action)
@QtCore.pyqtSlot(bool) @QtCore.pyqtSlot(bool)
def on_save_pushbutton_clicked(self, checked): def on_save_pushbutton_clicked(self, clicked):
""" """
Saves the current media and trackinfo as a clip to the mediamanager Saves the current media and trackinfo as a clip to the mediamanager
:param clicked: Given from signal, not used.
""" """
log.debug('in on_save_pushbutton_clicked') log.debug('in on_save_pushbutton_clicked')
start_time = self.start_timeedit.time() start_time = self.start_timeedit.time()
@ -362,13 +382,17 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
audio_track = self.audio_tracks_combobox.itemData(self.audio_tracks_combobox.currentIndex()) audio_track = self.audio_tracks_combobox.itemData(self.audio_tracks_combobox.currentIndex())
subtitle_track = self.subtitle_tracks_combobox.itemData(self.subtitle_tracks_combobox.currentIndex()) subtitle_track = self.subtitle_tracks_combobox.itemData(self.subtitle_tracks_combobox.currentIndex())
path = self.media_path_combobox.currentText() 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 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) self.media_item.add_optical_clip(optical)
def media_state_wait(self, media_state): def media_state_wait(self, media_state):
""" """
Wait for the video to change its state Wait for the video to change its state
Wait no longer than 15 seconds. (loading an iso file needs a long time) Wait no longer than 15 seconds. (loading an iso file needs a long time)
:param media_state: VLC media state to wait for.
:return: True if state was reached within 15 seconds, False if not or error occurred.
""" """
start = datetime.now() start = datetime.now()
while not media_state == self.vlc_media.get_state(): while not media_state == self.vlc_media.get_state():

View File

@ -29,6 +29,7 @@
import logging import logging
import os import os
from datetime import time
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
@ -37,7 +38,7 @@ from openlp.core.lib import ItemCapabilities, MediaManagerItem, MediaType, Servi
build_icon, check_item_selected build_icon, check_item_selected
from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box 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 import DisplayController, Display, DisplayControllerType
from openlp.core.ui.media import get_media_players, set_media_players from openlp.core.ui.media import get_media_players, set_media_players, parse_optical_path
from openlp.core.utils import get_locale_key from openlp.core.utils import get_locale_key
from openlp.plugins.media.forms.mediaclipselectorform import MediaClipSelectorForm from openlp.plugins.media.forms.mediaclipselectorform import MediaClipSelectorForm
from openlp.core.ui.media.vlcplayer import VLC_AVAILABLE from openlp.core.ui.media.vlcplayer import VLC_AVAILABLE
@ -47,9 +48,10 @@ log = logging.getLogger(__name__)
CLAPPERBOARD = ':/media/slidecontroller_multimedia.png' CLAPPERBOARD = ':/media/slidecontroller_multimedia.png'
OPTICAL = ':/media/media_optical.png'
VIDEO_ICON = build_icon(':/media/media_video.png') VIDEO_ICON = build_icon(':/media/media_video.png')
AUDIO_ICON = build_icon(':/media/media_audio.png') AUDIO_ICON = build_icon(':/media/media_audio.png')
OPTICAL_ICON = build_icon(':/media/media_optical.png') OPTICAL_ICON = build_icon(OPTICAL)
ERROR_ICON = build_icon(':/general/general_delete.png') ERROR_ICON = build_icon(':/general/general_delete.png')
@ -89,6 +91,10 @@ class MediaMediaItem(MediaManagerItem):
self.list_view.activateDnD() self.list_view.activateDnD()
def retranslateUi(self): def retranslateUi(self):
"""
This method is called automatically to provide OpenLP with the opportunity to translate the ``MediaManagerItem``
to another language.
"""
self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media') self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
self.replace_action.setText(UiStrings().ReplaceBG) self.replace_action.setText(UiStrings().ReplaceBG)
self.replace_action.setToolTip(UiStrings().ReplaceLiveBG) self.replace_action.setToolTip(UiStrings().ReplaceLiveBG)
@ -108,16 +114,25 @@ class MediaMediaItem(MediaManagerItem):
self.has_edit_icon = False self.has_edit_icon = False
def add_list_view_to_toolbar(self): def add_list_view_to_toolbar(self):
"""
Creates the main widget for listing items.
"""
MediaManagerItem.add_list_view_to_toolbar(self) MediaManagerItem.add_list_view_to_toolbar(self)
self.list_view.addAction(self.replace_action) self.list_view.addAction(self.replace_action)
def add_start_header_bar(self): def add_start_header_bar(self):
"""
Adds buttons to the start of the header bar.
"""
self.load_optical = self.toolbar.add_toolbar_action('load_optical', icon=OPTICAL_ICON, text='Load optical disc', self.load_optical = self.toolbar.add_toolbar_action('load_optical', icon=OPTICAL_ICON, text='Load optical disc',
tooltip='Load optical disc', triggers=self.on_load_optical) tooltip='Load optical disc', triggers=self.on_load_optical)
if not VLC_AVAILABLE: if not VLC_AVAILABLE:
self.load_optical.setDisabled(True) self.load_optical.setDisabled(True)
def add_end_header_bar(self): def add_end_header_bar(self):
"""
Adds buttons to the end of the header bar.
"""
# Replace backgrounds do not work at present so remove functionality. # Replace backgrounds do not work at present so remove functionality.
self.replace_action = self.toolbar.add_toolbar_action('replace_action', icon=':/slides/slide_blank.png', self.replace_action = self.toolbar.add_toolbar_action('replace_action', icon=':/slides/slide_blank.png',
triggers=self.on_replace_click) triggers=self.on_replace_click)
@ -139,6 +154,11 @@ class MediaMediaItem(MediaManagerItem):
self.display_type_combo_box.currentIndexChanged.connect(self.override_player_changed) self.display_type_combo_box.currentIndexChanged.connect(self.override_player_changed)
def override_player_changed(self, index): def override_player_changed(self, index):
"""
Change to the selected override media player
:param index: Index of the new selected player.
"""
player = get_media_players()[0] player = get_media_players()[0]
if index == 0: if index == 0:
set_media_players(player) set_media_players(player)
@ -163,7 +183,7 @@ class MediaMediaItem(MediaManagerItem):
Called to replace Live background with the media selected. Called to replace Live background with the media selected.
""" """
if check_item_selected(self.list_view, if check_item_selected(self.list_view,
translate('MediaPlugin.MediaItem', translate('MediaPlugin.MediaItem',
'You must select a media file to replace the background with.')): 'You must select a media file to replace the background with.')):
item = self.list_view.currentItem() item = self.list_view.currentItem()
filename = item.data(QtCore.Qt.UserRole) filename = item.data(QtCore.Qt.UserRole)
@ -172,12 +192,12 @@ class MediaMediaItem(MediaManagerItem):
service_item.title = 'webkit' service_item.title = 'webkit'
service_item.processor = 'webkit' service_item.processor = 'webkit'
(path, name) = os.path.split(filename) (path, name) = os.path.split(filename)
service_item.add_from_command(path, name,CLAPPERBOARD) service_item.add_from_command(path, name, CLAPPERBOARD)
if self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True): if self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True):
self.reset_action.setVisible(True) self.reset_action.setVisible(True)
else: else:
critical_error_message_box(UiStrings().LiveBGError, critical_error_message_box(UiStrings().LiveBGError,
translate('MediaPlugin.MediaItem', translate('MediaPlugin.MediaItem',
'There was no display item to amend.')) 'There was no display item to amend.'))
else: else:
critical_error_message_box(UiStrings().LiveBGError, critical_error_message_box(UiStrings().LiveBGError,
@ -195,10 +215,9 @@ class MediaMediaItem(MediaManagerItem):
if item is None: if item is None:
return False return False
filename = item.data(QtCore.Qt.UserRole) filename = item.data(QtCore.Qt.UserRole)
log.debug('generate_slide_data, filename: ' + filename) # Special handling if the filename is a optical clip
if filename.startswith('optical:'): if filename.startswith('optical:'):
(name, title, audio_track, subtitle_track, start, end) = self.parse_optical_path(filename) (name, title, audio_track, subtitle_track, start, end) = parse_optical_path(filename)
log.debug('generate_slide_data, optical name: ' + name)
if not os.path.exists(name): if not os.path.exists(name):
if not remote: if not remote:
# Optical disc is no longer present # Optical disc is no longer present
@ -206,16 +225,16 @@ class MediaMediaItem(MediaManagerItem):
translate('MediaPlugin.MediaItem', 'Missing Media File'), translate('MediaPlugin.MediaItem', 'Missing Media File'),
translate('MediaPlugin.MediaItem', 'The optical disc %s is no longer available.') % name) translate('MediaPlugin.MediaItem', 'The optical disc %s is no longer available.') % name)
return False return False
service_item.title = name
service_item.processor = self.display_type_combo_box.currentText() service_item.processor = self.display_type_combo_box.currentText()
service_item.add_from_command(filename, name, OPTICAL_ICON) service_item.add_from_command(filename, name, CLAPPERBOARD)
service_item.title = name + '@' + self.format_milliseconds(start) + '-' + self.format_milliseconds(end)
# Only set start and end times if going to a service # Only set start and end times if going to a service
#if context == ServiceItemContext.Service: #if context == ServiceItemContext.Service:
# Set the length # Set the length
self.media_controller.media_setup_optical(name, title, audio_track, subtitle_track, start, end, None, None) 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.set_media_length((end - start) / 1000)
service_item.start_time = start/1000 service_item.start_time = start / 1000
service_item.end_time = end/1000 service_item.end_time = end / 1000
service_item.add_capability(ItemCapabilities.IsOptical) service_item.add_capability(ItemCapabilities.IsOptical)
else: else:
if not os.path.exists(filename): if not os.path.exists(filename):
@ -243,12 +262,15 @@ class MediaMediaItem(MediaManagerItem):
return True return True
def initialise(self): def initialise(self):
"""
Initialize media item.
"""
self.list_view.clear() self.list_view.clear()
self.list_view.setIconSize(QtCore.QSize(88, 50)) self.list_view.setIconSize(QtCore.QSize(88, 50))
self.service_path = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails') self.service_path = os.path.join(AppLocation.get_section_data_path(self.settings_section), 'thumbnails')
check_directory_exists(self.service_path) check_directory_exists(self.service_path)
self.load_list(Settings().value(self.settings_section + '/media files')) self.load_list(Settings().value(self.settings_section + '/media files'))
self.populate_display_types() self.rebuild_players()
self.media_clip_selector_form = MediaClipSelectorForm(self, self.main_window, None) self.media_clip_selector_form = MediaClipSelectorForm(self, self.main_window, None)
def rebuild_players(self): def rebuild_players(self):
@ -261,6 +283,9 @@ class MediaMediaItem(MediaManagerItem):
' '.join(self.media_controller.audio_extensions_list), UiStrings().AllFiles) ' '.join(self.media_controller.audio_extensions_list), UiStrings().AllFiles)
def display_setup(self): def display_setup(self):
"""
Setup media controller display.
"""
self.media_controller.setup_display(self.display_controller.preview_display, False) self.media_controller.setup_display(self.display_controller.preview_display, False)
def populate_display_types(self): def populate_display_types(self):
@ -300,24 +325,32 @@ class MediaMediaItem(MediaManagerItem):
Settings().setValue(self.settings_section + '/media files', self.get_file_list()) Settings().setValue(self.settings_section + '/media files', self.get_file_list())
def load_list(self, media, target_group=None): def load_list(self, media, target_group=None):
# Sort the media by its filename considering language specific characters. """
Sort the media by its filename considering language specific characters.
:param media: List if media to sort and list.
:param target_group: Not used in media.
"""
media.sort(key=lambda file_name: get_locale_key(os.path.split(str(file_name))[1])) media.sort(key=lambda file_name: get_locale_key(os.path.split(str(file_name))[1]))
for track in media: for track in media:
track_info = QtCore.QFileInfo(track) track_info = QtCore.QFileInfo(track)
if track.startswith('optical:'): if track.startswith('optical:'):
(file_name, title, audio_track, subtitle_track, start, end) = self.parse_optical_path(track) # Handle optical based item
optical = file_name + '@' + str(title) + ':' + str(start) + '-' + str(end) (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) item_name = QtGui.QListWidgetItem(optical)
item_name.setIcon(build_icon(OPTICAL_ICON)) item_name.setIcon(OPTICAL_ICON)
item_name.setData(QtCore.Qt.UserRole, track) item_name.setData(QtCore.Qt.UserRole, track)
item_name.setToolTip(optical) item_name.setToolTip(optical)
elif not os.path.exists(track): elif not os.path.exists(track):
# File doesn't exist, mark as error.
file_name = os.path.split(str(track))[1] file_name = os.path.split(str(track))[1]
item_name = QtGui.QListWidgetItem(file_name) item_name = QtGui.QListWidgetItem(file_name)
item_name.setIcon(ERROR_ICON) item_name.setIcon(ERROR_ICON)
item_name.setData(QtCore.Qt.UserRole, track) item_name.setData(QtCore.Qt.UserRole, track)
item_name.setToolTip(track) item_name.setToolTip(track)
elif track_info.isFile(): elif track_info.isFile():
# Normal media file handling.
file_name = os.path.split(str(track))[1] file_name = os.path.split(str(track))[1]
item_name = QtGui.QListWidgetItem(file_name) item_name = QtGui.QListWidgetItem(file_name)
if '*.%s' % (file_name.split('.')[-1].lower()) in self.media_controller.audio_extensions_list: if '*.%s' % (file_name.split('.')[-1].lower()) in self.media_controller.audio_extensions_list:
@ -329,6 +362,12 @@ class MediaMediaItem(MediaManagerItem):
self.list_view.addItem(item_name) self.list_view.addItem(item_name)
def get_list(self, type=MediaType.Audio): def get_list(self, type=MediaType.Audio):
"""
Get the list of media, optional select media type.
:param type: Type to get, defaults to audio.
:return: The media list
"""
media = Settings().value(self.settings_section + '/media files') media = Settings().value(self.settings_section + '/media files')
media.sort(key=lambda filename: get_locale_key(os.path.split(str(filename))[1])) media.sort(key=lambda filename: get_locale_key(os.path.split(str(filename))[1]))
extension = [] extension = []
@ -341,6 +380,13 @@ class MediaMediaItem(MediaManagerItem):
return media return media
def search(self, string, show_error): def search(self, string, show_error):
"""
Performs a search for items containing ``string``
:param string: String to be displayed
:param show_error: Should the error be shown (True)
:return: The search result.
"""
files = Settings().value(self.settings_section + '/media files') files = Settings().value(self.settings_section + '/media files')
results = [] results = []
string = string.lower() string = string.lower()
@ -351,25 +397,29 @@ class MediaMediaItem(MediaManagerItem):
return results return results
def on_load_optical(self): def on_load_optical(self):
log.debug('in on_load_optical') """
When the load optical button is clicked, open the clip selector window.
"""
self.media_clip_selector_form.exec_() self.media_clip_selector_form.exec_()
def add_optical_clip(self, optical): def add_optical_clip(self, optical):
"""
Add a optical based clip to the mediamanager, called from media_clip_selector_form.
:param optical: The clip to add.
"""
full_list = self.get_file_list() full_list = self.get_file_list()
full_list.append(optical) full_list.append(optical)
self.load_list([optical]) self.load_list([optical])
Settings().setValue(self.settings_section + '/media files', self.get_file_list()) Settings().setValue(self.settings_section + '/media files', self.get_file_list())
@staticmethod def format_milliseconds(self, milliseconds):
def parse_optical_path(input): """
# split the clip info Format milliseconds into a human readable time string.
clip_info = input.split(sep=':') :param milliseconds: Milliseconds to format
title = int(clip_info[1]) :return: Time string in format: hh.mm.ss,ttt
audio_track = int(clip_info[2]) """
subtitle_track = int(clip_info[3]) seconds, millis = divmod(milliseconds, 1000)
start = float(clip_info[4]) minutes, seconds = divmod(millis, 60)
end = float(clip_info[5]) hours, minutes = divmod(minutes, 60)
filename = clip_info[6] return "%02d:%02d:%02d,%03d" % (hours, minutes, seconds, millis)
if len(clip_info) > 7:
filename += clip_info[7]
return filename, title, audio_track, subtitle_track, start, end