openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #00138
[Merge] lp:~mjthompson/openlp/media_plugin into lp:openlp
Martin Thompson has proposed merging lp:~mjthompson/openlp/media_plugin into lp:openlp.
Requested reviews:
openlp.org Core (openlp-core)
Previews for video items - uses gstreamer as I can;t find a way to make Phonon do it. This may be unportable? But gets us through until Phonon gets the functionality.
No previews for audio files yet
--
https://code.launchpad.net/~mjthompson/openlp/media_plugin/+merge/8066
Your team openlp.org Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/listwithpreviews.py'
--- openlp/core/lib/listwithpreviews.py 2009-06-23 20:59:38 +0000
+++ openlp/core/lib/listwithpreviews.py 2009-06-30 20:35:53 +0000
@@ -35,14 +35,18 @@
self.items = []
self.rowheight = 50
self.maximagewidth = self.rowheight * 16 / 9.0;
- if new_preview_function is not None:
- self.make_preview=new_preview_function
- else:
- self.make_preview=self.preview_function
+ self.preview_function = new_preview_function
- def preview_function(self, filename):
+ def make_preview(self, filename):
if os.path.exists(filename):
- preview = QtGui.QImage(filename)
+ if self.preview_function is not None:
+ preview=self.preview_function(filename)
+ else:
+ preview = QtGui.QImage(filename)
+ else:
+ preview = None
+
+ if preview is not None:
w = self.maximagewidth;
h = self.rowheight
preview = preview.scaled(w, h, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py 2009-06-25 20:03:41 +0000
+++ openlp/core/lib/mediamanageritem.py 2009-06-30 20:35:53 +0000
@@ -18,7 +18,7 @@
Place, Suite 330, Boston, MA 02111-1307 USA
"""
import types
-
+import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib.toolbar import *
from openlp.core.lib import translate
@@ -122,6 +122,10 @@
# self.ListViewWithDnD_class - there is a base list class with DnD assigned to it (openlp.core.lib.BaseListWithDnD())
# each plugin needs to inherit a class from this and pass that *class* (not an instance) to here
# via the ListViewWithDnD_class member
+ # self.ServiceItemIconName - string referring to an icon file or a resource icon
+ # self.PreviewFunction - a function which returns a QImage to represent the item (a preview usually) - no scaling required - that's done later
+ # If this fn is not defined, a default will be used (treat the filename as an image)
+
# The assumption is that given that at least two plugins are of the form
# "text with an icon" then all this will help
# even for plugins of another sort, the setup of the right-click menu, common toolbar
@@ -166,7 +170,10 @@
#Add the List widget
self.ListView = self.ListViewWithDnD_class()
self.ListView.uniformItemSizes = True
- self.ListData = ListWithPreviews()
+ try:
+ self.ListData = ListWithPreviews(self.PreviewFunction)
+ except AttributeError:
+ self.ListData = ListWithPreviews(None)
self.ListView.setModel(self.ListData)
self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591))
self.ListView.setSpacing(1)
@@ -219,25 +226,25 @@
self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList())
def generateSlideData(self):
- assert (0, 'This fn needs to be defined by the plugin');
+ assert 0, 'This fn needs to be defined by the plugin'
def onPreviewClick(self):
log.debug(self.PluginTextShort+u'Preview Requested')
service_item = ServiceItem(self.parent)
- service_item.addIcon(u':/media/media_image.png')
+ service_item.addIcon(self.ServiceItemIconName)
self.generateSlideData(service_item)
self.parent.preview_controller.addServiceItem(service_item)
def onLiveClick(self):
log.debug(self.PluginTextShort+u' Live Requested')
service_item = ServiceItem(self.parent)
- service_item.addIcon(u':/media/media_image.png')
+ service_item.addIcon(self.ServiceItemIconName)
self.generateSlideData(service_item)
self.parent.live_controller.addServiceItem(service_item)
def onAddClick(self):
log.debug(self.PluginTextShort+u' Add Requested')
service_item = ServiceItem(self.parent)
- service_item.addIcon(u':/media/media_image.png')
+ service_item.addIcon(self.ServiceItemIconName)
self.generateSlideData(service_item)
self.parent.service_manager.addServiceItem(service_item)
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py 2009-06-25 20:01:02 +0000
+++ openlp/plugins/images/lib/mediaitem.py 2009-06-25 21:09:52 +0000
@@ -49,7 +49,8 @@
self.OnNewFileMasks = u'Images (*.jpg *jpeg *.gif *.png *.bmp)'
# this next is a class, not an instance of a class - it will
# be instanced by the base MediaManagerItem
- self.ListViewWithDnD_class = ImageListView
+ self.ListViewWithDnD_class = ImageListView
+ self.ServiceItemIconName = u':/media/media_image.png'
MediaManagerItem.__init__(self, parent, icon, title)
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py 2009-06-16 18:21:24 +0000
+++ openlp/plugins/media/lib/mediaitem.py 2009-06-30 20:35:53 +0000
@@ -19,13 +19,25 @@
"""
import logging
import os
-
+import tempfile
+try:
+ import gst
+except:
+ log = logging.getLogger(u'MediaMediaItemSetup')
+ log.warning(u'Can\'t generate Vidoe previews - import gst failed');
+
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, translate
from openlp.plugins.media.lib import MediaTab
from openlp.plugins.media.lib import FileListData
+# from listwithpreviews import ListWithPreviews
+from openlp.core.lib import MediaManagerItem, ServiceItem, translate, BaseListWithDnD
+class MediaListView(BaseListWithDnD):
+ def __init__(self, parent=None):
+ self.PluginName = u'Media'
+ BaseListWithDnD.__init__(self, parent)
class MediaMediaItem(MediaManagerItem):
"""
@@ -36,100 +48,76 @@
log.info(u'Media Media Item loaded')
def __init__(self, parent, icon, title):
+ self.TranslationContext = u'MediaPlugin'
+ self.PluginTextShort = u'Media'
+ self.ConfigSection = u'images'
+ self.OnNewPrompt = u'Select Media(s)'
+ self.OnNewFileMasks = u'Videos (*.avi *.mpeg *.mpg *.mp4);;Audio (*.ogg *.mp3 *.wma);;All files (*)'
+ # this next is a class, not an instance of a class - it will
+ # be instanced by the base MediaManagerItem
+ self.ListViewWithDnD_class = MediaListView
+ self.ServiceItemIconName = u':/media/media_image.png'
+ self.PreviewFunction = self.video_get_preview
MediaManagerItem.__init__(self, parent, icon, title)
- def setupUi(self):
- # Add a toolbar
- self.addToolbar()
- # Create buttons for the toolbar
- ## New Media Button ##
- self.addToolbarButton(
- translate(u'MediaMediaItem',u'New Media'),
- translate(u'MediaMediaItem',u'Load Media into openlp.org'),
- ':/videos/video_load.png', self.onMediaNewClick, 'MediaNewItem')
- ## Delete Media Button ##
- self.addToolbarButton(
- translate(u'MediaMediaItem',u'Delete Media'),
- translate(u'MediaMediaItem',u'Delete the selected Media item'),
- ':/videos/video_delete.png', self.onMediaDeleteClick, 'MediaDeleteItem')
- ## Separator Line ##
- self.addToolbarSeparator()
- ## Preview Media Button ##
- self.addToolbarButton(
- translate(u'MediaMediaItem',u'Preview Media'),
- translate(u'MediaMediaItem',u'Preview the selected Media item'),
- ':/system/system_preview.png', self.onMediaPreviewClick, 'MediaPreviewItem')
- ## Live Media Button ##
- self.addToolbarButton(
- translate(u'MediaMediaItem',u'Go Live'),
- translate(u'MediaMediaItem',u'Send the selected Media item live'),
- ':/system/system_live.png', self.onMediaLiveClick, 'MediaLiveItem')
- ## Add Media Button ##
- self.addToolbarButton(
- translate(u'MediaMediaItem',u'Add Media To Service'),
- translate(u'MediaMediaItem',u'Add the selected Media items(s) to the service'),
- ':/system/system_add.png',self.onMediaAddClick, 'MediaAddItem')
- ## Add the Medialist widget ##
-
- self.MediaListView = QtGui.QListView()
- self.MediaListView.setAlternatingRowColors(True)
- self.MediaListData = FileListData()
- self.MediaListView.setModel(self.MediaListData)
-
- self.PageLayout.addWidget(self.MediaListView)
-
- #define and add the context menu
- self.MediaListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
-
- self.MediaListView.addAction(self.contextMenuAction(
- self.MediaListView, ':/system/system_preview.png',
- translate(u'MediaMediaItem',u'&Preview Media'), self.onMediaPreviewClick))
- self.MediaListView.addAction(self.contextMenuAction(
- self.MediaListView, ':/system/system_live.png',
- translate(u'MediaMediaItem',u'&Show Live'), self.onMediaLiveClick))
- self.MediaListView.addAction(self.contextMenuAction(
- self.MediaListView, ':/system/system_add.png',
- translate(u'MediaMediaItem',u'&Add to Service'), self.onMediaAddClick))
-
- def initialise(self):
- list = self.parent.config.load_list(u'Media')
- self.loadMediaList(list)
-
- def onMediaNewClick(self):
- files = QtGui.QFileDialog.getOpenFileNames(None,
- translate(u'MediaMediaItem', u'Select Media(s) items'),
- self.parent.config.get_last_dir(),
- u'Videos (*.avi *.mpeg);;Audio (*.mp3 *.ogg *.wma);;All files (*)')
- if len(files) > 0:
- self.loadMediaList(files)
- dir, filename = os.path.split(unicode(files[0]))
- self.parent.config.set_last_dir(dir)
- self.parent.config.set_list(u'media', self.MediaListData.getFileList())
-
- def getFileList(self):
- filelist = [item[0] for item in self.MediaListView];
- return filelist
-
- def loadMediaList(self, list):
- for files in list:
- self.MediaListData.addRow(files)
-
- def onMediaDeleteClick(self):
- indexes = self.MediaListView.selectedIndexes()
+ def video_get_preview(self, filename):
+
+ """Gets a preview of the first frame of a video file using
+ GSTREAMER (non-portable??? - Can't figure out how to do with
+ Phonon - returns a QImage"""
+
+ try:
+ # Define your pipeline, just as you would at the command prompt.
+ # This is much easier than trying to create and link each gstreamer element in Python.
+ # This is great for pipelines that end with a filesink (i.e. there is no audible or visual output)
+ log.info ("Video preview %s"%( filename))
+ outfile=tempfile.NamedTemporaryFile(suffix='.png')
+ cmd=u'filesrc location="%s" ! decodebin ! ffmpegcolorspace ! pngenc ! filesink location="%s"'% (filename, outfile.name)
+ pipe = gst.parse_launch(cmd)
+ # Get a reference to the pipeline's bus
+ bus = pipe.get_bus()
+
+ # Set the pipeline's state to PLAYING
+ pipe.set_state(gst.STATE_PLAYING)
+
+ # Listen to the pipeline's bus indefinitely until we receive a EOS (end of stream) message.
+ # This is a super important step, or the pipeline might not work as expected. For example,
+ # in my example pipeline above, the pngenc will not export an actual image unless you have
+ # this line of code. It just exports a 0 byte png file. So... don't forget this step.
+ bus.poll(gst.MESSAGE_EOS, -1)
+ img=QtGui.QImage(outfile.name)
+ outfile.close()
+# os.unlink(outfile.name)
+ pipe.set_state(gst.STATE_NULL)
+ return img
+ except:
+ log.info("Can't generate video preview for some reason");
+ import sys
+ print sys.exc_info()
+ return QtGui.QImage()
+
+
+ def generateSlideData(self, service_item):
+ indexes = self.ListView.selectedIndexes()
+ service_item.title = u'Media'
for index in indexes:
- current_row = int(index.row())
- self.MediaListData.removeRow(current_row)
- self.parent.config.set_list(u'media', self.MediaListData.getFileList())
-
- def onMediaPreviewClick(self):
+ filename = self.ListData.getFilename(index)
+ frame = QtGui.QImage(unicode(filename))
+ (path, name) = os.path.split(filename)
+ service_item.add_from_image(path, name, frame)
+
+
+ def onPreviewClick(self):
log.debug(u'Media Preview Button pressed')
- items = self.MediaListView.selectedIndexes()
+ items = self.ListView.selectedIndexes()
for item in items:
- text = self.MediaListData.getValue(item)
+ text = self.ListData.getValue(item)
print text
def onMediaLiveClick(self):
+ log.debug(u'Media Live Button pressed')
pass
- def onMediaAddClick(self):
- pass
\ No newline at end of file
+# def onMediaAddClick(self):
+# log.debug(u'Media Add Button pressed')
+# pass
=== modified file 'openlp/plugins/media/mediaplugin.py'
--- openlp/plugins/media/mediaplugin.py 2009-06-16 18:21:24 +0000
+++ openlp/plugins/media/mediaplugin.py 2009-06-30 20:35:53 +0000
@@ -22,7 +22,7 @@
from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab
from openlp.plugins.media.lib import MediaTab,MediaMediaItem
-
+from video_preview import video_get_preview
class MediaPlugin(Plugin):
def __init__(self, plugin_helpers):
=== removed file 'openlp/plugins/media/video_render.py'
--- openlp/plugins/media/video_render.py 2009-06-22 20:44:35 +0000
+++ openlp/plugins/media/video_render.py 1970-01-01 00:00:00 +0000
@@ -1,70 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-"""
-OpenLP - Open Source Lyrics Projection
-Copyright (c) 2008 Raoul Snyman
-Portions copyright (c) 2008 Martin Thompson, Tim Bentley,
-
-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
-"""
-import os
-from PyQt4 import QtCore, QtGui
-
-# xxx this needs a try, except once we've decided what to do if it fails
-from PyQt4.phonon import Phonon
-
-# from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab
-# from openlp.plugins.media.lib import MediaTab,MediaMediaItem
-
-"""Renders a video to some surface or other """
-
-class w(QtGui.QMainWindow):
- def __init__(self, parent=None):
- super(QtGui.QMainWindow, self).__init__(parent)
- self.resize(640,480)
- self.setWindowTitle(u'simple media player')
- self.show()
-
-if __name__==u'__main__':
- app = QtGui.QApplication([])
-# widget = QtGui.QWidget()
-# widget.resize(320, 240)
-# widget.setWindowTitle(u'simple')
-# widget.show()
-# QCore.QCoreApplication.setApplicationName(u'OpenLP')
- mainwindow=w()
- widget=QtGui.QWidget(mainwindow)
- mainwindow.setCentralWidget(widget)
- widget.setLayout(QtGui.QVBoxLayout(widget))
-# videofile=u'r-128.rm'
- videofile=u'/extra_space/Download/coa360download56Kbps240x160.mpg'
- source=Phonon.MediaSource(videofile)
-
- media=Phonon.MediaObject(widget)
- media.setCurrentSource(source)
-
- video=Phonon.VideoWidget(widget)
- audio=Phonon.AudioOutput(Phonon.MusicCategory)
-# controller=Phonon.MediaController(media)
- Phonon.createPath(media, video);
- Phonon.createPath(media, audio);
-# player=Phonon.VideoPlayer(Phonon.VideoCategory, widget)
- slider=Phonon.SeekSlider(media, mainwindow)
- widget.layout().addWidget(slider)
- widget.layout().addWidget(video)
- slider.show()
-
- video.show()
- media.play()
- app.exec_()
-
Follow ups