openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #18138
[Merge] lp:~trb143/openlp/media into lp:openlp
Tim Bentley has proposed merging lp:~trb143/openlp/media into lp:openlp.
Requested reviews:
Andreas Preikschat (googol)
Related bugs:
Bug #885150 in OpenLP: "Need non self contained service files"
https://bugs.launchpad.net/openlp/+bug/885150
Bug #899714 in OpenLP: "Play/Pause button should be merged"
https://bugs.launchpad.net/openlp/+bug/899714
Bug #927829 in OpenLP: "media backends should provide some information about themselves in the settings"
https://bugs.launchpad.net/openlp/+bug/927829
Bug #952821 in OpenLP: "Unable to play videos from web"
https://bugs.launchpad.net/openlp/+bug/952821
Bug #958198 in OpenLP: "Replacing live background with a video shows theme behind"
https://bugs.launchpad.net/openlp/+bug/958198
Bug #999618 in OpenLP: "Video position slider jumps to part way through video"
https://bugs.launchpad.net/openlp/+bug/999618
Bug #1022053 in OpenLP: "Previewing media item interferes with live media item"
https://bugs.launchpad.net/openlp/+bug/1022053
Bug #1063211 in OpenLP: "Media and Presentation Plugins do not update the service suffix lists if players are added or removed without a restart"
https://bugs.launchpad.net/openlp/+bug/1063211
For more details, see:
https://code.launchpad.net/~trb143/openlp/media/+merge/136003
Ok time to get this in the Open. This is for 2.1
New Features.
- Added ability for an individual service item to bypass the "do not go live if blanked" check.
- Used above feature to allow web to go live automatically.
- Added ability to save a "lite" service with no files (non transportable)
- Media buttons are state aware
Changes
- Split media plugin from media core as 2 players are in core this makes no sense.
- Cleaned up the arrays in Media Controller to use propped indexes not objects.
- Cleaned up API's
- Simplified the understanding of which Controller and why media was being called.
- Added icon for audio.
- Video length is only called when the item is going to a service.
- Split Play and length to their own methods.
- Used ServiceItem to control playing media not passing individual fields.
- Move the players in to a consistent directory structure.
- refactored and renamed code to make it more understandable.
- fixed bug where if you remove a player (Presentation or Media) it's suffexes are not reset!
--
https://code.launchpad.net/~trb143/openlp/media/+merge/136003
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py 2012-11-11 21:16:14 +0000
+++ openlp/core/lib/__init__.py 2012-11-24 07:26:33 +0000
@@ -37,6 +37,14 @@
log = logging.getLogger(__name__)
+class ServiceItemContext(object):
+ """
+ The context in which a Service Item is being generated
+ """
+ Preview = 0
+ Live = 1
+ Service = 2
+
class ImageSource(object):
"""
@@ -395,4 +403,4 @@
from imagemanager import ImageManager
from renderer import Renderer
from mediamanageritem import MediaManagerItem
-from openlp.core.utils.actions import ActionList
+
=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py 2012-11-11 21:16:14 +0000
+++ openlp/core/lib/mediamanageritem.py 2012-11-24 07:26:33 +0000
@@ -36,7 +36,8 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \
- StringContent, build_icon, translate, Receiver, ListWidgetWithDnD
+ StringContent, build_icon, translate, Receiver, ListWidgetWithDnD, \
+ ServiceItemContext
from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import UiStrings, create_widget_action, \
critical_error_message_box
@@ -459,7 +460,7 @@
pass
def generateSlideData(self, serviceItem, item=None, xmlVersion=False,
- remote=False):
+ remote=False, context=ServiceItemContext.Live):
raise NotImplementedError(u'MediaManagerItem.generateSlideData needs '
u'to be defined by the plugin')
@@ -521,6 +522,8 @@
if serviceItem:
if not item_id:
serviceItem.from_plugin = True
+ if remote:
+ serviceItem.will_auto_start = True
self.plugin.liveController.addServiceItem(serviceItem)
def createItemFromId(self, item_id):
@@ -548,7 +551,8 @@
self.addToService(item)
def addToService(self, item=None, replace=None, remote=False):
- serviceItem = self.buildServiceItem(item, True, remote=remote)
+ serviceItem = self.buildServiceItem(item, True, remote=remote,
+ context=ServiceItemContext.Service)
if serviceItem:
serviceItem.from_plugin = False
self.plugin.serviceManager.addServiceItem(serviceItem,
@@ -581,13 +585,15 @@
unicode(translate('OpenLP.MediaManagerItem',
'You must select a %s service item.')) % self.title)
- def buildServiceItem(self, item=None, xmlVersion=False, remote=False):
+ def buildServiceItem(self, item=None, xmlVersion=False, remote=False,
+ context=ServiceItemContext.Live):
"""
Common method for generating a service item
"""
serviceItem = ServiceItem(self.plugin)
serviceItem.add_icon(self.plugin.iconPath)
- if self.generateSlideData(serviceItem, item, xmlVersion, remote):
+ if self.generateSlideData(serviceItem, item, xmlVersion, remote,
+ context):
return serviceItem
else:
return None
=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py 2012-11-11 21:16:14 +0000
+++ openlp/core/lib/serviceitem.py 2012-11-24 07:26:33 +0000
@@ -53,7 +53,65 @@
class ItemCapabilities(object):
"""
- Provides an enumeration of a serviceitem's capabilities
+ Provides an enumeration of a service item's capabilities
+
+ ``CanPreview``
+ The capability to allow the ServiceManager to add to the preview
+ tab when making the previous item live.
+
+ ``CanEdit``
+ The capability to allow the ServiceManager to allow the item to be
+ edited
+
+ ``CanMaintain``
+ The capability to allow the ServiceManager to allow the item to be
+ reordered.
+
+ ``RequiresMedia``
+ Determines is the serviceItem needs a Media Player
+
+ ``CanLoop``
+ The capability to allow the SlideController to allow the loop
+ processing.
+
+ ``CanAppend``
+ The capability to allow the ServiceManager to add leaves to the
+ item
+
+ ``NoLineBreaks``
+ The capability to remove lines breaks in the renderer
+
+ ``OnLoadUpdate``
+ The capability to update MediaManager when a service Item is
+ loaded.
+
+ ``AddIfNewItem``
+ Not Used
+
+ ``ProvidesOwnDisplay``
+ The capability to tell the SlideController the service Item has a
+ different display.
+
+ ``HasDetailedTitleDisplay``
+ ServiceItem provides a title
+
+ ``HasVariableStartTime``
+ The capability to tell the ServiceManager that a change to start
+ time is possible.
+
+ ``CanSoftBreak``
+ The capability to tell the renderer that Soft Break is allowed
+
+ ``CanWordSplit``
+ The capability to tell the renderer that it can split words is
+ allowed
+
+ ``HasBackgroundAudio``
+ That a audio file is present with the text.
+
+ ``CanAutoStartForLive``
+ The capability to ignore the do not play if display blank flag.
+
"""
CanPreview = 1
CanEdit = 2
@@ -70,6 +128,7 @@
CanSoftBreak = 13
CanWordSplit = 14
HasBackgroundAudio = 15
+ CanAutoStartForLive = 16
class ServiceItem(object):
@@ -123,6 +182,7 @@
self.background_audio = []
self.theme_overwritten = False
self.temporary_edit = False
+ self.will_auto_start = False
self._new_item()
def _new_item(self):
@@ -256,7 +316,7 @@
{u'title': file_name, u'image': image, u'path': path})
self._new_item()
- def get_service_repr(self):
+ def get_service_repr(self, lite_save):
"""
This method returns some text which can be saved into the service
file to represent this item.
@@ -280,17 +340,24 @@
u'end_time': self.end_time,
u'media_length': self.media_length,
u'background_audio': self.background_audio,
- u'theme_overwritten': self.theme_overwritten
+ u'theme_overwritten': self.theme_overwritten,
+ u'will_auto_start': self.will_auto_start
}
service_data = []
if self.service_item_type == ServiceItemType.Text:
service_data = [slide for slide in self._raw_frames]
elif self.service_item_type == ServiceItemType.Image:
- service_data = [slide[u'title'] for slide in self._raw_frames]
+ if lite_save:
+ for slide in self._raw_frames:
+ service_data.append(
+ {u'title': slide[u'title'], u'path': slide[u'path']})
+ else:
+ service_data = [slide[u'title'] for slide in self._raw_frames]
elif self.service_item_type == ServiceItemType.Command:
for slide in self._raw_frames:
service_data.append(
- {u'title': slide[u'title'], u'image': slide[u'image']})
+ {u'title': slide[u'title'], u'image': slide[u'image'],
+ u'path': slide[u'path']})
return {u'header': service_header, u'data': service_data}
def set_from_service(self, serviceitem, path=None):
@@ -302,7 +369,9 @@
The item to extract data from.
``path``
- Defaults to *None*. Any path data, usually for images.
+ Defaults to *None*. This is the service manager path for things
+ which have their files saved with them or None when the saved
+ service is lite and the original file paths need to be preserved..
"""
log.debug(u'set_from_service called with path %s' % path)
header = serviceitem[u'serviceitem'][u'header']
@@ -324,6 +393,7 @@
self.start_time = header.get(u'start_time', 0)
self.end_time = header.get(u'end_time', 0)
self.media_length = header.get(u'media_length', 0)
+ self.will_auto_start = header.get(u'will_auto_start', False)
if u'background_audio' in header:
self.background_audio = []
for filename in header[u'background_audio']:
@@ -334,14 +404,24 @@
for slide in serviceitem[u'serviceitem'][u'data']:
self._raw_frames.append(slide)
elif self.service_item_type == ServiceItemType.Image:
- for text_image in serviceitem[u'serviceitem'][u'data']:
- filename = os.path.join(path, text_image)
- self.add_from_image(filename, text_image)
+ if path:
+ for text_image in serviceitem[u'serviceitem'][u'data']:
+ filename = os.path.join(path, text_image)
+ self.add_from_image(filename, text_image)
+ else:
+ for text_image in serviceitem[u'serviceitem'][u'data']:
+ self.add_from_image(text_image[u'path'],
+ text_image[u'title'])
elif self.service_item_type == ServiceItemType.Command:
for text_image in serviceitem[u'serviceitem'][u'data']:
- filename = os.path.join(path, text_image[u'title'])
- self.add_from_command(
- path, text_image[u'title'], text_image[u'image'])
+ if path:
+ self.add_from_command(
+ path, text_image[u'title'], text_image[u'image'])
+ else:
+ self.add_from_command(
+ text_image[u'path'], text_image[u'title'],
+ text_image[u'image'])
+
self._new_item()
def get_display_title(self):
@@ -423,6 +503,17 @@
"""
return self.service_item_type == ServiceItemType.Text
+ def set_media_length(self, length):
+ """
+ Stores the media length of the item
+
+ ``length``
+ The length of the media item
+ """
+ self.media_length = length
+ if length > 0:
+ self.add_capability(ItemCapabilities.HasVariableStartTime)
+
def get_frames(self):
"""
Returns the frames for the ServiceItem
@@ -435,6 +526,8 @@
def get_rendered_frame(self, row):
"""
Returns the correct frame for a given list and renders it if required.
+ ``row``
+ The service item slide to be returned
"""
if self.service_item_type == ServiceItemType.Text:
return self._display_frames[row][u'html'].split(u'\n')[0]
=== modified file 'openlp/core/lib/ui.py'
--- openlp/core/lib/ui.py 2012-11-11 21:16:14 +0000
+++ openlp/core/lib/ui.py 2012-11-24 07:26:33 +0000
@@ -61,6 +61,7 @@
self.Add = translate('OpenLP.Ui', '&Add')
self.Advanced = translate('OpenLP.Ui', 'Advanced')
self.AllFiles = translate('OpenLP.Ui', 'All Files')
+ self.Automatic = translate('OpenLP.Ui', 'Automatic')
self.Bottom = translate('OpenLP.Ui', 'Bottom')
self.Browse = translate('OpenLP.Ui', 'Browse...')
self.Cancel = translate('OpenLP.Ui', 'Cancel')
=== modified file 'openlp/core/ui/__init__.py'
--- openlp/core/ui/__init__.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/__init__.py 2012-11-24 07:26:33 +0000
@@ -72,6 +72,16 @@
Middle = 1
Bottom = 2
+class DisplayControllerType(object):
+ """
+ This is an enumeration class which says where a display controller
+ originated from.
+ """
+ Live = 0
+ Preview = 1
+ Plugin = 2
+
+
from firsttimeform import FirstTimeForm
from firsttimelanguageform import FirstTimeLanguageForm
from themelayoutform import ThemeLayoutForm
@@ -82,7 +92,7 @@
from maindisplay import MainDisplay, Display
from servicenoteform import ServiceNoteForm
from serviceitemeditform import ServiceItemEditForm
-from slidecontroller import SlideController, Controller
+from slidecontroller import SlideController, DisplayController
from splashscreen import SplashScreen
from generaltab import GeneralTab
from themestab import ThemesTab
@@ -98,4 +108,4 @@
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay',
'SlideController', 'ServiceManager', 'ThemeManager', 'MediaDockManager',
- 'ServiceItemEditForm', u'FirstTimeForm']
+ 'ServiceItemEditForm', 'FirstTimeForm']
=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/maindisplay.py 2012-11-24 07:26:33 +0000
@@ -53,8 +53,8 @@
class Display(QtGui.QGraphicsView):
"""
This is a general display screen class. Here the general display settings
- will done. It will be used as specialized classes by Main Display and
- Preview display.
+ will done. It will be used as specialized classes by Main Display and
+ Preview display.
"""
def __init__(self, parent, live, controller):
if live:
@@ -327,7 +327,7 @@
"""
log.debug(u'image to display')
image = self.imageManager.getImageBytes(path, ImageSource.ImagePlugin)
- self.controller.mediaController.video_reset(self.controller)
+ self.controller.mediaController.media_reset(self.controller)
self.displayImage(image)
def displayImage(self, image):
=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/mainwindow.py 2012-11-24 07:26:33 +0000
@@ -576,6 +576,7 @@
self.headerSection = u'SettingsImport'
self.serviceNotSaved = False
self.aboutForm = AboutForm(self)
+ self.mediaController = MediaController(self)
self.settingsForm = SettingsForm(self, self)
self.formattingTagForm = FormattingTagForm(self)
self.shortcutForm = ShortcutListForm(self)
@@ -585,9 +586,10 @@
self.pluginManager = PluginManager(plugin_path)
self.pluginHelpers = {}
self.imageManager = ImageManager()
- self.mediaController = MediaController(self)
# Set up the interface
self.setupUi(self)
+ # Register the active media players and suffixes
+ self.mediaController.check_available_media_players()
# Load settings after setupUi so default UI sizes are overwritten
self.loadSettings()
# Once settings are loaded update the menu with the recent files.
@@ -1169,7 +1171,7 @@
if self.serviceManagerContents.isModified():
ret = self.serviceManagerContents.saveModifiedService()
if ret == QtGui.QMessageBox.Save:
- if self.serviceManagerContents.saveFile():
+ if self.serviceManagerContents.decideSaveMethod():
self.cleanUp()
event.accept()
else:
=== modified file 'openlp/core/ui/media/__init__.py'
--- openlp/core/ui/media/__init__.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/media/__init__.py 2012-11-24 07:26:33 +0000
@@ -47,7 +47,7 @@
class MediaType(object):
"""
- An enumeration of possibible Media Types
+ An enumeration of possible Media Types
"""
Unused = 0
Audio = 1
@@ -59,7 +59,7 @@
class MediaInfo(object):
"""
- This class hold the media related infos
+ This class hold the media related info
"""
file_info = None
volume = 100
@@ -72,30 +72,26 @@
def get_media_players():
"""
- This method extract the configured media players and overridden player from
- the settings.
-
- ``players_list``
- A list with all active media players.
-
- ``overridden_player``
- Here an special media player is chosen for all media actions.
+ This method extracts the configured media players and overridden player
+ from the settings.
"""
log.debug(u'get_media_players')
- players = unicode(Settings().value(u'media/players').toString())
- if not players:
- players = u'webkit'
+ saved_players = unicode(Settings().value(u'media/players').toString())
+ if not saved_players:
+ # we must always have a player and Webkit is the core one.
+ saved_players = u'webkit'
reg_ex = QtCore.QRegExp(".*\[(.*)\].*")
if Settings().value(u'media/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0] == QtCore.Qt.Checked:
- if reg_ex.exactMatch(players):
+ if reg_ex.exactMatch(saved_players):
overridden_player = u'%s' % reg_ex.cap(1)
else:
overridden_player = u'auto'
else:
overridden_player = u''
- players_list = players.replace(u'[', u'').replace(u']', u'').split(u',')
- return players_list, overridden_player
+ saved_players_list = saved_players.replace(u'[', u'').\
+ replace(u']',u'').split(u',')
+ return saved_players_list, overridden_player
def set_media_players(players_list, overridden_player=u'auto'):
@@ -118,3 +114,4 @@
Settings().setValue(u'media/players', QtCore.QVariant(players))
from mediacontroller import MediaController
+from playertab import PlayerTab
=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/media/mediacontroller.py 2012-11-24 07:26:33 +0000
@@ -34,11 +34,12 @@
from openlp.core.lib import OpenLPToolbar, Receiver, translate
from openlp.core.lib.settings import Settings
-from openlp.core.lib.mediaplayer import MediaPlayer
-from openlp.core.lib.ui import critical_error_message_box
+from openlp.core.lib.ui import UiStrings, 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
from openlp.core.utils import AppLocation
+from openlp.core.ui import DisplayControllerType
log = logging.getLogger(__name__)
@@ -46,68 +47,104 @@
"""
The implementation of the Media Controller. The Media Controller adds an own
class for every Player. Currently these are QtWebkit, Phonon and Vlc.
+
+ displayControllers are an array of controllers keyed on the
+ slidecontroller or plugin which built them. ControllerType is the class
+ containing the key values.
+
+ mediaPlayers are an array of media players keyed on player name.
+
+ currentMediaPlayer is an array of player instances keyed on ControllerType.
+
"""
-
def __init__(self, parent):
- self.parent = parent
+ self.mainWindow = parent
self.mediaPlayers = {}
- self.controller = []
- self.curDisplayMediaPlayer = {}
+ self.displayControllers = {}
+ self.currentMediaPlayer = {}
# Timer for video state
self.timer = QtCore.QTimer()
self.timer.setInterval(200)
- self.withLivePreview = False
- self.check_available_media_players()
# Signals
QtCore.QObject.connect(self.timer,
- QtCore.SIGNAL("timeout()"), self.video_state)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'playbackPlay'), self.video_play)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'playbackPause'), self.video_pause)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'playbackStop'), self.video_stop)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'seekSlider'), self.video_seek)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'volumeSlider'), self.video_volume)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'media_hide'), self.video_hide)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'media_blank'), self.video_blank)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'media_unblank'), self.video_unblank)
+ QtCore.SIGNAL("timeout()"), self.media_state)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'playbackPlay'), self.media_play_msg)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'playbackPause'), self.media_pause_msg)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'playbackStop'), self.media_stop_msg)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'seekSlider'), self.media_seek)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'volumeSlider'), self.media_volume)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'media_hide'), self.media_hide)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'media_blank'), self.media_blank)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'media_unblank'), self.media_unblank)
# Signals for background video
QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'songs_hide'), self.video_hide)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'songs_unblank'), self.video_unblank)
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.set_active_players)
+ QtCore.SIGNAL(u'songs_hide'), self.media_hide)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'songs_unblank'), self.media_unblank)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'mediaitem_media_rebuild'), self._set_active_players)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'mediaitem_suffexes'),
+ self._generate_extensions_lists)
- def set_active_players(self):
+ def _set_active_players(self):
+ """
+ Set the active players and available media files
+ """
savedPlayers = get_media_players()[0]
for player in self.mediaPlayers.keys():
self.mediaPlayers[player].isActive = player in savedPlayers
- def register_controllers(self, controller):
- """
- Register each media Player controller (Webkit, Phonon, etc) and store
+ def _generate_extensions_lists(self):
+ """
+ Set the active players and available media files
+ """
+ self.audio_extensions_list = []
+ for player in self.mediaPlayers.values():
+ if player.isActive:
+ for item in player.audio_extensions_list:
+ if not item in self.audio_extensions_list:
+ self.audio_extensions_list.append(item)
+ self.mainWindow.serviceManagerContents. \
+ supportedSuffixes(item[2:])
+ self.video_extensions_list = []
+ for player in self.mediaPlayers.values():
+ if player.isActive:
+ for item in player.video_extensions_list:
+ if item not in self.video_extensions_list:
+ self.video_extensions_list.extend(item)
+ self.mainWindow.serviceManagerContents. \
+ supportedSuffixes(item[2:])
+
+ def register_players(self, player):
+ """
+ Register each media Player (Webkit, Phonon, etc) and store
for later use
+
+ ``player``
+ Individual player class which has been enabled
"""
- self.mediaPlayers[controller.name] = controller
+ self.mediaPlayers[player.name] = player
def check_available_media_players(self):
"""
- Check to see if we have any media Player's available. If Not do not
- install the plugin.
+ Check to see if we have any media Player's available.
"""
- log.debug(u'check_available_media_players')
+ log.debug(u'_check_available_media_players')
controller_dir = os.path.join(
AppLocation.get_directory(AppLocation.AppDir),
u'core', u'ui', u'media')
for filename in os.listdir(controller_dir):
- if filename.endswith(u'player.py'):
+ if filename.endswith(u'player.py') and \
+ not filename == 'mediaplayer.py':
path = os.path.join(controller_dir, filename)
if os.path.isfile(path):
modulename = u'openlp.core.ui.media.' + \
@@ -120,10 +157,10 @@
except (ImportError, OSError):
log.warn(u'Failed to import %s on path %s',
modulename, path)
- controller_classes = MediaPlayer.__subclasses__()
- for controller_class in controller_classes:
- controller = controller_class(self)
- self.register_controllers(controller)
+ player_classes = MediaPlayer.__subclasses__()
+ for player_class in player_classes:
+ player = player_class(self)
+ self.register_players(player)
if not self.mediaPlayers:
return False
savedPlayers, overriddenPlayer = get_media_players()
@@ -134,31 +171,33 @@
for invalidPlayer in invalidMediaPlayers:
savedPlayers.remove(invalidPlayer)
set_media_players(savedPlayers, overriddenPlayer)
- self.set_active_players()
+ self._set_active_players()
+ self._generate_extensions_lists()
return True
- def video_state(self):
+ def media_state(self):
"""
Check if there is a running media Player and do updating stuff (e.g.
update the UI)
"""
- if not self.curDisplayMediaPlayer.keys():
+ if not self.currentMediaPlayer.keys():
self.timer.stop()
else:
any_active = False
- for display in self.curDisplayMediaPlayer.keys():
- self.curDisplayMediaPlayer[display].resize(display)
- self.curDisplayMediaPlayer[display].update_ui(display)
- if self.curDisplayMediaPlayer[display].state == \
- MediaState.Playing:
+ for source in self.currentMediaPlayer.keys():
+ display = self._define_display(self.displayControllers[source])
+ self.currentMediaPlayer[source].resize(display)
+ self.currentMediaPlayer[source].update_ui(display)
+ if self.currentMediaPlayer[source].state == \
+ MediaState.Playing:
any_active = True
- # There are still any active players - no need to stop timer.
+ # There are still any active players - no need to stop timer.
if any_active:
return
-
- # No players are active anymore.
- for display in self.curDisplayMediaPlayer.keys():
- if self.curDisplayMediaPlayer[display].state != MediaState.Paused:
+ # no players are active anymore
+ for source in self.currentMediaPlayer.keys():
+ if self.currentMediaPlayer[source].state != MediaState.Paused:
+ display = self._define_display(self.displayControllers[source])
display.controller.seekSlider.setSliderPosition(0)
self.timer.stop()
@@ -192,14 +231,22 @@
html += player.get_media_display_html()
return html
- def add_controller_items(self, controller, control_panel):
- self.controller.append(controller)
- self.setup_generic_controls(controller, control_panel)
- self.setup_special_controls(controller, control_panel)
-
- def setup_generic_controls(self, controller, control_panel):
- """
- Add generic media control items (valid for all types of medias)
+ def register_controller(self, controller):
+ """
+ Registers media controls where the players will be placed to run.
+
+ ``controller``
+ The controller where a player will be placed
+ """
+ self.displayControllers[controller.controllerType] = controller
+ self.setup_generic_controls(controller)
+
+ def setup_generic_controls(self, controller):
+ """
+ Set up controls on the control_panel for a given controller
+
+ ``controller``
+ First element is the controller which should be used
"""
controller.media_info = MediaInfo()
# Build a Media ToolBar
@@ -212,7 +259,8 @@
controller.mediabar.addToolbarAction(u'playbackPause',
text=u'media_playback_pause',
icon=u':/slides/media_playback_pause.png',
- tooltip=translate('OpenLP.SlideController', 'Pause playing media.'),
+ tooltip=translate('OpenLP.SlideController',
+ 'Pause playing media.'),
triggers=controller.sendToPlugins)
controller.mediabar.addToolbarAction(u'playbackStop',
text=u'media_playback_stop',
@@ -241,7 +289,7 @@
controller.volumeSlider.setGeometry(QtCore.QRect(90, 160, 221, 24))
controller.volumeSlider.setObjectName(u'volumeSlider')
controller.mediabar.addToolbarWidget(controller.volumeSlider)
- control_panel.addWidget(controller.mediabar)
+ controller.controllerLayout.addWidget(controller.mediabar)
controller.mediabar.setVisible(False)
# Signals
QtCore.QObject.connect(controller.seekSlider,
@@ -249,75 +297,94 @@
QtCore.QObject.connect(controller.volumeSlider,
QtCore.SIGNAL(u'valueChanged(int)'), controller.sendToPlugins)
- def setup_special_controls(self, controller, control_panel):
- """
- Special media Toolbars will be created here (e.g. for DVD Playback)
- """
- controller.media_info = MediaInfo()
- # TODO: add Toolbar for DVD, ...
- def setup_display(self, display):
+ def setup_display(self, display, preview):
"""
After a new display is configured, all media related widget will be
created too
+
+ ``display``
+ Display on which the output is to be played
+
+ ``preview``
+ Whether the display is a main or preview display
"""
# clean up possible running old media files
self.finalise()
# update player status
- self.set_active_players()
+ self._set_active_players()
display.hasAudio = True
- if not self.withLivePreview and \
- display == self.parent.liveController.previewDisplay:
- return
- if display == self.parent.previewController.previewDisplay or \
- display == self.parent.liveController.previewDisplay:
+ if preview:
display.hasAudio = False
for player in self.mediaPlayers.values():
if player.isActive:
player.setup(display)
def set_controls_visible(self, controller, value):
+ """
+ After a new display is configured, all media related widget will be
+ created too
+
+ ``controller``
+ The controller on which controls act.
+
+ ``value``
+ control name to be changed.
+ """
# Generic controls
controller.mediabar.setVisible(value)
if controller.isLive and controller.display:
- if self.curDisplayMediaPlayer and value:
- if self.curDisplayMediaPlayer[controller.display] != \
+ if self.currentMediaPlayer and value:
+ if self.currentMediaPlayer[controller.controllerType] != \
self.mediaPlayers[u'webkit']:
controller.display.setTransparency(False)
- # Special controls: Here media type specific Controls will be enabled
- # (e.g. for DVD control, ...)
- # TODO
- def resize(self, controller, display, player):
+ def resize(self, display, player):
"""
After Mainwindow changes or Splitter moved all related media widgets
have to be resized
+
+ ``display``
+ The display on which output is playing.
+
+ ``player``
+ The player which is doing the playing.
"""
player.resize(display)
- def video(self, controller, file, muted, isBackground, hidden=False,
- isInfo=False, controlsVisible=True):
+ def video(self, source, serviceItem, hidden=False, videoBehindText=False):
"""
Loads and starts a video to run with the option of sound
+
+ ``source``
+ Where the call originated form
+
+ ``serviceItem``
+ The player which is doing the playing
+
+ ``hidden``
+ The player which is doing the playing
+
+ ``videoBehindText``
+ Is the video to be played behind text.
"""
log.debug(u'video')
isValid = False
+ controller = self.displayControllers[source]
# stop running videos
- self.video_reset(controller)
+ self.media_reset(controller)
controller.media_info = MediaInfo()
- if muted:
+ if videoBehindText:
controller.media_info.volume = 0
+ controller.media_info.is_background = True
else:
controller.media_info.volume = controller.volumeSlider.value()
- controller.media_info.file_info = QtCore.QFileInfo(file)
- controller.media_info.is_background = isBackground
- display = None
+ controller.media_info.is_background = False
+ controller.media_info.file_info = \
+ QtCore.QFileInfo(serviceItem.get_frame_path())
+ display = self._define_display(controller)
if controller.isLive:
- if self.withLivePreview and controller.previewDisplay:
- display = controller.previewDisplay
- isValid = self.check_file_type(controller, display)
- display = controller.display
- isValid = self.check_file_type(controller, display)
+ isValid = self._check_file_type(controller, display, serviceItem)
display.override[u'theme'] = u''
display.override[u'video'] = True
if controller.media_info.is_background:
@@ -327,10 +394,9 @@
else:
controller.media_info.start_time = \
display.serviceItem.start_time
- controller.media_info.end_time = display.serviceItem.end_time
+ controller.media_info.end_time = serviceItem.end_time
elif controller.previewDisplay:
- display = controller.previewDisplay
- isValid = self.check_file_type(controller, display)
+ isValid = self._check_file_type(controller, display, serviceItem)
if not isValid:
# Media could not be loaded correctly
critical_error_message_box(
@@ -347,33 +413,74 @@
# Preview requested
if not controller.isLive:
autoplay = True
- # Visible or background requested
- elif not hidden or controller.media_info.is_background:
+ # Visible or background requested or Service Item wants to autostart
+ elif not hidden or controller.media_info.is_background or \
+ serviceItem.will_auto_start:
autoplay = True
# Unblank on load set
elif Settings().value(u'general/auto unblank',
QtCore.QVariant(False)).toBool():
autoplay = True
- # Start playback only for visible widgets. If we need just load a video
- # and get video information, do not start playback.
- if autoplay and not isInfo:
- if not self.video_play([controller]):
+ if autoplay:
+ if not self.media_play(controller):
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Unsupported File'),
unicode(translate('MediaPlugin.MediaItem',
'Unsupported File')))
return False
- self.set_controls_visible(controller, controlsVisible)
- log.debug(u'use %s controller' % self.curDisplayMediaPlayer[display])
- return True
-
- def check_file_type(self, controller, display):
+ self.set_controls_visible(controller, True)
+ log.debug(u'use %s controller' %
+ self.currentMediaPlayer[controller.controllerType])
+ return True
+
+ def media_length(self, serviceItem):
+ """
+ Loads and starts a media item to obtain the media length
+
+ ``serviceItem``
+ The ServiceItem containing the details to be played.
+ """
+ controller = self.displayControllers[DisplayControllerType.Plugin]
+ log.debug(u'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(serviceItem
+ .get_frame_path())
+ display = controller.previewDisplay
+ if not self._check_file_type(controller, display, serviceItem):
+ # Media could not be loaded correctly
+ critical_error_message_box(
+ translate('MediaPlugin.MediaItem', 'Unsupported File'),
+ unicode(translate('MediaPlugin.MediaItem',
+ 'Unsupported File')))
+ return False
+ if not self.media_play(controller):
+ critical_error_message_box(
+ translate('MediaPlugin.MediaItem', 'Unsupported File'),
+ unicode(translate('MediaPlugin.MediaItem',
+ 'Unsupported File')))
+ return False
+ serviceItem.set_media_length(controller.media_info.length)
+ self.media_stop(controller)
+ log.debug(u'use %s controller' %
+ self.currentMediaPlayer[controller.controllerType])
+ return True
+
+ def _check_file_type(self, controller, display, serviceItem):
"""
Select the correct media Player type from the prioritized Player list
+
+ ``controller``
+ First element is the controller which should be used
+
+ ``serviceItem``
+ The ServiceItem containing the details to be played.
"""
- usedPlayers, overriddenPlayer = get_media_players()
- if overriddenPlayer and overriddenPlayer != u'auto':
- usedPlayers = [overriddenPlayer]
+ usedPlayers = get_media_players()[0]
+ if serviceItem.title != UiStrings().Automatic:
+ usedPlayers = [serviceItem.title.lower()]
if controller.media_info.file_info.isFile():
suffix = u'*.%s' % \
controller.media_info.file_info.suffix().toLower()
@@ -383,83 +490,122 @@
if not controller.media_info.is_background or \
controller.media_info.is_background and \
player.canBackground:
- self.resize(controller, display, player)
+ self.resize(display, player)
if player.load(display):
- self.curDisplayMediaPlayer[display] = player
+ self.currentMediaPlayer[controller.controllerType] \
+ = player
controller.media_info.media_type = MediaType.Video
return True
if suffix in player.audio_extensions_list:
if player.load(display):
- self.curDisplayMediaPlayer[display] = player
+ self.currentMediaPlayer[controller.controllerType] \
+ = player
controller.media_info.media_type = MediaType.Audio
return True
else:
for title in usedPlayers:
player = self.mediaPlayers[title]
if player.canFolder:
- self.resize(controller, display, player)
+ self.resize(display, player)
if player.load(display):
- self.curDisplayMediaPlayer[display] = player
+ self.currentMediaPlayer[controller.controllerType] \
+ = player
controller.media_info.media_type = MediaType.Video
return True
# no valid player found
return False
- def video_play(self, msg, status=True):
+ def media_play_msg(self, msg, status=True):
"""
Responds to the request to play a loaded video
``msg``
First element is the controller which should be used
"""
- log.debug(u'video_play')
- controller = msg[0]
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller == controller:
- if not self.curDisplayMediaPlayer[display].play(display):
- return False
- if status:
- display.frame.evaluateJavaScript(u'show_blank("desktop");')
- self.curDisplayMediaPlayer[display].set_visible(display,
- True)
- if controller.isLive:
- if controller.hideMenu.defaultAction().isChecked():
- controller.hideMenu.defaultAction().trigger()
+ log.debug(u'media_play_msg')
+ self.media_play(msg[0],status)
+
+
+ def media_play(self, controller, status=True):
+ """
+ Responds to the request to play a loaded video
+
+ ``controller``
+ The controller to be played
+ """
+ log.debug(u'media_play')
+ display = self._define_display(controller)
+ if not self.currentMediaPlayer[controller.controllerType].play(display):
+ return False
+ if status:
+ display.frame.evaluateJavaScript(u'show_blank("desktop");')
+ self.currentMediaPlayer[controller.controllerType]\
+ .set_visible(display, True)
+ controller.mediabar.actions[u'playbackPlay'].setVisible(False)
+ controller.mediabar.actions[u'playbackStop'].setVisible(True)
+ controller.mediabar.actions[u'playbackPause'].setVisible(True)
+ if controller.isLive:
+ if controller.hideMenu.defaultAction().isChecked():
+ controller.hideMenu.defaultAction().trigger()
# Start Timer for ui updates
if not self.timer.isActive():
self.timer.start()
return True
- def video_pause(self, msg):
- """
- Responds to the request to pause a loaded video
-
- ``msg``
- First element is the controller which should be used
- """
- log.debug(u'video_pause')
- controller = msg[0]
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller == controller:
- self.curDisplayMediaPlayer[display].pause(display)
-
- def video_stop(self, msg):
- """
- Responds to the request to stop a loaded video
-
- ``msg``
- First element is the controller which should be used
- """
- log.debug(u'video_stop')
- controller = msg[0]
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller == controller:
- display.frame.evaluateJavaScript(u'show_blank("black");')
- self.curDisplayMediaPlayer[display].stop(display)
- self.curDisplayMediaPlayer[display].set_visible(display, False)
- controller.seekSlider.setSliderPosition(0)
-
- def video_volume(self, msg):
+ def media_pause_msg(self, msg):
+ """
+ Responds to the request to pause a loaded video
+
+ ``msg``
+ First element is the controller which should be used
+ """
+ log.debug(u'media_pause_msg')
+ self.media_pause( msg[0])
+
+ def media_pause(self, controller):
+ """
+ Responds to the request to pause a loaded video
+
+ ``controller``
+ The Controller to be paused
+ """
+ log.debug(u'media_pause')
+ display = self._define_display(controller)
+ self.currentMediaPlayer[controller.controllerType].pause(display)
+ controller.mediabar.actions[u'playbackPlay'].setVisible(True)
+ controller.mediabar.actions[u'playbackStop'].setVisible(True)
+ controller.mediabar.actions[u'playbackPause'].setVisible(False)
+
+ def media_stop_msg(self, msg):
+ """
+ Responds to the request to stop a loaded video
+
+ ``msg``
+ First element is the controller which should be used
+ """
+ log.debug(u'media_stop_msg')
+ self.media_stop(msg[0])
+
+ def media_stop(self, controller):
+ """
+ Responds to the request to stop a loaded video
+
+ ``controller``
+ The controller that needs to be stopped
+ """
+ log.debug(u'media_stop')
+ display = self._define_display(controller)
+ if display in self.currentMediaPlayer:
+ display.frame.evaluateJavaScript(u'show_blank("black");')
+ self.currentMediaPlayer[controller.controllerType].stop(display)
+ self.currentMediaPlayer[controller.controllerType] \
+ .set_visible(display, False)
+ controller.seekSlider.setSliderPosition(0)
+ controller.mediabar.actions[u'playbackPlay'].setVisible(True)
+ controller.mediabar.actions[u'playbackStop'].setVisible(False)
+ controller.mediabar.actions[u'playbackPause'].setVisible(False)
+
+ def media_volume(self, msg):
"""
Changes the volume of a running video
@@ -468,12 +614,11 @@
"""
controller = msg[0]
vol = msg[1][0]
- log.debug(u'video_volume %d' % vol)
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller == controller:
- self.curDisplayMediaPlayer[display].volume(display, vol)
+ log.debug(u'media_volume %d' % vol)
+ display = self._define_display(controller)
+ self.currentMediaPlayer[controller.controllerType].volume(display, vol)
- def video_seek(self, msg):
+ def media_seek(self, msg):
"""
Responds to the request to change the seek Slider of a loaded video
@@ -481,29 +626,30 @@
First element is the controller which should be used
Second element is a list with the seek Value as first element
"""
- log.debug(u'video_seek')
+ log.debug(u'media_seek')
controller = msg[0]
seekVal = msg[1][0]
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller == controller:
- self.curDisplayMediaPlayer[display].seek(display, seekVal)
+ display = self._define_display(controller)
+ self.currentMediaPlayer[controller.controllerType] \
+ .seek(display, seekVal)
- def video_reset(self, controller):
+ def media_reset(self, controller):
"""
Responds to the request to reset a loaded video
"""
- log.debug(u'video_reset')
+ log.debug(u'media_reset')
self.set_controls_visible(controller, False)
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller == controller:
- display.override = {}
- self.curDisplayMediaPlayer[display].reset(display)
- self.curDisplayMediaPlayer[display].set_visible(display, False)
- display.frame.evaluateJavaScript(u'show_video( \
+ display = self._define_display(controller)
+ if display in self.currentMediaPlayer:
+ display.override = {}
+ self.currentMediaPlayer[controller.controllerType].reset(display)
+ self.currentMediaPlayer[controller.controllerType] \
+ .set_visible(display, False)
+ display.frame.evaluateJavaScript(u'show_video( \
"setBackBoard", null, null, null,"hidden");')
- del self.curDisplayMediaPlayer[display]
+ del self.currentMediaPlayer[controller.controllerType]
- def video_hide(self, msg):
+ def media_hide(self, msg):
"""
Hide the related video Widget
@@ -513,15 +659,15 @@
isLive = msg[1]
if not isLive:
return
- controller = self.parent.liveController
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller != controller or \
- self.curDisplayMediaPlayer[display].state != MediaState.Playing:
- continue
- self.curDisplayMediaPlayer[display].pause(display)
- self.curDisplayMediaPlayer[display].set_visible(display, False)
+ controller = self.mainWindow.liveController
+ display = self._define_display(controller)
+ if self.currentMediaPlayer[controller.controllerType].state \
+ == MediaState.Playing:
+ self.currentMediaPlayer[controller.controllerType].pause(display)
+ self.currentMediaPlayer[controller.controllerType] \
+ .set_visible(display, False)
- def video_blank(self, msg):
+ def media_blank(self, msg):
"""
Blank the related video Widget
@@ -534,15 +680,15 @@
if not isLive:
return
Receiver.send_message(u'live_display_hide', hide_mode)
- controller = self.parent.liveController
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller != controller or \
- self.curDisplayMediaPlayer[display].state != MediaState.Playing:
- continue
- self.curDisplayMediaPlayer[display].pause(display)
- self.curDisplayMediaPlayer[display].set_visible(display, False)
+ controller = self.mainWindow.liveController
+ display = self._define_display(controller)
+ if self.currentMediaPlayer[controller.controllerType].state \
+ == MediaState.Playing:
+ self.currentMediaPlayer[controller.controllerType].pause(display)
+ self.currentMediaPlayer[controller.controllerType] \
+ .set_visible(display, False)
- def video_unblank(self, msg):
+ def media_unblank(self, msg):
"""
Unblank the related video Widget
@@ -554,35 +700,29 @@
isLive = msg[1]
if not isLive:
return
- controller = self.parent.liveController
- for display in self.curDisplayMediaPlayer.keys():
- if display.controller != controller or \
- self.curDisplayMediaPlayer[display].state != MediaState.Paused:
- continue
- if self.curDisplayMediaPlayer[display].play(display):
- self.curDisplayMediaPlayer[display].set_visible(display, True)
+ controller = self.mainWindow.liveController
+ display = self._define_display(controller)
+ if self.currentMediaPlayer[controller.controllerType].state \
+ != MediaState.Playing:
+ if self.currentMediaPlayer[controller.controllerType].play(display):
+ self.currentMediaPlayer[controller.controllerType] \
+ .set_visible(display, True)
# Start Timer for ui updates
if not self.timer.isActive():
self.timer.start()
- def get_audio_extensions_list(self):
- audio_list = []
- for player in self.mediaPlayers.values():
- if player.isActive:
- for item in player.audio_extensions_list:
- if not item in audio_list:
- audio_list.append(item)
- return audio_list
-
- def get_video_extensions_list(self):
- video_list = []
- for player in self.mediaPlayers.values():
- if player.isActive:
- video_list.extend([item for item in player.video_extensions_list
- if item not in video_list])
- return video_list
-
def finalise(self):
self.timer.stop()
- for controller in self.controller:
- self.video_reset(controller)
+ for controller in self.displayControllers:
+ self.media_reset(self.displayControllers[controller])
+
+ def _define_display(self, controller):
+ """
+ Extract the correct display for a given controller
+
+ ``controller``
+ Controller to be used
+ """
+ if controller.isLive:
+ return controller.display
+ return controller.previewDisplay
=== renamed file 'openlp/core/lib/mediaplayer.py' => 'openlp/core/ui/media/mediaplayer.py'
--- openlp/core/lib/mediaplayer.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/media/mediaplayer.py 2012-11-24 07:26:33 +0000
@@ -31,8 +31,8 @@
class MediaPlayer(object):
"""
- This is the base class media Player class to provide OpenLP with a pluggable media display
- framework.
+ This is the base class media Player class to provide OpenLP with a
+ pluggable media display framework.
"""
def __init__(self, parent, name=u'media_player'):
@@ -137,3 +137,9 @@
Add html code to htmlbuilder
"""
return u''
+
+ def get_info(self):
+ """
+ Returns Information about the player
+ """
+ return u''
=== modified file 'openlp/core/ui/media/phononplayer.py'
--- openlp/core/ui/media/phononplayer.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/media/phononplayer.py 2012-11-24 07:26:33 +0000
@@ -31,11 +31,15 @@
import mimetypes
from datetime import datetime
+from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
-from openlp.core.lib import Receiver
-from openlp.core.lib.mediaplayer import MediaPlayer
+from openlp.core.lib import Receiver, translate
+from openlp.core.lib.settings import Settings
+
from openlp.core.ui.media import MediaState
+from openlp.core.ui.media.mediaplayer import MediaPlayer
+
log = logging.getLogger(__name__)
@@ -56,6 +60,20 @@
u'video/mpeg' : [u'.mp4', u'.mts', u'.mov'],
u'video/x-ms-wmv': [u'.wmv']}
+VIDEO_CSS = u"""
+#videobackboard {
+ z-index:3;
+ background-color: %s;
+}
+#video1 {
+ background-color: %s;
+ z-index:4;
+}
+#video2 {
+ background-color: %s;
+ z-index:4;
+}
+"""
class PhononPlayer(MediaPlayer):
"""
@@ -205,3 +223,20 @@
if not controller.seekSlider.isSliderDown():
controller.seekSlider.setSliderPosition(
display.mediaObject.currentTime())
+
+ def get_media_display_css(self):
+ """
+ Add css style sheets to htmlbuilder
+ """
+ background = unicode(QtGui.QColor(Settings().value(
+ u'players/background color', QtCore.QVariant(u'#000000'))).name())
+ return VIDEO_CSS % (background,background,background)
+
+ def get_info(self):
+ return(translate('Media.player', 'Phonon is a media player which '
+ 'interacts with the operating system to provide media capabilities'
+ '.') +
+ u'<br/> <strong>' + translate('Media.player', 'Audio') +
+ u'</strong><br/>' + unicode(self.audio_extensions_list) +
+ u'<br/><strong>' + translate('Media.player', 'Video') +
+ u'</strong><br/>' + unicode(self.video_extensions_list) + u'<br/>')
\ No newline at end of file
=== added file 'openlp/core/ui/media/playertab.py'
--- openlp/core/ui/media/playertab.py 1970-01-01 00:00:00 +0000
+++ openlp/core/ui/media/playertab.py 2012-11-24 07:26:33 +0000
@@ -0,0 +1,257 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2012 Raoul Snyman #
+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Eric Ludin, 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, #
+# Erode Woldsund, Martin Zibricky #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import SettingsTab, translate, Receiver
+from openlp.core.lib.ui import UiStrings, create_button
+from openlp.core.lib.settings import Settings
+from openlp.core.ui.media import get_media_players, set_media_players
+
+class MediaQCheckBox(QtGui.QCheckBox):
+ """
+ MediaQCheckBox adds an extra property, playerName to the QCheckBox class.
+ """
+ def setPlayerName(self, name):
+ self.playerName = name
+
+
+class PlayerTab(SettingsTab):
+ """
+ MediaTab is the Media settings tab in the settings dialog.
+ """
+ def __init__(self, parent, mainWindow):
+ self.parent = parent
+ self.mainWindow = mainWindow
+ self.mediaPlayers = mainWindow.mediaController.mediaPlayers
+ self.savedUsedPlayers = None
+ self.iconPath = u':/system/system_settings.png'
+ player_translated = translate('OpenLP.PlayerTab', 'Players')
+ SettingsTab.__init__(self, parent, u'Players', player_translated)
+
+ def setupUi(self):
+ self.setObjectName(u'MediaTab')
+ SettingsTab.setupUi(self)
+ self.bgColorGroupBox = QtGui.QGroupBox(self.leftColumn)
+ self.bgColorGroupBox.setObjectName(u'FontGroupBox')
+ self.formLayout = QtGui.QFormLayout(self.bgColorGroupBox)
+ self.formLayout.setObjectName(u'FormLayout')
+ self.colorLayout = QtGui.QHBoxLayout()
+ self.backgroundColorLabel = QtGui.QLabel(self.bgColorGroupBox)
+ self.backgroundColorLabel.setObjectName(u'BackgroundColorLabel')
+ self.colorLayout.addWidget(self.backgroundColorLabel)
+ self.backgroundColorButton = QtGui.QPushButton(self.bgColorGroupBox)
+ self.backgroundColorButton.setObjectName(u'BackgroundColorButton')
+ self.colorLayout.addWidget(self.backgroundColorButton)
+ self.formLayout.addRow(self.colorLayout)
+ self.informationLabel = QtGui.QLabel(self.bgColorGroupBox)
+ self.informationLabel.setObjectName(u'InformationLabel')
+ self.informationLabel.setWordWrap(True)
+ self.formLayout.addRow(self.informationLabel)
+ self.leftLayout.addWidget(self.bgColorGroupBox)
+ self.leftLayout.addStretch()
+ self.rightColumn.setSizePolicy(
+ QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
+ self.rightLayout.addStretch()
+ self.mediaPlayerGroupBox = QtGui.QGroupBox(self.leftColumn)
+ self.mediaPlayerGroupBox.setObjectName(u'mediaPlayerGroupBox')
+ self.mediaPlayerLayout = QtGui.QVBoxLayout(self.mediaPlayerGroupBox)
+ self.mediaPlayerLayout.setObjectName(u'mediaPlayerLayout')
+ self.playerCheckBoxes = {}
+ self.leftLayout.addWidget(self.mediaPlayerGroupBox)
+ self.playerOrderGroupBox = QtGui.QGroupBox(self.leftColumn)
+ self.playerOrderGroupBox.setObjectName(u'playerOrderGroupBox')
+ self.playerOrderLayout = QtGui.QHBoxLayout(self.playerOrderGroupBox)
+ self.playerOrderLayout.setObjectName(u'playerOrderLayout')
+ self.playerOrderlistWidget = QtGui.QListWidget(
+ self.playerOrderGroupBox)
+ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,
+ QtGui.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.playerOrderlistWidget.\
+ sizePolicy().hasHeightForWidth())
+ self.playerOrderlistWidget.setSizePolicy(sizePolicy)
+ self.playerOrderlistWidget.setVerticalScrollBarPolicy(
+ QtCore.Qt.ScrollBarAsNeeded)
+ self.playerOrderlistWidget.setHorizontalScrollBarPolicy(
+ QtCore.Qt.ScrollBarAlwaysOff)
+ self.playerOrderlistWidget.setEditTriggers(
+ QtGui.QAbstractItemView.NoEditTriggers)
+ self.playerOrderlistWidget.setObjectName(u'playerOrderlistWidget')
+ self.playerOrderLayout.addWidget(self.playerOrderlistWidget)
+ self.orderingButtonLayout = QtGui.QVBoxLayout()
+ self.orderingButtonLayout.setObjectName(u'orderingButtonLayout')
+ self.orderingButtonLayout.addStretch(1)
+ self.orderingUpButton = create_button(self, u'orderingUpButton',
+ role=u'up', click=self.onUpButtonClicked)
+ self.orderingDownButton = create_button(self, u'orderingDownButton',
+ role=u'down', click=self.onDownButtonClicked)
+ self.orderingButtonLayout.addWidget(self.orderingUpButton)
+ self.orderingButtonLayout.addWidget(self.orderingDownButton)
+ self.orderingButtonLayout.addStretch(1)
+ self.playerOrderLayout.addLayout(self.orderingButtonLayout)
+ self.leftLayout.addWidget(self.playerOrderGroupBox)
+ self.leftLayout.addStretch()
+ self.rightLayout.addStretch()
+ # Signals and slots
+ QtCore.QObject.connect(self.backgroundColorButton,
+ QtCore.SIGNAL(u'clicked()'), self.onbackgroundColorButtonClicked)
+
+ def retranslateUi(self):
+ self.mediaPlayerGroupBox.setTitle(
+ translate('OpenLP.PlayerTab', 'Available Media Players'))
+ self.playerOrderGroupBox.setTitle(
+ translate('OpenLP.PlayerTab', 'Player Search Order'))
+ self.bgColorGroupBox.setTitle(
+ translate('ImagesPlugin.ImageTab', 'Background Color'))
+ self.backgroundColorLabel.setText(
+ translate('ImagesPlugin.ImageTab', 'Default Color:'))
+ self.informationLabel.setText(
+ translate('OpenLP.PlayerTab', 'Visible background for videos '
+ 'with aspect ratio different to screen.'))
+ self.retranslatePlayers()
+
+ def onbackgroundColorButtonClicked(self):
+ new_color = QtGui.QColorDialog.getColor(
+ QtGui.QColor(self.bg_color), self)
+ if new_color.isValid():
+ self.bg_color = new_color.name()
+ self.backgroundColorButton.setStyleSheet(
+ u'background-color: %s' % self.bg_color)
+
+ def onPlayerCheckBoxChanged(self, check_state):
+ player = self.sender().playerName
+ if check_state == QtCore.Qt.Checked:
+ if player not in self.usedPlayers:
+ self.usedPlayers.append(player)
+ else:
+ if player in self.usedPlayers:
+ self.usedPlayers.remove(player)
+ self.updatePlayerList()
+
+ def updatePlayerList(self):
+ self.playerOrderlistWidget.clear()
+ for player in self.usedPlayers:
+ if player in self.playerCheckBoxes.keys():
+ if len(self.usedPlayers) == 1:
+ # At least one media player has to stay active
+ self.playerCheckBoxes[u'%s' % player].setEnabled(False)
+ else:
+ self.playerCheckBoxes[u'%s' % player].setEnabled(True)
+ self.playerOrderlistWidget.addItem(
+ self.mediaPlayers[unicode(player)].original_name)
+
+ def onUpButtonClicked(self):
+ row = self.playerOrderlistWidget.currentRow()
+ if row <= 0:
+ return
+ item = self.playerOrderlistWidget.takeItem(row)
+ self.playerOrderlistWidget.insertItem(row - 1, item)
+ self.playerOrderlistWidget.setCurrentRow(row - 1)
+ self.usedPlayers.insert(row - 1, self.usedPlayers.pop(row))
+
+ def onDownButtonClicked(self):
+ row = self.playerOrderlistWidget.currentRow()
+ if row == -1 or row > self.playerOrderlistWidget.count() - 1:
+ return
+ item = self.playerOrderlistWidget.takeItem(row)
+ self.playerOrderlistWidget.insertItem(row + 1, item)
+ self.playerOrderlistWidget.setCurrentRow(row + 1)
+ self.usedPlayers.insert(row + 1, self.usedPlayers.pop(row))
+
+ def load(self):
+ if self.savedUsedPlayers:
+ self.usedPlayers = self.savedUsedPlayers
+ self.usedPlayers = get_media_players()[0]
+ self.savedUsedPlayers = self.usedPlayers
+
+ settings = Settings()
+ settings.beginGroup(self.settingsSection)
+ self.updatePlayerList()
+ self.bg_color = unicode(settings.value(
+ u'background color', QtCore.QVariant(u'#000000')).toString())
+ self.initial_color = self.bg_color
+ settings.endGroup()
+ self.backgroundColorButton.setStyleSheet(
+ u'background-color: %s' % self.bg_color)
+
+ def save(self):
+ player_string_changed = False
+ settings = Settings()
+ settings.beginGroup(self.settingsSection)
+ settings.setValue(u'background color', QtCore.QVariant(self.bg_color))
+ settings.endGroup()
+ old_players, override_player = get_media_players()
+ if self.usedPlayers != old_players:
+ # clean old Media stuff
+ set_media_players(self.usedPlayers, override_player)
+ player_string_changed = True
+ if player_string_changed:
+ self.parent.resetSupportedSuffixes()
+ Receiver.send_message(u'mediaitem_media_rebuild')
+ Receiver.send_message(u'config_screen_changed')
+
+ def postSetUp(self, postUpdate=False):
+ """
+ Late setup for players as the MediaController has to be initialised
+ first.
+ """
+ for key, player in self.mediaPlayers.iteritems():
+ player = self.mediaPlayers[key]
+ checkbox = MediaQCheckBox(self.mediaPlayerGroupBox)
+ checkbox.setEnabled(player.available)
+ checkbox.setObjectName(player.name + u'CheckBox')
+ checkbox.setToolTip(player.get_info())
+ checkbox.setPlayerName(player.name)
+ self.playerCheckBoxes[player.name] = checkbox
+ QtCore.QObject.connect(checkbox,QtCore.SIGNAL(u'stateChanged(int)'),
+ self.onPlayerCheckBoxChanged)
+ self.mediaPlayerLayout.addWidget(checkbox)
+ if player.available and player.name in self.usedPlayers:
+ checkbox.setChecked(True)
+ else:
+ checkbox.setChecked(False)
+ self.updatePlayerList()
+ self.retranslatePlayers()
+
+ def retranslatePlayers(self):
+ """
+ Translations for players is dependent on their setup as well
+ """
+ for key in self.mediaPlayers:
+ player = self.mediaPlayers[key]
+ checkbox = self.playerCheckBoxes[player.name]
+ checkbox.setPlayerName(player.name)
+ if player.available:
+ checkbox.setText(player.display_name)
+ else:
+ checkbox.setText(
+ unicode(translate('OpenLP.PlayerTab',
+ '%s (unavailable)')) % player.display_name)
\ No newline at end of file
=== added directory 'openlp/core/ui/media/vendor'
=== added file 'openlp/core/ui/media/vendor/__init__.py'
--- openlp/core/ui/media/vendor/__init__.py 1970-01-01 00:00:00 +0000
+++ openlp/core/ui/media/vendor/__init__.py 2012-11-24 07:26:33 +0000
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2012 Raoul Snyman #
+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Eric Ludin, 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, #
+# Erode Woldsund, Martin Zibricky #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
=== renamed file 'openlp/core/ui/media/vlc.py' => 'openlp/core/ui/media/vendor/vlc.py'
=== modified file 'openlp/core/ui/media/vlcplayer.py'
--- openlp/core/ui/media/vlcplayer.py 2012-11-20 13:04:46 +0000
+++ openlp/core/ui/media/vlcplayer.py 2012-11-24 07:26:33 +0000
@@ -35,16 +35,16 @@
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import Receiver
+from openlp.core.lib import Receiver, translate
from openlp.core.lib.settings import Settings
-from openlp.core.lib.mediaplayer import MediaPlayer
from openlp.core.ui.media import MediaState
+from openlp.core.ui.media.mediaplayer import MediaPlayer
log = logging.getLogger(__name__)
VLC_AVAILABLE = False
try:
- import vlc
+ from openlp.core.ui.media.vendor import vlc
VLC_AVAILABLE = bool(vlc.get_default_instance())
except (ImportError, NameError, NotImplementedError):
pass
@@ -188,7 +188,8 @@
def play(self, display):
controller = display.controller
start_time = 0
- if controller.media_info.start_time > 0:
+ if self.state != MediaState.Paused and \
+ controller.media_info.start_time > 0:
start_time = controller.media_info.start_time
display.vlcMediaPlayer.play()
if not self.media_state_wait(display, vlc.State.Playing):
@@ -244,3 +245,10 @@
controller.seekSlider.setSliderPosition( \
display.vlcMediaPlayer.get_time())
+ def get_info(self):
+ return(translate('Media.player', 'VLC is an external player which '
+ 'supports a number of different formats.') +
+ u'<br/> <strong>' + translate('Media.player', 'Audio') +
+ u'</strong><br/>' + unicode(AUDIO_EXT) + u'<br/><strong>' +
+ translate('Media.player', 'Video') + u'</strong><br/>' +
+ unicode(VIDEO_EXT) + u'<br/>')
\ No newline at end of file
=== modified file 'openlp/core/ui/media/webkitplayer.py'
--- openlp/core/ui/media/webkitplayer.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/media/webkitplayer.py 2012-11-24 07:26:33 +0000
@@ -27,22 +27,28 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
+from PyQt4 import QtCore, QtGui
+
import logging
-from openlp.core.lib.mediaplayer import MediaPlayer
+from openlp.core.lib import translate
from openlp.core.ui.media import MediaState
+from openlp.core.ui.media.mediaplayer import MediaPlayer
+from openlp.core.lib.settings import Settings
log = logging.getLogger(__name__)
VIDEO_CSS = u"""
#videobackboard {
z-index:3;
- background-color: black;
+ background-color: %s;
}
#video1 {
+ background-color: %s;
z-index:4;
}
#video2 {
+ background-color: %s;
z-index:4;
}
"""
@@ -277,7 +283,10 @@
"""
Add css style sheets to htmlbuilder
"""
- return VIDEO_CSS + FLASH_CSS
+ background = unicode(QtGui.QColor(Settings().value(
+ u'players/background color', QtCore.QVariant(u'#000000'))).name())
+ css = VIDEO_CSS % (background,background,background)
+ return css + FLASH_CSS
def get_media_display_javascript(self):
"""
@@ -324,7 +333,6 @@
return True
def resize(self, display):
- controller = display.controller
display.webView.resize(display.size())
def play(self, display):
@@ -431,3 +439,12 @@
controller.seekSlider.setMaximum(length)
if not controller.seekSlider.isSliderDown():
controller.seekSlider.setSliderPosition(currentTime)
+
+ def get_info(self):
+ return(translate('Media.player', 'Webkit is a media player which runs '
+ 'inside a web browser. This player allows text over video to be '
+ 'rendered.') +
+ u'<br/> <strong>' + translate('Media.player', 'Audio') +
+ u'</strong><br/>' + unicode(AUDIO_EXT) + u'<br/><strong>' +
+ translate('Media.player', 'Video') + u'</strong><br/>' +
+ unicode(VIDEO_EXT) + u'<br/>')
\ No newline at end of file
=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/servicemanager.py 2012-11-24 07:26:33 +0000
@@ -99,8 +99,8 @@
"""
Manages the services. This involves taking text strings from plugins and
adding them to the service. This service can then be zipped up with all
- the resources used into one OSZ file for use on any OpenLP v2 installation.
- Also handles the UI tasks of moving things up and down etc.
+ the resources used into one OSZ or oszl file for use on any OpenLP v2
+ installation. Also handles the UI tasks of moving things up and down etc.
"""
def __init__(self, mainwindow, parent=None):
"""
@@ -136,7 +136,7 @@
self.toolbar.addToolbarAction(u'saveService',
text=UiStrings().SaveService, icon=u':/general/general_save.png',
tooltip=translate('OpenLP.ServiceManager', 'Save this service.'),
- triggers=self.saveFile)
+ triggers=self.decideSaveMethod)
self.toolbar.addSeparator()
self.themeLabel = QtGui.QLabel(u'%s:' % UiStrings().Theme, self)
self.themeLabel.setMargin(3)
@@ -307,6 +307,9 @@
self.timeAction = create_widget_action(self.menu,
text=translate('OpenLP.ServiceManager', '&Start Time'),
icon=u':/media/media_time.png', triggers=self.onStartTimeForm)
+ self.autoStartAction = create_widget_action(self.menu,
+ text=u'',
+ icon=u':/media/media_time.png', triggers=self.onAutoStart)
# Add already existing delete action to the menu.
self.menu.addAction(self.serviceManagerList.delete)
self.menu.addSeparator()
@@ -359,6 +362,7 @@
self.shortFileName())
Settings(). \
setValue(u'servicemanager/last file',QtCore.QVariant(fileName))
+ self._saveLite = True if self._fileName.endswith(u'.oszl') else False
def fileName(self):
"""
@@ -380,6 +384,13 @@
u'advanced/expand service item',
QtCore.QVariant(u'False')).toBool()
+ def resetSupportedSuffixes(self):
+ """
+ Resets the Suffexes list.
+
+ """
+ self.suffixes = []
+
def supportedSuffixes(self, suffix):
"""
Adds Suffixes supported to the master list. Called from Plugins.
@@ -387,7 +398,8 @@
``suffix``
New Suffix to be supported
"""
- self.suffixes.append(suffix)
+ if not suffix in self.suffixes:
+ self.suffixes.append(suffix)
def onNewServiceClicked(self):
"""
@@ -398,7 +410,7 @@
if result == QtGui.QMessageBox.Cancel:
return False
elif result == QtGui.QMessageBox.Save:
- if not self.saveFile():
+ if not self.decideSaveMethod():
return False
self.newFile()
@@ -416,7 +428,7 @@
if result == QtGui.QMessageBox.Cancel:
return False
elif result == QtGui.QMessageBox.Save:
- self.saveFile()
+ self.decideSaveMethod()
if not loadFile:
fileName = unicode(QtGui.QFileDialog.getOpenFileName(
self.mainwindow,
@@ -424,7 +436,7 @@
SettingsManager.get_last_dir(
self.mainwindow.serviceManagerSettingsSection),
translate('OpenLP.ServiceManager',
- 'OpenLP Service Files (*.osz)')))
+ 'OpenLP Service Files (*.osz *.oszl)')))
if not fileName:
return False
else:
@@ -596,6 +608,73 @@
delete_file(temp_file_name)
return success
+ def saveLocalFile(self):
+ """
+ Save the current service file.
+
+ A temporary file is created so that we don't overwrite the existing one
+ and leave a mangled service file should there be an error when saving.
+ No files are added to this version of the service as it is deisgned
+ to only work on the machine it was save on if there are files.
+ """
+ if not self.fileName():
+ return self.saveFileAs()
+ temp_file, temp_file_name = mkstemp(u'.oszl', u'openlp_')
+ # We don't need the file handle.
+ os.close(temp_file)
+ log.debug(temp_file_name)
+ path_file_name = unicode(self.fileName())
+ path, file_name = os.path.split(path_file_name)
+ basename = os.path.splitext(file_name)[0]
+ service_file_name = '%s.osd' % basename
+ log.debug(u'ServiceManager.saveFile - %s', path_file_name)
+ SettingsManager.set_last_dir(
+ self.mainwindow.serviceManagerSettingsSection,
+ path)
+ service = []
+ Receiver.send_message(u'cursor_busy')
+ # Number of items + 1 to zip it
+ self.mainwindow.displayProgressBar(len(self.serviceItems) + 1)
+ for item in self.serviceItems:
+ self.mainwindow.incrementProgressBar()
+ service_item = item[u'service_item']. \
+ get_service_repr(self._saveLite)
+ #@todo check for file item on save.
+ service.append({u'serviceitem': service_item})
+ self.mainwindow.incrementProgressBar()
+ service_content = cPickle.dumps(service)
+ zip = None
+ success = True
+ self.mainwindow.incrementProgressBar()
+ try:
+ zip = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED,
+ True)
+ # First we add service contents.
+ zip.writestr(service_file_name.encode(u'utf-8'), service_content)
+ except IOError:
+ log.exception(u'Failed to save service to disk: %s', temp_file_name)
+ Receiver.send_message(u'openlp_error_message', {
+ u'title': translate(u'OpenLP.ServiceManager',
+ u'Error Saving File'),
+ u'message': translate(u'OpenLP.ServiceManager',
+ u'There was an error saving your file.')
+ })
+ success = False
+ finally:
+ if zip:
+ zip.close()
+ self.mainwindow.finishedProgressBar()
+ Receiver.send_message(u'cursor_normal')
+ if success:
+ try:
+ shutil.copy(temp_file_name, path_file_name)
+ except:
+ return self.saveFileAs()
+ self.mainwindow.addRecentFile(path_file_name)
+ self.setModified(False)
+ delete_file(temp_file_name)
+ return success
+
def saveFileAs(self):
"""
Get a file name and then call :func:`ServiceManager.saveFile` to
@@ -632,9 +711,19 @@
directory = unicode(SettingsManager.get_last_dir(
self.mainwindow.serviceManagerSettingsSection))
path = os.path.join(directory, default_filename)
- fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow,
- UiStrings().SaveService, path,
- translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')))
+ # SaveAs from osz to oszl is not valid as the files will be deleted
+ # on exit which is not sensible or usable in the long term.
+ if self._fileName.endswith(u'oszl') or not self._fileName:
+ fileName = unicode(QtGui.QFileDialog.getSaveFileName(
+ self.mainwindow, UiStrings().SaveService, path,
+ translate('OpenLP.ServiceManager',
+ 'OpenLP Service Files (*.osz);;'
+ 'OpenLP Service Files - lite (*.oszl)')))
+ else:
+ fileName = unicode(QtGui.QFileDialog.getSaveFileName(
+ self.mainwindow, UiStrings().SaveService, path,
+ translate('OpenLP.ServiceManager',
+ 'OpenLP Service Files (*.osz);;')))
if not fileName:
return False
if os.path.splitext(fileName)[1] == u'':
@@ -643,9 +732,23 @@
ext = os.path.splitext(fileName)[1]
fileName.replace(ext, u'.osz')
self.setFileName(fileName)
- return self.saveFile()
+ self.decideSaveMethod()
+
+ def decideSaveMethod(self):
+ """
+ Determine which type of save method to use.
+ """
+ if not self.fileName():
+ return self.saveFileAs()
+ if self._saveLite:
+ return self.saveLocalFile()
+ else:
+ return self.saveFile()
def loadFile(self, fileName):
+ """
+ Load an existing service file
+ """
if not fileName:
return False
fileName = unicode(fileName)
@@ -680,12 +783,16 @@
items = cPickle.load(fileTo)
fileTo.close()
self.newFile()
+ self.setFileName(fileName)
self.mainwindow.displayProgressBar(len(items))
for item in items:
self.mainwindow.incrementProgressBar()
serviceItem = ServiceItem()
serviceItem.renderer = self.mainwindow.renderer
- serviceItem.set_from_service(item, self.servicePath)
+ if self._saveLite:
+ serviceItem.set_from_service(item)
+ else:
+ serviceItem.set_from_service(item, self.servicePath)
self.validateItem(serviceItem)
self.load_item_uuid = 0
if serviceItem.is_capable(ItemCapabilities.OnLoadUpdate):
@@ -697,7 +804,6 @@
serviceItem.temporary_edit = self.load_item_temporary
self.addServiceItem(serviceItem, repaint=False)
delete_file(p_file)
- self.setFileName(fileName)
self.mainwindow.addRecentFile(fileName)
self.setModified(False)
Settings().setValue(
@@ -760,6 +866,7 @@
self.maintainAction.setVisible(False)
self.notesAction.setVisible(False)
self.timeAction.setVisible(False)
+ self.autoStartAction.setVisible(False)
if serviceItem[u'service_item'].is_capable(ItemCapabilities.CanEdit)\
and serviceItem[u'service_item'].edit_id:
self.editAction.setVisible(True)
@@ -771,6 +878,14 @@
if serviceItem[u'service_item']\
.is_capable(ItemCapabilities.HasVariableStartTime):
self.timeAction.setVisible(True)
+ if serviceItem[u'service_item']\
+ .is_capable(ItemCapabilities.CanAutoStartForLive):
+ self.autoStartAction.setVisible(True)
+ self.autoStartAction.setText(translate('OpenLP.ServiceManager',
+ '&Auto Start - inactive'))
+ if serviceItem[u'service_item'].will_auto_start:
+ self.autoStartAction.setText(translate('OpenLP.ServiceManager',
+ '&Auto Start - active'))
self.themeMenu.menuAction().setVisible(False)
# Set up the theme menu.
if serviceItem[u'service_item'].is_text() and \
@@ -805,6 +920,14 @@
if self.startTimeForm.exec_():
self.repaintServiceList(item, -1)
+ def onAutoStart(self):
+ """
+ Toggles to Auto Start Setting.
+ """
+ item = self.findServiceItem()[0]
+ self.serviceItems[item][u'service_item'].will_auto_start = \
+ not self.serviceItems[item][u'service_item'].will_auto_start
+
def onServiceItemEditForm(self):
"""
Opens a dialog to edit the service item and update the service
@@ -1095,10 +1218,12 @@
Validates the service item and if the suffix matches an accepted
one it allows the item to be displayed.
"""
+ #@todo check file items exist
if serviceItem.is_command():
type = serviceItem._raw_frames[0][u'title'].split(u'.')[-1]
if type.lower() not in self.suffixes:
serviceItem.is_valid = False
+ #@todo check file items exist
def cleanUp(self):
"""
@@ -1379,6 +1504,9 @@
filename = unicode(url.toLocalFile())
if filename.endswith(u'.osz'):
self.onLoadServiceClicked(filename)
+ elif filename.endswith(u'.oszl'):
+ # todo correct
+ self.onLoadServiceClicked(filename)
elif link.hasText():
plugin = unicode(link.text())
item = self.serviceManagerList.itemAt(event.pos())
=== modified file 'openlp/core/ui/settingsform.py'
--- openlp/core/ui/settingsform.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/settingsform.py 2012-11-24 07:26:33 +0000
@@ -35,6 +35,7 @@
from openlp.core.lib import Receiver, build_icon, PluginStatus
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
+from openlp.core.ui.media import PlayerTab
from settingsdialog import Ui_SettingsDialog
log = logging.getLogger(__name__)
@@ -47,6 +48,7 @@
"""
Initialise the settings form
"""
+ self.mainWindow = mainWindow
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
# General tab
@@ -55,6 +57,8 @@
self.themesTab = ThemesTab(self, mainWindow)
# Advanced tab
self.advancedTab = AdvancedTab(self)
+ # Advanced tab
+ self.playerTab = PlayerTab(self, mainWindow)
def exec_(self):
# load all the settings
@@ -65,7 +69,8 @@
self.insertTab(self.generalTab, 0, PluginStatus.Active)
self.insertTab(self.themesTab, 1, PluginStatus.Active)
self.insertTab(self.advancedTab, 2, PluginStatus.Active)
- count = 3
+ self.insertTab(self.playerTab, 3, PluginStatus.Active)
+ count = 4
for plugin in self.plugins:
if plugin.settingsTab:
self.insertTab(plugin.settingsTab, count, plugin.status)
@@ -94,6 +99,7 @@
"""
Process the form saving the settings
"""
+ self.resetSuffexes = True
for tabIndex in range(self.stackedLayout.count()):
self.stackedLayout.widget(tabIndex).save()
# Must go after all settings are save
@@ -115,6 +121,7 @@
self.generalTab.postSetUp()
self.themesTab.postSetUp()
self.advancedTab.postSetUp()
+ self.playerTab.postSetUp()
for plugin in self.plugins:
if plugin.settingsTab:
plugin.settingsTab.postSetUp()
@@ -125,3 +132,13 @@
"""
self.stackedLayout.setCurrentIndex(tabIndex)
self.stackedLayout.currentWidget().tabVisible()
+
+ def resetSupportedSuffixes(self):
+ """
+ Control the resetting of the serviceManager suffex list as can be
+ called by a number of settings tab and only needs to be called once
+ per save.
+ """
+ if self.resetSuffexes:
+ self.mainWindow.serviceManagerContents.resetSupportedSuffixes()
+ self.resetSuffexes = False
\ No newline at end of file
=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py 2012-11-11 21:16:14 +0000
+++ openlp/core/ui/slidecontroller.py 2012-11-24 07:26:33 +0000
@@ -39,7 +39,8 @@
from openlp.core.lib.ui import UiStrings, create_action
from openlp.core.lib.settings import Settings
from openlp.core.lib import SlideLimits, ServiceItemAction
-from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList
+from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList, \
+ DisplayControllerType
from openlp.core.utils.actions import ActionList, CategoryOrder
log = logging.getLogger(__name__)
@@ -53,9 +54,9 @@
QtGui.QTableWidget.__init__(self, parent.controller)
-class Controller(QtGui.QWidget):
+class DisplayController(QtGui.QWidget):
"""
- Controller is a general controller widget.
+ Controller is a general display controller widget.
"""
def __init__(self, parent, isLive=False):
"""
@@ -64,6 +65,7 @@
QtGui.QWidget.__init__(self, parent)
self.isLive = isLive
self.display = None
+ self.controllerType = DisplayControllerType.Plugin
def sendToPlugins(self, *args):
"""
@@ -77,7 +79,7 @@
Receiver.send_message('%s' % sender, [controller, args])
-class SlideController(Controller):
+class SlideController(DisplayController):
"""
SlideController is the slide controller widget. This widget is what the
user uses to control the displaying of verses/slides/etc on the screen.
@@ -86,7 +88,7 @@
"""
Set up the Slide Controller.
"""
- Controller.__init__(self, parent, isLive)
+ DisplayController.__init__(self, parent, isLive)
self.screens = ScreenList()
try:
self.ratio = float(self.screens.current[u'size'].width()) / \
@@ -193,7 +195,9 @@
category=self.category, triggers=self.onSlideSelectedNextAction)
self.toolbar.addAction(self.nextItem)
self.toolbar.addSeparator()
+ self.controllerType = DisplayControllerType.Preview
if self.isLive:
+ self.controllerType = DisplayControllerType.Live
# Hide Menu
self.hideMenu = QtGui.QToolButton(self.toolbar)
self.hideMenu.setObjectName(u'hideMenu')
@@ -271,7 +275,7 @@
'Edit and reload song preview.'), triggers=self.onEditSong)
self.controllerLayout.addWidget(self.toolbar)
# Build the Media Toolbar
- self.mediaController.add_controller_items(self, self.controllerLayout)
+ self.mediaController.register_controller(self)
if self.isLive:
# Build the Song Toolbar
self.songMenu = QtGui.QToolButton(self.toolbar)
@@ -524,7 +528,7 @@
def liveEscape(self):
self.display.setVisible(False)
- self.mediaController.video_stop([self])
+ self.mediaController.media_stop(self)
def toggleDisplay(self, action):
"""
@@ -594,14 +598,14 @@
float(self.screens.current[u'size'].height())
except ZeroDivisionError:
self.ratio = 1
- self.mediaController.setup_display(self.display)
+ self.mediaController.setup_display(self.display, False)
self.previewSizeChanged()
self.previewDisplay.setup()
serviceItem = ServiceItem()
self.previewDisplay.webView.setHtml(build_html(serviceItem,
self.previewDisplay.screen, None, self.isLive,
plugins=PluginManager.get_instance().plugins))
- self.mediaController.setup_display(self.previewDisplay)
+ self.mediaController.setup_display(self.previewDisplay,True)
if self.serviceItem:
self.refreshServiceItem()
@@ -1351,9 +1355,8 @@
Respond to the arrival of a media service item
"""
log.debug(u'SlideController onMediaStart')
- file = item.get_frame_path()
- self.mediaController.video(self, file, False, False, self.hideMode())
- if not self.isLive or self.mediaController.withLivePreview:
+ self.mediaController.video(self.controllerType, item, self.hideMode())
+ if not self.isLive:
self.previewDisplay.show()
self.slidePreview.hide()
@@ -1362,7 +1365,7 @@
Respond to a request to close the Video
"""
log.debug(u'SlideController onMediaClose')
- self.mediaController.video_reset(self)
+ self.mediaController.media_reset(self)
self.previewDisplay.hide()
self.slidePreview.show()
=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py 2012-11-24 07:26:33 +0000
@@ -32,7 +32,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
- translate, create_separated_list
+ translate, create_separated_list, ServiceItemContext
from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings, set_case_insensitive_completer, \
@@ -894,7 +894,7 @@
return items
def generateSlideData(self, service_item, item=None, xmlVersion=False,
- remote=False):
+ remote=False,context=ServiceItemContext.Service):
"""
Generates and formats the slides for the service item as well as the
service item's title.
=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/custom/lib/mediaitem.py 2012-11-24 07:26:33 +0000
@@ -33,7 +33,7 @@
from sqlalchemy.sql import or_, func
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
- check_item_selected, translate
+ check_item_selected, translate, ServiceItemContext
from openlp.core.lib.ui import UiStrings
from openlp.core.lib.settings import Settings
from openlp.plugins.custom.forms import EditCustomForm
@@ -195,7 +195,7 @@
self.searchTextEdit.setFocus()
def generateSlideData(self, service_item, item=None, xmlVersion=False,
- remote=False):
+ remote=False, context=ServiceItemContext.Service):
item_id = self._getIdOfItemToGenerate(item, self.remoteCustom)
service_item.add_capability(ItemCapabilities.CanEdit)
service_item.add_capability(ItemCapabilities.CanPreview)
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/images/lib/mediaitem.py 2012-11-24 07:26:33 +0000
@@ -34,7 +34,7 @@
from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
SettingsManager, translate, check_item_selected, check_directory_exists, \
- Receiver, create_thumb, validate_thumb
+ Receiver, create_thumb, validate_thumb, ServiceItemContext
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation, delete_file, locale_compare, \
@@ -153,7 +153,7 @@
Receiver.send_message(u'cursor_normal')
def generateSlideData(self, service_item, item=None, xmlVersion=False,
- remote=False):
+ remote=False,context=ServiceItemContext.Service):
background = QtGui.QColor(Settings().value(self.settingsSection
+ u'/background color', QtCore.QVariant(u'#000000')))
if item:
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/media/lib/mediaitem.py 2012-11-24 07:26:33 +0000
@@ -34,20 +34,21 @@
from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
SettingsManager, translate, check_item_selected, Receiver, MediaType, \
- ServiceItem, build_html
+ ServiceItem, build_html, ServiceItemContext
+from openlp.core.lib.settings import Settings
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
create_horizontal_adjusting_combo_box
-from openlp.core.ui import Controller, Display
+from openlp.core.ui import DisplayController, Display, DisplayControllerType
from openlp.core.ui.media import get_media_players, set_media_players
from openlp.core.utils import locale_compare
log = logging.getLogger(__name__)
CLAPPERBOARD = u':/media/slidecontroller_multimedia.png'
-VIDEO = QtGui.QImage(u':/media/media_video.png')
-AUDIO = QtGui.QImage(u':/media/media_audio.png')
-DVD_ICON = QtGui.QImage(u':/media/media_video.png')
-ERROR = QtGui.QImage(u':/general/general_delete.png')
+VIDEO = build_icon(QtGui.QImage(u':/media/media_video.png'))
+AUDIO = build_icon(QtGui.QImage(u':/media/media_audio.png'))
+DVDICON = build_icon(QtGui.QImage(u':/media/media_video.png'))
+ERROR = build_icon(QtGui.QImage(u':/general/general_delete.png'))
class MediaMediaItem(MediaManagerItem):
"""
@@ -58,39 +59,31 @@
def __init__(self, parent, plugin, icon):
self.iconPath = u'images/image'
self.background = False
- self.previewFunction = CLAPPERBOARD
self.automatic = u''
MediaManagerItem.__init__(self, parent, plugin, icon)
self.singleServiceItem = False
self.hasSearch = True
self.mediaObject = None
- self.mediaController = Controller(parent)
- self.mediaController.controllerLayout = QtGui.QVBoxLayout()
- self.plugin.mediaController.add_controller_items(self.mediaController, \
- self.mediaController.controllerLayout)
- self.plugin.mediaController.set_controls_visible(self.mediaController, \
+ self.displayController = DisplayController(parent)
+ self.displayController.controllerLayout = QtGui.QVBoxLayout()
+ self.plugin.mediaController.register_controller(self.displayController)
+ self.plugin.mediaController.set_controls_visible(self.displayController,
False)
- self.mediaController.previewDisplay = Display(self.mediaController, \
- False, self.mediaController)
- self.mediaController.previewDisplay.setGeometry(
+ self.displayController.previewDisplay = Display(self.displayController,
+ False, self.displayController)
+ self.displayController.previewDisplay.hide()
+ self.displayController.previewDisplay.setGeometry(
QtCore.QRect(0, 0, 300, 300))
- self.mediaController.previewDisplay.screen = \
- {u'size':self.mediaController.previewDisplay.geometry()}
- self.mediaController.previewDisplay.setup()
- serviceItem = ServiceItem()
- self.mediaController.previewDisplay.webView.setHtml(build_html( \
- serviceItem, self.mediaController.previewDisplay.screen, None, \
- False, None))
- self.mediaController.previewDisplay.setup()
- self.plugin.mediaController.setup_display( \
- self.mediaController.previewDisplay)
- self.mediaController.previewDisplay.hide()
-
+ self.displayController.previewDisplay.screen = \
+ {u'size':self.displayController.previewDisplay.geometry()}
+ self.displayController.previewDisplay.setup()
+ self.plugin.mediaController.setup_display(
+ self.displayController.previewDisplay, False)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'video_background_replaced'),
self.videobackgroundReplaced)
QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.rebuild)
+ QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.rebuild_players)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_screen_changed'), self.displaySetup)
# Allow DnD from the desktop
@@ -98,18 +91,14 @@
def retranslateUi(self):
self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
- self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem',
- 'Videos (%s);;Audio (%s);;%s (*)')) % (
- u' '.join(self.plugin.video_extensions_list),
- u' '.join(self.plugin.audio_extensions_list), UiStrings().AllFiles)
self.replaceAction.setText(UiStrings().ReplaceBG)
self.replaceAction.setToolTip(UiStrings().ReplaceLiveBG)
self.resetAction.setText(UiStrings().ResetBG)
self.resetAction.setToolTip(UiStrings().ResetLiveBG)
- self.automatic = translate('MediaPlugin.MediaItem',
- 'Automatic')
+ self.automatic = UiStrings().Automatic
self.displayTypeLabel.setText(
translate('MediaPlugin.MediaItem', 'Use Player:'))
+ self.rebuild_players()
def requiredIcons(self):
MediaManagerItem.requiredIcons(self)
@@ -157,7 +146,7 @@
"""
Called to reset the Live background with the media selected,
"""
- self.plugin.liveController.mediaController.video_reset( \
+ self.plugin.liveController.mediaController.media_reset(
self.plugin.liveController)
self.resetAction.setVisible(False)
@@ -177,8 +166,15 @@
item = self.listView.currentItem()
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
- if self.plugin.liveController.mediaController.video( \
- self.plugin.liveController, filename, True, True):
+ service_item = ServiceItem()
+ service_item.title = \
+ unicode(self.displayTypeComboBox.currentText())
+ service_item.shortname = service_item.title
+ (path, name) = os.path.split(filename)
+ service_item.add_from_command(path, name,CLAPPERBOARD)
+ if self.plugin.liveController.mediaController.video(
+ DisplayControllerType.Live, service_item,
+ videoBehindText=True):
self.resetAction.setVisible(True)
else:
critical_error_message_box(UiStrings().LiveBGError,
@@ -191,7 +187,7 @@
'the media file "%s" no longer exists.')) % filename)
def generateSlideData(self, service_item, item=None, xmlVersion=False,
- remote=False):
+ remote=False, context=ServiceItemContext.Live):
if item is None:
item = self.listView.currentItem()
if item is None:
@@ -202,37 +198,27 @@
# File is no longer present
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Missing Media File'),
- unicode(translate('MediaPlugin.MediaItem',
- 'The file %s no longer exists.')) % filename)
- return False
- self.mediaLength = 0
- # Get media information and its length.
- #
- # This code (mediaController.video()) starts playback but we
- # need only media information not video to start. Otherwise
- # video is played twice. Find another way to get media info
- # without loading and starting video playback.
- #
- # TODO Test getting media length with other media backends
- # Phonon/Webkit.
- if self.plugin.mediaController.video(self.mediaController,
- filename, muted=False, isBackground=False, isInfo=True,
- controlsVisible=False):
- self.mediaLength = self.mediaController.media_info.length
- service_item.media_length = self.mediaLength
- if self.mediaLength > 0:
- service_item.add_capability(
- ItemCapabilities.HasVariableStartTime)
- else:
- return False
- service_item.media_length = self.mediaLength
- service_item.title = unicode(self.plugin.nameStrings[u'singular'])
+ unicode(translate('MediaPlugin.MediaItem',
+ 'The file %s no longer exists.')) % filename)
+ return False
+ service_item.title = unicode(self.displayTypeComboBox.currentText())
+ service_item.shortname = service_item.title
+ (path, name) = os.path.split(filename)
+ 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.plugin.mediaController.media_length(service_item):
+ return False
+ service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
service_item.add_capability(ItemCapabilities.RequiresMedia)
- # force a non-existent theme
+ service_item.add_capability(ItemCapabilities.HasDetailedTitleDisplay)
+ if Settings().value(self.settingsSection + u'/media auto start',
+ QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0]\
+ == QtCore.Qt.Checked:
+ service_item.will_auto_start = True
+ # force a non-existent theme
service_item.theme = -1
- frame = CLAPPERBOARD
- (path, name) = os.path.split(filename)
- service_item.add_from_command(path, name, frame)
return True
def initialise(self):
@@ -241,7 +227,7 @@
self.loadList(SettingsManager.load_list(self.settingsSection, u'media'))
self.populateDisplayTypes()
- def rebuild(self):
+ def rebuild_players(self):
"""
Rebuild the tab in the media manager when changes are made in
the settings
@@ -249,12 +235,13 @@
self.populateDisplayTypes()
self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem',
'Videos (%s);;Audio (%s);;%s (*)')) % (
- u' '.join(self.plugin.video_extensions_list),
- u' '.join(self.plugin.audio_extensions_list), UiStrings().AllFiles)
+ u' '.join(self.plugin.mediaController.video_extensions_list),
+ u' '.join(self.plugin.mediaController.audio_extensions_list),
+ UiStrings().AllFiles)
def displaySetup(self):
- self.plugin.mediaController.setup_display( \
- self.mediaController.previewDisplay)
+ self.plugin.mediaController.setup_display(
+ self.displayController.previewDisplay, False)
def populateDisplayTypes(self):
"""
@@ -305,18 +292,21 @@
if not os.path.exists(track):
filename = os.path.split(unicode(track))[1]
item_name = QtGui.QListWidgetItem(filename)
- item_name.setIcon(build_icon(ERROR))
+ item_name.setIcon(ERROR)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
elif track_info.isFile():
filename = os.path.split(unicode(track))[1]
item_name = QtGui.QListWidgetItem(filename)
- item_name.setIcon(build_icon(VIDEO))
+ if u'*.%s' % (filename.split(u'.')[-1].lower()) in \
+ self.plugin.mediaController.audio_extensions_list:
+ item_name.setIcon(AUDIO)
+ else:
+ item_name.setIcon(VIDEO)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
else:
filename = os.path.split(unicode(track))[1]
item_name = QtGui.QListWidgetItem(filename)
- #TODO: add the appropriate Icon
- #item_name.setIcon(build_icon(DVD_ICON))
+ item_name.setIcon(build_icon(DVDICON))
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(track))
item_name.setToolTip(track)
self.listView.addItem(item_name)
=== modified file 'openlp/plugins/media/lib/mediatab.py'
--- openlp/plugins/media/lib/mediatab.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/media/lib/mediatab.py 2012-11-24 07:26:33 +0000
@@ -33,6 +33,7 @@
from openlp.core.lib.ui import UiStrings, create_button
from openlp.core.lib.settings import Settings
from openlp.core.ui.media import get_media_players, set_media_players
+
class MediaQCheckBox(QtGui.QCheckBox):
"""
MediaQCheckBox adds an extra property, playerName to the QCheckBox class.
@@ -45,60 +46,13 @@
"""
MediaTab is the Media settings tab in the settings dialog.
"""
- def __init__(self, parent, title, visible_title, media_players, icon_path):
- self.mediaPlayers = media_players
- self.savedUsedPlayers = None
+ def __init__(self, parent, title, visible_title, icon_path):
+ self.parent = parent
SettingsTab.__init__(self, parent, title, visible_title, icon_path)
def setupUi(self):
self.setObjectName(u'MediaTab')
SettingsTab.setupUi(self)
- self.mediaPlayerGroupBox = QtGui.QGroupBox(self.leftColumn)
- self.mediaPlayerGroupBox.setObjectName(u'mediaPlayerGroupBox')
- self.mediaPlayerLayout = QtGui.QVBoxLayout(self.mediaPlayerGroupBox)
- self.mediaPlayerLayout.setObjectName(u'mediaPlayerLayout')
- self.playerCheckBoxes = {}
- for key, player in self.mediaPlayers.iteritems():
- player = self.mediaPlayers[key]
- checkbox = MediaQCheckBox(self.mediaPlayerGroupBox)
- checkbox.setEnabled(player.available)
- checkbox.setObjectName(player.name + u'CheckBox')
- self.playerCheckBoxes[player.name] = checkbox
- self.mediaPlayerLayout.addWidget(checkbox)
- self.leftLayout.addWidget(self.mediaPlayerGroupBox)
- self.playerOrderGroupBox = QtGui.QGroupBox(self.leftColumn)
- self.playerOrderGroupBox.setObjectName(u'playerOrderGroupBox')
- self.playerOrderLayout = QtGui.QHBoxLayout(self.playerOrderGroupBox)
- self.playerOrderLayout.setObjectName(u'playerOrderLayout')
- self.playerOrderlistWidget = QtGui.QListWidget( \
- self.playerOrderGroupBox)
- sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,
- QtGui.QSizePolicy.Expanding)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.playerOrderlistWidget. \
- sizePolicy().hasHeightForWidth())
- self.playerOrderlistWidget.setSizePolicy(sizePolicy)
- self.playerOrderlistWidget.setVerticalScrollBarPolicy( \
- QtCore.Qt.ScrollBarAsNeeded)
- self.playerOrderlistWidget.setHorizontalScrollBarPolicy( \
- QtCore.Qt.ScrollBarAlwaysOff)
- self.playerOrderlistWidget.setEditTriggers( \
- QtGui.QAbstractItemView.NoEditTriggers)
- self.playerOrderlistWidget.setObjectName(u'playerOrderlistWidget')
- self.playerOrderLayout.addWidget(self.playerOrderlistWidget)
- self.orderingButtonLayout = QtGui.QVBoxLayout()
- self.orderingButtonLayout.setObjectName(u'orderingButtonLayout')
- self.orderingButtonLayout.addStretch(1)
- self.orderingUpButton = create_button(self, u'orderingUpButton',
- role=u'up', click=self.onUpButtonClicked)
- self.orderingDownButton = create_button(self, u'orderingDownButton',
- role=u'down', click=self.onDownButtonClicked)
- self.orderingButtonLayout.addWidget(self.orderingUpButton)
- self.orderingButtonLayout.addWidget(self.orderingDownButton)
- self.orderingButtonLayout.addStretch(1)
- self.playerOrderLayout.addLayout(self.orderingButtonLayout)
- self.leftLayout.addWidget(self.playerOrderGroupBox)
self.advancedGroupBox = QtGui.QGroupBox(self.leftColumn)
self.advancedGroupBox.setObjectName(u'advancedGroupBox')
self.advancedLayout = QtGui.QVBoxLayout(self.advancedGroupBox)
@@ -106,110 +60,44 @@
self.overridePlayerCheckBox = QtGui.QCheckBox(self.advancedGroupBox)
self.overridePlayerCheckBox.setObjectName(u'overridePlayerCheckBox')
self.advancedLayout.addWidget(self.overridePlayerCheckBox)
+ self.autoStartCheckBox = QtGui.QCheckBox(self.advancedGroupBox)
+ self.autoStartCheckBox.setObjectName(u'autoStartCheckBox')
+ self.advancedLayout.addWidget(self.autoStartCheckBox)
self.leftLayout.addWidget(self.advancedGroupBox)
self.leftLayout.addStretch()
self.rightLayout.addStretch()
- for key in self.mediaPlayers:
- player = self.mediaPlayers[key]
- checkbox = self.playerCheckBoxes[player.name]
- QtCore.QObject.connect(checkbox,
- QtCore.SIGNAL(u'stateChanged(int)'),
- self.onPlayerCheckBoxChanged)
def retranslateUi(self):
- self.mediaPlayerGroupBox.setTitle(
- translate('MediaPlugin.MediaTab', 'Available Media Players'))
- for key in self.mediaPlayers:
- player = self.mediaPlayers[key]
- checkbox = self.playerCheckBoxes[player.name]
- checkbox.setPlayerName(player.name)
- if player.available:
- checkbox.setText(player.display_name)
- else:
- checkbox.setText(
- unicode(translate('MediaPlugin.MediaTab',
- '%s (unavailable)')) % player.display_name)
- self.playerOrderGroupBox.setTitle(
- translate('MediaPlugin.MediaTab', 'Player Order'))
self.advancedGroupBox.setTitle(UiStrings().Advanced)
self.overridePlayerCheckBox.setText(
translate('MediaPlugin.MediaTab',
'Allow media player to be overridden'))
-
- def onPlayerCheckBoxChanged(self, check_state):
- player = self.sender().playerName
- if check_state == QtCore.Qt.Checked:
- if player not in self.usedPlayers:
- self.usedPlayers.append(player)
- else:
- if player in self.usedPlayers:
- self.usedPlayers.remove(player)
- self.updatePlayerList()
-
- def updatePlayerList(self):
- self.playerOrderlistWidget.clear()
- for player in self.usedPlayers:
- if player in self.playerCheckBoxes.keys():
- if len(self.usedPlayers) == 1:
- # At least one media player has to stay active
- self.playerCheckBoxes[u'%s' % player].setEnabled(False)
- else:
- self.playerCheckBoxes[u'%s' % player].setEnabled(True)
- self.playerOrderlistWidget.addItem(
- self.mediaPlayers[unicode(player)].original_name)
-
- def onUpButtonClicked(self):
- row = self.playerOrderlistWidget.currentRow()
- if row <= 0:
- return
- item = self.playerOrderlistWidget.takeItem(row)
- self.playerOrderlistWidget.insertItem(row - 1, item)
- self.playerOrderlistWidget.setCurrentRow(row - 1)
- self.usedPlayers.insert(row - 1, self.usedPlayers.pop(row))
-
- def onDownButtonClicked(self):
- row = self.playerOrderlistWidget.currentRow()
- if row == -1 or row > self.playerOrderlistWidget.count() - 1:
- return
- item = self.playerOrderlistWidget.takeItem(row)
- self.playerOrderlistWidget.insertItem(row + 1, item)
- self.playerOrderlistWidget.setCurrentRow(row + 1)
- self.usedPlayers.insert(row + 1, self.usedPlayers.pop(row))
+ self.autoStartCheckBox.setText(
+ translate('MediaPlugin.MediaTab',
+ 'Start Live items automatically'))
def load(self):
- if self.savedUsedPlayers:
- self.usedPlayers = self.savedUsedPlayers
- self.usedPlayers = get_media_players()[0]
- self.savedUsedPlayers = self.usedPlayers
- for key in self.mediaPlayers:
- player = self.mediaPlayers[key]
- checkbox = self.playerCheckBoxes[player.name]
- if player.available and player.name in self.usedPlayers:
- checkbox.setChecked(True)
- else:
- checkbox.setChecked(False)
- self.updatePlayerList()
self.overridePlayerCheckBox.setChecked(Settings().value(
self.settingsSection + u'/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0])
+ self.autoStartCheckBox.setChecked(Settings().value(
+ self.settingsSection + u'/media auto start',
+ QtCore.QVariant(QtCore.Qt.Unchecked)).toInt()[0])
def save(self):
override_changed = False
- player_string_changed = False
- old_players, override_player = get_media_players()
- if self.usedPlayers != old_players:
- # clean old Media stuff
- set_media_players(self.usedPlayers, override_player)
- player_string_changed = True
- override_changed = True
setting_key = self.settingsSection + u'/override player'
if Settings().value(setting_key).toInt()[0] != \
self.overridePlayerCheckBox.checkState():
Settings().setValue(setting_key,
QtCore.QVariant(self.overridePlayerCheckBox.checkState()))
override_changed = True
+ setting_key = self.settingsSection + u'/media auto start'
+ if Settings().value(setting_key).toInt()[0] !=\
+ self.autoStartCheckBox.checkState():
+ Settings().setValue(setting_key,
+ QtCore.QVariant(self.autoStartCheckBox.checkState()))
if override_changed:
- Receiver.send_message(u'mediaitem_media_rebuild')
- if player_string_changed:
- Receiver.send_message(u'mediaitem_media_rebuild')
- Receiver.send_message(u'config_screen_changed')
+ self.parent.resetSupportedSuffixes()
+ Receiver.send_message(u'mediaitem_media_rebuild')
+ Receiver.send_message(u'mediaitem_suffexes')
\ No newline at end of file
=== modified file 'openlp/plugins/media/mediaplugin.py'
--- openlp/plugins/media/mediaplugin.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/media/mediaplugin.py 2012-11-24 07:26:33 +0000
@@ -48,14 +48,6 @@
self.icon = build_icon(self.iconPath)
# passed with drag and drop messages
self.dnd_id = u'Media'
- self.audio_extensions_list = \
- self.mediaController.get_audio_extensions_list()
- for ext in self.audio_extensions_list:
- self.serviceManager.supportedSuffixes(ext[2:])
- self.video_extensions_list = \
- self.mediaController.get_video_extensions_list()
- for ext in self.video_extensions_list:
- self.serviceManager.supportedSuffixes(ext[2:])
def createSettingsTab(self, parent):
"""
@@ -63,7 +55,7 @@
"""
visible_name = self.getString(StringContent.VisibleName)
self.settingsTab = MediaTab(parent, self.name, visible_name[u'title'],
- self.mediaController.mediaPlayers, self.iconPath)
+ self.iconPath)
def about(self):
about_text = translate('MediaPlugin', '<strong>Media Plugin</strong>'
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py 2012-11-24 07:26:33 +0000
@@ -34,7 +34,7 @@
from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
translate, check_item_selected, Receiver, ItemCapabilities, create_thumb, \
- validate_thumb
+ validate_thumb, ServiceItemContext
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
create_horizontal_adjusting_combo_box
from openlp.core.lib.settings import Settings
@@ -64,7 +64,10 @@
self.hasSearch = True
self.singleServiceItem = False
QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
+ QtCore.SIGNAL(u'mediaitem_presentation_rebuild'),
+ self.populateDisplayTypes)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'mediaitem_suffexes'), self.buildFileMaskString)
# Allow DnD from the desktop
self.listView.activateDnD()
@@ -133,14 +136,6 @@
self.loadList(files, True)
self.populateDisplayTypes()
- def rebuild(self):
- """
- Rebuild the tab in the media manager when changes are made in
- the settings
- """
- self.populateDisplayTypes()
- self.buildFileMaskString()
-
def populateDisplayTypes(self):
"""
Load the combobox with the enabled presentation controllers,
@@ -260,7 +255,7 @@
u'presentations', self.getFileList())
def generateSlideData(self, service_item, item=None, xmlVersion=False,
- remote=False):
+ remote=False, context=ServiceItemContext.Service):
"""
Load the relevant information for displaying the presentation
in the slidecontroller. In the case of powerpoints, an image
=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
--- openlp/plugins/presentations/lib/presentationtab.py 2012-11-11 21:16:14 +0000
+++ openlp/plugins/presentations/lib/presentationtab.py 2012-11-24 07:26:33 +0000
@@ -41,6 +41,7 @@
"""
Constructor
"""
+ self.parent = parent
self.controllers = controllers
SettingsTab.__init__(self, parent, title, visible_title, icon_path)
self.activated = False
@@ -142,7 +143,9 @@
QtCore.QVariant(self.OverrideAppCheckBox.checkState()))
changed = True
if changed:
+ self.parent.resetSupportedSuffixes()
Receiver.send_message(u'mediaitem_presentation_rebuild')
+ Receiver.send_message(u'mediaitem_suffexes')
def tabVisible(self):
"""
=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py 2012-11-21 18:45:37 +0000
+++ openlp/plugins/songs/lib/mediaitem.py 2012-11-24 07:26:33 +0000
@@ -37,7 +37,7 @@
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
translate, check_item_selected, PluginStatus, create_separated_list, \
- check_directory_exists
+ check_directory_exists, ServiceItemContext
from openlp.core.lib.ui import UiStrings, create_widget_action
from openlp.core.lib.settings import Settings
from openlp.core.utils import AppLocation, locale_direct_compare
@@ -488,7 +488,7 @@
self.onSongListLoad()
def generateSlideData(self, service_item, item=None, xmlVersion=False,
- remote=False):
+ remote=False, context=ServiceItemContext.Service):
log.debug(u'generateSlideData: %s, %s, %s' %
(service_item, item, self.remoteSong))
item_id = self._getIdOfItemToGenerate(item, self.remoteSong)
=== modified file 'resources/openlp.xml'
--- resources/openlp.xml 2011-03-25 18:50:25 +0000
+++ resources/openlp.xml 2012-11-24 07:26:33 +0000
@@ -18,6 +18,11 @@
<comment>OpenLP Service File</comment>
<glob pattern="*.osz"/>
</mime-type>
+ <mime-type type="application/x-openlp-service">
+ <sub-class-of type="application/zip"/>
+ <comment>OpenLP Service File</comment>
+ <glob pattern="*.oszl"/>
+ </mime-type>
<mime-type type="application/x-openlp-theme">
<sub-class-of type="application/zip"/>
<comment>OpenLP Theme File</comment>