← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~mjthompson/openlp/media_plugin into lp:openlp

 

Martin Thompson has proposed merging lp:~mjthompson/openlp/media_plugin into lp:openlp.


-- 
https://code.launchpad.net/~mjthompson/openlp/media_plugin/+merge/8156
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-07-01 20:21:13 +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
@@ -27,7 +27,32 @@
 class MediaManagerItem(QtGui.QWidget):
     """
     MediaManagerItem is a helper widget for plugins.
-    """
+
+    None of the following *need* to be used, feel free to override
+    them cmopletely in your plugin's implementation.  Alternatively, call them from your
+    plugin before or after you've done etra things that you need to.
+
+    The plugin will be assigned an icon called 
+     u':/media/media_' + 'self.ShortPluginName + u'image.png'
+     which needs to be available in the main resources
+
+    in order for them to work, you need to have setup
+
+     self.TranslationContext
+     self.PluginTextShort # eg 'Image' for the image plugin
+     self.ConfigSection - where the items in the media manager are stored
+       this could potentially be self.PluginTextShort.lower()
+    
+     self.OnNewPrompt=u'Select Image(s)'
+     self.OnNewFileMasks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)'
+       assumes that the new action is to load a file. If not, override onnew
+     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.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)
+    
+"""
     global log
     log = logging.getLogger(u'MediaManagerItem')
     log.info(u'Media Item loaded')
@@ -106,49 +131,23 @@
         QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), slot)
         return action
 
-####################################################################################################
-    ### None of the following *need* to be used, feel free to override
-    ### them cmopletely in your plugin's implementation.  Alternatively, call them from your
-    ### plugin before or after you've done etra things that you need to.
-    ### in order for them to work, you need to have setup
-    # self.TranslationContext
-    # self.PluginTextShort # eg "Image" for the image plugin
-    # self.ConfigSection - where the items in the media manager are stored
-    #   this could potentially be self.PluginTextShort.lower()
-    #
-    # self.OnNewPrompt=u'Select Image(s)'
-    # self.OnNewFileMasks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)'
-    #   assumes that the new action is to load a file. If not, override onnew
-    # 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
-    # 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
-    # will help to keep things consistent and ease the creation of new plugins
-    
-    # also a set of completely consistent action anesm then exist
-    # (onPreviewClick() is always called that, rather than having the
-    # name of the plugin added in as well... I regard that as a
-    # feature, I guess others might differ!)
-    
     def setupUi(self):
         # Add a toolbar
         self.addToolbar()
         # Create buttons for the toolbar
-        ## New Song Button ##
+        ## New Button ##
         self.addToolbarButton(
             translate(self.TranslationContext, u'Load '+self.PluginTextShort),
             translate(self.TranslationContext, u'Load item into openlp.org'),
-            u':/images/image_load.png', self.onNewClick, u'ImageNewItem')
-        ## Delete Song Button ##
+            u':/images/image_load.png', self.onNewClick, u'NewItem')
+        ## Delete Button ##
         self.addToolbarButton(
             translate(self.TranslationContext, u'Delete '+self.PluginTextShort),
             translate(self.TranslationContext, u'Delete the selected item'),
             u':/images/image_delete.png', self.onDeleteClick, u'DeleteItem')
         ## Separator Line ##
         self.addToolbarSeparator()
-        ## Preview  Button ##
+        ## Preview ##
         self.addToolbarButton(
             translate(self.TranslationContext, u'Preview '+self.PluginTextShort),
             translate(self.TranslationContext, u'Preview the selected item'),
@@ -158,7 +157,7 @@
             translate(self.TranslationContext, u'Go Live'),
             translate(self.TranslationContext, u'Send the selected item live'),
             u':/system/system_live.png', self.onLiveClick, u'LiveItem')
-        ## Add  Button ##
+        ## Add to service Button ##
         self.addToolbarButton(
             translate(self.TranslationContext, u'Add '+self.PluginTextShort+u' To Service'),
             translate(self.TranslationContext, u'Add the selected item(s) to the service'),
@@ -166,7 +165,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)
@@ -203,7 +205,7 @@
         log.info(u'New files(s)', unicode(files))
         if len(files) > 0:
             self.loadList(files)
-            dir, filename = os.path.split(unicode(files[0]))
+            dir, filename = os.path.split(uniClickcode(files[0]))
             self.parent.config.set_last_dir(dir)
             self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList())
 
@@ -219,25 +221,26 @@
         self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList())
 
     def generateSlideData(self):
-        assert (0, 'This fn needs to be defined by the plugin');
+        raise NotImplementedError(u'This function 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-07-01 20:21:13 +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 None
+        
+
+    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-07-01 20:21:13 +0000
@@ -22,7 +22,6 @@
 
 from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab
 from openlp.plugins.media.lib import MediaTab,MediaMediaItem
-
 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_()
-