Merge lp:~trb143/openlp/webengine-migrate-trunk into lp:~openlp-dev/openlp/webengine-migrate

Proposed by Tim Bentley
Status: Merged
Merged at revision: 2865
Proposed branch: lp:~trb143/openlp/webengine-migrate-trunk
Merge into: lp:~openlp-dev/openlp/webengine-migrate
Diff against target: 13824 lines (+5142/-2981)
57 files modified
openlp/core/app.py (+5/-1)
openlp/core/common/actions.py (+1/-1)
openlp/core/common/mixins.py (+2/-1)
openlp/core/common/registry.py (+7/-0)
openlp/core/lib/mediamanageritem.py (+37/-26)
openlp/core/lib/plugin.py (+5/-4)
openlp/core/lib/pluginmanager.py (+74/-62)
openlp/core/lib/serviceitem.py (+7/-2)
openlp/core/loader.py (+48/-0)
openlp/core/state.py (+175/-0)
openlp/core/ui/icons.py (+1/-1)
openlp/core/ui/mainwindow.py (+4/-26)
openlp/core/ui/media/__init__.py (+1/-38)
openlp/core/ui/media/mediacontroller.py (+70/-163)
openlp/core/ui/media/mediaplayer.py (+2/-1)
openlp/core/ui/media/playertab.py (+9/-10)
openlp/core/ui/media/vendor/mediainfoWrapper.py (+0/-129)
openlp/core/ui/media/vendor/vlc.py (+3861/-1850)
openlp/core/ui/media/vlcplayer.py (+4/-4)
openlp/core/ui/pluginform.py (+29/-27)
openlp/core/ui/settingsform.py (+5/-6)
openlp/core/ui/slidecontroller.py (+52/-104)
openlp/plugins/alerts/alertsplugin.py (+3/-0)
openlp/plugins/alerts/lib/alertsmanager.py (+1/-1)
openlp/plugins/bibles/bibleplugin.py (+3/-0)
openlp/plugins/custom/customplugin.py (+3/-0)
openlp/plugins/images/imageplugin.py (+3/-0)
openlp/plugins/media/lib/mediaitem.py (+52/-149)
openlp/plugins/media/mediaplugin.py (+4/-51)
openlp/plugins/presentations/presentationplugin.py (+3/-0)
openlp/plugins/songs/lib/mediaitem.py (+11/-5)
openlp/plugins/songs/songsplugin.py (+3/-0)
openlp/plugins/songusage/songusageplugin.py (+3/-0)
scripts/check_dependencies.py (+2/-1)
scripts/jenkins_script.py (+7/-6)
tests/functional/openlp_core/api/endpoint/test_controller.py (+4/-0)
tests/functional/openlp_core/common/test_registry.py (+1/-1)
tests/functional/openlp_core/lib/test_mediamanageritem.py (+12/-0)
tests/functional/openlp_core/lib/test_pluginmanager.py (+70/-25)
tests/functional/openlp_core/lib/test_serviceitem.py (+19/-8)
tests/functional/openlp_core/test_state.py (+151/-0)
tests/functional/openlp_core/ui/media/test_mediacontroller.py (+33/-104)
tests/functional/openlp_core/ui/media/test_vlcplayer.py (+4/-4)
tests/functional/openlp_core/ui/test_maindisplay.py.THIS (+283/-0)
tests/functional/openlp_core/ui/test_mainwindow.py (+4/-6)
tests/functional/openlp_core/ui/test_media.py (+13/-11)
tests/functional/openlp_core/ui/test_slidecontroller.py (+1/-0)
tests/functional/openlp_core/widgets/test_views.py (+15/-13)
tests/functional/openlp_plugins/images/test_upgrade.py (+4/-2)
tests/functional/openlp_plugins/media/test_mediaplugin.py (+1/-27)
tests/functional/openlp_plugins/songs/test_mediaitem.py (+0/-1)
tests/interfaces/openlp_core/lib/test_pluginmanager.py (+16/-12)
tests/interfaces/openlp_core/ui/media/__init__.py (+0/-21)
tests/interfaces/openlp_core/ui/media/vendor/__init__.py (+0/-21)
tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py (+0/-49)
tests/interfaces/openlp_core/ui/test_mainwindow.py (+14/-3)
tests/openlp_core/projectors/test_projector_db.py (+0/-4)
To merge this branch: bzr merge lp:~trb143/openlp/webengine-migrate-trunk
Reviewer Review Type Date Requested Status
Tomas Groth Approve
Review via email: mp+362287@code.launchpad.net

Commit message

Fixed trunk merge so now matches that.

To post a comment you must log in.
Revision history for this message
Tomas Groth (tomasgroth) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/app.py'
2--- openlp/core/app.py 2018-10-24 21:02:06 +0000
3+++ openlp/core/app.py 2019-01-27 20:26:59 +0000
4@@ -35,8 +35,10 @@
5
6 from PyQt5 import QtCore, QtWebEngineWidgets, QtWidgets # noqa
7
8+from openlp.core.state import State
9 from openlp.core.common import is_macosx, is_win
10 from openlp.core.common.applocation import AppLocation
11+from openlp.core.loader import loader
12 from openlp.core.common.i18n import LanguageManager, UiStrings, translate
13 from openlp.core.common.path import copytree, create_paths
14 from openlp.core.common.registry import Registry
15@@ -115,8 +117,10 @@
16 # Check if OpenLP has been upgrade and if a backup of data should be created
17 self.backup_on_upgrade(has_run_wizard, can_show_splash)
18 # start the main app window
19+ loader()
20 self.main_window = MainWindow()
21 Registry().execute('bootstrap_initialise')
22+ State().flush_preconditions()
23 Registry().execute('bootstrap_post_set_up')
24 Registry().initialise = False
25 self.main_window.show()
26@@ -134,7 +138,7 @@
27 if Settings().value('core/update check'):
28 check_for_update(self.main_window)
29 self.main_window.is_display_blank()
30- self.main_window.app_startup()
31+ Registry().execute('bootstrap_completion')
32 return self.exec()
33
34 @staticmethod
35
36=== modified file 'openlp/core/common/actions.py'
37--- openlp/core/common/actions.py 2018-10-02 04:39:42 +0000
38+++ openlp/core/common/actions.py 2019-01-27 20:26:59 +0000
39@@ -20,7 +20,7 @@
40 # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
41 ###############################################################################
42 """
43-The :mod:`~openlp.core.utils.actions` module provides action list classes used
44+The :mod:`~openlp.core.common.actions` module provides action list classes used
45 by the shortcuts system.
46 """
47 import logging
48
49=== modified file 'openlp/core/common/mixins.py'
50--- openlp/core/common/mixins.py 2018-10-02 04:39:42 +0000
51+++ openlp/core/common/mixins.py 2019-01-27 20:26:59 +0000
52@@ -50,7 +50,8 @@
53 setattr(self, name, self.logging_wrapper(m, self))
54 return self._logger
55
56- def logging_wrapper(self, func, parent):
57+ @staticmethod
58+ def logging_wrapper(func, parent):
59 """
60 Code to added debug wrapper to work on called functions within a decorated class.
61 """
62
63=== modified file 'openlp/core/common/registry.py'
64--- openlp/core/common/registry.py 2018-10-24 21:02:06 +0000
65+++ openlp/core/common/registry.py 2019-01-27 20:26:59 +0000
66@@ -205,6 +205,7 @@
67 Registry().register(de_hump(self.__class__.__name__), self)
68 Registry().register_function('bootstrap_initialise', self.bootstrap_initialise)
69 Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up)
70+ Registry().register_function('bootstrap_completion', self.bootstrap_completion)
71
72 def bootstrap_initialise(self):
73 """
74@@ -217,3 +218,9 @@
75 Dummy method to be overridden
76 """
77 pass
78+
79+ def bootstrap_completion(self):
80+ """
81+ Dummy method to be overridden
82+ """
83+ pass
84
85=== modified file 'openlp/core/lib/mediamanageritem.py'
86--- openlp/core/lib/mediamanageritem.py 2018-10-02 04:39:42 +0000
87+++ openlp/core/lib/mediamanageritem.py 2019-01-27 20:26:59 +0000
88@@ -130,6 +130,9 @@
89 self.has_file_icon = False
90 self.has_delete_icon = True
91 self.add_to_service_item = False
92+ self.can_preview = True
93+ self.can_make_live = True
94+ self.can_add_to_service = True
95
96 def retranslate_ui(self):
97 """
98@@ -183,11 +186,14 @@
99 if self.has_delete_icon:
100 toolbar_actions.append(['Delete', StringContent.Delete, UiIcons().delete, self.on_delete_click])
101 # Preview
102- toolbar_actions.append(['Preview', StringContent.Preview, UiIcons().preview, self.on_preview_click])
103+ if self.can_preview:
104+ toolbar_actions.append(['Preview', StringContent.Preview, UiIcons().preview, self.on_preview_click])
105 # Live Button
106- toolbar_actions.append(['Live', StringContent.Live, UiIcons().live, self.on_live_click])
107+ if self.can_make_live:
108+ toolbar_actions.append(['Live', StringContent.Live, UiIcons().live, self.on_live_click])
109 # Add to service Button
110- toolbar_actions.append(['Service', StringContent.Service, UiIcons().add, self.on_add_click])
111+ if self.can_add_to_service:
112+ toolbar_actions.append(['Service', StringContent.Service, UiIcons().add, self.on_add_click])
113 for action in toolbar_actions:
114 if action[0] == StringContent.Preview:
115 self.toolbar.addSeparator()
116@@ -211,27 +217,30 @@
117 icon=UiIcons().edit,
118 triggers=self.on_edit_click)
119 create_widget_action(self.list_view, separator=True)
120- create_widget_action(self.list_view,
121- 'listView{plugin}{preview}Item'.format(plugin=self.plugin.name.title(),
122- preview=StringContent.Preview.title()),
123- text=self.plugin.get_string(StringContent.Preview)['title'],
124- icon=UiIcons().preview,
125- can_shortcuts=True,
126- triggers=self.on_preview_click)
127- create_widget_action(self.list_view,
128- 'listView{plugin}{live}Item'.format(plugin=self.plugin.name.title(),
129- live=StringContent.Live.title()),
130- text=self.plugin.get_string(StringContent.Live)['title'],
131- icon=UiIcons().live,
132- can_shortcuts=True,
133- triggers=self.on_live_click)
134- create_widget_action(self.list_view,
135- 'listView{plugin}{service}Item'.format(plugin=self.plugin.name.title(),
136- service=StringContent.Service.title()),
137- can_shortcuts=True,
138- text=self.plugin.get_string(StringContent.Service)['title'],
139- icon=UiIcons().add,
140- triggers=self.on_add_click)
141+ if self.can_preview:
142+ create_widget_action(self.list_view,
143+ 'listView{plugin}{preview}Item'.format(plugin=self.plugin.name.title(),
144+ preview=StringContent.Preview.title()),
145+ text=self.plugin.get_string(StringContent.Preview)['title'],
146+ icon=UiIcons().preview,
147+ can_shortcuts=True,
148+ triggers=self.on_preview_click)
149+ if self.can_make_live:
150+ create_widget_action(self.list_view,
151+ 'listView{plugin}{live}Item'.format(plugin=self.plugin.name.title(),
152+ live=StringContent.Live.title()),
153+ text=self.plugin.get_string(StringContent.Live)['title'],
154+ icon=UiIcons().live,
155+ can_shortcuts=True,
156+ triggers=self.on_live_click)
157+ if self.can_add_to_service:
158+ create_widget_action(self.list_view,
159+ 'listView{plugin}{service}Item'.format(plugin=self.plugin.name.title(),
160+ service=StringContent.Service.title()),
161+ can_shortcuts=True,
162+ text=self.plugin.get_string(StringContent.Service)['title'],
163+ icon=UiIcons().add,
164+ triggers=self.on_add_click)
165 if self.has_delete_icon:
166 create_widget_action(self.list_view, separator=True)
167 create_widget_action(self.list_view,
168@@ -462,10 +471,12 @@
169 Allows the list click action to be determined dynamically
170 """
171 if Settings().value('advanced/double click live'):
172- self.on_live_click()
173+ if self.can_make_live:
174+ self.on_live_click()
175 elif not Settings().value('advanced/single click preview'):
176 # NOTE: The above check is necessary to prevent bug #1419300
177- self.on_preview_click()
178+ if self.can_preview:
179+ self.on_preview_click()
180
181 def on_selection_change(self):
182 """
183
184=== modified file 'openlp/core/lib/plugin.py'
185--- openlp/core/lib/plugin.py 2018-10-02 04:39:42 +0000
186+++ openlp/core/lib/plugin.py 2019-01-27 20:26:59 +0000
187@@ -24,11 +24,9 @@
188 """
189 import logging
190
191-from PyQt5 import QtCore
192-
193 from openlp.core.common.i18n import UiStrings
194 from openlp.core.common.mixins import RegistryProperties
195-from openlp.core.common.registry import Registry
196+from openlp.core.common.registry import Registry, RegistryBase
197 from openlp.core.common.settings import Settings
198 from openlp.core.version import get_version
199
200@@ -61,7 +59,7 @@
201 VisibleName = 'visible_name'
202
203
204-class Plugin(QtCore.QObject, RegistryProperties):
205+class Plugin(RegistryBase, RegistryProperties):
206 """
207 Base class for openlp plugins to inherit from.
208
209@@ -326,6 +324,9 @@
210 """
211 return self.text_strings[name]
212
213+ def set_plugin_text_strings(self):
214+ pass
215+
216 def set_plugin_ui_text_strings(self, tooltips):
217 """
218 Called to define all translatable texts of the plugin
219
220=== modified file 'openlp/core/lib/pluginmanager.py'
221--- openlp/core/lib/pluginmanager.py 2018-09-07 14:59:21 +0000
222+++ openlp/core/lib/pluginmanager.py 2019-01-27 20:26:59 +0000
223@@ -26,9 +26,10 @@
224
225 from PyQt5 import QtWidgets
226
227+from openlp.core.state import State
228 from openlp.core.common import extension_loader
229 from openlp.core.common.applocation import AppLocation
230-from openlp.core.common.i18n import UiStrings
231+from openlp.core.common.i18n import translate, UiStrings
232 from openlp.core.common.mixins import LogMixin, RegistryProperties
233 from openlp.core.common.registry import RegistryBase
234 from openlp.core.lib.plugin import Plugin, PluginStatus
235@@ -53,11 +54,22 @@
236 def bootstrap_initialise(self):
237 """
238 Bootstrap all the plugin manager functions
239- """
240- self.find_plugins()
241- # hook methods have to happen after find_plugins. Find plugins needs
242- # the controllers hence the hooks have moved from setupUI() to here
243- # Find and insert settings tabs
244+ Scan a directory for objects inheriting from the ``Plugin`` class.
245+ """
246+ glob_pattern = os.path.join('plugins', '*', '[!.]*plugin.py')
247+ extension_loader(glob_pattern)
248+ plugin_classes = Plugin.__subclasses__()
249+ for p in plugin_classes:
250+ try:
251+ p()
252+ self.log_debug('Loaded plugin {plugin}'.format(plugin=str(p)))
253+ except TypeError:
254+ self.log_exception('Failed to load plugin {plugin}'.format(plugin=str(p)))
255+
256+ def bootstrap_post_set_up(self):
257+ """
258+ Bootstrap all the plugin manager functions
259+ """
260 self.hook_settings_tabs()
261 # Find and insert media manager items
262 self.hook_media_manager()
263@@ -70,36 +82,23 @@
264 # Call the initialise method to setup plugins.
265 self.initialise_plugins()
266
267- def find_plugins(self):
268- """
269- Scan a directory for objects inheriting from the ``Plugin`` class.
270- """
271- glob_pattern = os.path.join('plugins', '*', '[!.]*plugin.py')
272- extension_loader(glob_pattern)
273- plugin_classes = Plugin.__subclasses__()
274- plugin_objects = []
275- for p in plugin_classes:
276- try:
277- plugin = p()
278- self.log_debug('Loaded plugin {plugin}'.format(plugin=str(p)))
279- plugin_objects.append(plugin)
280- except TypeError:
281- self.log_exception('Failed to load plugin {plugin}'.format(plugin=str(p)))
282- plugins_list = sorted(plugin_objects, key=lambda plugin: plugin.weight)
283- for plugin in plugins_list:
284- if plugin.check_pre_conditions():
285- self.log_debug('Plugin {plugin} active'.format(plugin=str(plugin.name)))
286- plugin.set_status()
287- else:
288- plugin.status = PluginStatus.Disabled
289- self.plugins.append(plugin)
290+ def bootstrap_completion(self):
291+ """
292+ Give all the plugins a chance to perform some tasks at startup
293+ """
294+ self.application.process_events()
295+ for plugin in State().list_plugins():
296+ if plugin and plugin.is_active():
297+ plugin.app_startup()
298+ self.application.process_events()
299
300- def hook_media_manager(self):
301+ @staticmethod
302+ def hook_media_manager():
303 """
304 Create the plugins' media manager items.
305 """
306- for plugin in self.plugins:
307- if plugin.status is not PluginStatus.Disabled:
308+ for plugin in State().list_plugins():
309+ if plugin and plugin.status is not PluginStatus.Disabled:
310 plugin.create_media_manager_item()
311
312 def hook_settings_tabs(self):
313@@ -109,8 +108,8 @@
314 Tabs are set for all plugins not just Active ones
315
316 """
317- for plugin in self.plugins:
318- if plugin.status is not PluginStatus.Disabled:
319+ for plugin in State().list_plugins():
320+ if plugin and plugin.status is not PluginStatus.Disabled:
321 plugin.create_settings_tab(self.settings_form)
322
323 def hook_import_menu(self):
324@@ -119,8 +118,8 @@
325 item to the import menu.
326
327 """
328- for plugin in self.plugins:
329- if plugin.status is not PluginStatus.Disabled:
330+ for plugin in State().list_plugins():
331+ if plugin and plugin.status is not PluginStatus.Disabled:
332 plugin.add_import_menu_item(self.main_window.file_import_menu)
333
334 def hook_export_menu(self):
335@@ -128,8 +127,8 @@
336 Loop through all the plugins and give them an opportunity to add an
337 item to the export menu.
338 """
339- for plugin in self.plugins:
340- if plugin.status is not PluginStatus.Disabled:
341+ for plugin in State().list_plugins():
342+ if plugin and plugin.status is not PluginStatus.Disabled:
343 plugin.add_export_menu_item(self.main_window.file_export_menu)
344
345 def hook_tools_menu(self):
346@@ -137,18 +136,19 @@
347 Loop through all the plugins and give them an opportunity to add an
348 item to the tools menu.
349 """
350- for plugin in self.plugins:
351- if plugin.status is not PluginStatus.Disabled:
352+ for plugin in State().list_plugins():
353+ if plugin and plugin.status is not PluginStatus.Disabled:
354 plugin.add_tools_menu_item(self.main_window.tools_menu)
355
356- def hook_upgrade_plugin_settings(self, settings):
357+ @staticmethod
358+ def hook_upgrade_plugin_settings(settings):
359 """
360 Loop through all the plugins and give them an opportunity to upgrade their settings.
361
362 :param settings: The Settings object containing the old settings.
363 """
364- for plugin in self.plugins:
365- if plugin.status is not PluginStatus.Disabled:
366+ for plugin in State().list_plugins():
367+ if plugin and plugin.status is not PluginStatus.Disabled:
368 plugin.upgrade_settings(settings)
369
370 def initialise_plugins(self):
371@@ -156,43 +156,55 @@
372 Loop through all the plugins and give them an opportunity to initialise themselves.
373 """
374 uninitialised_plugins = []
375- for plugin in self.plugins:
376- self.log_info('initialising plugins {plugin} in a {state} state'.format(plugin=plugin.name,
377- state=plugin.is_active()))
378- if plugin.is_active():
379- try:
380- plugin.initialise()
381- self.log_info('Initialisation Complete for {plugin}'.format(plugin=plugin.name))
382- except Exception:
383- uninitialised_plugins.append(plugin.name.title())
384- self.log_exception('Unable to initialise plugin {plugin}'.format(plugin=plugin.name))
385+
386+ for plugin in State().list_plugins():
387+ if plugin:
388+ self.log_info('initialising plugins {plugin} in a {state} state'.format(plugin=plugin.name,
389+ state=plugin.is_active()))
390+ if plugin.is_active():
391+ try:
392+ plugin.initialise()
393+ self.log_info('Initialisation Complete for {plugin}'.format(plugin=plugin.name))
394+ except Exception:
395+ uninitialised_plugins.append(plugin.name.title())
396+ self.log_exception('Unable to initialise plugin {plugin}'.format(plugin=plugin.name))
397+ display_text = ''
398+
399 if uninitialised_plugins:
400- QtWidgets.QMessageBox.critical(None, UiStrings().Error, 'Unable to initialise the following plugins:\n' +
401- '\n'.join(uninitialised_plugins) + '\n\nSee the log file for more details',
402+ display_text = translate('OpenLP.PluginManager', 'Unable to initialise the following plugins:') + \
403+ '\n\n'.join(uninitialised_plugins) + '\n\n'
404+ error_text = State().get_text()
405+ if error_text:
406+ display_text = display_text + error_text + '\n'
407+ if display_text:
408+ display_text = display_text + translate('OpenLP.PluginManager', 'See the log file for more details')
409+ QtWidgets.QMessageBox.critical(None, UiStrings().Error, display_text,
410 QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
411
412 def finalise_plugins(self):
413 """
414 Loop through all the plugins and give them an opportunity to clean themselves up
415 """
416- for plugin in self.plugins:
417- if plugin.is_active():
418+ for plugin in State().list_plugins():
419+ if plugin and plugin.is_active():
420 plugin.finalise()
421 self.log_info('Finalisation Complete for {plugin}'.format(plugin=plugin.name))
422
423- def get_plugin_by_name(self, name):
424+ @staticmethod
425+ def get_plugin_by_name(name):
426 """
427 Return the plugin which has a name with value ``name``.
428 """
429- for plugin in self.plugins:
430- if plugin.name == name:
431+ for plugin in State().list_plugins():
432+ if plugin and plugin.name == name:
433 return plugin
434 return None
435
436- def new_service_created(self):
437+ @staticmethod
438+ def new_service_created():
439 """
440 Loop through all the plugins and give them an opportunity to handle a new service
441 """
442- for plugin in self.plugins:
443+ for plugin in State().list_plugins():
444 if plugin.is_active():
445 plugin.new_service_created()
446
447=== modified file 'openlp/core/lib/serviceitem.py'
448--- openlp/core/lib/serviceitem.py 2018-12-01 05:52:49 +0000
449+++ openlp/core/lib/serviceitem.py 2019-01-27 20:26:59 +0000
450@@ -32,6 +32,7 @@
451
452 from PyQt5 import QtGui
453
454+from openlp.core.state import State
455 from openlp.core.common import md5_hash
456 from openlp.core.common.applocation import AppLocation
457 from openlp.core.common.i18n import translate
458@@ -348,7 +349,7 @@
459 self.processor = header.get('processor', None)
460 self.has_original_files = True
461 self.metadata = header.get('item_meta_data', [])
462- if 'background_audio' in header:
463+ if 'background_audio' in header and State().check_preconditions('media'):
464 self.background_audio = []
465 for file_path in header['background_audio']:
466 # In OpenLP 3.0 we switched to storing Path objects in JSON files
467@@ -525,6 +526,10 @@
468 path_from = frame['path']
469 else:
470 path_from = os.path.join(frame['path'], frame['title'])
471+ if isinstance(path_from, str):
472+ # Handle service files prior to OpenLP 3.0
473+ # Windows can handle both forward and backward slashes, so we use ntpath to get the basename
474+ path_from = Path(path_from)
475 return path_from
476
477 def remove_frame(self, frame):
478@@ -593,7 +598,7 @@
479 self.is_valid = False
480 break
481 elif self.is_command():
482- if self.is_capable(ItemCapabilities.IsOptical):
483+ if self.is_capable(ItemCapabilities.IsOptical) and State().check_preconditions('media'):
484 if not os.path.exists(slide['title']):
485 self.is_valid = False
486 break
487
488=== added file 'openlp/core/loader.py'
489--- openlp/core/loader.py 1970-01-01 00:00:00 +0000
490+++ openlp/core/loader.py 2019-01-27 20:26:59 +0000
491@@ -0,0 +1,48 @@
492+# -*- coding: utf-8 -*-
493+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
494+
495+###############################################################################
496+# OpenLP - Open Source Lyrics Projection #
497+# --------------------------------------------------------------------------- #
498+# Copyright (c) 2008-2018 OpenLP Developers #
499+# --------------------------------------------------------------------------- #
500+# This program is free software; you can redistribute it and/or modify it #
501+# under the terms of the GNU General Public License as published by the Free #
502+# Software Foundation; version 2 of the License. #
503+# #
504+# This program is distributed in the hope that it will be useful, but WITHOUT #
505+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
506+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
507+# more details. #
508+# #
509+# You should have received a copy of the GNU General Public License along #
510+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
511+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
512+###############################################################################
513+"""
514+The :mod:`~openlp.core.loader` module provides a bootstrap for the singleton classes
515+"""
516+
517+from openlp.core.state import State
518+from openlp.core.ui.media.mediacontroller import MediaController
519+from openlp.core.lib.pluginmanager import PluginManager
520+from openlp.core.display.render import Renderer
521+from openlp.core.lib.imagemanager import ImageManager
522+from openlp.core.ui.slidecontroller import LiveController, PreviewController
523+
524+
525+def loader():
526+ """
527+ God class to load all the components which are registered with the Registry
528+
529+ :return: None
530+ """
531+ State().load_settings()
532+ MediaController()
533+ PluginManager()
534+ # Set up the path with plugins
535+ ImageManager()
536+ Renderer()
537+ # Create slide controllers
538+ PreviewController()
539+ LiveController()
540
541=== added file 'openlp/core/state.py'
542--- openlp/core/state.py 1970-01-01 00:00:00 +0000
543+++ openlp/core/state.py 2019-01-27 20:26:59 +0000
544@@ -0,0 +1,175 @@
545+# -*- coding: utf-8 -*-
546+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
547+
548+###############################################################################
549+# OpenLP - Open Source Lyrics Projection #
550+# --------------------------------------------------------------------------- #
551+# Copyright (c) 2008-2018 OpenLP Developers #
552+# --------------------------------------------------------------------------- #
553+# This program is free software; you can redistribute it and/or modify it #
554+# under the terms of the GNU General Public License as published by the Free #
555+# Software Foundation; version 2 of the License. #
556+# #
557+# This program is distributed in the hope that it will be useful, but WITHOUT #
558+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
559+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
560+# more details. #
561+# #
562+# You should have received a copy of the GNU General Public License along #
563+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
564+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
565+###############################################################################
566+
567+"""
568+The :mod:`core` module provides state management
569+
570+All the core functions of the OpenLP application including the GUI, settings, logging and a plugin framework are
571+contained within the openlp.core module.
572+"""
573+import logging
574+
575+from openlp.core.common.registry import Registry
576+from openlp.core.common.mixins import LogMixin
577+from openlp.core.lib.plugin import PluginStatus
578+
579+
580+log = logging.getLogger()
581+
582+
583+class StateModule(LogMixin):
584+ def __init__(self):
585+ """
586+ Holder of State information per module
587+ """
588+ super(StateModule, self).__init__()
589+ self.name = None
590+ self.order = 0
591+ self.is_plugin = None
592+ self.status = PluginStatus.Inactive
593+ self.pass_preconditions = False
594+ self.requires = None
595+ self.required_by = None
596+ self.text = None
597+
598+
599+class State(LogMixin):
600+
601+ __instance__ = None
602+
603+ def __new__(cls):
604+ """
605+ Re-implement the __new__ method to make sure we create a true singleton.
606+ """
607+ if not cls.__instance__:
608+ cls.__instance__ = object.__new__(cls)
609+ return cls.__instance__
610+
611+ def load_settings(self):
612+ self.modules = {}
613+
614+ def save_settings(self):
615+ pass
616+
617+ def add_service(self, name, order, is_plugin=False, status=PluginStatus.Active, requires=None):
618+ """
619+ Add a module to the array and load dependencies. There will only be one item per module
620+ :param name: Module name
621+ :param order: Order to display
622+ :param is_plugin: Am I a plugin
623+ :param status: The active status
624+ :param requires: Module name this requires
625+ :return:
626+ """
627+ if name not in self.modules:
628+ state = StateModule()
629+ state.name = name
630+ state.order = order
631+ state.is_plugin = is_plugin
632+ state.status = status
633+ state.requires = requires
634+ state.required_by = []
635+ self.modules[name] = state
636+ if requires and requires in self.modules:
637+ if requires not in self.modules[requires].required_by:
638+ self.modules[requires].required_by.append(name)
639+
640+ def missing_text(self, name, text):
641+ """
642+ Updates the preconditions state of a module
643+
644+ :param name: Module name
645+ :param text: Module missing text
646+ :return:
647+ """
648+ self.modules[name].text = text
649+
650+ def get_text(self):
651+ """
652+ return an string of error text
653+ :return: a string of text
654+ """
655+ error_text = ''
656+ for mod in self.modules:
657+ if self.modules[mod].text:
658+ error_text = error_text + self.modules[mod].text + '\n'
659+ return error_text
660+
661+ def update_pre_conditions(self, name, status):
662+ """
663+ Updates the preconditions state of a module
664+
665+ :param name: Module name
666+ :param status: Module new status
667+ :return:
668+ """
669+ self.modules[name].pass_preconditions = status
670+ if self.modules[name].is_plugin:
671+ plugin = Registry().get('{mod}_plugin'.format(mod=name))
672+ if status:
673+ self.log_debug('Plugin {plugin} active'.format(plugin=str(plugin.name)))
674+ plugin.set_status()
675+ else:
676+ plugin.status = PluginStatus.Disabled
677+
678+ def flush_preconditions(self):
679+ """
680+ Now all modules are loaded lets update all the preconditions.
681+
682+ :return:
683+ """
684+ for mods in self.modules:
685+ for req in self.modules[mods].required_by:
686+ self.modules[req].pass_preconditions = self.modules[mods].pass_preconditions
687+ plugins_list = sorted(self.modules, key=lambda state: self.modules[state].order)
688+ mdl = {}
689+ for pl in plugins_list:
690+ mdl[pl] = self.modules[pl]
691+ self.modules = mdl
692+
693+ def is_module_active(self, name):
694+ return self.modules[name].status == PluginStatus.Active
695+
696+ def check_preconditions(self, name):
697+ """
698+ Checks if a modules preconditions have been met.
699+
700+ :param name: Module name
701+ :return: Have the preconditions been met.
702+ :rtype: bool
703+ """
704+ if self.modules[name].requires is None:
705+ return self.modules[name].pass_preconditions
706+ else:
707+ mod = self.modules[name].requires
708+ return self.modules[mod].pass_preconditions
709+
710+ def list_plugins(self):
711+ """
712+ Return a list of plugins
713+ :return: an array of plugins
714+ """
715+ plugins = []
716+ for mod in self.modules:
717+ if self.modules[mod].is_plugin:
718+ plugins.append(Registry().get('{mod}_plugin'.format(mod=mod)))
719+ return plugins
720
721=== modified file 'openlp/core/ui/icons.py'
722--- openlp/core/ui/icons.py 2018-10-30 19:46:55 +0000
723+++ openlp/core/ui/icons.py 2019-01-27 20:26:59 +0000
724@@ -79,7 +79,7 @@
725 'book': {'icon': 'fa.book'},
726 'bottom': {'icon': 'fa.angle-double-down'},
727 'box': {'icon': 'fa.briefcase'},
728- 'clapperboard': {'icon': 'fa.chess-board'},
729+ 'clapperboard': {'icon': 'fa.film'},
730 'clock': {'icon': 'fa.clock-o'},
731 'clone': {'icon': 'fa.clone'},
732 'close': {'icon': 'fa.times-circle-o'},
733
734=== modified file 'openlp/core/ui/mainwindow.py'
735--- openlp/core/ui/mainwindow.py 2018-10-30 19:46:55 +0000
736+++ openlp/core/ui/mainwindow.py 2019-01-27 20:26:59 +0000
737@@ -30,6 +30,7 @@
738
739 from PyQt5 import QtCore, QtGui, QtWidgets
740
741+from openlp.core.state import State
742 from openlp.core.api import websockets
743 from openlp.core.api.http import server
744 from openlp.core.common import add_actions, is_macosx, is_win
745@@ -41,23 +42,18 @@
746 from openlp.core.common.registry import Registry
747 from openlp.core.common.settings import Settings
748 from openlp.core.display.screens import ScreenList
749-from openlp.core.lib.imagemanager import ImageManager
750-from openlp.core.display.render import Renderer
751 from openlp.core.lib.plugin import PluginStatus
752-from openlp.core.lib.pluginmanager import PluginManager
753 from openlp.core.lib.ui import create_action
754 from openlp.core.projectors.manager import ProjectorManager
755 from openlp.core.ui.aboutform import AboutForm
756 from openlp.core.ui.firsttimeform import FirstTimeForm
757 from openlp.core.ui.formattingtagform import FormattingTagForm
758 from openlp.core.ui.icons import UiIcons
759-from openlp.core.ui.media.mediacontroller import MediaController
760 from openlp.core.ui.pluginform import PluginForm
761 from openlp.core.ui.printserviceform import PrintServiceForm
762 from openlp.core.ui.servicemanager import ServiceManager
763 from openlp.core.ui.settingsform import SettingsForm
764 from openlp.core.ui.shortcutlistform import ShortcutListForm
765-from openlp.core.ui.slidecontroller import LiveController, PreviewController
766 from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet
767 from openlp.core.ui.thememanager import ThemeManager
768 from openlp.core.version import get_version
769@@ -90,9 +86,6 @@
770 self.control_splitter.setOrientation(QtCore.Qt.Horizontal)
771 self.control_splitter.setObjectName('control_splitter')
772 self.main_content_layout.addWidget(self.control_splitter)
773- # Create slide controllers
774- PreviewController(self)
775- LiveController(self)
776 preview_visible = Settings().value('user interface/preview panel')
777 live_visible = Settings().value('user interface/live panel')
778 panel_locked = Settings().value('user interface/lock panel')
779@@ -501,16 +494,11 @@
780 self.copy_data = False
781 Settings().set_up_default_values()
782 self.about_form = AboutForm(self)
783- MediaController()
784 self.ws_server = websockets.WebSocketServer()
785 self.http_server = server.HttpServer(self)
786 SettingsForm(self)
787 self.formatting_tag_form = FormattingTagForm(self)
788 self.shortcut_form = ShortcutListForm(self)
789- # Set up the path with plugins
790- PluginManager(self)
791- ImageManager()
792- Renderer()
793 # Set up the interface
794 self.setup_ui(self)
795 # Define the media Dock Manager
796@@ -660,22 +648,12 @@
797 self.set_view_mode(False, True, False, False, True, True)
798 self.mode_live_item.setChecked(True)
799
800- def app_startup(self):
801- """
802- Give all the plugins a chance to perform some tasks at startup
803- """
804- self.application.process_events()
805- for plugin in self.plugin_manager.plugins:
806- if plugin.is_active():
807- plugin.app_startup()
808- self.application.process_events()
809-
810 def first_time(self):
811 """
812 Import themes if first time
813 """
814 self.application.process_events()
815- for plugin in self.plugin_manager.plugins:
816+ for plugin in State().list_plugins():
817 if hasattr(plugin, 'first_time'):
818 self.application.process_events()
819 plugin.first_time()
820@@ -713,7 +691,7 @@
821 self.projector_manager_dock.setVisible(True)
822 else:
823 self.projector_manager_dock.setVisible(False)
824- for plugin in self.plugin_manager.plugins:
825+ for plugin in State().list_plugins():
826 self.active_plugin = plugin
827 old_status = self.active_plugin.status
828 self.active_plugin.set_status()
829@@ -880,7 +858,7 @@
830 setting_sections.extend([self.header_section])
831 setting_sections.extend(['crashreport'])
832 # Add plugin sections.
833- setting_sections.extend([plugin.name for plugin in self.plugin_manager.plugins])
834+ setting_sections.extend([plugin.name for plugin in State().list_plugins()])
835 # Copy the settings file to the tmp dir, because we do not want to change the original one.
836 temp_dir_path = Path(gettempdir(), 'openlp')
837 create_paths(temp_dir_path)
838
839=== modified file 'openlp/core/ui/media/__init__.py'
840--- openlp/core/ui/media/__init__.py 2018-10-27 01:40:20 +0000
841+++ openlp/core/ui/media/__init__.py 2019-01-27 20:26:59 +0000
842@@ -24,10 +24,6 @@
843 """
844 import logging
845
846-from PyQt5 import QtCore
847-
848-from openlp.core.common.settings import Settings
849-
850 log = logging.getLogger(__name__ + '.__init__')
851
852
853@@ -54,7 +50,7 @@
854 Folder = 5
855
856
857-class MediaInfo(object):
858+class ItemMediaInfo(object):
859 """
860 This class hold the media related info
861 """
862@@ -73,39 +69,6 @@
863 media_type = MediaType()
864
865
866-def get_media_players():
867- """
868- This method extracts the configured media players and overridden player
869- from the settings.
870- """
871- log.debug('get_media_players')
872- saved_players = Settings().value('media/players')
873- reg_ex = QtCore.QRegExp(r'.*\[(.*)\].*')
874- if Settings().value('media/override player') == QtCore.Qt.Checked:
875- if reg_ex.exactMatch(saved_players):
876- overridden_player = '{text}'.format(text=reg_ex.cap(1))
877- else:
878- overridden_player = 'auto'
879- else:
880- overridden_player = ''
881- saved_players_list = saved_players.replace('[', '').replace(']', '').split(',') if saved_players else []
882- return saved_players_list, overridden_player
883-
884-
885-def set_media_players(players_list, overridden_player='auto'):
886- """
887- This method saves the configured media players and overridden player to the settings
888-
889- :param players_list: A list with all active media players.
890- :param overridden_player: Here an special media player is chosen for all media actions.
891- """
892- log.debug('set_media_players')
893- players = ','.join(players_list)
894- if Settings().value('media/override player') == QtCore.Qt.Checked and overridden_player != 'auto':
895- players = players.replace(overridden_player, '[{text}]'.format(text=overridden_player))
896- Settings().setValue('media/players', players)
897-
898-
899 def parse_optical_path(input_string):
900 """
901 Split the optical path info.
902
903=== modified file 'openlp/core/ui/media/mediacontroller.py'
904--- openlp/core/ui/media/mediacontroller.py 2018-10-02 04:39:42 +0000
905+++ openlp/core/ui/media/mediacontroller.py 2019-01-27 20:26:59 +0000
906@@ -25,13 +25,19 @@
907 """
908 import datetime
909 import logging
910-import os
911-
912+
913+try:
914+ from pymediainfo import MediaInfo
915+ pymediainfo_available = True
916+except ImportError:
917+ pymediainfo_available = False
918+
919+from subprocess import check_output
920 from PyQt5 import QtCore, QtWidgets
921
922+from openlp.core.state import State
923 from openlp.core.api.http import register_endpoint
924-from openlp.core.common import extension_loader
925-from openlp.core.common.i18n import UiStrings, translate
926+from openlp.core.common.i18n import translate
927 from openlp.core.common.mixins import LogMixin, RegistryProperties
928 from openlp.core.common.registry import Registry, RegistryBase
929 from openlp.core.common.settings import Settings
930@@ -39,11 +45,9 @@
931 from openlp.core.lib.ui import critical_error_message_box
932 from openlp.core.ui import DisplayControllerType
933 from openlp.core.ui.icons import UiIcons
934-from openlp.core.ui.media import MediaInfo, MediaState, MediaType, get_media_players, parse_optical_path, \
935- set_media_players
936+from openlp.core.ui.media import MediaState, ItemMediaInfo, MediaType, parse_optical_path
937 from openlp.core.ui.media.endpoint import media_endpoint
938-from openlp.core.ui.media.mediaplayer import MediaPlayer
939-from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper
940+from openlp.core.ui.media.vlcplayer import VlcPlayer, get_vlc
941 from openlp.core.widgets.toolbar import OpenLPToolbar
942
943
944@@ -63,7 +67,6 @@
945 super(MediaSlider, self).__init__(direction)
946 self.manager = manager
947 self.controller = controller
948- self.no_matching_player = translate('MediaPlugin.MediaItem', 'File %s not supported using player %s')
949
950 def mouseMoveEvent(self, event):
951 """
952@@ -78,7 +81,6 @@
953 def mousePressEvent(self, event):
954 """
955 Mouse Press event no new functionality
956-
957 :param event: The triggering event
958 """
959 QtWidgets.QSlider.mousePressEvent(self, event)
960@@ -111,7 +113,9 @@
961 Constructor
962 """
963 super(MediaController, self).__init__(parent)
964- self.media_players = {}
965+
966+ def setup(self):
967+ self.vlc_player = None
968 self.display_controllers = {}
969 self.current_media_players = {}
970 # Timer for video state
971@@ -135,70 +139,40 @@
972 Registry().register_function('songs_hide', self.media_hide)
973 Registry().register_function('songs_blank', self.media_blank)
974 Registry().register_function('songs_unblank', self.media_unblank)
975- Registry().register_function('mediaitem_media_rebuild', self._set_active_players)
976 Registry().register_function('mediaitem_suffixes', self._generate_extensions_lists)
977 register_endpoint(media_endpoint)
978
979- def _set_active_players(self):
980- """
981- Set the active players and available media files
982- """
983- saved_players = get_media_players()[0]
984- for player in list(self.media_players.keys()):
985- self.media_players[player].is_active = player in saved_players
986-
987 def _generate_extensions_lists(self):
988 """
989 Set the active players and available media files
990 """
991 suffix_list = []
992 self.audio_extensions_list = []
993- for player in list(self.media_players.values()):
994- if player.is_active:
995- for item in player.audio_extensions_list:
996- if item not in self.audio_extensions_list:
997- self.audio_extensions_list.append(item)
998- suffix_list.append(item[2:])
999+ if self.vlc_player.is_active:
1000+ for item in self.vlc_player.audio_extensions_list:
1001+ if item not in self.audio_extensions_list:
1002+ self.audio_extensions_list.append(item)
1003+ suffix_list.append(item[2:])
1004 self.video_extensions_list = []
1005- for player in list(self.media_players.values()):
1006- if player.is_active:
1007- for item in player.video_extensions_list:
1008- if item not in self.video_extensions_list:
1009- self.video_extensions_list.append(item)
1010- suffix_list.append(item[2:])
1011+ if self.vlc_player.is_active:
1012+ for item in self.vlc_player.video_extensions_list:
1013+ if item not in self.video_extensions_list:
1014+ self.video_extensions_list.append(item)
1015+ suffix_list.append(item[2:])
1016 self.service_manager.supported_suffixes(suffix_list)
1017
1018- def register_players(self, player):
1019- """
1020- Register each media Player (Webkit, Phonon, etc) and store
1021- for later use
1022-
1023- :param player: Individual player class which has been enabled
1024- """
1025- self.media_players[player.name] = player
1026-
1027 def bootstrap_initialise(self):
1028 """
1029 Check to see if we have any media Player's available.
1030 """
1031- controller_dir = os.path.join('core', 'ui', 'media')
1032- # Find all files that do not begin with '.' (lp:#1738047) and end with player.py
1033- glob_pattern = os.path.join(controller_dir, '[!.]*player.py')
1034- extension_loader(glob_pattern, ['mediaplayer.py'])
1035- player_classes = MediaPlayer.__subclasses__()
1036- for player_class in player_classes:
1037- self.register_players(player_class(self))
1038- if not self.media_players:
1039- return False
1040- saved_players, overridden_player = get_media_players()
1041- invalid_media_players = \
1042- [media_player for media_player in saved_players if media_player not in self.media_players or
1043- not self.media_players[media_player].check_available()]
1044- if invalid_media_players:
1045- for invalidPlayer in invalid_media_players:
1046- saved_players.remove(invalidPlayer)
1047- set_media_players(saved_players, overridden_player)
1048- self._set_active_players()
1049+ self.setup()
1050+ self.vlc_player = VlcPlayer(self)
1051+ State().add_service("mediacontroller", 0)
1052+ if get_vlc() and pymediainfo_available:
1053+ State().update_pre_conditions("mediacontroller", True)
1054+ else:
1055+ State().missing_text("mediacontroller", translate('OpenLP.SlideController',
1056+ "VLC or pymediainfo are missing, so you are unable to play any media"))
1057 self._generate_extensions_lists()
1058 return True
1059
1060@@ -236,36 +210,6 @@
1061 if self.display_controllers[DisplayControllerType.Preview].media_info.can_loop_playback:
1062 self.media_play(self.display_controllers[DisplayControllerType.Preview], True)
1063
1064- def get_media_display_css(self):
1065- """
1066- Add css style sheets to htmlbuilder
1067- """
1068- css = ''
1069- for player in list(self.media_players.values()):
1070- if player.is_active:
1071- css += player.get_media_display_css()
1072- return css
1073-
1074- def get_media_display_javascript(self):
1075- """
1076- Add javascript functions to htmlbuilder
1077- """
1078- js = ''
1079- for player in list(self.media_players.values()):
1080- if player.is_active:
1081- js += player.get_media_display_javascript()
1082- return js
1083-
1084- def get_media_display_html(self):
1085- """
1086- Add html code to htmlbuilder
1087- """
1088- html = ''
1089- for player in list(self.media_players.values()):
1090- if player.is_active:
1091- html += player.get_media_display_html()
1092- return html
1093-
1094 def register_controller(self, controller):
1095 """
1096 Registers media controls where the players will be placed to run.
1097@@ -281,7 +225,7 @@
1098
1099 :param controller: First element is the controller which should be used
1100 """
1101- controller.media_info = MediaInfo()
1102+ controller.media_info = ItemMediaInfo()
1103 # Build a Media ToolBar
1104 controller.mediabar = OpenLPToolbar(controller)
1105 controller.mediabar.add_toolbar_action('playbackPlay', text='media_playback_play',
1106@@ -345,16 +289,12 @@
1107 """
1108 # clean up possible running old media files
1109 self.finalise()
1110- # update player status
1111- self._set_active_players()
1112 display.has_audio = True
1113 if display.is_live and preview:
1114 return
1115 if preview:
1116 display.has_audio = False
1117- for player in list(self.media_players.values()):
1118- if player.is_active:
1119- player.setup(display)
1120+ self.vlc_player.setup(display)
1121
1122 def set_controls_visible(self, controller, value):
1123 """
1124@@ -367,8 +307,7 @@
1125 controller.mediabar.setVisible(value)
1126 if controller.is_live and controller.display:
1127 if self.current_media_players and value:
1128- if self.current_media_players[controller.controller_type] != self.media_players['webkit']:
1129- controller.display.set_transparency(False)
1130+ controller.display.set_transparency(False)
1131
1132 @staticmethod
1133 def resize(display, player):
1134@@ -389,16 +328,19 @@
1135 :param hidden: The player which is doing the playing
1136 :param video_behind_text: Is the video to be played behind text.
1137 """
1138- is_valid = False
1139+ is_valid = True
1140 controller = self.display_controllers[source]
1141 # stop running videos
1142 self.media_reset(controller)
1143- controller.media_info = MediaInfo()
1144+ controller.media_info = ItemMediaInfo()
1145 controller.media_info.volume = controller.volume_slider.value()
1146 controller.media_info.is_background = video_behind_text
1147 # background will always loop video.
1148 controller.media_info.can_loop_playback = video_behind_text
1149- controller.media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path())
1150+ if service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
1151+ controller.media_info.file_info = service_item.background_audio
1152+ else:
1153+ controller.media_info.file_info = [service_item.get_frame_path()]
1154 display = self._define_display(controller)
1155 if controller.is_live:
1156 # if this is an optical device use special handling
1157@@ -411,7 +353,7 @@
1158 else:
1159 log.debug('video is not optical and live')
1160 controller.media_info.length = service_item.media_length
1161- is_valid = self._check_file_type(controller, display, service_item)
1162+ is_valid = self._check_file_type(controller, display)
1163 display.override['theme'] = ''
1164 display.override['video'] = True
1165 if controller.media_info.is_background:
1166@@ -431,7 +373,7 @@
1167 else:
1168 log.debug('video is not optical and preview')
1169 controller.media_info.length = service_item.media_length
1170- is_valid = self._check_file_type(controller, display, service_item)
1171+ is_valid = self._check_file_type(controller, display)
1172 if not is_valid:
1173 # Media could not be loaded correctly
1174 critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
1175@@ -462,19 +404,21 @@
1176 return True
1177
1178 @staticmethod
1179- def media_length(service_item):
1180+ def media_length(media_path):
1181 """
1182 Uses Media Info to obtain the media length
1183
1184- :param service_item: The ServiceItem containing the details to be played.
1185+ :param media_path: The file path to be checked..
1186 """
1187- media_info = MediaInfo()
1188- media_info.volume = 0
1189- media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path())
1190- media_data = MediaInfoWrapper.parse(service_item.get_frame_path())
1191+ if MediaInfo.can_parse():
1192+ media_data = MediaInfo.parse(media_path)
1193+ else:
1194+ xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', media_path])
1195+ if not xml.startswith(b'<?xml'):
1196+ xml = check_output(['mediainfo', '-f', '--Output=XML', media_path])
1197+ media_data = MediaInfo(xml.decode("utf-8"))
1198 # duration returns in milli seconds
1199- service_item.set_media_length(media_data.tracks[0].duration)
1200- return True
1201+ return media_data.tracks[0].duration
1202
1203 def media_setup_optical(self, filename, title, audio_track, subtitle_track, start, end, display, controller):
1204 """
1205@@ -493,7 +437,7 @@
1206 # stop running videos
1207 self.media_reset(controller)
1208 # Setup media info
1209- controller.media_info = MediaInfo()
1210+ controller.media_info = ItemMediaInfo()
1211 controller.media_info.file_info = QtCore.QFileInfo(filename)
1212 if audio_track == -1 and subtitle_track == -1:
1213 controller.media_info.media_type = MediaType.CD
1214@@ -508,86 +452,49 @@
1215 # When called from mediaitem display is None
1216 if display is None:
1217 display = controller.preview_display
1218- # Find vlc player
1219- used_players = get_media_players()[0]
1220- vlc_player = None
1221- for title in used_players:
1222- player = self.media_players[title]
1223- if player.name == 'vlc':
1224- vlc_player = player
1225- if vlc_player is None:
1226- critical_error_message_box(translate('MediaPlugin.MediaItem', 'VLC player required'),
1227- translate('MediaPlugin.MediaItem',
1228- 'VLC player required for playback of optical devices'))
1229- return False
1230- vlc_player.load(display)
1231- self.resize(display, vlc_player)
1232- self.current_media_players[controller.controller_type] = vlc_player
1233+ self.vlc_player.load(display)
1234+ self.resize(display, self.vlc_player)
1235+ self.current_media_players[controller.controller_type] = self.vlc_player
1236 if audio_track == -1 and subtitle_track == -1:
1237 controller.media_info.media_type = MediaType.CD
1238 else:
1239 controller.media_info.media_type = MediaType.DVD
1240 return True
1241
1242- @staticmethod
1243- def _get_used_players(service_item):
1244- """
1245- Find the player for a given service item
1246-
1247- :param service_item: where the information is about the media and required player
1248- :return: player description
1249- """
1250- used_players = get_media_players()[0]
1251- # If no player, we can't play
1252- if not used_players:
1253- return False
1254- default_player = [used_players[0]]
1255- if service_item.processor and service_item.processor != UiStrings().Automatic:
1256- # check to see if the player is usable else use the default one.
1257- if service_item.processor.lower() not in used_players:
1258- used_players = default_player
1259- else:
1260- used_players = [service_item.processor.lower()]
1261- return used_players
1262-
1263- def _check_file_type(self, controller, display, service_item):
1264+ def _check_file_type(self, controller, display):
1265 """
1266 Select the correct media Player type from the prioritized Player list
1267
1268 :param controller: First element is the controller which should be used
1269 :param display: Which display to use
1270- :param service_item: The ServiceItem containing the details to be played.
1271 """
1272- used_players = self._get_used_players(service_item)
1273- if controller.media_info.file_info.isFile():
1274- suffix = '*.%s' % controller.media_info.file_info.suffix().lower()
1275- for title in used_players:
1276- if not title:
1277- continue
1278- player = self.media_players[title]
1279+ for file in controller.media_info.file_info:
1280+ if file.is_file:
1281+ suffix = '*%s' % file.suffix.lower()
1282+ player = self.vlc_player
1283+ file = str(file)
1284 if suffix in player.video_extensions_list:
1285 if not controller.media_info.is_background or controller.media_info.is_background and \
1286 player.can_background:
1287 self.resize(display, player)
1288- if player.load(display):
1289+ if player.load(display, file):
1290 self.current_media_players[controller.controller_type] = player
1291 controller.media_info.media_type = MediaType.Video
1292 return True
1293 if suffix in player.audio_extensions_list:
1294- if player.load(display):
1295+ if player.load(display, file):
1296 self.current_media_players[controller.controller_type] = player
1297 controller.media_info.media_type = MediaType.Audio
1298 return True
1299- else:
1300- for title in used_players:
1301- player = self.media_players[title]
1302+ else:
1303+ player = self.vlc_player
1304+ file = str(file)
1305 if player.can_folder:
1306 self.resize(display, player)
1307- if player.load(display):
1308+ if player.load(display, file):
1309 self.current_media_players[controller.controller_type] = player
1310 controller.media_info.media_type = MediaType.Video
1311 return True
1312- # no valid player found
1313 return False
1314
1315 def media_play_msg(self, msg, status=True):
1316
1317=== modified file 'openlp/core/ui/media/mediaplayer.py'
1318--- openlp/core/ui/media/mediaplayer.py 2017-12-29 09:15:48 +0000
1319+++ openlp/core/ui/media/mediaplayer.py 2019-01-27 20:26:59 +0000
1320@@ -60,11 +60,12 @@
1321 """
1322 pass
1323
1324- def load(self, display):
1325+ def load(self, display, file):
1326 """
1327 Load a new media file and check if it is valid
1328
1329 :param display: The display to be updated.
1330+ :param file: The file to be loaded
1331 """
1332 return True
1333
1334
1335=== modified file 'openlp/core/ui/media/playertab.py'
1336--- openlp/core/ui/media/playertab.py 2018-09-12 05:43:27 +0000
1337+++ openlp/core/ui/media/playertab.py 2019-01-27 20:26:59 +0000
1338@@ -32,7 +32,6 @@
1339 from openlp.core.lib.settingstab import SettingsTab
1340 from openlp.core.lib.ui import create_button
1341 from openlp.core.ui.icons import UiIcons
1342-from openlp.core.ui.media import get_media_players, set_media_players
1343 from openlp.core.widgets.buttons import ColorButton
1344
1345
1346@@ -55,7 +54,7 @@
1347 """
1348 Constructor
1349 """
1350- self.media_players = Registry().get('media_controller').media_players
1351+ # self.media_players = Registry().get('media_controller').media_players
1352 self.saved_used_players = None
1353 self.icon_path = UiIcons().player
1354 player_translated = translate('OpenLP.PlayerTab', 'Players')
1355@@ -202,7 +201,7 @@
1356 """
1357 if self.saved_used_players:
1358 self.used_players = self.saved_used_players
1359- self.used_players = get_media_players()[0]
1360+ # self.used_players = get_media_players()[0]
1361 self.saved_used_players = self.used_players
1362 settings = Settings()
1363 settings.beginGroup(self.settings_section)
1364@@ -220,13 +219,13 @@
1365 settings.beginGroup(self.settings_section)
1366 settings.setValue('background color', self.background_color)
1367 settings.endGroup()
1368- old_players, override_player = get_media_players()
1369- if self.used_players != old_players:
1370- # clean old Media stuff
1371- set_media_players(self.used_players, override_player)
1372- self.settings_form.register_post_process('mediaitem_suffix_reset')
1373- self.settings_form.register_post_process('mediaitem_media_rebuild')
1374- self.settings_form.register_post_process('config_screen_changed')
1375+ # old_players, override_player = get_media_players()
1376+ # if self.used_players != old_players:
1377+ # # clean old Media stuff
1378+ # set_media_players(self.used_players, override_player)
1379+ # self.settings_form.register_post_process('mediaitem_suffix_reset')
1380+ # self.settings_form.register_post_process('mediaitem_media_rebuild')
1381+ # self.settings_form.register_post_process('config_screen_changed')
1382
1383 def post_set_up(self, post_update=False):
1384 """
1385
1386=== removed file 'openlp/core/ui/media/vendor/mediainfoWrapper.py'
1387--- openlp/core/ui/media/vendor/mediainfoWrapper.py 2018-10-30 19:46:55 +0000
1388+++ openlp/core/ui/media/vendor/mediainfoWrapper.py 1970-01-01 00:00:00 +0000
1389@@ -1,129 +0,0 @@
1390-# -*- coding: utf-8 -*-
1391-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
1392-
1393-###############################################################################
1394-# OpenLP - Open Source Lyrics Projection #
1395-# --------------------------------------------------------------------------- #
1396-# Copyright (c) 2008-2018 OpenLP Developers #
1397-# --------------------------------------------------------------------------- #
1398-# This program is free software; you can redistribute it and/or modify it #
1399-# under the terms of the GNU General Public License as published by the Free #
1400-# Software Foundation; version 2 of the License. #
1401-# #
1402-# This program is distributed in the hope that it will be useful, but WITHOUT #
1403-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
1404-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
1405-# more details. #
1406-# #
1407-# You should have received a copy of the GNU General Public License along #
1408-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
1409-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
1410-###############################################################################
1411-"""
1412-The :mod:`~openlp.core.ui.media.mediainfo` module contains code to run mediainfo on a media file and obtain
1413-information related to the rwquested media.
1414-"""
1415-import json
1416-import os
1417-from subprocess import check_output
1418-
1419-from bs4 import BeautifulSoup, NavigableString
1420-
1421-
1422-ENV_DICT = os.environ
1423-
1424-
1425-class Track(object):
1426-
1427- def __getattribute__(self, name):
1428- try:
1429- return object.__getattribute__(self, name)
1430- except Exception:
1431- pass
1432- return None
1433-
1434- def __init__(self, xml_dom_fragment):
1435- self.xml_dom_fragment = xml_dom_fragment
1436- self.track_type = xml_dom_fragment.attrs['type']
1437- for el in self.xml_dom_fragment.children:
1438- if not isinstance(el, NavigableString):
1439- node_name = el.name.lower().strip().strip('_')
1440- if node_name == 'id':
1441- node_name = 'track_id'
1442- node_value = el.string
1443- other_node_name = "other_%s" % node_name
1444- if getattr(self, node_name) is None:
1445- setattr(self, node_name, node_value)
1446- else:
1447- if getattr(self, other_node_name) is None:
1448- setattr(self, other_node_name, [node_value, ])
1449- else:
1450- getattr(self, other_node_name).append(node_value)
1451-
1452- for o in [d for d in self.__dict__.keys() if d.startswith('other_')]:
1453- try:
1454- primary = o.replace('other_', '')
1455- setattr(self, primary, int(getattr(self, primary)))
1456- except Exception:
1457- for v in getattr(self, o):
1458- try:
1459- current = getattr(self, primary)
1460- setattr(self, primary, int(v))
1461- getattr(self, o).append(current)
1462- break
1463- except Exception:
1464- pass
1465-
1466- def __repr__(self):
1467- return "<Track track_id='{0}', track_type='{1}'>".format(self.track_id, self.track_type)
1468-
1469- def to_data(self):
1470- data = {}
1471- for k, v in self.__dict__.items():
1472- if k != 'xml_dom_fragment':
1473- data[k] = v
1474- return data
1475-
1476-
1477-class MediaInfoWrapper(object):
1478-
1479- def __init__(self, xml):
1480- self.xml_dom = xml
1481- xml_types = (str,) # no unicode type in python3
1482- if isinstance(xml, xml_types):
1483- self.xml_dom = MediaInfoWrapper.parse_xml_data_into_dom(xml)
1484-
1485- @staticmethod
1486- def parse_xml_data_into_dom(xml_data):
1487- return BeautifulSoup(xml_data, "xml")
1488-
1489- @staticmethod
1490- def parse(filename, environment=ENV_DICT):
1491- xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', filename])
1492- if not xml.startswith(b'<?xml'):
1493- xml = check_output(['mediainfo', '-f', '--Output=XML', filename])
1494- xml_dom = MediaInfoWrapper.parse_xml_data_into_dom(xml)
1495- return MediaInfoWrapper(xml_dom)
1496-
1497- def _populate_tracks(self):
1498- if self.xml_dom is None:
1499- return
1500- for xml_track in self.xml_dom.Mediainfo.File.find_all("track"):
1501- self._tracks.append(Track(xml_track))
1502-
1503- @property
1504- def tracks(self):
1505- if not hasattr(self, "_tracks"):
1506- self._tracks = []
1507- if len(self._tracks) == 0:
1508- self._populate_tracks()
1509- return self._tracks
1510-
1511- def to_data(self):
1512- data = {'tracks': []}
1513- for track in self.tracks:
1514- data['tracks'].append(track.to_data())
1515- return data
1516-
1517- def to_json(self):
1518- return json.dumps(self.to_data())
1519
1520=== modified file 'openlp/core/ui/media/vendor/vlc.py'
1521--- openlp/core/ui/media/vendor/vlc.py 2018-10-02 04:39:42 +0000
1522+++ openlp/core/ui/media/vendor/vlc.py 2019-01-27 20:26:59 +0000
1523@@ -1,8 +1,9 @@
1524 #! /usr/bin/python
1525+# -*- coding: utf-8 -*-
1526
1527 # Python ctypes bindings for VLC
1528 #
1529-# Copyright (C) 2009-2012 the VideoLAN team
1530+# Copyright (C) 2009-2017 the VideoLAN team
1531 # $Id: $
1532 #
1533 # Authors: Olivier Aubert <contact at olivieraubert.net>
1534@@ -27,7 +28,7 @@
1535 U{http://wiki.videolan.org/LibVLC}.
1536
1537 You can find the documentation and a README file with some examples
1538-at U{http://www.advene.org/download/python-ctypes/}.
1539+at U{http://www.olivieraubert.net/vlc/python-ctypes/}.
1540
1541 Basically, the most important class is L{Instance}, which is used
1542 to create a libvlc instance. From this instance, you then create
1543@@ -40,16 +41,22 @@
1544 """
1545
1546 import ctypes
1547-import functools
1548+from ctypes.util import find_library
1549 import os
1550 import sys
1551-from ctypes.util import find_library
1552+import functools
1553+
1554 # Used by EventManager in override.py
1555 from inspect import getargspec
1556
1557-
1558-__version__ = "N/A"
1559-build_date = "Mon Jan 25 19:40:05 2016"
1560+import logging
1561+
1562+logger = logging.getLogger(__name__)
1563+
1564+__version__ = "3.0.3104"
1565+__libvlc_version__ = "3.0.3"
1566+__generator_version__ = "1.4"
1567+build_date = "Fri Jul 13 15:18:27 2018 3.0.3"
1568
1569 # The libvlc doc states that filenames are expected to be in UTF8, do
1570 # not rely on sys.getfilesystemencoding() which will be confused,
1571@@ -62,6 +69,8 @@
1572 bytes = bytes
1573 basestring = (str, bytes)
1574 PYTHON3 = True
1575+
1576+
1577 def str_to_bytes(s):
1578 """Translate string or bytes to bytes.
1579 """
1580@@ -70,6 +79,7 @@
1581 else:
1582 return s
1583
1584+
1585 def bytes_to_str(b):
1586 """Translate bytes to string.
1587 """
1588@@ -83,6 +93,8 @@
1589 bytes = str
1590 basestring = basestring
1591 PYTHON3 = False
1592+
1593+
1594 def str_to_bytes(s):
1595 """Translate string or bytes to bytes.
1596 """
1597@@ -91,6 +103,7 @@
1598 else:
1599 return s
1600
1601+
1602 def bytes_to_str(b):
1603 """Translate bytes to unicode string.
1604 """
1605@@ -103,9 +116,22 @@
1606 # instanciated.
1607 _internal_guard = object()
1608
1609+
1610 def find_lib():
1611 dll = None
1612- plugin_path = None
1613+ plugin_path = os.environ.get('PYTHON_VLC_MODULE_PATH', None)
1614+ if 'PYTHON_VLC_LIB_PATH' in os.environ:
1615+ try:
1616+ dll = ctypes.CDLL(os.environ['PYTHON_VLC_LIB_PATH'])
1617+ except OSError:
1618+ logger.error("Cannot load lib specified by PYTHON_VLC_LIB_PATH env. variable")
1619+ sys.exit(1)
1620+ if plugin_path and not os.path.isdir(plugin_path):
1621+ logger.error("Invalid PYTHON_VLC_MODULE_PATH specified. Please fix.")
1622+ sys.exit(1)
1623+ if dll is not None:
1624+ return dll, plugin_path
1625+
1626 if sys.platform.startswith('linux'):
1627 p = find_library('vlc')
1628 try:
1629@@ -113,7 +139,8 @@
1630 except OSError: # may fail
1631 dll = ctypes.CDLL('libvlc.so.5')
1632 elif sys.platform.startswith('win'):
1633- p = find_library('libvlc.dll')
1634+ libname = 'libvlc.dll'
1635+ p = find_library(libname)
1636 if p is None:
1637 try: # some registry settings
1638 # leaner than win32api, win32con
1639@@ -132,22 +159,26 @@
1640 except ImportError: # no PyWin32
1641 pass
1642 if plugin_path is None:
1643- # try some standard locations.
1644- for p in ('Program Files\\VideoLan\\', 'VideoLan\\',
1645- 'Program Files\\', ''):
1646- p = 'C:\\' + p + 'VLC\\libvlc.dll'
1647+ # try some standard locations.
1648+ programfiles = os.environ["ProgramFiles"]
1649+ homedir = os.environ["HOMEDRIVE"]
1650+ for p in ('{programfiles}\\VideoLan{libname}', '{homedir}:\\VideoLan{libname}',
1651+ '{programfiles}{libname}', '{homedir}:{libname}'):
1652+ p = p.format(homedir=homedir,
1653+ programfiles=programfiles,
1654+ libname='\\VLC\\' + libname)
1655 if os.path.exists(p):
1656 plugin_path = os.path.dirname(p)
1657 break
1658 if plugin_path is not None: # try loading
1659 p = os.getcwd()
1660 os.chdir(plugin_path)
1661- # if chdir failed, this will raise an exception
1662- dll = ctypes.CDLL('libvlc.dll')
1663- # restore cwd after dll has been loaded
1664+ # if chdir failed, this will raise an exception
1665+ dll = ctypes.CDLL(libname)
1666+ # restore cwd after dll has been loaded
1667 os.chdir(p)
1668 else: # may fail
1669- dll = ctypes.CDLL('libvlc.dll')
1670+ dll = ctypes.CDLL(libname)
1671 else:
1672 plugin_path = os.path.dirname(p)
1673 dll = ctypes.CDLL(p)
1674@@ -155,13 +186,20 @@
1675 elif sys.platform.startswith('darwin'):
1676 # FIXME: should find a means to configure path
1677 d = '/Applications/VLC.app/Contents/MacOS/'
1678+ c = d + 'lib/libvlccore.dylib'
1679 p = d + 'lib/libvlc.dylib'
1680- if os.path.exists(p):
1681+ if os.path.exists(p) and os.path.exists(c):
1682+ # pre-load libvlccore VLC 2.2.8+
1683+ ctypes.CDLL(c)
1684 dll = ctypes.CDLL(p)
1685- d += 'modules'
1686- if os.path.isdir(d):
1687- plugin_path = d
1688- else: # hope, some PATH is set...
1689+ for p in ('modules', 'plugins'):
1690+ p = d + p
1691+ if os.path.isdir(p):
1692+ plugin_path = p
1693+ break
1694+ else: # hope, some [DY]LD_LIBRARY_PATH is set...
1695+ # pre-load libvlccore VLC 2.2.8+
1696+ ctypes.CDLL('libvlccore.dylib')
1697 dll = ctypes.CDLL('libvlc.dylib')
1698
1699 else:
1700@@ -169,20 +207,24 @@
1701
1702 return (dll, plugin_path)
1703
1704+
1705 # plugin_path used on win32 and MacOS in override.py
1706-dll, plugin_path = find_lib()
1707+dll, plugin_path = find_lib()
1708+
1709
1710 class VLCException(Exception):
1711 """Exception raised by libvlc methods.
1712 """
1713 pass
1714
1715+
1716 try:
1717 _Ints = (int, long)
1718 except NameError: # no long in Python 3+
1719- _Ints = int
1720+ _Ints = int
1721 _Seqs = (list, tuple)
1722
1723+
1724 # Used for handling *event_manager() methods.
1725 class memoize_parameterless(object):
1726 """Decorator. Caches a parameterless method's return value each time it is called.
1727@@ -191,6 +233,7 @@
1728 (not reevaluated).
1729 Adapted from https://wiki.python.org/moin/PythonDecoratorLibrary
1730 """
1731+
1732 def __init__(self, func):
1733 self.func = func
1734 self._cache = {}
1735@@ -208,14 +251,16 @@
1736 return self.func.__doc__
1737
1738 def __get__(self, obj, objtype):
1739- """Support instance methods.
1740- """
1741- return functools.partial(self.__call__, obj)
1742+ """Support instance methods.
1743+ """
1744+ return functools.partial(self.__call__, obj)
1745+
1746
1747 # Default instance. It is used to instanciate classes directly in the
1748 # OO-wrapper.
1749 _default_instance = None
1750
1751+
1752 def get_default_instance():
1753 """Return the default VLC.Instance.
1754 """
1755@@ -224,9 +269,11 @@
1756 _default_instance = Instance()
1757 return _default_instance
1758
1759+
1760 _Cfunctions = {} # from LibVLC __version__
1761 _Globals = globals() # sys.modules[__name__].__dict__
1762
1763+
1764 def _Cfunction(name, flags, errcheck, *types):
1765 """(INTERNAL) New ctypes function binding.
1766 """
1767@@ -245,6 +292,7 @@
1768 return f
1769 raise NameError('no function %r' % (name,))
1770
1771+
1772 def _Cobject(cls, ctype):
1773 """(INTERNAL) New instance from ctypes.
1774 """
1775@@ -252,15 +300,18 @@
1776 o._as_parameter_ = ctype
1777 return o
1778
1779+
1780 def _Constructor(cls, ptr=_internal_guard):
1781 """(INTERNAL) New wrapper from ctypes.
1782 """
1783 if ptr == _internal_guard:
1784- raise VLCException("(INTERNAL) ctypes class. You should get references for this class through methods of the LibVLC API.")
1785+ raise VLCException(
1786+ "(INTERNAL) ctypes class. You should get references for this class through methods of the LibVLC API.")
1787 if ptr is None or ptr == 0:
1788 return None
1789 return _Cobject(cls, ctypes.c_void_p(ptr))
1790
1791+
1792 class _Cstruct(ctypes.Structure):
1793 """(INTERNAL) Base class for ctypes structures.
1794 """
1795@@ -273,9 +324,11 @@
1796 def __repr__(self):
1797 return '%s.%s' % (self.__class__.__module__, self)
1798
1799+
1800 class _Ctype(object):
1801 """(INTERNAL) Base class for ctypes.
1802 """
1803+
1804 @staticmethod
1805 def from_param(this): # not self
1806 """(INTERNAL) ctypes parameter conversion method.
1807@@ -284,15 +337,20 @@
1808 return None
1809 return this._as_parameter_
1810
1811+
1812 class ListPOINTER(object):
1813 """Just like a POINTER but accept a list of ctype as an argument.
1814 """
1815+
1816 def __init__(self, etype):
1817 self.etype = etype
1818
1819 def from_param(self, param):
1820 if isinstance(param, _Seqs):
1821 return (self.etype * len(param))(*param)
1822+ else:
1823+ return ctypes.POINTER(param)
1824+
1825
1826 # errcheck functions for some native functions.
1827 def string_result(result, func, arguments):
1828@@ -308,24 +366,33 @@
1829 return s
1830 return None
1831
1832+
1833 def class_result(classname):
1834 """Errcheck function. Returns a function that creates the specified class.
1835 """
1836+
1837 def wrap_errcheck(result, func, arguments):
1838 if result is None:
1839 return None
1840 return classname(result)
1841+
1842 return wrap_errcheck
1843
1844+
1845 # Wrapper for the opaque struct libvlc_log_t
1846 class Log(ctypes.Structure):
1847 pass
1848+
1849+
1850 Log_ptr = ctypes.POINTER(Log)
1851
1852+
1853 # FILE* ctypes wrapper, copied from
1854 # http://svn.python.org/projects/ctypes/trunk/ctypeslib/ctypeslib/contrib/pythonhdr.py
1855 class FILE(ctypes.Structure):
1856 pass
1857+
1858+
1859 FILE_ptr = ctypes.POINTER(FILE)
1860
1861 if PYTHON3:
1862@@ -338,7 +405,7 @@
1863 ctypes.c_char_p,
1864 ctypes.c_char_p,
1865 ctypes.c_char_p,
1866- ctypes.c_int ]
1867+ ctypes.c_int]
1868
1869 PyFile_AsFd = ctypes.pythonapi.PyObject_AsFileDescriptor
1870 PyFile_AsFd.restype = ctypes.c_int
1871@@ -355,7 +422,8 @@
1872 PyFile_AsFile.restype = FILE_ptr
1873 PyFile_AsFile.argtypes = [ctypes.py_object]
1874
1875- # Generated enum types #
1876+
1877+# Generated enum types #
1878
1879 class _Enum(ctypes.c_uint):
1880 '''(INTERNAL) Base class
1881@@ -373,12 +441,13 @@
1882 return '.'.join((self.__class__.__module__, self.__str__()))
1883
1884 def __eq__(self, other):
1885- return ( (isinstance(other, _Enum) and self.value == other.value)
1886- or (isinstance(other, _Ints) and self.value == other) )
1887+ return ((isinstance(other, _Enum) and self.value == other.value)
1888+ or (isinstance(other, _Ints) and self.value == other))
1889
1890 def __ne__(self, other):
1891 return not self.__eq__(other)
1892
1893+
1894 class LogLevel(_Enum):
1895 '''Logging messages level.
1896 \note future libvlc versions may define new levels.
1897@@ -389,11 +458,51 @@
1898 3: 'WARNING',
1899 4: 'ERROR',
1900 }
1901-LogLevel.DEBUG = LogLevel(0)
1902-LogLevel.ERROR = LogLevel(4)
1903-LogLevel.NOTICE = LogLevel(2)
1904+
1905+
1906+LogLevel.DEBUG = LogLevel(0)
1907+LogLevel.ERROR = LogLevel(4)
1908+LogLevel.NOTICE = LogLevel(2)
1909 LogLevel.WARNING = LogLevel(3)
1910
1911+
1912+class MediaDiscovererCategory(_Enum):
1913+ '''Category of a media discoverer
1914+See libvlc_media_discoverer_list_get().
1915+ '''
1916+ _enum_names_ = {
1917+ 0: 'devices',
1918+ 1: 'lan',
1919+ 2: 'podcasts',
1920+ 3: 'localdirs',
1921+ }
1922+
1923+
1924+MediaDiscovererCategory.devices = MediaDiscovererCategory(0)
1925+MediaDiscovererCategory.lan = MediaDiscovererCategory(1)
1926+MediaDiscovererCategory.localdirs = MediaDiscovererCategory(3)
1927+MediaDiscovererCategory.podcasts = MediaDiscovererCategory(2)
1928+
1929+
1930+class DialogQuestionType(_Enum):
1931+ '''@defgroup libvlc_dialog libvlc dialog
1932+@ingroup libvlc
1933+@{
1934+@file
1935+libvlc dialog external api.
1936+ '''
1937+ _enum_names_ = {
1938+ 0: 'NORMAL',
1939+ 1: 'WARNING',
1940+ 2: 'CRITICAL',
1941+ }
1942+
1943+
1944+DialogQuestionType.CRITICAL = DialogQuestionType(2)
1945+DialogQuestionType.NORMAL = DialogQuestionType(0)
1946+DialogQuestionType.WARNING = DialogQuestionType(1)
1947+
1948+
1949 class EventType(_Enum):
1950 '''Event types.
1951 '''
1952@@ -425,10 +534,21 @@
1953 273: 'MediaPlayerLengthChanged',
1954 274: 'MediaPlayerVout',
1955 275: 'MediaPlayerScrambledChanged',
1956+ 276: 'MediaPlayerESAdded',
1957+ 277: 'MediaPlayerESDeleted',
1958+ 278: 'MediaPlayerESSelected',
1959+ 279: 'MediaPlayerCorked',
1960+ 280: 'MediaPlayerUncorked',
1961+ 281: 'MediaPlayerMuted',
1962+ 282: 'MediaPlayerUnmuted',
1963+ 283: 'MediaPlayerAudioVolume',
1964+ 284: 'MediaPlayerAudioDevice',
1965+ 285: 'MediaPlayerChapterChanged',
1966 0x200: 'MediaListItemAdded',
1967 513: 'MediaListWillAddItem',
1968 514: 'MediaListItemDeleted',
1969 515: 'MediaListWillDeleteItem',
1970+ 516: 'MediaListEndReached',
1971 0x300: 'MediaListViewItemAdded',
1972 769: 'MediaListViewWillAddItem',
1973 770: 'MediaListViewItemDeleted',
1974@@ -438,6 +558,8 @@
1975 1026: 'MediaListPlayerStopped',
1976 0x500: 'MediaDiscovererStarted',
1977 1281: 'MediaDiscovererEnded',
1978+ 1282: 'RendererDiscovererItemAdded',
1979+ 1283: 'RendererDiscovererItemDeleted',
1980 0x600: 'VlmMediaAdded',
1981 1537: 'VlmMediaRemoved',
1982 1538: 'VlmMediaChanged',
1983@@ -450,57 +572,73 @@
1984 1545: 'VlmMediaInstanceStatusEnd',
1985 1546: 'VlmMediaInstanceStatusError',
1986 }
1987-EventType.MediaDiscovererEnded = EventType(1281)
1988-EventType.MediaDiscovererStarted = EventType(0x500)
1989-EventType.MediaDurationChanged = EventType(2)
1990-EventType.MediaFreed = EventType(4)
1991-EventType.MediaListItemAdded = EventType(0x200)
1992-EventType.MediaListItemDeleted = EventType(514)
1993-EventType.MediaListPlayerNextItemSet = EventType(1025)
1994-EventType.MediaListPlayerPlayed = EventType(0x400)
1995-EventType.MediaListPlayerStopped = EventType(1026)
1996-EventType.MediaListViewItemAdded = EventType(0x300)
1997-EventType.MediaListViewItemDeleted = EventType(770)
1998-EventType.MediaListViewWillAddItem = EventType(769)
1999-EventType.MediaListViewWillDeleteItem = EventType(771)
2000-EventType.MediaListWillAddItem = EventType(513)
2001-EventType.MediaListWillDeleteItem = EventType(515)
2002-EventType.MediaMetaChanged = EventType(0)
2003-EventType.MediaParsedChanged = EventType(3)
2004-EventType.MediaPlayerBackward = EventType(264)
2005-EventType.MediaPlayerBuffering = EventType(259)
2006-EventType.MediaPlayerEncounteredError = EventType(266)
2007-EventType.MediaPlayerEndReached = EventType(265)
2008-EventType.MediaPlayerForward = EventType(263)
2009-EventType.MediaPlayerLengthChanged = EventType(273)
2010-EventType.MediaPlayerMediaChanged = EventType(0x100)
2011-EventType.MediaPlayerNothingSpecial = EventType(257)
2012-EventType.MediaPlayerOpening = EventType(258)
2013-EventType.MediaPlayerPausableChanged = EventType(270)
2014-EventType.MediaPlayerPaused = EventType(261)
2015-EventType.MediaPlayerPlaying = EventType(260)
2016-EventType.MediaPlayerPositionChanged = EventType(268)
2017-EventType.MediaPlayerScrambledChanged = EventType(275)
2018-EventType.MediaPlayerSeekableChanged = EventType(269)
2019-EventType.MediaPlayerSnapshotTaken = EventType(272)
2020-EventType.MediaPlayerStopped = EventType(262)
2021-EventType.MediaPlayerTimeChanged = EventType(267)
2022-EventType.MediaPlayerTitleChanged = EventType(271)
2023-EventType.MediaPlayerVout = EventType(274)
2024-EventType.MediaStateChanged = EventType(5)
2025-EventType.MediaSubItemAdded = EventType(1)
2026-EventType.MediaSubItemTreeAdded = EventType(6)
2027-EventType.VlmMediaAdded = EventType(0x600)
2028-EventType.VlmMediaChanged = EventType(1538)
2029-EventType.VlmMediaInstanceStarted = EventType(1539)
2030-EventType.VlmMediaInstanceStatusEnd = EventType(1545)
2031-EventType.VlmMediaInstanceStatusError = EventType(1546)
2032-EventType.VlmMediaInstanceStatusInit = EventType(1541)
2033+
2034+
2035+EventType.MediaDiscovererEnded = EventType(1281)
2036+EventType.MediaDiscovererStarted = EventType(0x500)
2037+EventType.MediaDurationChanged = EventType(2)
2038+EventType.MediaFreed = EventType(4)
2039+EventType.MediaListEndReached = EventType(516)
2040+EventType.MediaListItemAdded = EventType(0x200)
2041+EventType.MediaListItemDeleted = EventType(514)
2042+EventType.MediaListPlayerNextItemSet = EventType(1025)
2043+EventType.MediaListPlayerPlayed = EventType(0x400)
2044+EventType.MediaListPlayerStopped = EventType(1026)
2045+EventType.MediaListViewItemAdded = EventType(0x300)
2046+EventType.MediaListViewItemDeleted = EventType(770)
2047+EventType.MediaListViewWillAddItem = EventType(769)
2048+EventType.MediaListViewWillDeleteItem = EventType(771)
2049+EventType.MediaListWillAddItem = EventType(513)
2050+EventType.MediaListWillDeleteItem = EventType(515)
2051+EventType.MediaMetaChanged = EventType(0)
2052+EventType.MediaParsedChanged = EventType(3)
2053+EventType.MediaPlayerAudioDevice = EventType(284)
2054+EventType.MediaPlayerAudioVolume = EventType(283)
2055+EventType.MediaPlayerBackward = EventType(264)
2056+EventType.MediaPlayerBuffering = EventType(259)
2057+EventType.MediaPlayerChapterChanged = EventType(285)
2058+EventType.MediaPlayerCorked = EventType(279)
2059+EventType.MediaPlayerESAdded = EventType(276)
2060+EventType.MediaPlayerESDeleted = EventType(277)
2061+EventType.MediaPlayerESSelected = EventType(278)
2062+EventType.MediaPlayerEncounteredError = EventType(266)
2063+EventType.MediaPlayerEndReached = EventType(265)
2064+EventType.MediaPlayerForward = EventType(263)
2065+EventType.MediaPlayerLengthChanged = EventType(273)
2066+EventType.MediaPlayerMediaChanged = EventType(0x100)
2067+EventType.MediaPlayerMuted = EventType(281)
2068+EventType.MediaPlayerNothingSpecial = EventType(257)
2069+EventType.MediaPlayerOpening = EventType(258)
2070+EventType.MediaPlayerPausableChanged = EventType(270)
2071+EventType.MediaPlayerPaused = EventType(261)
2072+EventType.MediaPlayerPlaying = EventType(260)
2073+EventType.MediaPlayerPositionChanged = EventType(268)
2074+EventType.MediaPlayerScrambledChanged = EventType(275)
2075+EventType.MediaPlayerSeekableChanged = EventType(269)
2076+EventType.MediaPlayerSnapshotTaken = EventType(272)
2077+EventType.MediaPlayerStopped = EventType(262)
2078+EventType.MediaPlayerTimeChanged = EventType(267)
2079+EventType.MediaPlayerTitleChanged = EventType(271)
2080+EventType.MediaPlayerUncorked = EventType(280)
2081+EventType.MediaPlayerUnmuted = EventType(282)
2082+EventType.MediaPlayerVout = EventType(274)
2083+EventType.MediaStateChanged = EventType(5)
2084+EventType.MediaSubItemAdded = EventType(1)
2085+EventType.MediaSubItemTreeAdded = EventType(6)
2086+EventType.RendererDiscovererItemAdded = EventType(1282)
2087+EventType.RendererDiscovererItemDeleted = EventType(1283)
2088+EventType.VlmMediaAdded = EventType(0x600)
2089+EventType.VlmMediaChanged = EventType(1538)
2090+EventType.VlmMediaInstanceStarted = EventType(1539)
2091+EventType.VlmMediaInstanceStatusEnd = EventType(1545)
2092+EventType.VlmMediaInstanceStatusError = EventType(1546)
2093+EventType.VlmMediaInstanceStatusInit = EventType(1541)
2094 EventType.VlmMediaInstanceStatusOpening = EventType(1542)
2095-EventType.VlmMediaInstanceStatusPause = EventType(1544)
2096+EventType.VlmMediaInstanceStatusPause = EventType(1544)
2097 EventType.VlmMediaInstanceStatusPlaying = EventType(1543)
2098-EventType.VlmMediaInstanceStopped = EventType(1540)
2099-EventType.VlmMediaRemoved = EventType(1537)
2100+EventType.VlmMediaInstanceStopped = EventType(1540)
2101+EventType.VlmMediaRemoved = EventType(1537)
2102+
2103
2104 class Meta(_Enum):
2105 '''Meta data types.
2106@@ -529,37 +667,46 @@
2107 20: 'Episode',
2108 21: 'ShowName',
2109 22: 'Actors',
2110+ 23: 'AlbumArtist',
2111+ 24: 'DiscNumber',
2112+ 25: 'DiscTotal',
2113 }
2114-Meta.Actors = Meta(22)
2115-Meta.Album = Meta(4)
2116-Meta.Artist = Meta(1)
2117-Meta.ArtworkURL = Meta(15)
2118-Meta.Copyright = Meta(3)
2119-Meta.Date = Meta(8)
2120+
2121+
2122+Meta.Actors = Meta(22)
2123+Meta.Album = Meta(4)
2124+Meta.AlbumArtist = Meta(23)
2125+Meta.Artist = Meta(1)
2126+Meta.ArtworkURL = Meta(15)
2127+Meta.Copyright = Meta(3)
2128+Meta.Date = Meta(8)
2129 Meta.Description = Meta(6)
2130-Meta.Director = Meta(18)
2131-Meta.EncodedBy = Meta(14)
2132-Meta.Episode = Meta(20)
2133-Meta.Genre = Meta(2)
2134-Meta.Language = Meta(11)
2135-Meta.NowPlaying = Meta(12)
2136-Meta.Publisher = Meta(13)
2137-Meta.Rating = Meta(7)
2138-Meta.Season = Meta(19)
2139-Meta.Setting = Meta(9)
2140-Meta.ShowName = Meta(21)
2141-Meta.Title = Meta(0)
2142-Meta.TrackID = Meta(16)
2143+Meta.Director = Meta(18)
2144+Meta.DiscNumber = Meta(24)
2145+Meta.DiscTotal = Meta(25)
2146+Meta.EncodedBy = Meta(14)
2147+Meta.Episode = Meta(20)
2148+Meta.Genre = Meta(2)
2149+Meta.Language = Meta(11)
2150+Meta.NowPlaying = Meta(12)
2151+Meta.Publisher = Meta(13)
2152+Meta.Rating = Meta(7)
2153+Meta.Season = Meta(19)
2154+Meta.Setting = Meta(9)
2155+Meta.ShowName = Meta(21)
2156+Meta.Title = Meta(0)
2157+Meta.TrackID = Meta(16)
2158 Meta.TrackNumber = Meta(5)
2159-Meta.TrackTotal = Meta(17)
2160-Meta.URL = Meta(10)
2161+Meta.TrackTotal = Meta(17)
2162+Meta.URL = Meta(10)
2163+
2164
2165 class State(_Enum):
2166 '''Note the order of libvlc_state_t enum must match exactly the order of
2167 See mediacontrol_playerstatus, See input_state_e enums,
2168 and videolan.libvlc.state (at bindings/cil/src/media.cs).
2169 expected states by web plugins are:
2170-idle/close=0, opening=1, buffering=2, playing=3, paused=4,
2171+idle/close=0, opening=1, playing=3, paused=4,
2172 stopping=5, ended=6, error=7.
2173 '''
2174 _enum_names_ = {
2175@@ -572,14 +719,17 @@
2176 6: 'Ended',
2177 7: 'Error',
2178 }
2179-State.Buffering = State(2)
2180-State.Ended = State(6)
2181-State.Error = State(7)
2182+
2183+
2184+State.Buffering = State(2)
2185+State.Ended = State(6)
2186+State.Error = State(7)
2187 State.NothingSpecial = State(0)
2188-State.Opening = State(1)
2189-State.Paused = State(4)
2190-State.Playing = State(3)
2191-State.Stopped = State(5)
2192+State.Opening = State(1)
2193+State.Paused = State(4)
2194+State.Playing = State(3)
2195+State.Stopped = State(5)
2196+
2197
2198 class TrackType(_Enum):
2199 '''N/A
2200@@ -590,22 +740,128 @@
2201 1: 'video',
2202 2: 'text',
2203 }
2204-TrackType.audio = TrackType(0)
2205-TrackType.text = TrackType(2)
2206+
2207+
2208+TrackType.audio = TrackType(0)
2209+TrackType.text = TrackType(2)
2210 TrackType.unknown = TrackType(-1)
2211-TrackType.video = TrackType(1)
2212-
2213-class PlaybackMode(_Enum):
2214- '''Defines playback modes for playlist.
2215- '''
2216- _enum_names_ = {
2217- 0: 'default',
2218- 1: 'loop',
2219- 2: 'repeat',
2220- }
2221-PlaybackMode.default = PlaybackMode(0)
2222-PlaybackMode.loop = PlaybackMode(1)
2223-PlaybackMode.repeat = PlaybackMode(2)
2224+TrackType.video = TrackType(1)
2225+
2226+
2227+class VideoOrient(_Enum):
2228+ '''N/A
2229+ '''
2230+ _enum_names_ = {
2231+ 0: 'left',
2232+ 1: 'right',
2233+ 2: 'left',
2234+ 3: 'right',
2235+ 4: 'top',
2236+ 5: 'bottom',
2237+ 6: 'top',
2238+ 7: 'bottom',
2239+ }
2240+
2241+
2242+VideoOrient.bottom = VideoOrient(5)
2243+VideoOrient.bottom = VideoOrient(7)
2244+VideoOrient.left = VideoOrient(0)
2245+VideoOrient.left = VideoOrient(2)
2246+VideoOrient.right = VideoOrient(1)
2247+VideoOrient.right = VideoOrient(3)
2248+VideoOrient.top = VideoOrient(4)
2249+VideoOrient.top = VideoOrient(6)
2250+
2251+
2252+class VideoProjection(_Enum):
2253+ '''N/A
2254+ '''
2255+ _enum_names_ = {
2256+ 0: 'rectangular',
2257+ 1: 'equirectangular',
2258+ 0x100: 'standard',
2259+ }
2260+
2261+
2262+VideoProjection.equirectangular = VideoProjection(1)
2263+VideoProjection.rectangular = VideoProjection(0)
2264+VideoProjection.standard = VideoProjection(0x100)
2265+
2266+
2267+class MediaType(_Enum):
2268+ '''Media type
2269+See libvlc_media_get_type.
2270+ '''
2271+ _enum_names_ = {
2272+ 0: 'unknown',
2273+ 1: 'file',
2274+ 2: 'directory',
2275+ 3: 'disc',
2276+ 4: 'stream',
2277+ 5: 'playlist',
2278+ }
2279+
2280+
2281+MediaType.directory = MediaType(2)
2282+MediaType.disc = MediaType(3)
2283+MediaType.file = MediaType(1)
2284+MediaType.playlist = MediaType(5)
2285+MediaType.stream = MediaType(4)
2286+MediaType.unknown = MediaType(0)
2287+
2288+
2289+class MediaParseFlag(_Enum):
2290+ '''Parse flags used by libvlc_media_parse_with_options()
2291+See libvlc_media_parse_with_options.
2292+ '''
2293+ _enum_names_ = {
2294+ 0x0: 'local',
2295+ 0x1: 'network',
2296+ 0x2: 'local',
2297+ 0x4: 'network',
2298+ 0x8: 'interact',
2299+ }
2300+
2301+
2302+MediaParseFlag.interact = MediaParseFlag(0x8)
2303+MediaParseFlag.local = MediaParseFlag(0x0)
2304+MediaParseFlag.local = MediaParseFlag(0x2)
2305+MediaParseFlag.network = MediaParseFlag(0x1)
2306+MediaParseFlag.network = MediaParseFlag(0x4)
2307+
2308+
2309+class MediaParsedStatus(_Enum):
2310+ '''Parse status used sent by libvlc_media_parse_with_options() or returned by
2311+libvlc_media_get_parsed_status()
2312+See libvlc_media_parse_with_options
2313+See libvlc_media_get_parsed_status.
2314+ '''
2315+ _enum_names_ = {
2316+ 1: 'skipped',
2317+ 2: 'failed',
2318+ 3: 'timeout',
2319+ 4: 'done',
2320+ }
2321+
2322+
2323+MediaParsedStatus.done = MediaParsedStatus(4)
2324+MediaParsedStatus.failed = MediaParsedStatus(2)
2325+MediaParsedStatus.skipped = MediaParsedStatus(1)
2326+MediaParsedStatus.timeout = MediaParsedStatus(3)
2327+
2328+
2329+class MediaSlaveType(_Enum):
2330+ '''Type of a media slave: subtitle or audio.
2331+ '''
2332+ _enum_names_ = {
2333+ 0: 'subtitle',
2334+ 1: 'audio',
2335+ }
2336+
2337+
2338+MediaSlaveType.audio = MediaSlaveType(1)
2339+MediaSlaveType.subtitle = MediaSlaveType(0)
2340+
2341
2342 class VideoMarqueeOption(_Enum):
2343 '''Marq options definition.
2344@@ -622,17 +878,20 @@
2345 8: 'marquee_X',
2346 9: 'marquee_Y',
2347 }
2348-VideoMarqueeOption.Color = VideoMarqueeOption(2)
2349-VideoMarqueeOption.Enable = VideoMarqueeOption(0)
2350-VideoMarqueeOption.Opacity = VideoMarqueeOption(3)
2351-VideoMarqueeOption.Position = VideoMarqueeOption(4)
2352-VideoMarqueeOption.Refresh = VideoMarqueeOption(5)
2353-VideoMarqueeOption.Size = VideoMarqueeOption(6)
2354-VideoMarqueeOption.Text = VideoMarqueeOption(1)
2355-VideoMarqueeOption.Timeout = VideoMarqueeOption(7)
2356+
2357+
2358+VideoMarqueeOption.Color = VideoMarqueeOption(2)
2359+VideoMarqueeOption.Enable = VideoMarqueeOption(0)
2360+VideoMarqueeOption.Opacity = VideoMarqueeOption(3)
2361+VideoMarqueeOption.Position = VideoMarqueeOption(4)
2362+VideoMarqueeOption.Refresh = VideoMarqueeOption(5)
2363+VideoMarqueeOption.Size = VideoMarqueeOption(6)
2364+VideoMarqueeOption.Text = VideoMarqueeOption(1)
2365+VideoMarqueeOption.Timeout = VideoMarqueeOption(7)
2366 VideoMarqueeOption.marquee_X = VideoMarqueeOption(8)
2367 VideoMarqueeOption.marquee_Y = VideoMarqueeOption(9)
2368
2369+
2370 class NavigateMode(_Enum):
2371 '''Navigation mode.
2372 '''
2373@@ -642,12 +901,17 @@
2374 2: 'down',
2375 3: 'left',
2376 4: 'right',
2377+ 5: 'popup',
2378 }
2379+
2380+
2381 NavigateMode.activate = NavigateMode(0)
2382-NavigateMode.down = NavigateMode(2)
2383-NavigateMode.left = NavigateMode(3)
2384-NavigateMode.right = NavigateMode(4)
2385-NavigateMode.up = NavigateMode(1)
2386+NavigateMode.down = NavigateMode(2)
2387+NavigateMode.left = NavigateMode(3)
2388+NavigateMode.popup = NavigateMode(5)
2389+NavigateMode.right = NavigateMode(4)
2390+NavigateMode.up = NavigateMode(1)
2391+
2392
2393 class Position(_Enum):
2394 '''Enumeration of values used to set position (e.g. of video title).
2395@@ -664,16 +928,39 @@
2396 7: 'left',
2397 8: 'right',
2398 }
2399-Position.bottom = Position(6)
2400-Position.center = Position(0)
2401+
2402+
2403+Position.bottom = Position(6)
2404+Position.center = Position(0)
2405 Position.disable = Position(-1)
2406-Position.left = Position(1)
2407-Position.left = Position(4)
2408-Position.left = Position(7)
2409-Position.right = Position(2)
2410-Position.right = Position(5)
2411-Position.right = Position(8)
2412-Position.top = Position(3)
2413+Position.left = Position(1)
2414+Position.left = Position(4)
2415+Position.left = Position(7)
2416+Position.right = Position(2)
2417+Position.right = Position(5)
2418+Position.right = Position(8)
2419+Position.top = Position(3)
2420+
2421+
2422+class TeletextKey(_Enum):
2423+ '''Enumeration of teletext keys than can be passed via
2424+libvlc_video_set_teletext().
2425+ '''
2426+ _enum_names_ = {
2427+ 7471104: 'red',
2428+ 6750208: 'green',
2429+ 7929856: 'yellow',
2430+ 6422528: 'blue',
2431+ 6881280: 'index',
2432+ }
2433+
2434+
2435+TeletextKey.blue = TeletextKey(6422528)
2436+TeletextKey.green = TeletextKey(6750208)
2437+TeletextKey.index = TeletextKey(6881280)
2438+TeletextKey.red = TeletextKey(7471104)
2439+TeletextKey.yellow = TeletextKey(7929856)
2440+
2441
2442 class VideoLogoOption(_Enum):
2443 '''Option values for libvlc_video_{get,set}_logo_{int,string}.
2444@@ -688,14 +975,17 @@
2445 6: 'opacity',
2446 7: 'position',
2447 }
2448-VideoLogoOption.delay = VideoLogoOption(4)
2449-VideoLogoOption.enable = VideoLogoOption(0)
2450-VideoLogoOption.file = VideoLogoOption(1)
2451-VideoLogoOption.logo_x = VideoLogoOption(2)
2452-VideoLogoOption.logo_y = VideoLogoOption(3)
2453-VideoLogoOption.opacity = VideoLogoOption(6)
2454+
2455+
2456+VideoLogoOption.delay = VideoLogoOption(4)
2457+VideoLogoOption.enable = VideoLogoOption(0)
2458+VideoLogoOption.file = VideoLogoOption(1)
2459+VideoLogoOption.logo_x = VideoLogoOption(2)
2460+VideoLogoOption.logo_y = VideoLogoOption(3)
2461+VideoLogoOption.opacity = VideoLogoOption(6)
2462 VideoLogoOption.position = VideoLogoOption(7)
2463-VideoLogoOption.repeat = VideoLogoOption(5)
2464+VideoLogoOption.repeat = VideoLogoOption(5)
2465+
2466
2467 class VideoAdjustOption(_Enum):
2468 '''Option values for libvlc_video_{get,set}_adjust_{int,float,bool}.
2469@@ -708,13 +998,16 @@
2470 4: 'Saturation',
2471 5: 'Gamma',
2472 }
2473+
2474+
2475 VideoAdjustOption.Brightness = VideoAdjustOption(2)
2476-VideoAdjustOption.Contrast = VideoAdjustOption(1)
2477-VideoAdjustOption.Enable = VideoAdjustOption(0)
2478-VideoAdjustOption.Gamma = VideoAdjustOption(5)
2479-VideoAdjustOption.Hue = VideoAdjustOption(3)
2480+VideoAdjustOption.Contrast = VideoAdjustOption(1)
2481+VideoAdjustOption.Enable = VideoAdjustOption(0)
2482+VideoAdjustOption.Gamma = VideoAdjustOption(5)
2483+VideoAdjustOption.Hue = VideoAdjustOption(3)
2484 VideoAdjustOption.Saturation = VideoAdjustOption(4)
2485
2486+
2487 class AudioOutputDeviceTypes(_Enum):
2488 '''Audio device types.
2489 '''
2490@@ -729,15 +1022,18 @@
2491 8: '_7_1',
2492 10: 'SPDIF',
2493 }
2494-AudioOutputDeviceTypes.Error = AudioOutputDeviceTypes(-1)
2495-AudioOutputDeviceTypes.Mono = AudioOutputDeviceTypes(1)
2496-AudioOutputDeviceTypes.SPDIF = AudioOutputDeviceTypes(10)
2497+
2498+
2499+AudioOutputDeviceTypes.Error = AudioOutputDeviceTypes(-1)
2500+AudioOutputDeviceTypes.Mono = AudioOutputDeviceTypes(1)
2501+AudioOutputDeviceTypes.SPDIF = AudioOutputDeviceTypes(10)
2502 AudioOutputDeviceTypes.Stereo = AudioOutputDeviceTypes(2)
2503-AudioOutputDeviceTypes._2F2R = AudioOutputDeviceTypes(4)
2504-AudioOutputDeviceTypes._3F2R = AudioOutputDeviceTypes(5)
2505-AudioOutputDeviceTypes._5_1 = AudioOutputDeviceTypes(6)
2506-AudioOutputDeviceTypes._6_1 = AudioOutputDeviceTypes(7)
2507-AudioOutputDeviceTypes._7_1 = AudioOutputDeviceTypes(8)
2508+AudioOutputDeviceTypes._2F2R = AudioOutputDeviceTypes(4)
2509+AudioOutputDeviceTypes._3F2R = AudioOutputDeviceTypes(5)
2510+AudioOutputDeviceTypes._5_1 = AudioOutputDeviceTypes(6)
2511+AudioOutputDeviceTypes._6_1 = AudioOutputDeviceTypes(7)
2512+AudioOutputDeviceTypes._7_1 = AudioOutputDeviceTypes(8)
2513+
2514
2515 class AudioOutputChannel(_Enum):
2516 '''Audio channels.
2517@@ -750,308 +1046,455 @@
2518 4: 'Right',
2519 5: 'Dolbys',
2520 }
2521-AudioOutputChannel.Dolbys = AudioOutputChannel(5)
2522-AudioOutputChannel.Error = AudioOutputChannel(-1)
2523-AudioOutputChannel.Left = AudioOutputChannel(3)
2524+
2525+
2526+AudioOutputChannel.Dolbys = AudioOutputChannel(5)
2527+AudioOutputChannel.Error = AudioOutputChannel(-1)
2528+AudioOutputChannel.Left = AudioOutputChannel(3)
2529 AudioOutputChannel.RStereo = AudioOutputChannel(2)
2530-AudioOutputChannel.Right = AudioOutputChannel(4)
2531-AudioOutputChannel.Stereo = AudioOutputChannel(1)
2532+AudioOutputChannel.Right = AudioOutputChannel(4)
2533+AudioOutputChannel.Stereo = AudioOutputChannel(1)
2534+
2535+
2536+class MediaPlayerRole(_Enum):
2537+ '''Media player roles.
2538+\version libvlc 3.0.0 and later.
2539+see \ref libvlc_media_player_set_role().
2540+ '''
2541+ _enum_names_ = {
2542+ 0: '_None',
2543+ 1: 'Music',
2544+ 2: 'Video',
2545+ 3: 'Communication',
2546+ 4: 'Game',
2547+ 5: 'Notification',
2548+ 6: 'Animation',
2549+ 7: 'Production',
2550+ 8: 'Accessibility',
2551+ 9: 'Test',
2552+ }
2553+
2554+
2555+MediaPlayerRole.Accessibility = MediaPlayerRole(8)
2556+MediaPlayerRole.Animation = MediaPlayerRole(6)
2557+MediaPlayerRole.Communication = MediaPlayerRole(3)
2558+MediaPlayerRole.Game = MediaPlayerRole(4)
2559+MediaPlayerRole.Music = MediaPlayerRole(1)
2560+MediaPlayerRole.Notification = MediaPlayerRole(5)
2561+MediaPlayerRole.Production = MediaPlayerRole(7)
2562+MediaPlayerRole.Test = MediaPlayerRole(9)
2563+MediaPlayerRole.Video = MediaPlayerRole(2)
2564+MediaPlayerRole._None = MediaPlayerRole(0)
2565+
2566+
2567+class PlaybackMode(_Enum):
2568+ '''Defines playback modes for playlist.
2569+ '''
2570+ _enum_names_ = {
2571+ 0: 'default',
2572+ 1: 'loop',
2573+ 2: 'repeat',
2574+ }
2575+
2576+
2577+PlaybackMode.default = PlaybackMode(0)
2578+PlaybackMode.loop = PlaybackMode(1)
2579+PlaybackMode.repeat = PlaybackMode(2)
2580+
2581
2582 class Callback(ctypes.c_void_p):
2583- """Callback function notification
2584-\param p_event the event triggering the callback
2585+ """Callback function notification.
2586+ @param p_event: the event triggering the callback.
2587 """
2588 pass
2589+
2590+
2591 class LogCb(ctypes.c_void_p):
2592 """Callback prototype for LibVLC log message handler.
2593-\param data data pointer as given to L{libvlc_log_set}()
2594-\param level message level (@ref enum libvlc_log_level)
2595-\param ctx message context (meta-information about the message)
2596-\param fmt printf() format string (as defined by ISO C11)
2597-\param args variable argument list for the format
2598-\note Log message handlers <b>must</b> be thread-safe.
2599-\warning The message context pointer, the format string parameters and the
2600- variable arguments are only valid until the callback returns.
2601- """
2602- pass
2603+ @param data: data pointer as given to L{libvlc_log_set}().
2604+ @param level: message level (@ref L{LogLevel}).
2605+ @param ctx: message context (meta-information about the message).
2606+ @param fmt: printf() format string (as defined by ISO C11).
2607+ @param args: variable argument list for the format @note Log message handlers B{must} be thread-safe. @warning The message context pointer, the format string parameters and the variable arguments are only valid until the callback returns.
2608+ """
2609+ pass
2610+
2611+
2612+class MediaOpenCb(ctypes.c_void_p):
2613+ """Callback prototype to open a custom bitstream input media.
2614+ The same media item can be opened multiple times. Each time, this callback
2615+ is invoked. It should allocate and initialize any instance-specific
2616+ resources, then store them in *datap. The instance resources can be freed
2617+ in the @ref libvlc_media_close_cb callback.
2618+ @param opaque: private pointer as passed to L{libvlc_media_new_callbacks}().
2619+ @return: datap storage space for a private data pointer, sizep byte length of the bitstream or UINT64_MAX if unknown.
2620+ """
2621+ pass
2622+
2623+
2624+class MediaReadCb(ctypes.c_void_p):
2625+ """Callback prototype to read data from a custom bitstream input media.
2626+ @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback.
2627+ @param buf: start address of the buffer to read data into.
2628+ @param len: bytes length of the buffer.
2629+ @return: strictly positive number of bytes read, 0 on end-of-stream, or -1 on non-recoverable error @note If no data is immediately available, then the callback should sleep. @warning The application is responsible for avoiding deadlock situations. In particular, the callback should return an error if playback is stopped; if it does not return, then L{libvlc_media_player_stop}() will never return.
2630+ """
2631+ pass
2632+
2633+
2634+class MediaSeekCb(ctypes.c_void_p):
2635+ """Callback prototype to seek a custom bitstream input media.
2636+ @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback.
2637+ @param offset: absolute byte offset to seek to.
2638+ @return: 0 on success, -1 on error.
2639+ """
2640+ pass
2641+
2642+
2643+class MediaCloseCb(ctypes.c_void_p):
2644+ """Callback prototype to close a custom bitstream input media.
2645+ @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback.
2646+ """
2647+ pass
2648+
2649+
2650 class VideoLockCb(ctypes.c_void_p):
2651 """Callback prototype to allocate and lock a picture buffer.
2652-Whenever a new video frame needs to be decoded, the lock callback is
2653-invoked. Depending on the video chroma, one or three pixel planes of
2654-adequate dimensions must be returned via the second parameter. Those
2655-planes must be aligned on 32-bytes boundaries.
2656-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}() [IN]
2657-\param planes start address of the pixel planes (LibVLC allocates the array
2658- of void pointers, this callback must initialize the array) [OUT]
2659-\return a private pointer for the display and unlock callbacks to identify
2660- the picture buffers
2661+ Whenever a new video frame needs to be decoded, the lock callback is
2662+ invoked. Depending on the video chroma, one or three pixel planes of
2663+ adequate dimensions must be returned via the second parameter. Those
2664+ planes must be aligned on 32-bytes boundaries.
2665+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN].
2666+ @param planes: start address of the pixel planes (LibVLC allocates the array of void pointers, this callback must initialize the array) [OUT].
2667+ @return: a private pointer for the display and unlock callbacks to identify the picture buffers.
2668 """
2669 pass
2670+
2671+
2672 class VideoUnlockCb(ctypes.c_void_p):
2673 """Callback prototype to unlock a picture buffer.
2674-When the video frame decoding is complete, the unlock callback is invoked.
2675-This callback might not be needed at all. It is only an indication that the
2676-application can now read the pixel values if it needs to.
2677-\warning A picture buffer is unlocked after the picture is decoded,
2678-but before the picture is displayed.
2679-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}() [IN]
2680-\param picture private pointer returned from the @ref libvlc_video_lock_cb
2681- callback [IN]
2682-\param planes pixel planes as defined by the @ref libvlc_video_lock_cb
2683- callback (this parameter is only for convenience) [IN]
2684+ When the video frame decoding is complete, the unlock callback is invoked.
2685+ This callback might not be needed at all. It is only an indication that the
2686+ application can now read the pixel values if it needs to.
2687+ @note: A picture buffer is unlocked after the picture is decoded,
2688+ but before the picture is displayed.
2689+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN].
2690+ @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN].
2691+ @param planes: pixel planes as defined by the @ref libvlc_video_lock_cb callback (this parameter is only for convenience) [IN].
2692 """
2693 pass
2694+
2695+
2696 class VideoDisplayCb(ctypes.c_void_p):
2697 """Callback prototype to display a picture.
2698-When the video frame needs to be shown, as determined by the media playback
2699-clock, the display callback is invoked.
2700-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}() [IN]
2701-\param picture private pointer returned from the @ref libvlc_video_lock_cb
2702- callback [IN]
2703+ When the video frame needs to be shown, as determined by the media playback
2704+ clock, the display callback is invoked.
2705+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN].
2706+ @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN].
2707 """
2708 pass
2709+
2710+
2711 class VideoFormatCb(ctypes.c_void_p):
2712 """Callback prototype to configure picture buffers format.
2713-This callback gets the format of the video as output by the video decoder
2714-and the chain of video filters (if any). It can opt to change any parameter
2715-as it needs. In that case, LibVLC will attempt to convert the video format
2716-(rescaling and chroma conversion) but these operations can be CPU intensive.
2717-\param opaque pointer to the private pointer passed to
2718- L{libvlc_video_set_callbacks}() [IN/OUT]
2719-\param chroma pointer to the 4 bytes video format identifier [IN/OUT]
2720-\param width pointer to the pixel width [IN/OUT]
2721-\param height pointer to the pixel height [IN/OUT]
2722-\param pitches table of scanline pitches in bytes for each pixel plane
2723- (the table is allocated by LibVLC) [OUT]
2724-\param lines table of scanlines count for each plane [OUT]
2725-\return the number of picture buffers allocated, 0 indicates failure
2726-\note
2727-For each pixels plane, the scanline pitch must be bigger than or equal to
2728-the number of bytes per pixel multiplied by the pixel width.
2729-Similarly, the number of scanlines must be bigger than of equal to
2730-the pixel height.
2731-Furthermore, we recommend that pitches and lines be multiple of 32
2732-to not break assumption that might be made by various optimizations
2733-in the video decoders, video filters and/or video converters.
2734+ This callback gets the format of the video as output by the video decoder
2735+ and the chain of video filters (if any). It can opt to change any parameter
2736+ as it needs. In that case, LibVLC will attempt to convert the video format
2737+ (rescaling and chroma conversion) but these operations can be CPU intensive.
2738+ @param opaque: pointer to the private pointer passed to L{libvlc_video_set_callbacks}() [IN/OUT].
2739+ @param chroma: pointer to the 4 bytes video format identifier [IN/OUT].
2740+ @param width: pointer to the pixel width [IN/OUT].
2741+ @param height: pointer to the pixel height [IN/OUT].
2742+ @param pitches: table of scanline pitches in bytes for each pixel plane (the table is allocated by LibVLC) [OUT].
2743+ @return: lines table of scanlines count for each plane.
2744 """
2745 pass
2746+
2747+
2748 class VideoCleanupCb(ctypes.c_void_p):
2749 """Callback prototype to configure picture buffers format.
2750-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}()
2751- (and possibly modified by @ref libvlc_video_format_cb) [IN]
2752+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() (and possibly modified by @ref libvlc_video_format_cb) [IN].
2753 """
2754 pass
2755+
2756+
2757 class AudioPlayCb(ctypes.c_void_p):
2758 """Callback prototype for audio playback.
2759-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
2760-\param samples pointer to the first audio sample to play back [IN]
2761-\param count number of audio samples to play back
2762-\param pts expected play time stamp (see libvlc_delay())
2763+ The LibVLC media player decodes and post-processes the audio signal
2764+ asynchronously (in an internal thread). Whenever audio samples are ready
2765+ to be queued to the output, this callback is invoked.
2766+ The number of samples provided per invocation may depend on the file format,
2767+ the audio coding algorithm, the decoder plug-in, the post-processing
2768+ filters and timing. Application must not assume a certain number of samples.
2769+ The exact format of audio samples is determined by L{libvlc_audio_set_format}()
2770+ or L{libvlc_audio_set_format_callbacks}() as is the channels layout.
2771+ Note that the number of samples is per channel. For instance, if the audio
2772+ track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds
2773+ of audio signal - regardless of the number of audio channels.
2774+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
2775+ @param samples: pointer to a table of audio samples to play back [IN].
2776+ @param count: number of audio samples to play back.
2777+ @param pts: expected play time stamp (see libvlc_delay()).
2778 """
2779 pass
2780+
2781+
2782 class AudioPauseCb(ctypes.c_void_p):
2783 """Callback prototype for audio pause.
2784-\note The pause callback is never called if the audio is already paused.
2785-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
2786-\param pts time stamp of the pause request (should be elapsed already)
2787+ LibVLC invokes this callback to pause audio playback.
2788+ @note: The pause callback is never called if the audio is already paused.
2789+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
2790+ @param pts: time stamp of the pause request (should be elapsed already).
2791 """
2792 pass
2793+
2794+
2795 class AudioResumeCb(ctypes.c_void_p):
2796- """Callback prototype for audio resumption (i.e. restart from pause).
2797-\note The resume callback is never called if the audio is not paused.
2798-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
2799-\param pts time stamp of the resumption request (should be elapsed already)
2800+ """Callback prototype for audio resumption.
2801+ LibVLC invokes this callback to resume audio playback after it was
2802+ previously paused.
2803+ @note: The resume callback is never called if the audio is not paused.
2804+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
2805+ @param pts: time stamp of the resumption request (should be elapsed already).
2806 """
2807 pass
2808+
2809+
2810 class AudioFlushCb(ctypes.c_void_p):
2811- """Callback prototype for audio buffer flush
2812-(i.e. discard all pending buffers and stop playback as soon as possible).
2813-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
2814+ """Callback prototype for audio buffer flush.
2815+ LibVLC invokes this callback if it needs to discard all pending buffers and
2816+ stop playback as soon as possible. This typically occurs when the media is
2817+ stopped.
2818+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
2819 """
2820 pass
2821+
2822+
2823 class AudioDrainCb(ctypes.c_void_p):
2824- """Callback prototype for audio buffer drain
2825-(i.e. wait for pending buffers to be played).
2826-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
2827+ """Callback prototype for audio buffer drain.
2828+ LibVLC may invoke this callback when the decoded audio track is ending.
2829+ There will be no further decoded samples for the track, but playback should
2830+ nevertheless continue until all already pending buffers are rendered.
2831+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
2832 """
2833 pass
2834+
2835+
2836 class AudioSetVolumeCb(ctypes.c_void_p):
2837 """Callback prototype for audio volume change.
2838-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
2839-\param volume software volume (1. = nominal, 0. = mute)
2840-\param mute muted flag
2841+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
2842+ @param volume: software volume (1. = nominal, 0. = mute).
2843+ @param mute: muted flag.
2844 """
2845 pass
2846+
2847+
2848 class AudioSetupCb(ctypes.c_void_p):
2849 """Callback prototype to setup the audio playback.
2850-This is called when the media player needs to create a new audio output.
2851-\param opaque pointer to the data pointer passed to
2852- L{libvlc_audio_set_callbacks}() [IN/OUT]
2853-\param format 4 bytes sample format [IN/OUT]
2854-\param rate sample rate [IN/OUT]
2855-\param channels channels count [IN/OUT]
2856-\return 0 on success, anything else to skip audio playback
2857+ This is called when the media player needs to create a new audio output.
2858+ @param opaque: pointer to the data pointer passed to L{libvlc_audio_set_callbacks}() [IN/OUT].
2859+ @param format: 4 bytes sample format [IN/OUT].
2860+ @param rate: sample rate [IN/OUT].
2861+ @param channels: channels count [IN/OUT].
2862+ @return: 0 on success, anything else to skip audio playback.
2863 """
2864 pass
2865+
2866+
2867 class AudioCleanupCb(ctypes.c_void_p):
2868 """Callback prototype for audio playback cleanup.
2869-This is called when the media player no longer needs an audio output.
2870-\param opaque data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
2871+ This is called when the media player no longer needs an audio output.
2872+ @param opaque: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
2873 """
2874 pass
2875+
2876+
2877 class CallbackDecorators(object):
2878 "Class holding various method decorators for callback functions."
2879 Callback = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
2880- Callback.__doc__ = '''Callback function notification
2881-\param p_event the event triggering the callback
2882- '''
2883+ Callback.__doc__ = '''Callback function notification.
2884+ @param p_event: the event triggering the callback.
2885+ '''
2886 LogCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, Log_ptr, ctypes.c_char_p, ctypes.c_void_p)
2887 LogCb.__doc__ = '''Callback prototype for LibVLC log message handler.
2888-\param data data pointer as given to L{libvlc_log_set}()
2889-\param level message level (@ref enum libvlc_log_level)
2890-\param ctx message context (meta-information about the message)
2891-\param fmt printf() format string (as defined by ISO C11)
2892-\param args variable argument list for the format
2893-\note Log message handlers <b>must</b> be thread-safe.
2894-\warning The message context pointer, the format string parameters and the
2895- variable arguments are only valid until the callback returns.
2896- '''
2897- VideoLockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ListPOINTER(ctypes.c_void_p))
2898+ @param data: data pointer as given to L{libvlc_log_set}().
2899+ @param level: message level (@ref L{LogLevel}).
2900+ @param ctx: message context (meta-information about the message).
2901+ @param fmt: printf() format string (as defined by ISO C11).
2902+ @param args: variable argument list for the format @note Log message handlers B{must} be thread-safe. @warning The message context pointer, the format string parameters and the variable arguments are only valid until the callback returns.
2903+ '''
2904+ MediaOpenCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p),
2905+ ctypes.POINTER(ctypes.c_uint64))
2906+ MediaOpenCb.__doc__ = '''Callback prototype to open a custom bitstream input media.
2907+ The same media item can be opened multiple times. Each time, this callback
2908+ is invoked. It should allocate and initialize any instance-specific
2909+ resources, then store them in *datap. The instance resources can be freed
2910+ in the @ref libvlc_media_close_cb callback.
2911+ @param opaque: private pointer as passed to L{libvlc_media_new_callbacks}().
2912+ @return: datap storage space for a private data pointer, sizep byte length of the bitstream or UINT64_MAX if unknown.
2913+ '''
2914+ MediaReadCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_ssize_t), ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t)
2915+ MediaReadCb.__doc__ = '''Callback prototype to read data from a custom bitstream input media.
2916+ @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback.
2917+ @param buf: start address of the buffer to read data into.
2918+ @param len: bytes length of the buffer.
2919+ @return: strictly positive number of bytes read, 0 on end-of-stream, or -1 on non-recoverable error @note If no data is immediately available, then the callback should sleep. @warning The application is responsible for avoiding deadlock situations. In particular, the callback should return an error if playback is stopped; if it does not return, then L{libvlc_media_player_stop}() will never return.
2920+ '''
2921+ MediaSeekCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ctypes.c_void_p, ctypes.c_uint64)
2922+ MediaSeekCb.__doc__ = '''Callback prototype to seek a custom bitstream input media.
2923+ @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback.
2924+ @param offset: absolute byte offset to seek to.
2925+ @return: 0 on success, -1 on error.
2926+ '''
2927+ MediaCloseCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
2928+ MediaCloseCb.__doc__ = '''Callback prototype to close a custom bitstream input media.
2929+ @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback.
2930+ '''
2931+ VideoLockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p))
2932 VideoLockCb.__doc__ = '''Callback prototype to allocate and lock a picture buffer.
2933-Whenever a new video frame needs to be decoded, the lock callback is
2934-invoked. Depending on the video chroma, one or three pixel planes of
2935-adequate dimensions must be returned via the second parameter. Those
2936-planes must be aligned on 32-bytes boundaries.
2937-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}() [IN]
2938-\param planes start address of the pixel planes (LibVLC allocates the array
2939- of void pointers, this callback must initialize the array) [OUT]
2940-\return a private pointer for the display and unlock callbacks to identify
2941- the picture buffers
2942- '''
2943- VideoUnlockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ListPOINTER(ctypes.c_void_p))
2944+ Whenever a new video frame needs to be decoded, the lock callback is
2945+ invoked. Depending on the video chroma, one or three pixel planes of
2946+ adequate dimensions must be returned via the second parameter. Those
2947+ planes must be aligned on 32-bytes boundaries.
2948+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN].
2949+ @param planes: start address of the pixel planes (LibVLC allocates the array of void pointers, this callback must initialize the array) [OUT].
2950+ @return: a private pointer for the display and unlock callbacks to identify the picture buffers.
2951+ '''
2952+ VideoUnlockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p))
2953 VideoUnlockCb.__doc__ = '''Callback prototype to unlock a picture buffer.
2954-When the video frame decoding is complete, the unlock callback is invoked.
2955-This callback might not be needed at all. It is only an indication that the
2956-application can now read the pixel values if it needs to.
2957-\warning A picture buffer is unlocked after the picture is decoded,
2958-but before the picture is displayed.
2959-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}() [IN]
2960-\param picture private pointer returned from the @ref libvlc_video_lock_cb
2961- callback [IN]
2962-\param planes pixel planes as defined by the @ref libvlc_video_lock_cb
2963- callback (this parameter is only for convenience) [IN]
2964- '''
2965+ When the video frame decoding is complete, the unlock callback is invoked.
2966+ This callback might not be needed at all. It is only an indication that the
2967+ application can now read the pixel values if it needs to.
2968+ @note: A picture buffer is unlocked after the picture is decoded,
2969+ but before the picture is displayed.
2970+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN].
2971+ @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN].
2972+ @param planes: pixel planes as defined by the @ref libvlc_video_lock_cb callback (this parameter is only for convenience) [IN].
2973+ '''
2974 VideoDisplayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
2975 VideoDisplayCb.__doc__ = '''Callback prototype to display a picture.
2976-When the video frame needs to be shown, as determined by the media playback
2977-clock, the display callback is invoked.
2978-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}() [IN]
2979-\param picture private pointer returned from the @ref libvlc_video_lock_cb
2980- callback [IN]
2981- '''
2982- VideoFormatCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_uint), ListPOINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint))
2983+ When the video frame needs to be shown, as determined by the media playback
2984+ clock, the display callback is invoked.
2985+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN].
2986+ @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN].
2987+ '''
2988+ VideoFormatCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p,
2989+ ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint),
2990+ ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint))
2991 VideoFormatCb.__doc__ = '''Callback prototype to configure picture buffers format.
2992-This callback gets the format of the video as output by the video decoder
2993-and the chain of video filters (if any). It can opt to change any parameter
2994-as it needs. In that case, LibVLC will attempt to convert the video format
2995-(rescaling and chroma conversion) but these operations can be CPU intensive.
2996-\param opaque pointer to the private pointer passed to
2997- L{libvlc_video_set_callbacks}() [IN/OUT]
2998-\param chroma pointer to the 4 bytes video format identifier [IN/OUT]
2999-\param width pointer to the pixel width [IN/OUT]
3000-\param height pointer to the pixel height [IN/OUT]
3001-\param pitches table of scanline pitches in bytes for each pixel plane
3002- (the table is allocated by LibVLC) [OUT]
3003-\param lines table of scanlines count for each plane [OUT]
3004-\return the number of picture buffers allocated, 0 indicates failure
3005-\note
3006-For each pixels plane, the scanline pitch must be bigger than or equal to
3007-the number of bytes per pixel multiplied by the pixel width.
3008-Similarly, the number of scanlines must be bigger than of equal to
3009-the pixel height.
3010-Furthermore, we recommend that pitches and lines be multiple of 32
3011-to not break assumption that might be made by various optimizations
3012-in the video decoders, video filters and/or video converters.
3013- '''
3014+ This callback gets the format of the video as output by the video decoder
3015+ and the chain of video filters (if any). It can opt to change any parameter
3016+ as it needs. In that case, LibVLC will attempt to convert the video format
3017+ (rescaling and chroma conversion) but these operations can be CPU intensive.
3018+ @param opaque: pointer to the private pointer passed to L{libvlc_video_set_callbacks}() [IN/OUT].
3019+ @param chroma: pointer to the 4 bytes video format identifier [IN/OUT].
3020+ @param width: pointer to the pixel width [IN/OUT].
3021+ @param height: pointer to the pixel height [IN/OUT].
3022+ @param pitches: table of scanline pitches in bytes for each pixel plane (the table is allocated by LibVLC) [OUT].
3023+ @return: lines table of scanlines count for each plane.
3024+ '''
3025 VideoCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
3026 VideoCleanupCb.__doc__ = '''Callback prototype to configure picture buffers format.
3027-\param opaque private pointer as passed to L{libvlc_video_set_callbacks}()
3028- (and possibly modified by @ref libvlc_video_format_cb) [IN]
3029- '''
3030+ @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() (and possibly modified by @ref libvlc_video_format_cb) [IN].
3031+ '''
3032 AudioPlayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_int64)
3033 AudioPlayCb.__doc__ = '''Callback prototype for audio playback.
3034-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
3035-\param samples pointer to the first audio sample to play back [IN]
3036-\param count number of audio samples to play back
3037-\param pts expected play time stamp (see libvlc_delay())
3038- '''
3039+ The LibVLC media player decodes and post-processes the audio signal
3040+ asynchronously (in an internal thread). Whenever audio samples are ready
3041+ to be queued to the output, this callback is invoked.
3042+ The number of samples provided per invocation may depend on the file format,
3043+ the audio coding algorithm, the decoder plug-in, the post-processing
3044+ filters and timing. Application must not assume a certain number of samples.
3045+ The exact format of audio samples is determined by L{libvlc_audio_set_format}()
3046+ or L{libvlc_audio_set_format_callbacks}() as is the channels layout.
3047+ Note that the number of samples is per channel. For instance, if the audio
3048+ track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds
3049+ of audio signal - regardless of the number of audio channels.
3050+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
3051+ @param samples: pointer to a table of audio samples to play back [IN].
3052+ @param count: number of audio samples to play back.
3053+ @param pts: expected play time stamp (see libvlc_delay()).
3054+ '''
3055 AudioPauseCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64)
3056 AudioPauseCb.__doc__ = '''Callback prototype for audio pause.
3057-\note The pause callback is never called if the audio is already paused.
3058-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
3059-\param pts time stamp of the pause request (should be elapsed already)
3060- '''
3061+ LibVLC invokes this callback to pause audio playback.
3062+ @note: The pause callback is never called if the audio is already paused.
3063+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
3064+ @param pts: time stamp of the pause request (should be elapsed already).
3065+ '''
3066 AudioResumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64)
3067- AudioResumeCb.__doc__ = '''Callback prototype for audio resumption (i.e. restart from pause).
3068-\note The resume callback is never called if the audio is not paused.
3069-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
3070-\param pts time stamp of the resumption request (should be elapsed already)
3071- '''
3072+ AudioResumeCb.__doc__ = '''Callback prototype for audio resumption.
3073+ LibVLC invokes this callback to resume audio playback after it was
3074+ previously paused.
3075+ @note: The resume callback is never called if the audio is not paused.
3076+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
3077+ @param pts: time stamp of the resumption request (should be elapsed already).
3078+ '''
3079 AudioFlushCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64)
3080- AudioFlushCb.__doc__ = '''Callback prototype for audio buffer flush
3081-(i.e. discard all pending buffers and stop playback as soon as possible).
3082-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
3083- '''
3084+ AudioFlushCb.__doc__ = '''Callback prototype for audio buffer flush.
3085+ LibVLC invokes this callback if it needs to discard all pending buffers and
3086+ stop playback as soon as possible. This typically occurs when the media is
3087+ stopped.
3088+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
3089+ '''
3090 AudioDrainCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
3091- AudioDrainCb.__doc__ = '''Callback prototype for audio buffer drain
3092-(i.e. wait for pending buffers to be played).
3093-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
3094- '''
3095+ AudioDrainCb.__doc__ = '''Callback prototype for audio buffer drain.
3096+ LibVLC may invoke this callback when the decoded audio track is ending.
3097+ There will be no further decoded samples for the track, but playback should
3098+ nevertheless continue until all already pending buffers are rendered.
3099+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
3100+ '''
3101 AudioSetVolumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_float, ctypes.c_bool)
3102 AudioSetVolumeCb.__doc__ = '''Callback prototype for audio volume change.
3103-\param data data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
3104-\param volume software volume (1. = nominal, 0. = mute)
3105-\param mute muted flag
3106- '''
3107- AudioSetupCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ListPOINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint))
3108+ @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
3109+ @param volume: software volume (1. = nominal, 0. = mute).
3110+ @param mute: muted flag.
3111+ '''
3112+ AudioSetupCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p,
3113+ ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint))
3114 AudioSetupCb.__doc__ = '''Callback prototype to setup the audio playback.
3115-This is called when the media player needs to create a new audio output.
3116-\param opaque pointer to the data pointer passed to
3117- L{libvlc_audio_set_callbacks}() [IN/OUT]
3118-\param format 4 bytes sample format [IN/OUT]
3119-\param rate sample rate [IN/OUT]
3120-\param channels channels count [IN/OUT]
3121-\return 0 on success, anything else to skip audio playback
3122- '''
3123+ This is called when the media player needs to create a new audio output.
3124+ @param opaque: pointer to the data pointer passed to L{libvlc_audio_set_callbacks}() [IN/OUT].
3125+ @param format: 4 bytes sample format [IN/OUT].
3126+ @param rate: sample rate [IN/OUT].
3127+ @param channels: channels count [IN/OUT].
3128+ @return: 0 on success, anything else to skip audio playback.
3129+ '''
3130 AudioCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
3131 AudioCleanupCb.__doc__ = '''Callback prototype for audio playback cleanup.
3132-This is called when the media player no longer needs an audio output.
3133-\param opaque data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]
3134- '''
3135+ This is called when the media player no longer needs an audio output.
3136+ @param opaque: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN].
3137+ '''
3138+
3139+
3140 cb = CallbackDecorators
3141- # End of generated enum types #
3142-
3143- # From libvlc_structures.h
3144+
3145+
3146+# End of generated enum types #
3147+
3148+# From libvlc_structures.h
3149
3150 class AudioOutput(_Cstruct):
3151
3152 def __str__(self):
3153 return '%s(%s:%s)' % (self.__class__.__name__, self.name, self.description)
3154
3155+
3156 AudioOutput._fields_ = [ # recursive struct
3157- ('name', ctypes.c_char_p),
3158+ ('name', ctypes.c_char_p),
3159 ('description', ctypes.c_char_p),
3160- ('next', ctypes.POINTER(AudioOutput)),
3161- ]
3162+ ('next', ctypes.POINTER(AudioOutput)),
3163+]
3164+
3165
3166 class LogMessage(_Cstruct):
3167 _fields_ = [
3168- ('size', ctypes.c_uint ),
3169- ('severity', ctypes.c_int ),
3170- ('type', ctypes.c_char_p),
3171- ('name', ctypes.c_char_p),
3172- ('header', ctypes.c_char_p),
3173- ('message', ctypes.c_char_p),
3174+ ('size', ctypes.c_uint),
3175+ ('severity', ctypes.c_int),
3176+ ('type', ctypes.c_char_p),
3177+ ('name', ctypes.c_char_p),
3178+ ('header', ctypes.c_char_p),
3179+ ('message', ctypes.c_char_p),
3180 ]
3181
3182 def __init__(self):
3183@@ -1061,47 +1504,52 @@
3184 def __str__(self):
3185 return '%s(%d:%s): %s' % (self.__class__.__name__, self.severity, self.type, self.message)
3186
3187+
3188 class MediaEvent(_Cstruct):
3189 _fields_ = [
3190- ('media_name', ctypes.c_char_p),
3191+ ('media_name', ctypes.c_char_p),
3192 ('instance_name', ctypes.c_char_p),
3193 ]
3194
3195+
3196 class MediaStats(_Cstruct):
3197 _fields_ = [
3198- ('read_bytes', ctypes.c_int ),
3199- ('input_bitrate', ctypes.c_float),
3200- ('demux_read_bytes', ctypes.c_int ),
3201- ('demux_bitrate', ctypes.c_float),
3202- ('demux_corrupted', ctypes.c_int ),
3203- ('demux_discontinuity', ctypes.c_int ),
3204- ('decoded_video', ctypes.c_int ),
3205- ('decoded_audio', ctypes.c_int ),
3206- ('displayed_pictures', ctypes.c_int ),
3207- ('lost_pictures', ctypes.c_int ),
3208- ('played_abuffers', ctypes.c_int ),
3209- ('lost_abuffers', ctypes.c_int ),
3210- ('sent_packets', ctypes.c_int ),
3211- ('sent_bytes', ctypes.c_int ),
3212- ('send_bitrate', ctypes.c_float),
3213+ ('read_bytes', ctypes.c_int),
3214+ ('input_bitrate', ctypes.c_float),
3215+ ('demux_read_bytes', ctypes.c_int),
3216+ ('demux_bitrate', ctypes.c_float),
3217+ ('demux_corrupted', ctypes.c_int),
3218+ ('demux_discontinuity', ctypes.c_int),
3219+ ('decoded_video', ctypes.c_int),
3220+ ('decoded_audio', ctypes.c_int),
3221+ ('displayed_pictures', ctypes.c_int),
3222+ ('lost_pictures', ctypes.c_int),
3223+ ('played_abuffers', ctypes.c_int),
3224+ ('lost_abuffers', ctypes.c_int),
3225+ ('sent_packets', ctypes.c_int),
3226+ ('sent_bytes', ctypes.c_int),
3227+ ('send_bitrate', ctypes.c_float),
3228 ]
3229
3230+
3231 class MediaTrackInfo(_Cstruct):
3232 _fields_ = [
3233- ('codec', ctypes.c_uint32),
3234- ('id', ctypes.c_int ),
3235- ('type', TrackType ),
3236- ('profile', ctypes.c_int ),
3237- ('level', ctypes.c_int ),
3238- ('channels_or_height', ctypes.c_uint ),
3239- ('rate_or_width', ctypes.c_uint ),
3240+ ('codec', ctypes.c_uint32),
3241+ ('id', ctypes.c_int),
3242+ ('type', TrackType),
3243+ ('profile', ctypes.c_int),
3244+ ('level', ctypes.c_int),
3245+ ('channels_or_height', ctypes.c_uint),
3246+ ('rate_or_width', ctypes.c_uint),
3247 ]
3248
3249+
3250 class AudioTrack(_Cstruct):
3251 _fields_ = [
3252 ('channels', ctypes.c_uint),
3253 ('rate', ctypes.c_uint),
3254- ]
3255+ ]
3256+
3257
3258 class VideoTrack(_Cstruct):
3259 _fields_ = [
3260@@ -1111,87 +1559,98 @@
3261 ('sar_den', ctypes.c_uint),
3262 ('frame_rate_num', ctypes.c_uint),
3263 ('frame_rate_den', ctypes.c_uint),
3264- ]
3265+ ]
3266+
3267
3268 class SubtitleTrack(_Cstruct):
3269 _fields_ = [
3270 ('encoding', ctypes.c_char_p),
3271- ]
3272+ ]
3273+
3274
3275 class MediaTrackTracks(ctypes.Union):
3276 _fields_ = [
3277 ('audio', ctypes.POINTER(AudioTrack)),
3278 ('video', ctypes.POINTER(VideoTrack)),
3279 ('subtitle', ctypes.POINTER(SubtitleTrack)),
3280- ]
3281+ ]
3282+
3283
3284 class MediaTrack(_Cstruct):
3285 _anonymous_ = ("u",)
3286 _fields_ = [
3287- ('codec', ctypes.c_uint32),
3288- ('original_fourcc', ctypes.c_uint32),
3289- ('id', ctypes.c_int ),
3290- ('type', TrackType ),
3291- ('profile', ctypes.c_int ),
3292- ('level', ctypes.c_int ),
3293-
3294- ('u', MediaTrackTracks),
3295- ('bitrate', ctypes.c_uint),
3296- ('language', ctypes.c_char_p),
3297- ('description', ctypes.c_char_p),
3298- ]
3299+ ('codec', ctypes.c_uint32),
3300+ ('original_fourcc', ctypes.c_uint32),
3301+ ('id', ctypes.c_int),
3302+ ('type', TrackType),
3303+ ('profile', ctypes.c_int),
3304+ ('level', ctypes.c_int),
3305+
3306+ ('u', MediaTrackTracks),
3307+ ('bitrate', ctypes.c_uint),
3308+ ('language', ctypes.c_char_p),
3309+ ('description', ctypes.c_char_p),
3310+ ]
3311+
3312
3313 class PlaylistItem(_Cstruct):
3314 _fields_ = [
3315- ('id', ctypes.c_int ),
3316- ('uri', ctypes.c_char_p),
3317+ ('id', ctypes.c_int),
3318+ ('uri', ctypes.c_char_p),
3319 ('name', ctypes.c_char_p),
3320 ]
3321
3322 def __str__(self):
3323 return '%s #%d %s (uri %s)' % (self.__class__.__name__, self.id, self.name, self.uri)
3324
3325+
3326 class Position(object):
3327 """Enum-like, immutable window position constants.
3328
3329 See e.g. VideoMarqueeOption.Position.
3330 """
3331- Center = 0
3332- Left = 1
3333- CenterLeft = 1
3334- Right = 2
3335- CenterRight = 2
3336- Top = 4
3337- TopCenter = 4
3338- TopLeft = 5
3339- TopRight = 6
3340- Bottom = 8
3341+ Center = 0
3342+ Left = 1
3343+ CenterLeft = 1
3344+ Right = 2
3345+ CenterRight = 2
3346+ Top = 4
3347+ TopCenter = 4
3348+ TopLeft = 5
3349+ TopRight = 6
3350+ Bottom = 8
3351 BottomCenter = 8
3352- BottomLeft = 9
3353- BottomRight = 10
3354+ BottomLeft = 9
3355+ BottomRight = 10
3356+
3357 def __init__(self, *unused):
3358 raise TypeError('constants only')
3359- def __setattr__(self, *unused): #PYCHOK expected
3360+
3361+ def __setattr__(self, *unused): # PYCHOK expected
3362 raise TypeError('immutable constants')
3363
3364+
3365 class Rectangle(_Cstruct):
3366 _fields_ = [
3367- ('top', ctypes.c_int),
3368- ('left', ctypes.c_int),
3369+ ('top', ctypes.c_int),
3370+ ('left', ctypes.c_int),
3371 ('bottom', ctypes.c_int),
3372- ('right', ctypes.c_int),
3373+ ('right', ctypes.c_int),
3374 ]
3375
3376+
3377 class TrackDescription(_Cstruct):
3378
3379 def __str__(self):
3380 return '%s(%d:%s)' % (self.__class__.__name__, self.id, self.name)
3381
3382+
3383 TrackDescription._fields_ = [ # recursive struct
3384- ('id', ctypes.c_int ),
3385+ ('id', ctypes.c_int),
3386 ('name', ctypes.c_char_p),
3387 ('next', ctypes.POINTER(TrackDescription)),
3388- ]
3389+]
3390+
3391
3392 def track_description_list(head):
3393 """Convert a TrackDescription linked list to a Python list (and release the former).
3394@@ -1210,48 +1669,53 @@
3395
3396 return r
3397
3398+
3399 class EventUnion(ctypes.Union):
3400 _fields_ = [
3401- ('meta_type', ctypes.c_uint ),
3402- ('new_child', ctypes.c_uint ),
3403+ ('meta_type', ctypes.c_uint),
3404+ ('new_child', ctypes.c_uint),
3405 ('new_duration', ctypes.c_longlong),
3406- ('new_status', ctypes.c_int ),
3407- ('media', ctypes.c_void_p ),
3408- ('new_state', ctypes.c_uint ),
3409+ ('new_status', ctypes.c_int),
3410+ ('media', ctypes.c_void_p),
3411+ ('new_state', ctypes.c_uint),
3412 # FIXME: Media instance
3413- ('new_cache', ctypes.c_float ),
3414- ('new_position', ctypes.c_float ),
3415- ('new_time', ctypes.c_longlong),
3416- ('new_title', ctypes.c_int ),
3417+ ('new_cache', ctypes.c_float),
3418+ ('new_position', ctypes.c_float),
3419+ ('new_time', ctypes.c_longlong),
3420+ ('new_title', ctypes.c_int),
3421 ('new_seekable', ctypes.c_longlong),
3422 ('new_pausable', ctypes.c_longlong),
3423 ('new_scrambled', ctypes.c_longlong),
3424 ('new_count', ctypes.c_longlong),
3425 # FIXME: Skipped MediaList and MediaListView...
3426- ('filename', ctypes.c_char_p ),
3427- ('new_length', ctypes.c_longlong),
3428- ('media_event', MediaEvent ),
3429+ ('filename', ctypes.c_char_p),
3430+ ('new_length', ctypes.c_longlong),
3431+ ('media_event', MediaEvent),
3432 ]
3433
3434+
3435 class Event(_Cstruct):
3436 _fields_ = [
3437- ('type', EventType ),
3438+ ('type', EventType),
3439 ('object', ctypes.c_void_p),
3440- ('u', EventUnion ),
3441+ ('u', EventUnion),
3442 ]
3443
3444+
3445 class ModuleDescription(_Cstruct):
3446
3447 def __str__(self):
3448 return '%s %s (%s)' % (self.__class__.__name__, self.shortname, self.name)
3449
3450+
3451 ModuleDescription._fields_ = [ # recursive struct
3452- ('name', ctypes.c_char_p),
3453+ ('name', ctypes.c_char_p),
3454 ('shortname', ctypes.c_char_p),
3455- ('longname', ctypes.c_char_p),
3456- ('help', ctypes.c_char_p),
3457- ('next', ctypes.POINTER(ModuleDescription)),
3458- ]
3459+ ('longname', ctypes.c_char_p),
3460+ ('help', ctypes.c_char_p),
3461+ ('next', ctypes.POINTER(ModuleDescription)),
3462+]
3463+
3464
3465 def module_description_list(head):
3466 """Convert a ModuleDescription linked list to a Python list (and release the former).
3467@@ -1266,33 +1730,75 @@
3468 libvlc_module_description_list_release(head)
3469 return r
3470
3471+
3472 class AudioOutputDevice(_Cstruct):
3473
3474 def __str__(self):
3475 return '%s(%d:%s)' % (self.__class__.__name__, self.id, self.name)
3476
3477+
3478 AudioOutputDevice._fields_ = [ # recursive struct
3479 ('next', ctypes.POINTER(AudioOutputDevice)),
3480- ('device', ctypes.c_char_p ),
3481+ ('device', ctypes.c_char_p),
3482 ('description', ctypes.c_char_p),
3483- ]
3484+]
3485+
3486
3487 class TitleDescription(_Cstruct):
3488- _fields = [
3489+ _fields_ = [
3490 ('duration', ctypes.c_longlong),
3491 ('name', ctypes.c_char_p),
3492 ('menu', ctypes.c_bool),
3493 ]
3494
3495+
3496 class ChapterDescription(_Cstruct):
3497- _fields = [
3498+ _fields_ = [
3499 ('time_offset', ctypes.c_longlong),
3500 ('duration', ctypes.c_longlong),
3501 ('name', ctypes.c_char_p),
3502 ]
3503
3504- # End of header.py #
3505-
3506+
3507+class VideoViewpoint(_Cstruct):
3508+ _fields_ = [
3509+ ('yaw', ctypes.c_float),
3510+ ('pitch', ctypes.c_float),
3511+ ('roll', ctypes.c_float),
3512+ ('field_of_view', ctypes.c_float),
3513+ ]
3514+
3515+
3516+class MediaDiscovererDescription(_Cstruct):
3517+ _fields_ = [
3518+ ('name', ctypes.c_char_p),
3519+ ('longname', ctypes.c_char_p),
3520+ ('cat', MediaDiscovererCategory),
3521+ ]
3522+
3523+ def __str__(self):
3524+ return '%s %s (%d) - %s' % (self.__class__.__name__, self.name, self.cat, self.longname)
3525+
3526+
3527+# This struct depends on the MediaSlaveType enum that is defined only
3528+# in > 2.2
3529+if 'MediaSlaveType' in locals():
3530+ class MediaSlave(_Cstruct):
3531+ _fields_ = [
3532+ ('psz_uri', ctypes.c_char_p),
3533+ ('i_type', MediaSlaveType),
3534+ ('i_priority', ctypes.c_uint)
3535+ ]
3536+
3537+
3538+class RDDescription(_Cstruct):
3539+ _fields_ = [
3540+ ('name', ctypes.c_char_p),
3541+ ('longname', ctypes.c_char_p)
3542+ ]
3543+
3544+
3545+# End of header.py #
3546 class EventManager(_Ctype):
3547 '''Create an event manager with callback handler.
3548
3549@@ -1308,7 +1814,7 @@
3550
3551 @note: Only a single notification can be registered
3552 for each event type in an EventManager instance.
3553-
3554+
3555 '''
3556
3557 _callback_handler = None
3558@@ -1316,7 +1822,8 @@
3559
3560 def __new__(cls, ptr=_internal_guard):
3561 if ptr == _internal_guard:
3562- raise VLCException("(INTERNAL) ctypes class.\nYou should get a reference to EventManager through the MediaPlayer.event_manager() method.")
3563+ raise VLCException(
3564+ "(INTERNAL) ctypes class.\nYou should get a reference to EventManager through the MediaPlayer.event_manager() method.")
3565 return _Constructor(cls, ptr)
3566
3567 def event_attach(self, eventtype, callback, *args, **kwds):
3568@@ -1336,12 +1843,13 @@
3569 raise VLCException("%s required: %r" % ('EventType', eventtype))
3570 if not hasattr(callback, '__call__'): # callable()
3571 raise VLCException("%s required: %r" % ('callable', callback))
3572- # check that the callback expects arguments
3573+ # check that the callback expects arguments
3574 if not any(getargspec(callback)[:2]): # list(...)
3575 raise VLCException("%s required: %r" % ('argument', callback))
3576
3577 if self._callback_handler is None:
3578 _called_from_ctypes = ctypes.CFUNCTYPE(None, ctypes.POINTER(Event), ctypes.c_void_p)
3579+
3580 @_called_from_ctypes
3581 def _callback_handler(event, k):
3582 """(INTERNAL) handle callback call from ctypes.
3583@@ -1350,12 +1858,13 @@
3584 method since ctypes does not prepend self as the
3585 first parameter, hence this closure.
3586 """
3587- try: # retrieve Python callback and arguments
3588+ try: # retrieve Python callback and arguments
3589 call, args, kwds = self._callbacks[k]
3590- # deref event.contents to simplify callback code
3591+ # deref event.contents to simplify callback code
3592 call(event.contents, *args, **kwds)
3593 except KeyError: # detached?
3594 pass
3595+
3596 self._callback_handler = _callback_handler
3597 self._callbacks = {}
3598
3599@@ -1375,9 +1884,10 @@
3600
3601 k = eventtype.value
3602 if k in self._callbacks:
3603- del self._callbacks[k] # remove, regardless of libvlc return value
3604+ del self._callbacks[k] # remove, regardless of libvlc return value
3605 libvlc_event_detach(self, k, self._callback_handler, k)
3606
3607+
3608 class Instance(_Ctype):
3609 '''Create a new Instance instance.
3610
3611@@ -1385,7 +1895,7 @@
3612 - a string
3613 - a list of strings as first parameters
3614 - the parameters given as the constructor parameters (must be strings)
3615-
3616+
3617 '''
3618
3619 def __new__(cls, *args):
3620@@ -1398,16 +1908,24 @@
3621 elif isinstance(i, basestring):
3622 args = i.strip().split()
3623 elif isinstance(i, _Seqs):
3624- args = i
3625+ args = list(i)
3626 else:
3627 raise VLCException('Instance %r' % (args,))
3628-
3629- if not args and plugin_path is not None:
3630- # no parameters passed, for win32 and MacOS,
3631- # specify the plugin_path if detected earlier
3632- args = ['vlc', '--plugin-path=' + plugin_path]
3633+ else:
3634+ args = list(args)
3635+
3636+ if not args: # no parameters passed
3637+ args = ['vlc']
3638+ elif args[0] != 'vlc':
3639+ args.insert(0, 'vlc')
3640+
3641+ if plugin_path is not None:
3642+ # set plugin_path if detected, win32 and MacOS,
3643+ # if the user did not specify it itself.
3644+ os.environ.setdefault('VLC_PLUGIN_PATH', plugin_path)
3645+
3646 if PYTHON3:
3647- args = [ str_to_bytes(a) for a in args ]
3648+ args = [str_to_bytes(a) for a in args]
3649 return libvlc_new(len(args), args)
3650
3651 def media_player_new(self, uri=None):
3652@@ -1482,9 +2000,9 @@
3653 i = head
3654 while i:
3655 i = i.contents
3656- d = [{'id': libvlc_audio_output_device_id (self, i.name, d),
3657+ d = [{'id': libvlc_audio_output_device_id(self, i.name, d),
3658 'longname': libvlc_audio_output_device_longname(self, i.name, d)}
3659- for d in range(libvlc_audio_output_device_count (self, i.name))]
3660+ for d in range(libvlc_audio_output_device_count(self, i.name))]
3661 r.append({'name': i.name, 'description': i.description, 'devices': d})
3662 i = i.next
3663 libvlc_audio_output_list_release(head)
3664@@ -1502,22 +2020,18 @@
3665 """
3666 return module_description_list(libvlc_video_filter_list_get(self))
3667
3668-
3669-
3670 def release(self):
3671 '''Decrement the reference count of a libvlc instance, and destroy it
3672 if it reaches zero.
3673 '''
3674 return libvlc_release(self)
3675
3676-
3677 def retain(self):
3678 '''Increments the reference count of a libvlc instance.
3679 The initial reference count is 1 after L{new}() returns.
3680 '''
3681 return libvlc_retain(self)
3682
3683-
3684 def add_intf(self, name):
3685 '''Try to start a user interface for the libvlc instance.
3686 @param name: interface name, or None for default.
3687@@ -1525,7 +2039,6 @@
3688 '''
3689 return libvlc_add_intf(self, str_to_bytes(name))
3690
3691-
3692 def set_user_agent(self, name, http):
3693 '''Sets the application name. LibVLC passes this as the user agent string
3694 when a protocol requires it.
3695@@ -1535,7 +2048,6 @@
3696 '''
3697 return libvlc_set_user_agent(self, str_to_bytes(name), str_to_bytes(http))
3698
3699-
3700 def set_app_id(self, id, version, icon):
3701 '''Sets some meta-information about the application.
3702 See also L{set_user_agent}().
3703@@ -1546,18 +2058,18 @@
3704 '''
3705 return libvlc_set_app_id(self, str_to_bytes(id), str_to_bytes(version), str_to_bytes(icon))
3706
3707-
3708 def log_unset(self):
3709- '''Unsets the logging callback for a LibVLC instance. This is rarely needed:
3710- the callback is implicitly unset when the instance is destroyed.
3711- This function will wait for any pending callbacks invocation to complete
3712- (causing a deadlock if called from within the callback).
3713+ '''Unsets the logging callback.
3714+ This function deregisters the logging callback for a LibVLC instance.
3715+ This is rarely needed as the callback is implicitly unset when the instance
3716+ is destroyed.
3717+ @note: This function will wait for any pending callbacks invocation to
3718+ complete (causing a deadlock if called from within the callback).
3719 @version: LibVLC 2.1.0 or later.
3720 '''
3721 return libvlc_log_unset(self)
3722
3723-
3724- def log_set(self, data, p_instance):
3725+ def log_set(self, cb, data):
3726 '''Sets the logging callback for a LibVLC instance.
3727 This function is thread-safe: it will wait for any pending callbacks
3728 invocation to complete.
3729@@ -1565,9 +2077,8 @@
3730 @param p_instance: libvlc instance.
3731 @version: LibVLC 2.1.0 or later.
3732 '''
3733- return libvlc_log_set(self, data, p_instance)
3734+ return libvlc_log_set(self, cb, data)
3735
3736-
3737 def log_set_file(self, stream):
3738 '''Sets up logging to a file.
3739 @param stream: FILE pointer opened for writing (the FILE pointer must remain valid until L{log_unset}()).
3740@@ -1575,105 +2086,41 @@
3741 '''
3742 return libvlc_log_set_file(self, stream)
3743
3744-
3745- def media_new_location(self, psz_mrl):
3746- '''Create a media with a certain given media resource location,
3747- for instance a valid URL.
3748- @note: To refer to a local file with this function,
3749- the file://... URI syntax B{must} be used (see IETF RFC3986).
3750- We recommend using L{media_new_path}() instead when dealing with
3751- local files.
3752- See L{media_release}.
3753- @param psz_mrl: the media location.
3754- @return: the newly created media or None on error.
3755- '''
3756- return libvlc_media_new_location(self, str_to_bytes(psz_mrl))
3757-
3758-
3759- def media_new_path(self, path):
3760- '''Create a media for a certain file path.
3761- See L{media_release}.
3762- @param path: local filesystem path.
3763- @return: the newly created media or None on error.
3764- '''
3765- return libvlc_media_new_path(self, str_to_bytes(path))
3766-
3767-
3768- def media_new_fd(self, fd):
3769- '''Create a media for an already open file descriptor.
3770- The file descriptor shall be open for reading (or reading and writing).
3771- Regular file descriptors, pipe read descriptors and character device
3772- descriptors (including TTYs) are supported on all platforms.
3773- Block device descriptors are supported where available.
3774- Directory descriptors are supported on systems that provide fdopendir().
3775- Sockets are supported on all platforms where they are file descriptors,
3776- i.e. all except Windows.
3777- @note: This library will B{not} automatically close the file descriptor
3778- under any circumstance. Nevertheless, a file descriptor can usually only be
3779- rendered once in a media player. To render it a second time, the file
3780- descriptor should probably be rewound to the beginning with lseek().
3781- See L{media_release}.
3782- @param fd: open file descriptor.
3783- @return: the newly created media or None on error.
3784- @version: LibVLC 1.1.5 and later.
3785- '''
3786- return libvlc_media_new_fd(self, fd)
3787-
3788-
3789- def media_new_as_node(self, psz_name):
3790- '''Create a media as an empty node with a given name.
3791- See L{media_release}.
3792- @param psz_name: the name of the node.
3793- @return: the new empty media or None on error.
3794- '''
3795- return libvlc_media_new_as_node(self, str_to_bytes(psz_name))
3796-
3797-
3798- def media_discoverer_new_from_name(self, psz_name):
3799- '''Discover media service by name.
3800- @param psz_name: service name.
3801+ def media_discoverer_new(self, psz_name):
3802+ '''Create a media discoverer object by name.
3803+ After this object is created, you should attach to media_list events in
3804+ order to be notified of new items discovered.
3805+ You need to call L{media_discoverer_start}() in order to start the
3806+ discovery.
3807+ See L{media_discoverer_media_list}
3808+ See L{media_discoverer_event_manager}
3809+ See L{media_discoverer_start}.
3810+ @param psz_name: service name; use L{media_discoverer_list_get}() to get a list of the discoverer names available in this libVLC instance.
3811 @return: media discover object or None in case of error.
3812- '''
3813- return libvlc_media_discoverer_new_from_name(self, str_to_bytes(psz_name))
3814-
3815-
3816+ @version: LibVLC 3.0.0 or later.
3817+ '''
3818+ return libvlc_media_discoverer_new(self, str_to_bytes(psz_name))
3819+
3820+ def media_discoverer_list_get(self, i_cat, ppp_services):
3821+ '''Get media discoverer services by category.
3822+ @param i_cat: category of services to fetch.
3823+ @param ppp_services: address to store an allocated array of media discoverer services (must be freed with L{media_discoverer_list_release}() by the caller) [OUT].
3824+ @return: the number of media discoverer services (0 on error).
3825+ @version: LibVLC 3.0.0 and later.
3826+ '''
3827+ return libvlc_media_discoverer_list_get(self, i_cat, ppp_services)
3828+
3829 def media_library_new(self):
3830 '''Create an new Media Library object.
3831 @return: a new object or None on error.
3832 '''
3833 return libvlc_media_library_new(self)
3834
3835-
3836- def audio_output_list_get(self):
3837- '''Gets the list of available audio output modules.
3838- @return: list of available audio outputs. It must be freed it with In case of error, None is returned.
3839- '''
3840- return libvlc_audio_output_list_get(self)
3841-
3842-
3843- def audio_output_device_list_get(self, aout):
3844- '''Gets a list of audio output devices for a given audio output module,
3845- See L{audio_output_device_set}().
3846- @note: Not all audio outputs support this. In particular, an empty (None)
3847- list of devices does B{not} imply that the specified audio output does
3848- not work.
3849- @note: The list might not be exhaustive.
3850- @warning: Some audio output devices in the list might not actually work in
3851- some circumstances. By default, it is recommended to not specify any
3852- explicit audio device.
3853- @param psz_aout: audio output name (as returned by L{audio_output_list_get}()).
3854- @return: A None-terminated linked list of potential audio output devices. It must be freed it with L{audio_output_device_list_release}().
3855- @version: LibVLC 2.1.0 or later.
3856- '''
3857- return libvlc_audio_output_device_list_get(self, str_to_bytes(aout))
3858-
3859-
3860 def vlm_release(self):
3861 '''Release the vlm instance related to the given L{Instance}.
3862 '''
3863 return libvlc_vlm_release(self)
3864
3865-
3866 def vlm_add_broadcast(self, psz_name, psz_input, psz_output, i_options, ppsz_options, b_enabled, b_loop):
3867 '''Add a broadcast, with one input.
3868 @param psz_name: the name of the new broadcast.
3869@@ -1685,9 +2132,9 @@
3870 @param b_loop: Should this broadcast be played in loop ?
3871 @return: 0 on success, -1 on error.
3872 '''
3873- return libvlc_vlm_add_broadcast(self, str_to_bytes(psz_name), str_to_bytes(psz_input), str_to_bytes(psz_output), i_options, ppsz_options, b_enabled, b_loop)
3874+ return libvlc_vlm_add_broadcast(self, str_to_bytes(psz_name), str_to_bytes(psz_input), str_to_bytes(psz_output),
3875+ i_options, ppsz_options, b_enabled, b_loop)
3876
3877-
3878 def vlm_add_vod(self, psz_name, psz_input, i_options, ppsz_options, b_enabled, psz_mux):
3879 '''Add a vod, with one input.
3880 @param psz_name: the name of the new vod media.
3881@@ -1698,9 +2145,9 @@
3882 @param psz_mux: the muxer of the vod media.
3883 @return: 0 on success, -1 on error.
3884 '''
3885- return libvlc_vlm_add_vod(self, str_to_bytes(psz_name), str_to_bytes(psz_input), i_options, ppsz_options, b_enabled, str_to_bytes(psz_mux))
3886+ return libvlc_vlm_add_vod(self, str_to_bytes(psz_name), str_to_bytes(psz_input), i_options, ppsz_options,
3887+ b_enabled, str_to_bytes(psz_mux))
3888
3889-
3890 def vlm_del_media(self, psz_name):
3891 '''Delete a media (VOD or broadcast).
3892 @param psz_name: the media to delete.
3893@@ -1708,7 +2155,6 @@
3894 '''
3895 return libvlc_vlm_del_media(self, str_to_bytes(psz_name))
3896
3897-
3898 def vlm_set_enabled(self, psz_name, b_enabled):
3899 '''Enable or disable a media (VOD or broadcast).
3900 @param psz_name: the media to work on.
3901@@ -1717,7 +2163,6 @@
3902 '''
3903 return libvlc_vlm_set_enabled(self, str_to_bytes(psz_name), b_enabled)
3904
3905-
3906 def vlm_set_output(self, psz_name, psz_output):
3907 '''Set the output for a media.
3908 @param psz_name: the media to work on.
3909@@ -1726,7 +2171,6 @@
3910 '''
3911 return libvlc_vlm_set_output(self, str_to_bytes(psz_name), str_to_bytes(psz_output))
3912
3913-
3914 def vlm_set_input(self, psz_name, psz_input):
3915 '''Set a media's input MRL. This will delete all existing inputs and
3916 add the specified one.
3917@@ -1736,7 +2180,6 @@
3918 '''
3919 return libvlc_vlm_set_input(self, str_to_bytes(psz_name), str_to_bytes(psz_input))
3920
3921-
3922 def vlm_add_input(self, psz_name, psz_input):
3923 '''Add a media's input MRL. This will add the specified one.
3924 @param psz_name: the media to work on.
3925@@ -1745,7 +2188,6 @@
3926 '''
3927 return libvlc_vlm_add_input(self, str_to_bytes(psz_name), str_to_bytes(psz_input))
3928
3929-
3930 def vlm_set_loop(self, psz_name, b_loop):
3931 '''Set a media's loop status.
3932 @param psz_name: the media to work on.
3933@@ -1754,7 +2196,6 @@
3934 '''
3935 return libvlc_vlm_set_loop(self, str_to_bytes(psz_name), b_loop)
3936
3937-
3938 def vlm_set_mux(self, psz_name, psz_mux):
3939 '''Set a media's vod muxer.
3940 @param psz_name: the media to work on.
3941@@ -1763,7 +2204,6 @@
3942 '''
3943 return libvlc_vlm_set_mux(self, str_to_bytes(psz_name), str_to_bytes(psz_mux))
3944
3945-
3946 def vlm_change_media(self, psz_name, psz_input, psz_output, i_options, ppsz_options, b_enabled, b_loop):
3947 '''Edit the parameters of a media. This will delete all existing inputs and
3948 add the specified one.
3949@@ -1776,9 +2216,9 @@
3950 @param b_loop: Should this broadcast be played in loop ?
3951 @return: 0 on success, -1 on error.
3952 '''
3953- return libvlc_vlm_change_media(self, str_to_bytes(psz_name), str_to_bytes(psz_input), str_to_bytes(psz_output), i_options, ppsz_options, b_enabled, b_loop)
3954+ return libvlc_vlm_change_media(self, str_to_bytes(psz_name), str_to_bytes(psz_input), str_to_bytes(psz_output),
3955+ i_options, ppsz_options, b_enabled, b_loop)
3956
3957-
3958 def vlm_play_media(self, psz_name):
3959 '''Play the named broadcast.
3960 @param psz_name: the name of the broadcast.
3961@@ -1786,7 +2226,6 @@
3962 '''
3963 return libvlc_vlm_play_media(self, str_to_bytes(psz_name))
3964
3965-
3966 def vlm_stop_media(self, psz_name):
3967 '''Stop the named broadcast.
3968 @param psz_name: the name of the broadcast.
3969@@ -1794,7 +2233,6 @@
3970 '''
3971 return libvlc_vlm_stop_media(self, str_to_bytes(psz_name))
3972
3973-
3974 def vlm_pause_media(self, psz_name):
3975 '''Pause the named broadcast.
3976 @param psz_name: the name of the broadcast.
3977@@ -1802,7 +2240,6 @@
3978 '''
3979 return libvlc_vlm_pause_media(self, str_to_bytes(psz_name))
3980
3981-
3982 def vlm_seek_media(self, psz_name, f_percentage):
3983 '''Seek in the named broadcast.
3984 @param psz_name: the name of the broadcast.
3985@@ -1811,7 +2248,6 @@
3986 '''
3987 return libvlc_vlm_seek_media(self, str_to_bytes(psz_name), f_percentage)
3988
3989-
3990 def vlm_show_media(self, psz_name):
3991 '''Return information about the named media as a JSON
3992 string representation.
3993@@ -1826,7 +2262,6 @@
3994 '''
3995 return libvlc_vlm_show_media(self, str_to_bytes(psz_name))
3996
3997-
3998 def vlm_get_media_instance_position(self, psz_name, i_instance):
3999 '''Get vlm_media instance position by name or instance id.
4000 @param psz_name: name of vlm media instance.
4001@@ -1835,7 +2270,6 @@
4002 '''
4003 return libvlc_vlm_get_media_instance_position(self, str_to_bytes(psz_name), i_instance)
4004
4005-
4006 def vlm_get_media_instance_time(self, psz_name, i_instance):
4007 '''Get vlm_media instance time by name or instance id.
4008 @param psz_name: name of vlm media instance.
4009@@ -1844,7 +2278,6 @@
4010 '''
4011 return libvlc_vlm_get_media_instance_time(self, str_to_bytes(psz_name), i_instance)
4012
4013-
4014 def vlm_get_media_instance_length(self, psz_name, i_instance):
4015 '''Get vlm_media instance length by name or instance id.
4016 @param psz_name: name of vlm media instance.
4017@@ -1853,7 +2286,6 @@
4018 '''
4019 return libvlc_vlm_get_media_instance_length(self, str_to_bytes(psz_name), i_instance)
4020
4021-
4022 def vlm_get_media_instance_rate(self, psz_name, i_instance):
4023 '''Get vlm_media instance playback rate by name or instance id.
4024 @param psz_name: name of vlm media instance.
4025@@ -1862,7 +2294,6 @@
4026 '''
4027 return libvlc_vlm_get_media_instance_rate(self, str_to_bytes(psz_name), i_instance)
4028
4029-
4030 def vlm_get_media_instance_title(self, psz_name, i_instance):
4031 '''Get vlm_media instance title number by name or instance id.
4032 @param psz_name: name of vlm media instance.
4033@@ -1872,7 +2303,6 @@
4034 '''
4035 return libvlc_vlm_get_media_instance_title(self, str_to_bytes(psz_name), i_instance)
4036
4037-
4038 def vlm_get_media_instance_chapter(self, psz_name, i_instance):
4039 '''Get vlm_media instance chapter number by name or instance id.
4040 @param psz_name: name of vlm media instance.
4041@@ -1882,7 +2312,6 @@
4042 '''
4043 return libvlc_vlm_get_media_instance_chapter(self, str_to_bytes(psz_name), i_instance)
4044
4045-
4046 def vlm_get_media_instance_seekable(self, psz_name, i_instance):
4047 '''Is libvlc instance seekable ?
4048 @param psz_name: name of vlm media instance.
4049@@ -1900,13 +2329,219 @@
4050 '''
4051 return libvlc_vlm_get_event_manager(self)
4052
4053+ def media_new_location(self, psz_mrl):
4054+ '''Create a media with a certain given media resource location,
4055+ for instance a valid URL.
4056+ @note: To refer to a local file with this function,
4057+ the file://... URI syntax B{must} be used (see IETF RFC3986).
4058+ We recommend using L{media_new_path}() instead when dealing with
4059+ local files.
4060+ See L{media_release}.
4061+ @param psz_mrl: the media location.
4062+ @return: the newly created media or None on error.
4063+ '''
4064+ return libvlc_media_new_location(self, str_to_bytes(psz_mrl))
4065+
4066+ def media_new_path(self, path):
4067+ '''Create a media for a certain file path.
4068+ See L{media_release}.
4069+ @param path: local filesystem path.
4070+ @return: the newly created media or None on error.
4071+ '''
4072+ return libvlc_media_new_path(self, str_to_bytes(path))
4073+
4074+ def media_new_fd(self, fd):
4075+ '''Create a media for an already open file descriptor.
4076+ The file descriptor shall be open for reading (or reading and writing).
4077+ Regular file descriptors, pipe read descriptors and character device
4078+ descriptors (including TTYs) are supported on all platforms.
4079+ Block device descriptors are supported where available.
4080+ Directory descriptors are supported on systems that provide fdopendir().
4081+ Sockets are supported on all platforms where they are file descriptors,
4082+ i.e. all except Windows.
4083+ @note: This library will B{not} automatically close the file descriptor
4084+ under any circumstance. Nevertheless, a file descriptor can usually only be
4085+ rendered once in a media player. To render it a second time, the file
4086+ descriptor should probably be rewound to the beginning with lseek().
4087+ See L{media_release}.
4088+ @param fd: open file descriptor.
4089+ @return: the newly created media or None on error.
4090+ @version: LibVLC 1.1.5 and later.
4091+ '''
4092+ return libvlc_media_new_fd(self, fd)
4093+
4094+ def media_new_callbacks(self, open_cb, read_cb, seek_cb, close_cb, opaque):
4095+ '''Create a media with custom callbacks to read the data from.
4096+ @param open_cb: callback to open the custom bitstream input media.
4097+ @param read_cb: callback to read data (must not be None).
4098+ @param seek_cb: callback to seek, or None if seeking is not supported.
4099+ @param close_cb: callback to close the media, or None if unnecessary.
4100+ @param opaque: data pointer for the open callback.
4101+ @return: the newly created media or None on error @note If open_cb is None, the opaque pointer will be passed to read_cb, seek_cb and close_cb, and the stream size will be treated as unknown. @note The callbacks may be called asynchronously (from another thread). A single stream instance need not be reentrant. However the open_cb needs to be reentrant if the media is used by multiple player instances. @warning The callbacks may be used until all or any player instances that were supplied the media item are stopped. See L{media_release}.
4102+ @version: LibVLC 3.0.0 and later.
4103+ '''
4104+ return libvlc_media_new_callbacks(self, open_cb, read_cb, seek_cb, close_cb, opaque)
4105+
4106+ def media_new_as_node(self, psz_name):
4107+ '''Create a media as an empty node with a given name.
4108+ See L{media_release}.
4109+ @param psz_name: the name of the node.
4110+ @return: the new empty media or None on error.
4111+ '''
4112+ return libvlc_media_new_as_node(self, str_to_bytes(psz_name))
4113+
4114+ def renderer_discoverer_new(self, psz_name):
4115+ '''Create a renderer discoverer object by name
4116+ After this object is created, you should attach to events in order to be
4117+ notified of the discoverer events.
4118+ You need to call L{renderer_discoverer_start}() in order to start the
4119+ discovery.
4120+ See L{renderer_discoverer_event_manager}()
4121+ See L{renderer_discoverer_start}().
4122+ @param psz_name: service name; use L{renderer_discoverer_list_get}() to get a list of the discoverer names available in this libVLC instance.
4123+ @return: media discover object or None in case of error.
4124+ @version: LibVLC 3.0.0 or later.
4125+ '''
4126+ return libvlc_renderer_discoverer_new(self, str_to_bytes(psz_name))
4127+
4128+ def renderer_discoverer_list_get(self, ppp_services):
4129+ '''Get media discoverer services
4130+ See libvlc_renderer_list_release().
4131+ @param ppp_services: address to store an allocated array of renderer discoverer services (must be freed with libvlc_renderer_list_release() by the caller) [OUT].
4132+ @return: the number of media discoverer services (0 on error).
4133+ @version: LibVLC 3.0.0 and later.
4134+ '''
4135+ return libvlc_renderer_discoverer_list_get(self, ppp_services)
4136+
4137+ def audio_output_device_count(self, psz_audio_output):
4138+ '''Backward compatibility stub. Do not use in new code.
4139+ \deprecated Use L{audio_output_device_list_get}() instead.
4140+ @return: always 0.
4141+ '''
4142+ return libvlc_audio_output_device_count(self, str_to_bytes(psz_audio_output))
4143+
4144+ def audio_output_device_longname(self, psz_output, i_device):
4145+ '''Backward compatibility stub. Do not use in new code.
4146+ \deprecated Use L{audio_output_device_list_get}() instead.
4147+ @return: always None.
4148+ '''
4149+ return libvlc_audio_output_device_longname(self, str_to_bytes(psz_output), i_device)
4150+
4151+ def audio_output_device_id(self, psz_audio_output, i_device):
4152+ '''Backward compatibility stub. Do not use in new code.
4153+ \deprecated Use L{audio_output_device_list_get}() instead.
4154+ @return: always None.
4155+ '''
4156+ return libvlc_audio_output_device_id(self, str_to_bytes(psz_audio_output), i_device)
4157+
4158+ def media_discoverer_new_from_name(self, psz_name):
4159+ '''\deprecated Use L{media_discoverer_new}() and L{media_discoverer_start}().
4160+ '''
4161+ return libvlc_media_discoverer_new_from_name(self, str_to_bytes(psz_name))
4162+
4163+ def wait(self):
4164+ '''Waits until an interface causes the instance to exit.
4165+ You should start at least one interface first, using L{add_intf}().
4166+ '''
4167+ return libvlc_wait(self)
4168+
4169+ def get_log_verbosity(self):
4170+ '''Always returns minus one.
4171+ This function is only provided for backward compatibility.
4172+ @return: always -1.
4173+ '''
4174+ return libvlc_get_log_verbosity(self)
4175+
4176+ def set_log_verbosity(self, level):
4177+ '''This function does nothing.
4178+ It is only provided for backward compatibility.
4179+ @param level: ignored.
4180+ '''
4181+ return libvlc_set_log_verbosity(self, level)
4182+
4183+ def log_open(self):
4184+ '''This function does nothing useful.
4185+ It is only provided for backward compatibility.
4186+ @return: an unique pointer or None on error.
4187+ '''
4188+ return libvlc_log_open(self)
4189+
4190+ def playlist_play(self, i_id, i_options, ppsz_options):
4191+ '''Start playing (if there is any item in the playlist).
4192+ Additionnal playlist item options can be specified for addition to the
4193+ item before it is played.
4194+ @param i_id: the item to play. If this is a negative number, the next item will be selected. Otherwise, the item with the given ID will be played.
4195+ @param i_options: the number of options to add to the item.
4196+ @param ppsz_options: the options to add to the item.
4197+ '''
4198+ return libvlc_playlist_play(self, i_id, i_options, ppsz_options)
4199+
4200+ def audio_output_list_get(self):
4201+ '''Gets the list of available audio output modules.
4202+ @return: list of available audio outputs. It must be freed with In case of error, None is returned.
4203+ '''
4204+ return libvlc_audio_output_list_get(self)
4205+
4206+ def audio_output_device_list_get(self, aout):
4207+ '''Gets a list of audio output devices for a given audio output module,
4208+ See L{audio_output_device_set}().
4209+ @note: Not all audio outputs support this. In particular, an empty (None)
4210+ list of devices does B{not} imply that the specified audio output does
4211+ not work.
4212+ @note: The list might not be exhaustive.
4213+ @warning: Some audio output devices in the list might not actually work in
4214+ some circumstances. By default, it is recommended to not specify any
4215+ explicit audio device.
4216+ @param aout: audio output name (as returned by L{audio_output_list_get}()).
4217+ @return: A None-terminated linked list of potential audio output devices. It must be freed with L{audio_output_device_list_release}().
4218+ @version: LibVLC 2.1.0 or later.
4219+ '''
4220+ return libvlc_audio_output_device_list_get(self, str_to_bytes(aout))
4221+
4222+
4223+class LogIterator(_Ctype):
4224+ '''Create a new VLC log iterator.
4225+
4226+ '''
4227+
4228+ def __new__(cls, ptr=_internal_guard):
4229+ '''(INTERNAL) ctypes wrapper constructor.
4230+ '''
4231+ return _Constructor(cls, ptr)
4232+
4233+ def __iter__(self):
4234+ return self
4235+
4236+ def next(self):
4237+ if self.has_next():
4238+ b = LogMessage()
4239+ i = libvlc_log_iterator_next(self, b)
4240+ return i.contents
4241+ raise StopIteration
4242+
4243+ def __next__(self):
4244+ return self.next()
4245+
4246+ def free(self):
4247+ '''Frees memory allocated by L{log_get_iterator}().
4248+ '''
4249+ return libvlc_log_iterator_free(self)
4250+
4251+ def has_next(self):
4252+ '''Always returns zero.
4253+ This function is only provided for backward compatibility.
4254+ @return: always zero.
4255+ '''
4256+ return libvlc_log_iterator_has_next(self)
4257+
4258+
4259 class Media(_Ctype):
4260 '''Create a new Media instance.
4261-
4262+
4263 Usage: Media(MRL, *options)
4264
4265 See vlc.Instance.media_new documentation for details.
4266-
4267+
4268 '''
4269
4270 def __new__(cls, *args):
4271@@ -1946,11 +2581,16 @@
4272 """
4273 mediaTrack_pp = ctypes.POINTER(MediaTrack)()
4274 n = libvlc_media_tracks_get(self, ctypes.byref(mediaTrack_pp))
4275- info = ctypes.cast(ctypes.mediaTrack_pp, ctypes.POINTER(ctypes.POINTER(MediaTrack) * n))
4276- return info
4277-
4278-
4279-
4280+ info = ctypes.cast(mediaTrack_pp, ctypes.POINTER(ctypes.POINTER(MediaTrack) * n))
4281+ try:
4282+ contents = info.contents
4283+ except ValueError:
4284+ # Media not parsed, no info.
4285+ return None
4286+ tracks = (contents[i].contents for i in range(len(contents)))
4287+ # libvlc_media_tracks_release(mediaTrack_pp, n)
4288+ return tracks
4289+
4290 def add_option(self, psz_options):
4291 '''Add an option to the media.
4292 This option will be used to determine how the media_player will
4293@@ -1967,7 +2607,6 @@
4294 '''
4295 return libvlc_media_add_option(self, str_to_bytes(psz_options))
4296
4297-
4298 def add_option_flag(self, psz_options, i_flags):
4299 '''Add an option to the media with configurable flags.
4300 This option will be used to determine how the media_player will
4301@@ -1983,15 +2622,13 @@
4302 '''
4303 return libvlc_media_add_option_flag(self, str_to_bytes(psz_options), i_flags)
4304
4305-
4306 def retain(self):
4307- '''Retain a reference to a media descriptor object (libvlc_media_t). Use
4308+ '''Retain a reference to a media descriptor object (L{Media}). Use
4309 L{release}() to decrement the reference count of a
4310 media descriptor object.
4311 '''
4312 return libvlc_media_retain(self)
4313
4314-
4315 def release(self):
4316 '''Decrement the reference count of a media descriptor object. If the
4317 reference count is 0, then L{release}() will release the
4318@@ -2001,35 +2638,28 @@
4319 '''
4320 return libvlc_media_release(self)
4321
4322-
4323 def get_mrl(self):
4324 '''Get the media resource locator (mrl) from a media descriptor object.
4325 @return: string with mrl of media descriptor object.
4326 '''
4327 return libvlc_media_get_mrl(self)
4328
4329-
4330 def duplicate(self):
4331 '''Duplicate a media descriptor object.
4332 '''
4333 return libvlc_media_duplicate(self)
4334
4335-
4336 def get_meta(self, e_meta):
4337 '''Read the meta of the media.
4338 If the media has not yet been parsed this will return None.
4339- This methods automatically calls L{parse_async}(), so after calling
4340- it you may receive a libvlc_MediaMetaChanged event. If you prefer a synchronous
4341- version ensure that you call L{parse}() before get_meta().
4342 See L{parse}
4343- See L{parse_async}
4344+ See L{parse_with_options}
4345 See libvlc_MediaMetaChanged.
4346 @param e_meta: the meta to read.
4347 @return: the media's meta.
4348 '''
4349 return libvlc_media_get_meta(self, e_meta)
4350
4351-
4352 def set_meta(self, e_meta, psz_value):
4353 '''Set the meta of the media (this function will not save the meta, call
4354 L{save_meta} in order to save the meta).
4355@@ -2038,26 +2668,21 @@
4356 '''
4357 return libvlc_media_set_meta(self, e_meta, str_to_bytes(psz_value))
4358
4359-
4360 def save_meta(self):
4361 '''Save the meta previously set.
4362 @return: true if the write operation was successful.
4363 '''
4364 return libvlc_media_save_meta(self)
4365
4366-
4367 def get_state(self):
4368- '''Get current state of media descriptor object. Possible media states
4369- are defined in libvlc_structures.c ( libvlc_NothingSpecial=0,
4370- libvlc_Opening, libvlc_Buffering, libvlc_Playing, libvlc_Paused,
4371- libvlc_Stopped, libvlc_Ended,
4372- libvlc_Error).
4373- See libvlc_state_t.
4374+ '''Get current state of media descriptor object. Possible media states are
4375+ libvlc_NothingSpecial=0, libvlc_Opening, libvlc_Playing, libvlc_Paused,
4376+ libvlc_Stopped, libvlc_Ended, libvlc_Error.
4377+ See L{State}.
4378 @return: state of media descriptor object.
4379 '''
4380 return libvlc_media_get_state(self)
4381
4382-
4383 def get_stats(self, p_stats):
4384 '''Get the current statistics about the media.
4385 @param p_stats:: structure that contain the statistics about the media (this structure must be allocated by the caller).
4386@@ -2065,7 +2690,6 @@
4387 '''
4388 return libvlc_media_get_stats(self, p_stats)
4389
4390-
4391 def subitems(self):
4392 '''Get subitems of media descriptor object. This will increment
4393 the reference count of supplied media descriptor object. Use
4394@@ -2082,71 +2706,164 @@
4395 '''
4396 return libvlc_media_event_manager(self)
4397
4398-
4399 def get_duration(self):
4400 '''Get duration (in ms) of media descriptor object item.
4401 @return: duration of media item or -1 on error.
4402 '''
4403 return libvlc_media_get_duration(self)
4404
4405-
4406+ def parse_with_options(self, parse_flag, timeout):
4407+ '''Parse the media asynchronously with options.
4408+ This fetches (local or network) art, meta data and/or tracks information.
4409+ This method is the extended version of L{parse_with_options}().
4410+ To track when this is over you can listen to libvlc_MediaParsedChanged
4411+ event. However if this functions returns an error, you will not receive any
4412+ events.
4413+ It uses a flag to specify parse options (see L{MediaParseFlag}). All
4414+ these flags can be combined. By default, media is parsed if it's a local
4415+ file.
4416+ @note: Parsing can be aborted with L{parse_stop}().
4417+ See libvlc_MediaParsedChanged
4418+ See L{get_meta}
4419+ See L{tracks_get}
4420+ See L{get_parsed_status}
4421+ See L{MediaParseFlag}.
4422+ @param parse_flag: parse options:
4423+ @param timeout: maximum time allowed to preparse the media. If -1, the default "preparse-timeout" option will be used as a timeout. If 0, it will wait indefinitely. If > 0, the timeout will be used (in milliseconds).
4424+ @return: -1 in case of error, 0 otherwise.
4425+ @version: LibVLC 3.0.0 or later.
4426+ '''
4427+ return libvlc_media_parse_with_options(self, parse_flag, timeout)
4428+
4429+ def parse_stop(self):
4430+ '''Stop the parsing of the media
4431+ When the media parsing is stopped, the libvlc_MediaParsedChanged event will
4432+ be sent with the libvlc_media_parsed_status_timeout status.
4433+ See L{parse_with_options}.
4434+ @version: LibVLC 3.0.0 or later.
4435+ '''
4436+ return libvlc_media_parse_stop(self)
4437+
4438+ def get_parsed_status(self):
4439+ '''Get Parsed status for media descriptor object.
4440+ See libvlc_MediaParsedChanged
4441+ See L{MediaParsedStatus}.
4442+ @return: a value of the L{MediaParsedStatus} enum.
4443+ @version: LibVLC 3.0.0 or later.
4444+ '''
4445+ return libvlc_media_get_parsed_status(self)
4446+
4447+ def set_user_data(self, p_new_user_data):
4448+ '''Sets media descriptor's user_data. user_data is specialized data
4449+ accessed by the host application, VLC.framework uses it as a pointer to
4450+ an native object that references a L{Media} pointer.
4451+ @param p_new_user_data: pointer to user data.
4452+ '''
4453+ return libvlc_media_set_user_data(self, p_new_user_data)
4454+
4455+ def get_user_data(self):
4456+ '''Get media descriptor's user_data. user_data is specialized data
4457+ accessed by the host application, VLC.framework uses it as a pointer to
4458+ an native object that references a L{Media} pointer.
4459+ '''
4460+ return libvlc_media_get_user_data(self)
4461+
4462+ def get_type(self):
4463+ '''Get the media type of the media descriptor object.
4464+ @return: media type.
4465+ @version: LibVLC 3.0.0 and later. See L{MediaType}.
4466+ '''
4467+ return libvlc_media_get_type(self)
4468+
4469+ def slaves_add(self, i_type, i_priority, psz_uri):
4470+ '''Add a slave to the current media.
4471+ A slave is an external input source that may contains an additional subtitle
4472+ track (like a .srt) or an additional audio track (like a .ac3).
4473+ @note: This function must be called before the media is parsed (via
4474+ L{parse_with_options}()) or before the media is played (via
4475+ L{player_play}()).
4476+ @param i_type: subtitle or audio.
4477+ @param i_priority: from 0 (low priority) to 4 (high priority).
4478+ @param psz_uri: Uri of the slave (should contain a valid scheme).
4479+ @return: 0 on success, -1 on error.
4480+ @version: LibVLC 3.0.0 and later.
4481+ '''
4482+ return libvlc_media_slaves_add(self, i_type, i_priority, str_to_bytes(psz_uri))
4483+
4484+ def slaves_clear(self):
4485+ '''Clear all slaves previously added by L{slaves_add}() or
4486+ internally.
4487+ @version: LibVLC 3.0.0 and later.
4488+ '''
4489+ return libvlc_media_slaves_clear(self)
4490+
4491+ def slaves_get(self, ppp_slaves):
4492+ '''Get a media descriptor's slave list
4493+ The list will contain slaves parsed by VLC or previously added by
4494+ L{slaves_add}(). The typical use case of this function is to save
4495+ a list of slave in a database for a later use.
4496+ @param ppp_slaves: address to store an allocated array of slaves (must be freed with L{slaves_release}()) [OUT].
4497+ @return: the number of slaves (zero on error).
4498+ @version: LibVLC 3.0.0 and later. See L{slaves_add}.
4499+ '''
4500+ return libvlc_media_slaves_get(self, ppp_slaves)
4501+
4502 def parse(self):
4503 '''Parse a media.
4504- This fetches (local) meta data and tracks information.
4505+ This fetches (local) art, meta data and tracks information.
4506 The method is synchronous.
4507- See L{parse_async}
4508+ \deprecated This function could block indefinitely.
4509+ Use L{parse_with_options}() instead
4510+ See L{parse_with_options}
4511 See L{get_meta}
4512- See libvlc_media_get_tracks_info.
4513+ See L{get_tracks_info}.
4514 '''
4515 return libvlc_media_parse(self)
4516
4517-
4518 def parse_async(self):
4519 '''Parse a media.
4520- This fetches (local) meta data and tracks information.
4521+ This fetches (local) art, meta data and tracks information.
4522 The method is the asynchronous of L{parse}().
4523 To track when this is over you can listen to libvlc_MediaParsedChanged
4524 event. However if the media was already parsed you will not receive this
4525 event.
4526+ \deprecated You can't be sure to receive the libvlc_MediaParsedChanged
4527+ event (you can wait indefinitely for this event).
4528+ Use L{parse_with_options}() instead
4529 See L{parse}
4530 See libvlc_MediaParsedChanged
4531 See L{get_meta}
4532- See libvlc_media_get_tracks_info.
4533+ See L{get_tracks_info}.
4534 '''
4535 return libvlc_media_parse_async(self)
4536
4537-
4538 def is_parsed(self):
4539- '''Get Parsed status for media descriptor object.
4540+ '''Return true is the media descriptor object is parsed
4541+ \deprecated This can return true in case of failure.
4542+ Use L{get_parsed_status}() instead
4543 See libvlc_MediaParsedChanged.
4544 @return: true if media object has been parsed otherwise it returns false \libvlc_return_bool.
4545 '''
4546 return libvlc_media_is_parsed(self)
4547
4548-
4549- def set_user_data(self, p_new_user_data):
4550- '''Sets media descriptor's user_data. user_data is specialized data
4551- accessed by the host application, VLC.framework uses it as a pointer to
4552- an native object that references a L{Media} pointer.
4553- @param p_new_user_data: pointer to user data.
4554- '''
4555- return libvlc_media_set_user_data(self, p_new_user_data)
4556-
4557-
4558- def get_user_data(self):
4559- '''Get media descriptor's user_data. user_data is specialized data
4560- accessed by the host application, VLC.framework uses it as a pointer to
4561- an native object that references a L{Media} pointer.
4562- '''
4563- return libvlc_media_get_user_data(self)
4564-
4565-
4566+ def get_tracks_info(self):
4567+ '''Get media descriptor's elementary streams description
4568+ Note, you need to call L{parse}() or play the media at least once
4569+ before calling this function.
4570+ Not doing this will result in an empty array.
4571+ \deprecated Use L{tracks_get}() instead.
4572+ @param tracks: address to store an allocated array of Elementary Streams descriptions (must be freed by the caller) [OUT].
4573+ @return: the number of Elementary Streams.
4574+ '''
4575+ return libvlc_media_get_tracks_info(self)
4576+
4577 def player_new_from_media(self):
4578 '''Create a Media Player object from a Media.
4579 @return: a new media player object, or None on error.
4580 '''
4581 return libvlc_media_player_new_from_media(self)
4582
4583+
4584 class MediaDiscoverer(_Ctype):
4585 '''N/A
4586 '''
4587@@ -2155,41 +2872,60 @@
4588 '''(INTERNAL) ctypes wrapper constructor.
4589 '''
4590 return _Constructor(cls, ptr)
4591-
4592+
4593+ def start(self):
4594+ '''Start media discovery.
4595+ To stop it, call L{stop}() or
4596+ L{list_release}() directly.
4597+ See L{stop}.
4598+ @return: -1 in case of error, 0 otherwise.
4599+ @version: LibVLC 3.0.0 or later.
4600+ '''
4601+ return libvlc_media_discoverer_start(self)
4602+
4603+ def stop(self):
4604+ '''Stop media discovery.
4605+ See L{start}.
4606+ @version: LibVLC 3.0.0 or later.
4607+ '''
4608+ return libvlc_media_discoverer_stop(self)
4609+
4610 def release(self):
4611 '''Release media discover object. If the reference count reaches 0, then
4612 the object will be released.
4613 '''
4614 return libvlc_media_discoverer_release(self)
4615
4616-
4617- def localized_name(self):
4618- '''Get media service discover object its localized name.
4619- @return: localized name.
4620- '''
4621- return libvlc_media_discoverer_localized_name(self)
4622-
4623-
4624 def media_list(self):
4625 '''Get media service discover media list.
4626 @return: list of media items.
4627 '''
4628 return libvlc_media_discoverer_media_list(self)
4629
4630- @memoize_parameterless
4631- def event_manager(self):
4632- '''Get event manager from media service discover object.
4633- @return: event manager object.
4634- '''
4635- return libvlc_media_discoverer_event_manager(self)
4636-
4637-
4638 def is_running(self):
4639 '''Query if media service discover object is running.
4640 @return: true if running, false if not \libvlc_return_bool.
4641 '''
4642 return libvlc_media_discoverer_is_running(self)
4643
4644+ def localized_name(self):
4645+ '''Get media service discover object its localized name.
4646+ \deprecated Useless, use L{list_get}() to get the
4647+ longname of the service discovery.
4648+ @return: localized name or None if the media_discoverer is not started.
4649+ '''
4650+ return libvlc_media_discoverer_localized_name(self)
4651+
4652+ @memoize_parameterless
4653+ def event_manager(self):
4654+ '''Get event manager from media service discover object.
4655+ \deprecated Useless, media_discoverer events are only triggered when calling
4656+ L{start}() and L{stop}().
4657+ @return: event manager object.
4658+ '''
4659+ return libvlc_media_discoverer_event_manager(self)
4660+
4661+
4662 class MediaLibrary(_Ctype):
4663 '''N/A
4664 '''
4665@@ -2198,7 +2934,7 @@
4666 '''(INTERNAL) ctypes wrapper constructor.
4667 '''
4668 return _Constructor(cls, ptr)
4669-
4670+
4671 def release(self):
4672 '''Release media library object. This functions decrements the
4673 reference count of the media library object. If it reaches 0,
4674@@ -2206,7 +2942,6 @@
4675 '''
4676 return libvlc_media_library_release(self)
4677
4678-
4679 def retain(self):
4680 '''Retain a reference to a media library object. This function will
4681 increment the reference counting for this object. Use
4682@@ -2214,27 +2949,26 @@
4683 '''
4684 return libvlc_media_library_retain(self)
4685
4686-
4687 def load(self):
4688 '''Load media library.
4689 @return: 0 on success, -1 on error.
4690 '''
4691 return libvlc_media_library_load(self)
4692
4693-
4694 def media_list(self):
4695 '''Get media library subitems.
4696 @return: media list subitems.
4697 '''
4698 return libvlc_media_library_media_list(self)
4699
4700+
4701 class MediaList(_Ctype):
4702 '''Create a new MediaList instance.
4703-
4704+
4705 Usage: MediaList(list_of_MRLs)
4706
4707 See vlc.Instance.media_list_new documentation for details.
4708-
4709+
4710 '''
4711
4712 def __new__(cls, *args):
4713@@ -2250,10 +2984,10 @@
4714
4715 def get_instance(self):
4716 return getattr(self, '_instance', None)
4717-
4718+
4719 def add_media(self, mrl):
4720 """Add media instance to media list.
4721-
4722+
4723 The L{lock} should be held upon entering this function.
4724 @param mrl: a media instance or a MRL.
4725 @return: 0 on success, -1 if the media list is read-only.
4726@@ -2262,20 +2996,16 @@
4727 mrl = (self.get_instance() or get_default_instance()).media_new(mrl)
4728 return libvlc_media_list_add_media(self, mrl)
4729
4730-
4731-
4732 def release(self):
4733 '''Release media list created with L{new}().
4734 '''
4735 return libvlc_media_list_release(self)
4736
4737-
4738 def retain(self):
4739 '''Retain reference to a media list.
4740 '''
4741 return libvlc_media_list_retain(self)
4742
4743-
4744 def set_media(self, p_md):
4745 '''Associate media instance with this media list instance.
4746 If another media instance was present it will be released.
4747@@ -2284,7 +3014,6 @@
4748 '''
4749 return libvlc_media_list_set_media(self, p_md)
4750
4751-
4752 def media(self):
4753 '''Get media instance from this media list instance. This action will increase
4754 the refcount on the media instance.
4755@@ -2293,7 +3022,6 @@
4756 '''
4757 return libvlc_media_list_media(self)
4758
4759-
4760 def insert_media(self, p_md, i_pos):
4761 '''Insert media instance in media list on a position
4762 The L{lock} should be held upon entering this function.
4763@@ -2303,7 +3031,6 @@
4764 '''
4765 return libvlc_media_list_insert_media(self, p_md, i_pos)
4766
4767-
4768 def remove_index(self, i_pos):
4769 '''Remove media instance from media list on a position
4770 The L{lock} should be held upon entering this function.
4771@@ -2312,7 +3039,6 @@
4772 '''
4773 return libvlc_media_list_remove_index(self, i_pos)
4774
4775-
4776 def count(self):
4777 '''Get count on media list items
4778 The L{lock} should be held upon entering this function.
4779@@ -2323,7 +3049,6 @@
4780 def __len__(self):
4781 return libvlc_media_list_count(self)
4782
4783-
4784 def item_at_index(self, i_pos):
4785 '''List media instance in media list at a position
4786 The L{lock} should be held upon entering this function.
4787@@ -2339,7 +3064,6 @@
4788 for i in range(len(self)):
4789 yield self[i]
4790
4791-
4792 def index_of_item(self, p_md):
4793 '''Find index position of List media instance in media list.
4794 Warning: the function will return the first matched position.
4795@@ -2349,20 +3073,17 @@
4796 '''
4797 return libvlc_media_list_index_of_item(self, p_md)
4798
4799-
4800 def is_readonly(self):
4801 '''This indicates if this media list is read-only from a user point of view.
4802 @return: 1 on readonly, 0 on readwrite \libvlc_return_bool.
4803 '''
4804 return libvlc_media_list_is_readonly(self)
4805
4806-
4807 def lock(self):
4808 '''Get lock on media list items.
4809 '''
4810 return libvlc_media_list_lock(self)
4811
4812-
4813 def unlock(self):
4814 '''Release lock on media list items
4815 The L{lock} should be held upon entering this function.
4816@@ -2377,13 +3098,14 @@
4817 '''
4818 return libvlc_media_list_event_manager(self)
4819
4820+
4821 class MediaListPlayer(_Ctype):
4822 '''Create a new MediaListPlayer instance.
4823
4824 It may take as parameter either:
4825 - a vlc.Instance
4826 - nothing
4827-
4828+
4829 '''
4830
4831 def __new__(cls, arg=None):
4832@@ -2401,10 +3123,8 @@
4833 def get_instance(self):
4834 """Return the associated Instance.
4835 """
4836- return self._instance #PYCHOK expected
4837-
4838-
4839-
4840+ return self._instance # PYCHOK expected
4841+
4842 def release(self):
4843 '''Release a media_list_player after use
4844 Decrement the reference count of a media player object. If the
4845@@ -2414,7 +3134,6 @@
4846 '''
4847 return libvlc_media_list_player_release(self)
4848
4849-
4850 def retain(self):
4851 '''Retain a reference to a media player list object. Use
4852 L{release}() to decrement reference count.
4853@@ -2428,47 +3147,53 @@
4854 '''
4855 return libvlc_media_list_player_event_manager(self)
4856
4857-
4858 def set_media_player(self, p_mi):
4859 '''Replace media player in media_list_player with this instance.
4860 @param p_mi: media player instance.
4861 '''
4862 return libvlc_media_list_player_set_media_player(self, p_mi)
4863
4864-
4865+ def get_media_player(self):
4866+ '''Get media player of the media_list_player instance.
4867+ @return: media player instance @note the caller is responsible for releasing the returned instance.
4868+ '''
4869+ return libvlc_media_list_player_get_media_player(self)
4870+
4871 def set_media_list(self, p_mlist):
4872 '''Set the media list associated with the player.
4873 @param p_mlist: list of media.
4874 '''
4875 return libvlc_media_list_player_set_media_list(self, p_mlist)
4876
4877-
4878 def play(self):
4879 '''Play media list.
4880 '''
4881 return libvlc_media_list_player_play(self)
4882
4883-
4884 def pause(self):
4885 '''Toggle pause (or resume) media list.
4886 '''
4887 return libvlc_media_list_player_pause(self)
4888
4889-
4890+ def set_pause(self, do_pause):
4891+ '''Pause or resume media list.
4892+ @param do_pause: play/resume if zero, pause if non-zero.
4893+ @version: LibVLC 3.0.0 or later.
4894+ '''
4895+ return libvlc_media_list_player_set_pause(self, do_pause)
4896+
4897 def is_playing(self):
4898 '''Is media list playing?
4899 @return: true for playing and false for not playing \libvlc_return_bool.
4900 '''
4901 return libvlc_media_list_player_is_playing(self)
4902
4903-
4904 def get_state(self):
4905 '''Get current libvlc_state of media list player.
4906- @return: libvlc_state_t for media list player.
4907+ @return: L{State} for media list player.
4908 '''
4909 return libvlc_media_list_player_get_state(self)
4910
4911-
4912 def play_item_at_index(self, i_index):
4913 '''Play media list item at position index.
4914 @param i_index: index in media list to play.
4915@@ -2483,7 +3208,6 @@
4916 for i in range(len(self)):
4917 yield self[i]
4918
4919-
4920 def play_item(self, p_md):
4921 '''Play the given media item.
4922 @param p_md: the media instance.
4923@@ -2491,46 +3215,43 @@
4924 '''
4925 return libvlc_media_list_player_play_item(self, p_md)
4926
4927-
4928 def stop(self):
4929 '''Stop playing media list.
4930 '''
4931 return libvlc_media_list_player_stop(self)
4932
4933-
4934 def next(self):
4935 '''Play next item from media list.
4936 @return: 0 upon success -1 if there is no next item.
4937 '''
4938 return libvlc_media_list_player_next(self)
4939
4940-
4941 def previous(self):
4942 '''Play previous item from media list.
4943 @return: 0 upon success -1 if there is no previous item.
4944 '''
4945 return libvlc_media_list_player_previous(self)
4946
4947-
4948 def set_playback_mode(self, e_mode):
4949 '''Sets the playback mode for the playlist.
4950 @param e_mode: playback mode specification.
4951 '''
4952 return libvlc_media_list_player_set_playback_mode(self, e_mode)
4953
4954+
4955 class MediaPlayer(_Ctype):
4956 '''Create a new MediaPlayer instance.
4957
4958 It may take as parameter either:
4959 - a string (media URI), options... In this case, a vlc.Instance will be created.
4960 - a vlc.Instance, a string (media URI), options...
4961-
4962+
4963 '''
4964
4965 def __new__(cls, *args):
4966 if len(args) == 1 and isinstance(args[0], _Ints):
4967 return _Constructor(cls, args[0])
4968-
4969+
4970 if args and isinstance(args[0], Instance):
4971 instance = args[0]
4972 args = args[1:]
4973@@ -2545,7 +3266,7 @@
4974 def get_instance(self):
4975 """Return the associated Instance.
4976 """
4977- return self._instance #PYCHOK expected
4978+ return self._instance # PYCHOK expected
4979
4980 def set_mrl(self, mrl, *options):
4981 """Set the MRL to play.
4982@@ -2596,19 +3317,31 @@
4983 '''
4984 titleDescription_pp = ctypes.POINTER(TitleDescription)()
4985 n = libvlc_media_player_get_full_title_descriptions(self, ctypes.byref(titleDescription_pp))
4986- info = ctypes.cast(ctypes.titleDescription_pp, ctypes.POINTER(ctypes.POINTER(TitleDescription) * n))
4987- return info
4988+ info = ctypes.cast(titleDescription_pp, ctypes.POINTER(ctypes.POINTER(TitleDescription) * n))
4989+ try:
4990+ contents = info.contents
4991+ except ValueError:
4992+ # Media not parsed, no info.
4993+ return None
4994+ descr = (contents[i].contents for i in range(len(contents)))
4995+ return descr
4996
4997 def get_full_chapter_descriptions(self, i_chapters_of_title):
4998 '''Get the full description of available chapters.
4999- @param index: of the title to query for chapters.
5000- @return: the chapter list
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches