Merge lp:~mjthompson/openlp/media_plugin into lp:openlp
- media_plugin
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~mjthompson/openlp/media_plugin |
Merge into: | lp:openlp |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~mjthompson/openlp/media_plugin |
Related bugs: |
This proposal supersedes a proposal from 2009-06-30.
Commit message
Description of the change
Martin Thompson (mjthompson) wrote : Posted in a previous version of this proposal | # |
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal | # |
Sorry but this will break the other plugins.
adding self.ServiceIte
Also is incorrect.
- service_
92 + service_
should be
This does not work for bibles as the media_image for bibles is _verses instead of _bibles.
Use of assert causes problems and rejections on a number of boxes can we have throws error instead.
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
Please don't use this, it throws Eric4 out (and is incorrect Python):
assert 0, 'This fn needs to be defined by the plugin'
Rather use:
raise NotImplementedE
Rather return None, and do a check on the other side... "image is not None":
264 + except:
265 + log.info("Can't generate video preview for some reason");
266 + import sys
267 + print sys.exc_info()
268 + return QtGui.QImage()
This should be in a docstring:
43 # self.ListViewWi
44 # each plugin needs to inherit a class from this and pass that *class* (not an instance) to here
45 # via the ListViewWithDnD
46 + # self.ServiceIte
47 + # self.PreviewFun
48 + # If this fn is not defined, a default will be used (treat the filename as an image)
49 +
50 # The assumption is that given that at least two plugins are of the form
51 # "text with an icon" then all this will help
52 # even for plugins of another sort, the setup of the right-click menu, common toolbar
Martin Thompson (mjthompson) wrote : Posted in a previous version of this proposal | # |
On Wed, Jul 01, 2009 at 05:14:09AM -0000 or thereabouts, Tim Bentley wrote:
> Review: Needs Fixing
> Sorry but this will break the other plugins.
>
> adding self.ServiceIte
>
Should I add it to the other plugins then...?
> Also is incorrect.
> - service_
> 92 + service_
>
> should be
> service_
> This does not work for bibles as the media_image for bibles is _verses instead of _bibles.
which would also fix this problem.
>
> Use of assert causes problems and rejections on a number of boxes can we have throws error instead.
OK.
Cheers,
Martin
Preview Diff
1 | === modified file 'openlp/core/lib/listwithpreviews.py' | |||
2 | --- openlp/core/lib/listwithpreviews.py 2009-06-23 20:59:38 +0000 | |||
3 | +++ openlp/core/lib/listwithpreviews.py 2009-06-30 20:35:53 +0000 | |||
4 | @@ -35,14 +35,18 @@ | |||
5 | 35 | self.items = [] | 35 | self.items = [] |
6 | 36 | self.rowheight = 50 | 36 | self.rowheight = 50 |
7 | 37 | self.maximagewidth = self.rowheight * 16 / 9.0; | 37 | self.maximagewidth = self.rowheight * 16 / 9.0; |
12 | 38 | if new_preview_function is not None: | 38 | self.preview_function = new_preview_function |
9 | 39 | self.make_preview=new_preview_function | ||
10 | 40 | else: | ||
11 | 41 | self.make_preview=self.preview_function | ||
13 | 42 | 39 | ||
15 | 43 | def preview_function(self, filename): | 40 | def make_preview(self, filename): |
16 | 44 | if os.path.exists(filename): | 41 | if os.path.exists(filename): |
18 | 45 | preview = QtGui.QImage(filename) | 42 | if self.preview_function is not None: |
19 | 43 | preview=self.preview_function(filename) | ||
20 | 44 | else: | ||
21 | 45 | preview = QtGui.QImage(filename) | ||
22 | 46 | else: | ||
23 | 47 | preview = None | ||
24 | 48 | |||
25 | 49 | if preview is not None: | ||
26 | 46 | w = self.maximagewidth; | 50 | w = self.maximagewidth; |
27 | 47 | h = self.rowheight | 51 | h = self.rowheight |
28 | 48 | preview = preview.scaled(w, h, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) | 52 | preview = preview.scaled(w, h, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) |
29 | 49 | 53 | ||
30 | === modified file 'openlp/core/lib/mediamanageritem.py' | |||
31 | --- openlp/core/lib/mediamanageritem.py 2009-06-25 20:03:41 +0000 | |||
32 | +++ openlp/core/lib/mediamanageritem.py 2009-07-01 20:21:13 +0000 | |||
33 | @@ -18,7 +18,7 @@ | |||
34 | 18 | Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Place, Suite 330, Boston, MA 02111-1307 USA |
35 | 19 | """ | 19 | """ |
36 | 20 | import types | 20 | import types |
38 | 21 | 21 | import os | |
39 | 22 | from PyQt4 import QtCore, QtGui | 22 | from PyQt4 import QtCore, QtGui |
40 | 23 | from openlp.core.lib.toolbar import * | 23 | from openlp.core.lib.toolbar import * |
41 | 24 | from openlp.core.lib import translate | 24 | from openlp.core.lib import translate |
42 | @@ -27,7 +27,32 @@ | |||
43 | 27 | class MediaManagerItem(QtGui.QWidget): | 27 | class MediaManagerItem(QtGui.QWidget): |
44 | 28 | """ | 28 | """ |
45 | 29 | MediaManagerItem is a helper widget for plugins. | 29 | MediaManagerItem is a helper widget for plugins. |
47 | 30 | """ | 30 | |
48 | 31 | None of the following *need* to be used, feel free to override | ||
49 | 32 | them cmopletely in your plugin's implementation. Alternatively, call them from your | ||
50 | 33 | plugin before or after you've done etra things that you need to. | ||
51 | 34 | |||
52 | 35 | The plugin will be assigned an icon called | ||
53 | 36 | u':/media/media_' + 'self.ShortPluginName + u'image.png' | ||
54 | 37 | which needs to be available in the main resources | ||
55 | 38 | |||
56 | 39 | in order for them to work, you need to have setup | ||
57 | 40 | |||
58 | 41 | self.TranslationContext | ||
59 | 42 | self.PluginTextShort # eg 'Image' for the image plugin | ||
60 | 43 | self.ConfigSection - where the items in the media manager are stored | ||
61 | 44 | this could potentially be self.PluginTextShort.lower() | ||
62 | 45 | |||
63 | 46 | self.OnNewPrompt=u'Select Image(s)' | ||
64 | 47 | self.OnNewFileMasks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)' | ||
65 | 48 | assumes that the new action is to load a file. If not, override onnew | ||
66 | 49 | self.ListViewWithDnD_class - there is a base list class with DnD assigned to it (openlp.core.lib.BaseListWithDnD()) | ||
67 | 50 | each plugin needs to inherit a class from this and pass that *class* (not an instance) to here | ||
68 | 51 | via the ListViewWithDnD_class member | ||
69 | 52 | self.PreviewFunction - a function which returns a QImage to represent the item (a preview usually) - no scaling required - that's done later | ||
70 | 53 | If this fn is not defined, a default will be used (treat the filename as an image) | ||
71 | 54 | |||
72 | 55 | """ | ||
73 | 31 | global log | 56 | global log |
74 | 32 | log = logging.getLogger(u'MediaManagerItem') | 57 | log = logging.getLogger(u'MediaManagerItem') |
75 | 33 | log.info(u'Media Item loaded') | 58 | log.info(u'Media Item loaded') |
76 | @@ -106,49 +131,23 @@ | |||
77 | 106 | QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), slot) | 131 | QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), slot) |
78 | 107 | return action | 132 | return action |
79 | 108 | 133 | ||
80 | 109 | #################################################################################################### | ||
81 | 110 | ### None of the following *need* to be used, feel free to override | ||
82 | 111 | ### them cmopletely in your plugin's implementation. Alternatively, call them from your | ||
83 | 112 | ### plugin before or after you've done etra things that you need to. | ||
84 | 113 | ### in order for them to work, you need to have setup | ||
85 | 114 | # self.TranslationContext | ||
86 | 115 | # self.PluginTextShort # eg "Image" for the image plugin | ||
87 | 116 | # self.ConfigSection - where the items in the media manager are stored | ||
88 | 117 | # this could potentially be self.PluginTextShort.lower() | ||
89 | 118 | # | ||
90 | 119 | # self.OnNewPrompt=u'Select Image(s)' | ||
91 | 120 | # self.OnNewFileMasks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)' | ||
92 | 121 | # assumes that the new action is to load a file. If not, override onnew | ||
93 | 122 | # self.ListViewWithDnD_class - there is a base list class with DnD assigned to it (openlp.core.lib.BaseListWithDnD()) | ||
94 | 123 | # each plugin needs to inherit a class from this and pass that *class* (not an instance) to here | ||
95 | 124 | # via the ListViewWithDnD_class member | ||
96 | 125 | # The assumption is that given that at least two plugins are of the form | ||
97 | 126 | # "text with an icon" then all this will help | ||
98 | 127 | # even for plugins of another sort, the setup of the right-click menu, common toolbar | ||
99 | 128 | # will help to keep things consistent and ease the creation of new plugins | ||
100 | 129 | |||
101 | 130 | # also a set of completely consistent action anesm then exist | ||
102 | 131 | # (onPreviewClick() is always called that, rather than having the | ||
103 | 132 | # name of the plugin added in as well... I regard that as a | ||
104 | 133 | # feature, I guess others might differ!) | ||
105 | 134 | |||
106 | 135 | def setupUi(self): | 134 | def setupUi(self): |
107 | 136 | # Add a toolbar | 135 | # Add a toolbar |
108 | 137 | self.addToolbar() | 136 | self.addToolbar() |
109 | 138 | # Create buttons for the toolbar | 137 | # Create buttons for the toolbar |
111 | 139 | ## New Song Button ## | 138 | ## New Button ## |
112 | 140 | self.addToolbarButton( | 139 | self.addToolbarButton( |
113 | 141 | translate(self.TranslationContext, u'Load '+self.PluginTextShort), | 140 | translate(self.TranslationContext, u'Load '+self.PluginTextShort), |
114 | 142 | translate(self.TranslationContext, u'Load item into openlp.org'), | 141 | translate(self.TranslationContext, u'Load item into openlp.org'), |
117 | 143 | u':/images/image_load.png', self.onNewClick, u'ImageNewItem') | 142 | u':/images/image_load.png', self.onNewClick, u'NewItem') |
118 | 144 | ## Delete Song Button ## | 143 | ## Delete Button ## |
119 | 145 | self.addToolbarButton( | 144 | self.addToolbarButton( |
120 | 146 | translate(self.TranslationContext, u'Delete '+self.PluginTextShort), | 145 | translate(self.TranslationContext, u'Delete '+self.PluginTextShort), |
121 | 147 | translate(self.TranslationContext, u'Delete the selected item'), | 146 | translate(self.TranslationContext, u'Delete the selected item'), |
122 | 148 | u':/images/image_delete.png', self.onDeleteClick, u'DeleteItem') | 147 | u':/images/image_delete.png', self.onDeleteClick, u'DeleteItem') |
123 | 149 | ## Separator Line ## | 148 | ## Separator Line ## |
124 | 150 | self.addToolbarSeparator() | 149 | self.addToolbarSeparator() |
126 | 151 | ## Preview Button ## | 150 | ## Preview ## |
127 | 152 | self.addToolbarButton( | 151 | self.addToolbarButton( |
128 | 153 | translate(self.TranslationContext, u'Preview '+self.PluginTextShort), | 152 | translate(self.TranslationContext, u'Preview '+self.PluginTextShort), |
129 | 154 | translate(self.TranslationContext, u'Preview the selected item'), | 153 | translate(self.TranslationContext, u'Preview the selected item'), |
130 | @@ -158,7 +157,7 @@ | |||
131 | 158 | translate(self.TranslationContext, u'Go Live'), | 157 | translate(self.TranslationContext, u'Go Live'), |
132 | 159 | translate(self.TranslationContext, u'Send the selected item live'), | 158 | translate(self.TranslationContext, u'Send the selected item live'), |
133 | 160 | u':/system/system_live.png', self.onLiveClick, u'LiveItem') | 159 | u':/system/system_live.png', self.onLiveClick, u'LiveItem') |
135 | 161 | ## Add Button ## | 160 | ## Add to service Button ## |
136 | 162 | self.addToolbarButton( | 161 | self.addToolbarButton( |
137 | 163 | translate(self.TranslationContext, u'Add '+self.PluginTextShort+u' To Service'), | 162 | translate(self.TranslationContext, u'Add '+self.PluginTextShort+u' To Service'), |
138 | 164 | translate(self.TranslationContext, u'Add the selected item(s) to the service'), | 163 | translate(self.TranslationContext, u'Add the selected item(s) to the service'), |
139 | @@ -166,7 +165,10 @@ | |||
140 | 166 | #Add the List widget | 165 | #Add the List widget |
141 | 167 | self.ListView = self.ListViewWithDnD_class() | 166 | self.ListView = self.ListViewWithDnD_class() |
142 | 168 | self.ListView.uniformItemSizes = True | 167 | self.ListView.uniformItemSizes = True |
144 | 169 | self.ListData = ListWithPreviews() | 168 | try: |
145 | 169 | self.ListData = ListWithPreviews(self.PreviewFunction) | ||
146 | 170 | except AttributeError: | ||
147 | 171 | self.ListData = ListWithPreviews(None) | ||
148 | 170 | self.ListView.setModel(self.ListData) | 172 | self.ListView.setModel(self.ListData) |
149 | 171 | self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591)) | 173 | self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591)) |
150 | 172 | self.ListView.setSpacing(1) | 174 | self.ListView.setSpacing(1) |
151 | @@ -203,7 +205,7 @@ | |||
152 | 203 | log.info(u'New files(s)', unicode(files)) | 205 | log.info(u'New files(s)', unicode(files)) |
153 | 204 | if len(files) > 0: | 206 | if len(files) > 0: |
154 | 205 | self.loadList(files) | 207 | self.loadList(files) |
156 | 206 | dir, filename = os.path.split(unicode(files[0])) | 208 | dir, filename = os.path.split(uniClickcode(files[0])) |
157 | 207 | self.parent.config.set_last_dir(dir) | 209 | self.parent.config.set_last_dir(dir) |
158 | 208 | self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList()) | 210 | self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList()) |
159 | 209 | 211 | ||
160 | @@ -219,25 +221,26 @@ | |||
161 | 219 | self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList()) | 221 | self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList()) |
162 | 220 | 222 | ||
163 | 221 | def generateSlideData(self): | 223 | def generateSlideData(self): |
165 | 222 | assert (0, 'This fn needs to be defined by the plugin'); | 224 | raise NotImplementedError(u'This function needs to be defined by the plugin') |
166 | 223 | 225 | ||
167 | 224 | def onPreviewClick(self): | 226 | def onPreviewClick(self): |
168 | 225 | log.debug(self.PluginTextShort+u'Preview Requested') | 227 | log.debug(self.PluginTextShort+u'Preview Requested') |
169 | 226 | service_item = ServiceItem(self.parent) | 228 | service_item = ServiceItem(self.parent) |
171 | 227 | service_item.addIcon(u':/media/media_image.png') | 229 | service_item.addIcon(self.ServiceItemIconName) |
172 | 230 | |||
173 | 228 | self.generateSlideData(service_item) | 231 | self.generateSlideData(service_item) |
174 | 229 | self.parent.preview_controller.addServiceItem(service_item) | 232 | self.parent.preview_controller.addServiceItem(service_item) |
175 | 230 | 233 | ||
176 | 231 | def onLiveClick(self): | 234 | def onLiveClick(self): |
177 | 232 | log.debug(self.PluginTextShort+u' Live Requested') | 235 | log.debug(self.PluginTextShort+u' Live Requested') |
178 | 233 | service_item = ServiceItem(self.parent) | 236 | service_item = ServiceItem(self.parent) |
180 | 234 | service_item.addIcon(u':/media/media_image.png') | 237 | service_item.addIcon(self.ServiceItemIconName) |
181 | 235 | self.generateSlideData(service_item) | 238 | self.generateSlideData(service_item) |
182 | 236 | self.parent.live_controller.addServiceItem(service_item) | 239 | self.parent.live_controller.addServiceItem(service_item) |
183 | 237 | 240 | ||
184 | 238 | def onAddClick(self): | 241 | def onAddClick(self): |
185 | 239 | log.debug(self.PluginTextShort+u' Add Requested') | 242 | log.debug(self.PluginTextShort+u' Add Requested') |
186 | 240 | service_item = ServiceItem(self.parent) | 243 | service_item = ServiceItem(self.parent) |
188 | 241 | service_item.addIcon(u':/media/media_image.png') | 244 | service_item.addIcon(self.ServiceItemIconName) |
189 | 242 | self.generateSlideData(service_item) | 245 | self.generateSlideData(service_item) |
190 | 243 | self.parent.service_manager.addServiceItem(service_item) | 246 | self.parent.service_manager.addServiceItem(service_item) |
191 | 244 | 247 | ||
192 | === modified file 'openlp/plugins/images/lib/mediaitem.py' | |||
193 | --- openlp/plugins/images/lib/mediaitem.py 2009-06-25 20:01:02 +0000 | |||
194 | +++ openlp/plugins/images/lib/mediaitem.py 2009-06-25 21:09:52 +0000 | |||
195 | @@ -49,7 +49,8 @@ | |||
196 | 49 | self.OnNewFileMasks = u'Images (*.jpg *jpeg *.gif *.png *.bmp)' | 49 | self.OnNewFileMasks = u'Images (*.jpg *jpeg *.gif *.png *.bmp)' |
197 | 50 | # this next is a class, not an instance of a class - it will | 50 | # this next is a class, not an instance of a class - it will |
198 | 51 | # be instanced by the base MediaManagerItem | 51 | # be instanced by the base MediaManagerItem |
200 | 52 | self.ListViewWithDnD_class = ImageListView | 52 | self.ListViewWithDnD_class = ImageListView |
201 | 53 | self.ServiceItemIconName = u':/media/media_image.png' | ||
202 | 53 | MediaManagerItem.__init__(self, parent, icon, title) | 54 | MediaManagerItem.__init__(self, parent, icon, title) |
203 | 54 | 55 | ||
204 | 55 | 56 | ||
205 | 56 | 57 | ||
206 | === modified file 'openlp/plugins/media/lib/mediaitem.py' | |||
207 | --- openlp/plugins/media/lib/mediaitem.py 2009-06-16 18:21:24 +0000 | |||
208 | +++ openlp/plugins/media/lib/mediaitem.py 2009-07-01 20:21:13 +0000 | |||
209 | @@ -19,13 +19,25 @@ | |||
210 | 19 | """ | 19 | """ |
211 | 20 | import logging | 20 | import logging |
212 | 21 | import os | 21 | import os |
214 | 22 | 22 | import tempfile | |
215 | 23 | try: | ||
216 | 24 | import gst | ||
217 | 25 | except: | ||
218 | 26 | log = logging.getLogger(u'MediaMediaItemSetup') | ||
219 | 27 | log.warning(u'Can\'t generate Vidoe previews - import gst failed'); | ||
220 | 28 | |||
221 | 23 | from PyQt4 import QtCore, QtGui | 29 | from PyQt4 import QtCore, QtGui |
222 | 24 | 30 | ||
223 | 25 | from openlp.core.lib import MediaManagerItem, translate | 31 | from openlp.core.lib import MediaManagerItem, translate |
224 | 26 | 32 | ||
225 | 27 | from openlp.plugins.media.lib import MediaTab | 33 | from openlp.plugins.media.lib import MediaTab |
226 | 28 | from openlp.plugins.media.lib import FileListData | 34 | from openlp.plugins.media.lib import FileListData |
227 | 35 | # from listwithpreviews import ListWithPreviews | ||
228 | 36 | from openlp.core.lib import MediaManagerItem, ServiceItem, translate, BaseListWithDnD | ||
229 | 37 | class MediaListView(BaseListWithDnD): | ||
230 | 38 | def __init__(self, parent=None): | ||
231 | 39 | self.PluginName = u'Media' | ||
232 | 40 | BaseListWithDnD.__init__(self, parent) | ||
233 | 29 | 41 | ||
234 | 30 | class MediaMediaItem(MediaManagerItem): | 42 | class MediaMediaItem(MediaManagerItem): |
235 | 31 | """ | 43 | """ |
236 | @@ -36,100 +48,76 @@ | |||
237 | 36 | log.info(u'Media Media Item loaded') | 48 | log.info(u'Media Media Item loaded') |
238 | 37 | 49 | ||
239 | 38 | def __init__(self, parent, icon, title): | 50 | def __init__(self, parent, icon, title): |
240 | 51 | self.TranslationContext = u'MediaPlugin' | ||
241 | 52 | self.PluginTextShort = u'Media' | ||
242 | 53 | self.ConfigSection = u'images' | ||
243 | 54 | self.OnNewPrompt = u'Select Media(s)' | ||
244 | 55 | self.OnNewFileMasks = u'Videos (*.avi *.mpeg *.mpg *.mp4);;Audio (*.ogg *.mp3 *.wma);;All files (*)' | ||
245 | 56 | # this next is a class, not an instance of a class - it will | ||
246 | 57 | # be instanced by the base MediaManagerItem | ||
247 | 58 | self.ListViewWithDnD_class = MediaListView | ||
248 | 59 | self.ServiceItemIconName = u':/media/media_image.png' | ||
249 | 60 | self.PreviewFunction = self.video_get_preview | ||
250 | 39 | MediaManagerItem.__init__(self, parent, icon, title) | 61 | MediaManagerItem.__init__(self, parent, icon, title) |
251 | 40 | 62 | ||
330 | 41 | def setupUi(self): | 63 | def video_get_preview(self, filename): |
331 | 42 | # Add a toolbar | 64 | |
332 | 43 | self.addToolbar() | 65 | """Gets a preview of the first frame of a video file using |
333 | 44 | # Create buttons for the toolbar | 66 | GSTREAMER (non-portable??? - Can't figure out how to do with |
334 | 45 | ## New Media Button ## | 67 | Phonon - returns a QImage""" |
335 | 46 | self.addToolbarButton( | 68 | |
336 | 47 | translate(u'MediaMediaItem',u'New Media'), | 69 | try: |
337 | 48 | translate(u'MediaMediaItem',u'Load Media into openlp.org'), | 70 | # Define your pipeline, just as you would at the command prompt. |
338 | 49 | ':/videos/video_load.png', self.onMediaNewClick, 'MediaNewItem') | 71 | # This is much easier than trying to create and link each gstreamer element in Python. |
339 | 50 | ## Delete Media Button ## | 72 | # This is great for pipelines that end with a filesink (i.e. there is no audible or visual output) |
340 | 51 | self.addToolbarButton( | 73 | log.info ("Video preview %s"%( filename)) |
341 | 52 | translate(u'MediaMediaItem',u'Delete Media'), | 74 | outfile=tempfile.NamedTemporaryFile(suffix='.png') |
342 | 53 | translate(u'MediaMediaItem',u'Delete the selected Media item'), | 75 | cmd=u'filesrc location="%s" ! decodebin ! ffmpegcolorspace ! pngenc ! filesink location="%s"'% (filename, outfile.name) |
343 | 54 | ':/videos/video_delete.png', self.onMediaDeleteClick, 'MediaDeleteItem') | 76 | pipe = gst.parse_launch(cmd) |
344 | 55 | ## Separator Line ## | 77 | # Get a reference to the pipeline's bus |
345 | 56 | self.addToolbarSeparator() | 78 | bus = pipe.get_bus() |
346 | 57 | ## Preview Media Button ## | 79 | |
347 | 58 | self.addToolbarButton( | 80 | # Set the pipeline's state to PLAYING |
348 | 59 | translate(u'MediaMediaItem',u'Preview Media'), | 81 | pipe.set_state(gst.STATE_PLAYING) |
349 | 60 | translate(u'MediaMediaItem',u'Preview the selected Media item'), | 82 | |
350 | 61 | ':/system/system_preview.png', self.onMediaPreviewClick, 'MediaPreviewItem') | 83 | # Listen to the pipeline's bus indefinitely until we receive a EOS (end of stream) message. |
351 | 62 | ## Live Media Button ## | 84 | # This is a super important step, or the pipeline might not work as expected. For example, |
352 | 63 | self.addToolbarButton( | 85 | # in my example pipeline above, the pngenc will not export an actual image unless you have |
353 | 64 | translate(u'MediaMediaItem',u'Go Live'), | 86 | # this line of code. It just exports a 0 byte png file. So... don't forget this step. |
354 | 65 | translate(u'MediaMediaItem',u'Send the selected Media item live'), | 87 | bus.poll(gst.MESSAGE_EOS, -1) |
355 | 66 | ':/system/system_live.png', self.onMediaLiveClick, 'MediaLiveItem') | 88 | img=QtGui.QImage(outfile.name) |
356 | 67 | ## Add Media Button ## | 89 | outfile.close() |
357 | 68 | self.addToolbarButton( | 90 | # os.unlink(outfile.name) |
358 | 69 | translate(u'MediaMediaItem',u'Add Media To Service'), | 91 | pipe.set_state(gst.STATE_NULL) |
359 | 70 | translate(u'MediaMediaItem',u'Add the selected Media items(s) to the service'), | 92 | return img |
360 | 71 | ':/system/system_add.png',self.onMediaAddClick, 'MediaAddItem') | 93 | except: |
361 | 72 | ## Add the Medialist widget ## | 94 | log.info("Can't generate video preview for some reason"); |
362 | 73 | 95 | import sys | |
363 | 74 | self.MediaListView = QtGui.QListView() | 96 | print sys.exc_info() |
364 | 75 | self.MediaListView.setAlternatingRowColors(True) | 97 | return None |
365 | 76 | self.MediaListData = FileListData() | 98 | |
366 | 77 | self.MediaListView.setModel(self.MediaListData) | 99 | |
367 | 78 | 100 | def generateSlideData(self, service_item): | |
368 | 79 | self.PageLayout.addWidget(self.MediaListView) | 101 | indexes = self.ListView.selectedIndexes() |
369 | 80 | 102 | service_item.title = u'Media' | |
292 | 81 | #define and add the context menu | ||
293 | 82 | self.MediaListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) | ||
294 | 83 | |||
295 | 84 | self.MediaListView.addAction(self.contextMenuAction( | ||
296 | 85 | self.MediaListView, ':/system/system_preview.png', | ||
297 | 86 | translate(u'MediaMediaItem',u'&Preview Media'), self.onMediaPreviewClick)) | ||
298 | 87 | self.MediaListView.addAction(self.contextMenuAction( | ||
299 | 88 | self.MediaListView, ':/system/system_live.png', | ||
300 | 89 | translate(u'MediaMediaItem',u'&Show Live'), self.onMediaLiveClick)) | ||
301 | 90 | self.MediaListView.addAction(self.contextMenuAction( | ||
302 | 91 | self.MediaListView, ':/system/system_add.png', | ||
303 | 92 | translate(u'MediaMediaItem',u'&Add to Service'), self.onMediaAddClick)) | ||
304 | 93 | |||
305 | 94 | def initialise(self): | ||
306 | 95 | list = self.parent.config.load_list(u'Media') | ||
307 | 96 | self.loadMediaList(list) | ||
308 | 97 | |||
309 | 98 | def onMediaNewClick(self): | ||
310 | 99 | files = QtGui.QFileDialog.getOpenFileNames(None, | ||
311 | 100 | translate(u'MediaMediaItem', u'Select Media(s) items'), | ||
312 | 101 | self.parent.config.get_last_dir(), | ||
313 | 102 | u'Videos (*.avi *.mpeg);;Audio (*.mp3 *.ogg *.wma);;All files (*)') | ||
314 | 103 | if len(files) > 0: | ||
315 | 104 | self.loadMediaList(files) | ||
316 | 105 | dir, filename = os.path.split(unicode(files[0])) | ||
317 | 106 | self.parent.config.set_last_dir(dir) | ||
318 | 107 | self.parent.config.set_list(u'media', self.MediaListData.getFileList()) | ||
319 | 108 | |||
320 | 109 | def getFileList(self): | ||
321 | 110 | filelist = [item[0] for item in self.MediaListView]; | ||
322 | 111 | return filelist | ||
323 | 112 | |||
324 | 113 | def loadMediaList(self, list): | ||
325 | 114 | for files in list: | ||
326 | 115 | self.MediaListData.addRow(files) | ||
327 | 116 | |||
328 | 117 | def onMediaDeleteClick(self): | ||
329 | 118 | indexes = self.MediaListView.selectedIndexes() | ||
370 | 119 | for index in indexes: | 103 | for index in indexes: |
376 | 120 | current_row = int(index.row()) | 104 | filename = self.ListData.getFilename(index) |
377 | 121 | self.MediaListData.removeRow(current_row) | 105 | frame = QtGui.QImage(unicode(filename)) |
378 | 122 | self.parent.config.set_list(u'media', self.MediaListData.getFileList()) | 106 | (path, name) = os.path.split(filename) |
379 | 123 | 107 | service_item.add_from_image(path, name, frame) | |
380 | 124 | def onMediaPreviewClick(self): | 108 | |
381 | 109 | |||
382 | 110 | def onPreviewClick(self): | ||
383 | 125 | log.debug(u'Media Preview Button pressed') | 111 | log.debug(u'Media Preview Button pressed') |
385 | 126 | items = self.MediaListView.selectedIndexes() | 112 | items = self.ListView.selectedIndexes() |
386 | 127 | for item in items: | 113 | for item in items: |
388 | 128 | text = self.MediaListData.getValue(item) | 114 | text = self.ListData.getValue(item) |
389 | 129 | print text | 115 | print text |
390 | 130 | 116 | ||
391 | 131 | def onMediaLiveClick(self): | 117 | def onMediaLiveClick(self): |
392 | 118 | log.debug(u'Media Live Button pressed') | ||
393 | 132 | pass | 119 | pass |
394 | 133 | 120 | ||
395 | 134 | def onMediaAddClick(self): | ||
396 | 135 | pass | ||
397 | 136 | \ No newline at end of file | 121 | \ No newline at end of file |
398 | 122 | # def onMediaAddClick(self): | ||
399 | 123 | # log.debug(u'Media Add Button pressed') | ||
400 | 124 | # pass | ||
401 | 137 | 125 | ||
402 | === modified file 'openlp/plugins/media/mediaplugin.py' | |||
403 | --- openlp/plugins/media/mediaplugin.py 2009-06-16 18:21:24 +0000 | |||
404 | +++ openlp/plugins/media/mediaplugin.py 2009-07-01 20:21:13 +0000 | |||
405 | @@ -22,7 +22,6 @@ | |||
406 | 22 | 22 | ||
407 | 23 | from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab | 23 | from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab |
408 | 24 | from openlp.plugins.media.lib import MediaTab,MediaMediaItem | 24 | from openlp.plugins.media.lib import MediaTab,MediaMediaItem |
409 | 25 | |||
410 | 26 | class MediaPlugin(Plugin): | 25 | class MediaPlugin(Plugin): |
411 | 27 | 26 | ||
412 | 28 | def __init__(self, plugin_helpers): | 27 | def __init__(self, plugin_helpers): |
413 | 29 | 28 | ||
414 | === removed file 'openlp/plugins/media/video_render.py' | |||
415 | --- openlp/plugins/media/video_render.py 2009-06-22 20:44:35 +0000 | |||
416 | +++ openlp/plugins/media/video_render.py 1970-01-01 00:00:00 +0000 | |||
417 | @@ -1,70 +0,0 @@ | |||
418 | 1 | # -*- coding: utf-8 -*- | ||
419 | 2 | # vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 | ||
420 | 3 | """ | ||
421 | 4 | OpenLP - Open Source Lyrics Projection | ||
422 | 5 | Copyright (c) 2008 Raoul Snyman | ||
423 | 6 | Portions copyright (c) 2008 Martin Thompson, Tim Bentley, | ||
424 | 7 | |||
425 | 8 | This program is free software; you can redistribute it and/or modify it under | ||
426 | 9 | the terms of the GNU General Public License as published by the Free Software | ||
427 | 10 | Foundation; version 2 of the License. | ||
428 | 11 | |||
429 | 12 | This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
430 | 13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
431 | 14 | PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
432 | 15 | |||
433 | 16 | You should have received a copy of the GNU General Public License along with | ||
434 | 17 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
435 | 18 | Place, Suite 330, Boston, MA 02111-1307 USA | ||
436 | 19 | """ | ||
437 | 20 | import os | ||
438 | 21 | from PyQt4 import QtCore, QtGui | ||
439 | 22 | |||
440 | 23 | # xxx this needs a try, except once we've decided what to do if it fails | ||
441 | 24 | from PyQt4.phonon import Phonon | ||
442 | 25 | |||
443 | 26 | # from openlp.core.lib import Plugin, MediaManagerItem, SettingsTab | ||
444 | 27 | # from openlp.plugins.media.lib import MediaTab,MediaMediaItem | ||
445 | 28 | |||
446 | 29 | """Renders a video to some surface or other """ | ||
447 | 30 | |||
448 | 31 | class w(QtGui.QMainWindow): | ||
449 | 32 | def __init__(self, parent=None): | ||
450 | 33 | super(QtGui.QMainWindow, self).__init__(parent) | ||
451 | 34 | self.resize(640,480) | ||
452 | 35 | self.setWindowTitle(u'simple media player') | ||
453 | 36 | self.show() | ||
454 | 37 | |||
455 | 38 | if __name__==u'__main__': | ||
456 | 39 | app = QtGui.QApplication([]) | ||
457 | 40 | # widget = QtGui.QWidget() | ||
458 | 41 | # widget.resize(320, 240) | ||
459 | 42 | # widget.setWindowTitle(u'simple') | ||
460 | 43 | # widget.show() | ||
461 | 44 | # QCore.QCoreApplication.setApplicationName(u'OpenLP') | ||
462 | 45 | mainwindow=w() | ||
463 | 46 | widget=QtGui.QWidget(mainwindow) | ||
464 | 47 | mainwindow.setCentralWidget(widget) | ||
465 | 48 | widget.setLayout(QtGui.QVBoxLayout(widget)) | ||
466 | 49 | # videofile=u'r-128.rm' | ||
467 | 50 | videofile=u'/extra_space/Download/coa360download56Kbps240x160.mpg' | ||
468 | 51 | source=Phonon.MediaSource(videofile) | ||
469 | 52 | |||
470 | 53 | media=Phonon.MediaObject(widget) | ||
471 | 54 | media.setCurrentSource(source) | ||
472 | 55 | |||
473 | 56 | video=Phonon.VideoWidget(widget) | ||
474 | 57 | audio=Phonon.AudioOutput(Phonon.MusicCategory) | ||
475 | 58 | # controller=Phonon.MediaController(media) | ||
476 | 59 | Phonon.createPath(media, video); | ||
477 | 60 | Phonon.createPath(media, audio); | ||
478 | 61 | # player=Phonon.VideoPlayer(Phonon.VideoCategory, widget) | ||
479 | 62 | slider=Phonon.SeekSlider(media, mainwindow) | ||
480 | 63 | widget.layout().addWidget(slider) | ||
481 | 64 | widget.layout().addWidget(video) | ||
482 | 65 | slider.show() | ||
483 | 66 | |||
484 | 67 | video.show() | ||
485 | 68 | media.play() | ||
486 | 69 | app.exec_() | ||
487 | 70 |
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