forked from openlp/openlp
Merge branch 'features_june_1' into 'master'
Fix up a number of bugs from 2.9.1 Closes #294, #587, #584, and #295 See merge request openlp/openlp!204
This commit is contained in:
commit
af1dd70589
@ -57,7 +57,7 @@ def add(plugin_name, id):
|
||||
@plugins.route('/<plugin>/search')
|
||||
@login_required
|
||||
def search_view(plugin):
|
||||
log.debug(f'{plugin}/search search called')
|
||||
log.debug(f'{plugin}/search called')
|
||||
text = request.args.get('text', '')
|
||||
result = search(plugin, text)
|
||||
return jsonify(result)
|
||||
@ -66,7 +66,7 @@ def search_view(plugin):
|
||||
@plugins.route('/<plugin>/add', methods=['POST'])
|
||||
@login_required
|
||||
def add_view(plugin):
|
||||
log.debug(f'{plugin}/add search called')
|
||||
log.debug(f'{plugin}/add called')
|
||||
data = request.json
|
||||
if not data:
|
||||
abort(400)
|
||||
@ -78,7 +78,7 @@ def add_view(plugin):
|
||||
@plugins.route('/<plugin>/live', methods=['POST'])
|
||||
@login_required
|
||||
def live_view(plugin):
|
||||
log.debug(f'{plugin}/live search called')
|
||||
log.debug(f'{plugin}/live called')
|
||||
data = request.json
|
||||
if not data:
|
||||
abort(400)
|
||||
|
@ -120,11 +120,11 @@ class Registry(metaclass=Singleton):
|
||||
:param args: Parameters to be passed to the function.
|
||||
:param kwargs: Parameters to be passed to the function.
|
||||
"""
|
||||
log.debug(f'Running function {event}')
|
||||
results = []
|
||||
if event in self.functions_list:
|
||||
for function in self.functions_list[event]:
|
||||
try:
|
||||
log.debug('Running function {} for {}'.format(function, event))
|
||||
result = function(*args, **kwargs)
|
||||
if result is not None:
|
||||
results.append(result)
|
||||
|
@ -573,8 +573,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
||||
"""
|
||||
process the bootstrap post setup request
|
||||
"""
|
||||
# self.preview_controller.panel.setVisible(self.settings.value('user interface/preview panel'))
|
||||
# self.live_controller.panel.setVisible(self.settings.value('user interface/live panel'))
|
||||
self.load_settings()
|
||||
self.restore_current_media_manager_item()
|
||||
Registry().execute('theme_update_global')
|
||||
@ -637,8 +635,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
||||
Show the main form, as well as the display form
|
||||
"""
|
||||
QtWidgets.QWidget.show(self)
|
||||
# if self.live_controller.display.isVisible():
|
||||
# self.live_controller.display.setFocus()
|
||||
self.activateWindow()
|
||||
# We have -disable-web-security added by our code.
|
||||
# If a file is passed in we will have that as well so count of 2
|
||||
|
@ -411,13 +411,13 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
||||
:param msg: First element is the controller which should be used
|
||||
:param status:
|
||||
"""
|
||||
self.media_play(msg[0], status)
|
||||
return self.media_play(msg[0], status)
|
||||
|
||||
def on_media_play(self):
|
||||
"""
|
||||
Responds to the request to play a loaded video from the web.
|
||||
"""
|
||||
self.media_play(Registry().get('live_controller'), False)
|
||||
return self.media_play(Registry().get('live_controller'), False)
|
||||
|
||||
def media_play(self, controller, first_time=True):
|
||||
"""
|
||||
@ -495,13 +495,13 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
||||
|
||||
:param msg: First element is the controller which should be used
|
||||
"""
|
||||
self.media_pause(msg[0])
|
||||
return self.media_pause(msg[0])
|
||||
|
||||
def on_media_pause(self):
|
||||
"""
|
||||
Responds to the request to pause a loaded video from the web.
|
||||
"""
|
||||
self.media_pause(Registry().get('live_controller'))
|
||||
return self.media_pause(Registry().get('live_controller'))
|
||||
|
||||
def media_pause(self, controller):
|
||||
"""
|
||||
@ -515,6 +515,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
||||
controller.mediabar.actions['playbackStop'].setDisabled(False)
|
||||
controller.mediabar.actions['playbackPause'].setVisible(False)
|
||||
controller.media_info.is_playing = False
|
||||
return True
|
||||
return False
|
||||
|
||||
def media_loop_msg(self, msg):
|
||||
"""
|
||||
@ -540,13 +542,13 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
||||
|
||||
:param msg: First element is the controller which should be used
|
||||
"""
|
||||
self.media_stop(msg[0])
|
||||
return self.media_stop(msg[0])
|
||||
|
||||
def on_media_stop(self):
|
||||
"""
|
||||
Responds to the request to stop a loaded video from the web.
|
||||
"""
|
||||
self.media_stop(Registry().get('live_controller'))
|
||||
return self.media_stop(Registry().get('live_controller'))
|
||||
|
||||
def media_stop(self, controller):
|
||||
"""
|
||||
@ -570,6 +572,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
||||
controller.media_timer = 0
|
||||
display = self._define_display(controller)
|
||||
display.show_display()
|
||||
return True
|
||||
return False
|
||||
|
||||
def media_volume_msg(self, msg):
|
||||
"""
|
||||
|
@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
@ -20,79 +19,58 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.api.endpoint` module contains various API endpoints
|
||||
The :mod:`~openlp.core.ui.media` module contains various API endpoints
|
||||
"""
|
||||
import logging
|
||||
from flask import abort, jsonify, Blueprint
|
||||
from flask import abort, Blueprint
|
||||
|
||||
from openlp.core.api import app
|
||||
from openlp.core.api.lib import login_required, old_auth
|
||||
from openlp.core.api.lib import login_required
|
||||
from openlp.core.common.registry import Registry
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
v1_media = Blueprint('v1-media-controller', __name__)
|
||||
v2_media = Blueprint('v2-media-controller', __name__)
|
||||
|
||||
|
||||
@v2_media.route('/play', methods=['POST'])
|
||||
@login_required
|
||||
def media_play():
|
||||
media = Registry().get('media_controller')
|
||||
log.debug('media_play')
|
||||
live = Registry().get('live_controller')
|
||||
try:
|
||||
status = media.media_play(live, True)
|
||||
except Exception:
|
||||
# The current item probably isn't a media item
|
||||
if live.service_item.name != 'media':
|
||||
abort(400)
|
||||
status = live.mediacontroller_live_play.emit()
|
||||
if status:
|
||||
return '', 204
|
||||
return '', 202
|
||||
abort(400)
|
||||
|
||||
|
||||
@v2_media.route('/pause', methods=['POST'])
|
||||
@login_required
|
||||
def media_pause():
|
||||
media = Registry().get('media_controller')
|
||||
log.debug('media_pause')
|
||||
live = Registry().get('live_controller')
|
||||
media.media_pause(live)
|
||||
return '', 204
|
||||
if live.service_item.name != 'media':
|
||||
abort(400)
|
||||
status = live.mediacontroller_live_pause.emit()
|
||||
if status:
|
||||
return '', 202
|
||||
abort(400)
|
||||
|
||||
|
||||
@v2_media.route('/stop', methods=['POST'])
|
||||
@login_required
|
||||
def media_stop():
|
||||
Registry().get('live_controller').mediacontroller_live_stop.emit()
|
||||
return '', 204
|
||||
|
||||
|
||||
# -------------- DEPRECATED ------------------------
|
||||
@v1_media.route('/play')
|
||||
@old_auth
|
||||
def v1_media_play():
|
||||
media = Registry().get('media_controller')
|
||||
log.debug('media_stop')
|
||||
live = Registry().get('live_controller')
|
||||
status = media.media_play(live, False)
|
||||
return jsonify({'success': status})
|
||||
|
||||
|
||||
@v1_media.route('/pause')
|
||||
@old_auth
|
||||
def v1_media_pause():
|
||||
media = Registry().get('media_controller')
|
||||
live = Registry().get('live_controller')
|
||||
status = media.media_pause(live)
|
||||
return jsonify({'success': status})
|
||||
|
||||
|
||||
@v1_media.route('/stop')
|
||||
@old_auth
|
||||
def v1_media_stop():
|
||||
Registry().get('live_controller').mediacontroller_live_stop.emit()
|
||||
return ''
|
||||
# -------------- END OF DEPRECATED ------------------------
|
||||
if live.service_item.name != 'media':
|
||||
abort(400)
|
||||
status = live.mediacontroller_live_stop.emit()
|
||||
if status:
|
||||
return '', 202
|
||||
abort(400)
|
||||
|
||||
|
||||
def register_views():
|
||||
app.register_blueprint(v2_media, url_prefix='/api/v2/media/')
|
||||
app.register_blueprint(v1_media, url_prefix='/api/media/')
|
||||
|
@ -287,42 +287,26 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
icon=UiIcons().live_presentation,
|
||||
checked=False, can_shortcuts=True, category=self.category,
|
||||
triggers=self.on_show_display)
|
||||
self.theme_screen = create_action(self, 'setThemeScreen',
|
||||
self.theme_screen = create_action(self, 'themeScreen',
|
||||
text=translate('OpenLP.SlideController', 'Show Theme'),
|
||||
icon=UiIcons().live_theme,
|
||||
checked=False, can_shortcuts=False, category=self.category,
|
||||
checked=False, can_shortcuts=True, category=self.category,
|
||||
triggers=self.on_theme_display)
|
||||
self.blank_screen = create_action(self, 'setBlankScreen',
|
||||
self.blank_screen = create_action(self, 'blankScreen',
|
||||
text=translate('OpenLP.SlideController', 'Show Black'),
|
||||
icon=UiIcons().live_black,
|
||||
checked=False, can_shortcuts=False, category=self.category,
|
||||
checked=False, can_shortcuts=True, category=self.category,
|
||||
triggers=self.on_blank_display)
|
||||
self.desktop_screen = create_action(self, 'setDesktopScreen',
|
||||
self.desktop_screen = create_action(self, 'desktopScreen',
|
||||
text=translate('OpenLP.SlideController', 'Show Desktop'),
|
||||
icon=UiIcons().live_desktop,
|
||||
checked=False, can_shortcuts=False, category=self.category,
|
||||
checked=False, can_shortcuts=True, category=self.category,
|
||||
triggers=self.on_hide_display)
|
||||
self.hide_menu.setDefaultAction(self.show_screen)
|
||||
self.hide_menu.menu().addAction(self.show_screen)
|
||||
self.hide_menu.menu().addAction(self.theme_screen)
|
||||
self.hide_menu.menu().addAction(self.blank_screen)
|
||||
self.hide_menu.menu().addAction(self.desktop_screen)
|
||||
# Add togglable actions for keyboard shortcuts
|
||||
self.controller.addAction(create_action(self, 'desktopScreen',
|
||||
can_shortcuts=True,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut,
|
||||
category=self.category,
|
||||
triggers=self.on_toggle_desktop))
|
||||
self.controller.addAction(create_action(self, 'themeScreen',
|
||||
can_shortcuts=True,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut,
|
||||
category=self.category,
|
||||
triggers=self.on_toggle_theme))
|
||||
self.controller.addAction(create_action(self, 'blankScreen',
|
||||
can_shortcuts=True,
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut,
|
||||
category=self.category,
|
||||
triggers=self.on_toggle_blank))
|
||||
# Wide menu of display control buttons.
|
||||
self.show_screen_button = QtWidgets.QToolButton(self.toolbar)
|
||||
self.show_screen_button.setObjectName('show_screen_button')
|
||||
@ -922,7 +906,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.selected_row = 0
|
||||
# take a copy not a link to the servicemanager copy.
|
||||
self.service_item = copy.copy(service_item)
|
||||
if self.service_item.is_command():
|
||||
if self.service_item.is_command() and not self.service_item.is_media():
|
||||
Registry().execute(
|
||||
'{text}_start'.format(text=self.service_item.name.lower()),
|
||||
[self.service_item, self.is_live, self.get_hide_mode(), slide_no])
|
||||
@ -967,7 +951,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
self.preview_display.load_images(self.service_item.slides)
|
||||
for display in self.displays:
|
||||
display.load_images(self.service_item.slides)
|
||||
for slide_index, slide in enumerate(self.service_item.slides):
|
||||
for _, _ in enumerate(self.service_item.slides):
|
||||
row += 1
|
||||
self.slide_list[str(row)] = row - 1
|
||||
self.preview_widget.replace_service_item(self.service_item, width, slide_no)
|
||||
@ -987,7 +971,10 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||
# close the previous, so make sure we don't close the new one.
|
||||
if old_item.is_command() and not self.service_item.is_command() or \
|
||||
old_item.is_command() and not old_item.is_media() and self.service_item.is_media():
|
||||
Registry().execute('{name}_stop'.format(name=old_item.name.lower()), [old_item, self.is_live])
|
||||
if old_item.is_media():
|
||||
self.on_media_close()
|
||||
else:
|
||||
Registry().execute('{name}_stop'.format(name=old_item.name.lower()), [old_item, self.is_live])
|
||||
if old_item.is_media() and not self.service_item.is_media():
|
||||
self.on_media_close()
|
||||
if self.is_live:
|
||||
|
@ -314,12 +314,21 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
||||
:param show_error: Should the error be shown (True)
|
||||
:return: The search result.
|
||||
"""
|
||||
from pathlib import Path
|
||||
results = []
|
||||
string = string.lower()
|
||||
for file_path in self.settings.value('media/media files'):
|
||||
file_name = file_path.name
|
||||
if file_name.lower().find(string) > -1:
|
||||
results.append([str(file_path), file_name])
|
||||
if isinstance(file_path, Path):
|
||||
file_name = file_path.name
|
||||
if file_name.lower().find(string) > -1:
|
||||
results.append([str(file_path), file_name])
|
||||
else:
|
||||
if file_path.lower().find(string) > -1:
|
||||
if file_path.startswith('device'):
|
||||
(name, _, _) = parse_stream_path(file_path)
|
||||
results.append([str(file_path), name])
|
||||
else:
|
||||
results.append([str(file_path), file_path])
|
||||
return results
|
||||
|
||||
def on_load_optical(self):
|
||||
|
@ -160,6 +160,8 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
existing files, and when the user adds new files via the media manager.
|
||||
|
||||
:param list[pathlib.Path] file_paths: List of file paths to add to the media manager.
|
||||
:param list[pathlib.Path] target_group: Group to load.
|
||||
:param boolean initial_load: Is this the initial load of the list at start up
|
||||
"""
|
||||
current_paths = self.get_file_list()
|
||||
titles = [file_path.name for file_path in current_paths]
|
||||
|
@ -739,8 +739,8 @@ def test_process_item(mocked_execute, registry):
|
||||
slide_controller._process_item(mocked_media_item, 0)
|
||||
|
||||
# THEN: Registry.execute should have been called to stop the presentation
|
||||
assert 2 == mocked_execute.call_count, 'Execute should have been called 2 times'
|
||||
assert 'mocked_presentation_item_stop' == mocked_execute.call_args_list[1][0][0], \
|
||||
assert 1 == mocked_execute.call_count, 'Execute should have been called 2 times'
|
||||
assert 'mocked_presentation_item_stop' == mocked_execute.call_args_list[0][0][0], \
|
||||
'The presentation should have been stopped.'
|
||||
|
||||
|
||||
|
@ -55,6 +55,18 @@ def test_search_found(media_item):
|
||||
assert result == [['test.mp4', 'test.mp4']], 'The result file contain the file name'
|
||||
|
||||
|
||||
def test_search_found_mixed(media_item):
|
||||
"""
|
||||
Media Remote Search Successful find with Paths and Strings
|
||||
"""
|
||||
# GIVEN: The Mediaitem set up a list of media
|
||||
media_item.settings.setValue('media/media files', [Path('test.mp3'), 'test.mp4'])
|
||||
# WHEN: Retrieving the test file
|
||||
result = media_item.search('test.mp4', False)
|
||||
# THEN: a file should be found
|
||||
assert result == [['test.mp4', 'test.mp4']], 'The result file contain the file name'
|
||||
|
||||
|
||||
def test_search_not_found(media_item):
|
||||
"""
|
||||
Media Remote Search not find
|
||||
|
Loading…
Reference in New Issue
Block a user