← 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.

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