forked from openlp/openlp
HEAD
This commit is contained in:
commit
ca5e46eb49
@ -134,8 +134,8 @@ def extension_loader(glob_pattern, excluded_files=[]):
|
|||||||
importlib.import_module(module_name)
|
importlib.import_module(module_name)
|
||||||
except (ImportError, OSError):
|
except (ImportError, OSError):
|
||||||
# On some platforms importing vlc.py might cause OSError exceptions. (e.g. Mac OS X)
|
# On some platforms importing vlc.py might cause OSError exceptions. (e.g. Mac OS X)
|
||||||
log.warning('Failed to import {module_name} on path {extension_path}'
|
log.exception('Failed to import {module_name} on path {extension_path}'
|
||||||
.format(module_name=module_name, extension_path=extension_path))
|
.format(module_name=module_name, extension_path=extension_path))
|
||||||
|
|
||||||
|
|
||||||
def path_to_module(path):
|
def path_to_module(path):
|
||||||
@ -463,8 +463,8 @@ def get_file_encoding(file_path):
|
|||||||
Utility function to incrementally detect the file encoding.
|
Utility function to incrementally detect the file encoding.
|
||||||
|
|
||||||
:param openlp.core.common.path.Path file_path: Filename for the file to determine the encoding for.
|
:param openlp.core.common.path.Path file_path: Filename for the file to determine the encoding for.
|
||||||
:return: A dict with the keys 'encoding' and 'confidence'
|
:return: The name of the encoding detected
|
||||||
:rtype: dict[str, float]
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
detector = UniversalDetector()
|
detector = UniversalDetector()
|
||||||
try:
|
try:
|
||||||
@ -477,7 +477,7 @@ def get_file_encoding(file_path):
|
|||||||
except OSError:
|
except OSError:
|
||||||
log.exception('Error detecting file encoding')
|
log.exception('Error detecting file encoding')
|
||||||
finally:
|
finally:
|
||||||
return detector.close()
|
return detector.close()['encoding']
|
||||||
|
|
||||||
|
|
||||||
def normalize_str(irregular_string):
|
def normalize_str(irregular_string):
|
||||||
|
@ -180,15 +180,13 @@ class Settings(QtCore.QSettings):
|
|||||||
'api/thumbnails': True,
|
'api/thumbnails': True,
|
||||||
'crashreport/last directory': None,
|
'crashreport/last directory': None,
|
||||||
'formattingTags/html_tags': '',
|
'formattingTags/html_tags': '',
|
||||||
'core/audio repeat list': False,
|
|
||||||
'core/auto open': False,
|
'core/auto open': False,
|
||||||
'core/auto preview': False,
|
'core/auto preview': False,
|
||||||
'core/audio start paused': True,
|
|
||||||
'core/auto unblank': False,
|
'core/auto unblank': False,
|
||||||
'core/click live slide to unblank': False,
|
'core/click live slide to unblank': False,
|
||||||
'core/blank warning': False,
|
'core/blank warning': False,
|
||||||
'core/ccli number': '',
|
'core/ccli number': '',
|
||||||
'core/experimental': False,
|
'advanced/experimental': False,
|
||||||
'core/has run wizard': False,
|
'core/has run wizard': False,
|
||||||
'core/language': '[en]',
|
'core/language': '[en]',
|
||||||
'core/last version test': '',
|
'core/last version test': '',
|
||||||
@ -213,6 +211,7 @@ class Settings(QtCore.QSettings):
|
|||||||
'images/background color': '#000000',
|
'images/background color': '#000000',
|
||||||
'media/media auto start': QtCore.Qt.Unchecked,
|
'media/media auto start': QtCore.Qt.Unchecked,
|
||||||
'media/stream command': '',
|
'media/stream command': '',
|
||||||
|
'media/vlc arguments': '',
|
||||||
'remotes/download version': '0.0',
|
'remotes/download version': '0.0',
|
||||||
'players/background color': '#000000',
|
'players/background color': '#000000',
|
||||||
'servicemanager/last directory': None,
|
'servicemanager/last directory': None,
|
||||||
@ -317,7 +316,9 @@ class Settings(QtCore.QSettings):
|
|||||||
('bibles/proxy username', '', []),
|
('bibles/proxy username', '', []),
|
||||||
('bibles/proxy password', '', []),
|
('bibles/proxy password', '', []),
|
||||||
('media/players', '', []),
|
('media/players', '', []),
|
||||||
('media/override player', '', [])
|
('media/override player', '', []),
|
||||||
|
('core/audio start paused', '', []),
|
||||||
|
('core/audio repeat list', '', [])
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -180,7 +180,7 @@ class DisplayWindow(QtWidgets.QWidget):
|
|||||||
"""
|
"""
|
||||||
Set the URL of the webview
|
Set the URL of the webview
|
||||||
|
|
||||||
:param str url: The URL to set
|
:param QtCore.QUrl | str url: The URL to set
|
||||||
"""
|
"""
|
||||||
if not isinstance(url, QtCore.QUrl):
|
if not isinstance(url, QtCore.QUrl):
|
||||||
url = QtCore.QUrl(url)
|
url = QtCore.QUrl(url)
|
||||||
|
@ -29,7 +29,6 @@ from PyQt5 import QtCore, QtWidgets
|
|||||||
|
|
||||||
from openlp.core.common.i18n import UiStrings, translate
|
from openlp.core.common.i18n import UiStrings, translate
|
||||||
from openlp.core.common.mixins import RegistryProperties
|
from openlp.core.common.mixins import RegistryProperties
|
||||||
from openlp.core.common.path import path_to_str, str_to_path
|
|
||||||
from openlp.core.common.registry import Registry
|
from openlp.core.common.registry import Registry
|
||||||
from openlp.core.common.settings import Settings
|
from openlp.core.common.settings import Settings
|
||||||
from openlp.core.lib import ServiceItemContext
|
from openlp.core.lib import ServiceItemContext
|
||||||
@ -333,7 +332,7 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties):
|
|||||||
self.validate_and_load(file_paths)
|
self.validate_and_load(file_paths)
|
||||||
self.application.set_normal_cursor()
|
self.application.set_normal_cursor()
|
||||||
|
|
||||||
def load_file(self, data):
|
def handle_mime_data(self, data):
|
||||||
"""
|
"""
|
||||||
Turn file from Drag and Drop into an array so the Validate code can run it.
|
Turn file from Drag and Drop into an array so the Validate code can run it.
|
||||||
|
|
||||||
@ -379,11 +378,11 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties):
|
|||||||
duplicates_found = False
|
duplicates_found = False
|
||||||
files_added = False
|
files_added = False
|
||||||
for file_path in file_paths:
|
for file_path in file_paths:
|
||||||
if path_to_str(file_path) in full_list:
|
if file_path in full_list:
|
||||||
duplicates_found = True
|
duplicates_found = True
|
||||||
else:
|
else:
|
||||||
files_added = True
|
files_added = True
|
||||||
full_list.append(path_to_str(file_path))
|
full_list.append(file_path)
|
||||||
if full_list and files_added:
|
if full_list and files_added:
|
||||||
if target_group is None:
|
if target_group is None:
|
||||||
self.list_view.clear()
|
self.list_view.clear()
|
||||||
@ -416,8 +415,8 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties):
|
|||||||
file_paths = []
|
file_paths = []
|
||||||
for index in range(self.list_view.count()):
|
for index in range(self.list_view.count()):
|
||||||
list_item = self.list_view.item(index)
|
list_item = self.list_view.item(index)
|
||||||
filename = list_item.data(QtCore.Qt.UserRole)
|
file_path = list_item.data(QtCore.Qt.UserRole)
|
||||||
file_paths.append(str_to_path(filename))
|
file_paths.append(file_path)
|
||||||
return file_paths
|
return file_paths
|
||||||
|
|
||||||
def load_list(self, load_list, target_group):
|
def load_list(self, load_list, target_group):
|
||||||
|
@ -333,7 +333,7 @@ class Theme(object):
|
|||||||
else:
|
else:
|
||||||
# make string value unicode
|
# make string value unicode
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
value = str(str(value), 'utf-8')
|
value = str(value, 'utf-8')
|
||||||
# None means an empty string so lets have one.
|
# None means an empty string so lets have one.
|
||||||
if value == 'None':
|
if value == 'None':
|
||||||
value = ''
|
value = ''
|
||||||
|
@ -39,6 +39,7 @@ PJLINK_PREFIX = '%'
|
|||||||
PJLINK_PORT = 4352
|
PJLINK_PORT = 4352
|
||||||
PJLINK_SUFFIX = CR
|
PJLINK_SUFFIX = CR
|
||||||
PJLINK_TIMEOUT = 30.0
|
PJLINK_TIMEOUT = 30.0
|
||||||
|
PJLINK_TOKEN_SIZE = 8 # PJLINK 1 <token> : where <token> is 8 characters
|
||||||
|
|
||||||
# Error and status codes
|
# Error and status codes
|
||||||
S_OK = E_OK = 0 # E_OK included since I sometimes forget
|
S_OK = E_OK = 0 # E_OK included since I sometimes forget
|
||||||
|
@ -281,6 +281,7 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
self.pjlink_class = copy(PJLINK_CLASS)
|
self.pjlink_class = copy(PJLINK_CLASS)
|
||||||
self.pjlink_name = None # NAME
|
self.pjlink_name = None # NAME
|
||||||
self.power = S_OFF # POWR
|
self.power = S_OFF # POWR
|
||||||
|
self.projector_errors = {} # Full ERST errors
|
||||||
self.serial_no = None # SNUM
|
self.serial_no = None # SNUM
|
||||||
self.serial_no_received = None
|
self.serial_no_received = None
|
||||||
self.sw_version = None # SVER
|
self.sw_version = None # SVER
|
||||||
@ -520,14 +521,23 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
self.send_busy = False
|
self.send_busy = False
|
||||||
return
|
return
|
||||||
# Although we have a packet length limit, go ahead and use a larger buffer
|
# Although we have a packet length limit, go ahead and use a larger buffer
|
||||||
read = self.readLine(1024)
|
self.socket_timer.start()
|
||||||
log.debug('({ip}) get_socket(): "{buff}"'.format(ip=self.entry.name, buff=read))
|
while self.bytesAvailable() >= 1:
|
||||||
if read == -1:
|
data = self.readLine(1024)
|
||||||
|
data = data.strip()
|
||||||
|
if not data:
|
||||||
|
log.warning('({ip}) get_socket(): Ignoring empty packet'.format(ip=self.entry.name))
|
||||||
|
if self.bytesAvailable() < 1:
|
||||||
|
break
|
||||||
|
|
||||||
|
self.socket_timer.stop()
|
||||||
|
if data:
|
||||||
|
log.debug('({ip}) get_socket(): "{buff}"'.format(ip=self.entry.name, buff=data))
|
||||||
|
if data == -1:
|
||||||
# No data available
|
# No data available
|
||||||
log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.entry.name))
|
log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.entry.name))
|
||||||
return self.receive_data_signal()
|
return
|
||||||
self.socket_timer.stop()
|
return self.get_data(buff=data)
|
||||||
return self.get_data(buff=read)
|
|
||||||
|
|
||||||
def get_data(self, buff, *args, **kwargs):
|
def get_data(self, buff, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
@ -540,21 +550,22 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
# NOTE: Class2 has changed to some values being UTF-8
|
# NOTE: Class2 has changed to some values being UTF-8
|
||||||
data_in = decode(buff, 'utf-8') if isinstance(buff, bytes) else buff
|
data_in = decode(buff, 'utf-8') if isinstance(buff, bytes) else buff
|
||||||
data = data_in.strip()
|
data = data_in.strip()
|
||||||
|
self.receive_data_signal()
|
||||||
# Initial packet checks
|
# Initial packet checks
|
||||||
if (len(data) < 7):
|
if (len(data) < 7):
|
||||||
self._trash_buffer(msg='get_data(): Invalid packet - length')
|
self._trash_buffer(msg='get_data(): Invalid packet - length')
|
||||||
return self.receive_data_signal()
|
return
|
||||||
elif len(data) > self.max_size:
|
elif len(data) > self.max_size:
|
||||||
self._trash_buffer(msg='get_data(): Invalid packet - too long ({length} bytes)'.format(length=len(data)))
|
self._trash_buffer(msg='get_data(): Invalid packet - too long ({length} bytes)'.format(length=len(data)))
|
||||||
return self.receive_data_signal()
|
return
|
||||||
elif not data.startswith(PJLINK_PREFIX):
|
elif not data.startswith(PJLINK_PREFIX):
|
||||||
self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')
|
self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing')
|
||||||
return self.receive_data_signal()
|
return
|
||||||
elif data[6] != '=' and data[8] != '=':
|
elif data[6] != '=' and data[8] != '=':
|
||||||
# data[6] = standard command packet
|
# data[6] = standard command packet
|
||||||
# data[8] = initial PJLink connection (after mangling)
|
# data[8] = initial PJLink connection (after mangling)
|
||||||
self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')
|
self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="')
|
||||||
return self.receive_data_signal()
|
return
|
||||||
log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.entry.name, data=data))
|
log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.entry.name, data=data))
|
||||||
header, data = data.split('=')
|
header, data = data.split('=')
|
||||||
log.debug('({ip}) get_data() header="{header}" data="{data}"'.format(ip=self.entry.name,
|
log.debug('({ip}) get_data() header="{header}" data="{data}"'.format(ip=self.entry.name,
|
||||||
@ -572,20 +583,20 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
data=data))
|
data=data))
|
||||||
if cmd not in PJLINK_VALID_CMD:
|
if cmd not in PJLINK_VALID_CMD:
|
||||||
self._trash_buffer('get_data(): Invalid packet - unknown command "{data}"'.format(data=cmd))
|
self._trash_buffer('get_data(): Invalid packet - unknown command "{data}"'.format(data=cmd))
|
||||||
return self.receive_data_signal()
|
return
|
||||||
elif version not in PJLINK_VALID_CMD[cmd]['version']:
|
elif version not in PJLINK_VALID_CMD[cmd]['version']:
|
||||||
self._trash_buffer(msg='get_data() Command reply version does not match a valid command version')
|
self._trash_buffer(msg='get_data() Command reply version does not match a valid command version')
|
||||||
return self.receive_data_signal()
|
return
|
||||||
elif int(self.pjlink_class) < int(version):
|
elif int(self.pjlink_class) < int(version):
|
||||||
if not ignore_class:
|
if not ignore_class:
|
||||||
log.warning('({ip}) get_data(): Projector returned class reply higher '
|
log.warning('({ip}) get_data(): Projector returned class reply higher '
|
||||||
'than projector stated class'.format(ip=self.entry.name))
|
'than projector stated class'.format(ip=self.entry.name))
|
||||||
return self.receive_data_signal()
|
return
|
||||||
|
|
||||||
chk = process_command(self, cmd, data)
|
chk = process_command(self, cmd, data)
|
||||||
if chk is None:
|
if chk is None:
|
||||||
# Command processed normally and not initial connection, so skip other checks
|
# Command processed normally and not initial connection, so skip other checks
|
||||||
return self.receive_data_signal()
|
return
|
||||||
# PJLink initial connection checks
|
# PJLink initial connection checks
|
||||||
elif chk == S_DATA_OK:
|
elif chk == S_DATA_OK:
|
||||||
# Previous command returned OK
|
# Previous command returned OK
|
||||||
@ -612,7 +623,7 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
self.projectorAuthentication.emit(self.entry.name)
|
self.projectorAuthentication.emit(self.entry.name)
|
||||||
self.change_status(status=E_AUTHENTICATION)
|
self.change_status(status=E_AUTHENTICATION)
|
||||||
|
|
||||||
return self.receive_data_signal()
|
return
|
||||||
|
|
||||||
@QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)
|
@QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)
|
||||||
def get_error(self, err):
|
def get_error(self, err):
|
||||||
@ -728,17 +739,17 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
log.debug('({ip}) _send_command(): Normal queue = {data}'.format(ip=self.entry.name, data=self.send_queue))
|
log.debug('({ip}) _send_command(): Normal queue = {data}'.format(ip=self.entry.name, data=self.send_queue))
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(self.priority_queue) != 0:
|
if not self.priority_queue and not self.send_queue:
|
||||||
out = self.priority_queue.pop(0)
|
|
||||||
log.debug('({ip}) _send_command(): Getting priority queued packet'.format(ip=self.entry.name))
|
|
||||||
elif len(self.send_queue) != 0:
|
|
||||||
out = self.send_queue.pop(0)
|
|
||||||
log.debug('({ip}) _send_command(): Getting normal queued packet'.format(ip=self.entry.name))
|
|
||||||
else:
|
|
||||||
# No data to send
|
# No data to send
|
||||||
log.warning('({ip}) _send_command(): No data to send'.format(ip=self.entry.name))
|
log.warning('({ip}) _send_command(): No data to send'.format(ip=self.entry.name))
|
||||||
self.send_busy = False
|
self.send_busy = False
|
||||||
return
|
return
|
||||||
|
elif self.priority_queue:
|
||||||
|
out = self.priority_queue.pop(0)
|
||||||
|
log.debug('({ip}) _send_command(): Getting priority queued packet'.format(ip=self.entry.name))
|
||||||
|
elif self.send_queue:
|
||||||
|
out = self.send_queue.pop(0)
|
||||||
|
log.debug('({ip}) _send_command(): Getting normal queued packet'.format(ip=self.entry.name))
|
||||||
self.send_busy = True
|
self.send_busy = True
|
||||||
log.debug('({ip}) _send_command(): Sending "{data}"'.format(ip=self.entry.name, data=out.strip()))
|
log.debug('({ip}) _send_command(): Sending "{data}"'.format(ip=self.entry.name, data=out.strip()))
|
||||||
self.socket_timer.start()
|
self.socket_timer.start()
|
||||||
@ -861,6 +872,24 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
log.debug('({ip}) Sending POWR command'.format(ip=self.entry.name))
|
log.debug('({ip}) Sending POWR command'.format(ip=self.entry.name))
|
||||||
return self.send_command(cmd='POWR', priority=priority)
|
return self.send_command(cmd='POWR', priority=priority)
|
||||||
|
|
||||||
|
def set_audio_mute(self, priority=False):
|
||||||
|
"""
|
||||||
|
Send command to set audio to muted
|
||||||
|
"""
|
||||||
|
log.debug('({ip}) Setting AVMT to 21 (audio mute)'.format(ip=self.entry.name))
|
||||||
|
self.send_command(cmd='AVMT', opts='21', priority=True)
|
||||||
|
self.status_timer_add(cmd='AVMT', callback=self.get_av_mute_status)
|
||||||
|
self.poll_loop()
|
||||||
|
|
||||||
|
def set_audio_normal(self, priority=False):
|
||||||
|
"""
|
||||||
|
Send command to set audio to normal
|
||||||
|
"""
|
||||||
|
log.debug('({ip}) Setting AVMT to 20 (audio normal)'.format(ip=self.entry.name))
|
||||||
|
self.send_command(cmd='AVMT', opts='20', priority=True)
|
||||||
|
self.status_timer_add(cmd='AVMT', callback=self.get_av_mute_status)
|
||||||
|
self.poll_loop()
|
||||||
|
|
||||||
def set_input_source(self, src=None):
|
def set_input_source(self, src=None):
|
||||||
"""
|
"""
|
||||||
Verify input source available as listed in 'INST' command,
|
Verify input source available as listed in 'INST' command,
|
||||||
@ -924,9 +953,9 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
log.warning('({ip}) "{cmd}" already in checks - returning'.format(ip=self.entry.name, cmd=cmd))
|
log.warning('({ip}) "{cmd}" already in checks - returning'.format(ip=self.entry.name, cmd=cmd))
|
||||||
return
|
return
|
||||||
log.debug('({ip}) Adding "{cmd}" callback for status timer'.format(ip=self.entry.name, cmd=cmd))
|
log.debug('({ip}) Adding "{cmd}" callback for status timer'.format(ip=self.entry.name, cmd=cmd))
|
||||||
|
self.status_timer_checks[cmd] = callback
|
||||||
if not self.status_timer.isActive():
|
if not self.status_timer.isActive():
|
||||||
self.status_timer.start()
|
self.status_timer.start()
|
||||||
self.status_timer_checks[cmd] = callback
|
|
||||||
|
|
||||||
def status_timer_delete(self, cmd):
|
def status_timer_delete(self, cmd):
|
||||||
"""
|
"""
|
||||||
|
@ -29,13 +29,13 @@ NOTE: PJLink Class (version) checks are handled in the respective PJLink/PJLinkU
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
import string
|
||||||
|
|
||||||
from openlp.core.common.i18n import translate
|
|
||||||
from openlp.core.common.settings import Settings
|
from openlp.core.common.settings import Settings
|
||||||
|
|
||||||
from openlp.core.projectors.constants import E_AUTHENTICATION, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \
|
from openlp.core.projectors.constants import E_AUTHENTICATION, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \
|
||||||
PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_POWR_STATUS, S_AUTHENTICATE, S_CONNECT, S_DATA_OK, S_OFF, S_OK, S_ON, \
|
PJLINK_ERST_DATA, PJLINK_ERST_LIST, PJLINK_ERST_STATUS, PJLINK_POWR_STATUS, PJLINK_TOKEN_SIZE, \
|
||||||
S_STANDBY, STATUS_MSG
|
E_NO_AUTHENTICATION, S_AUTHENTICATE, S_CONNECT, S_DATA_OK, S_OFF, S_OK, S_ON, S_STANDBY, STATUS_MSG
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
log.debug('Loading pjlinkcommands')
|
log.debug('Loading pjlinkcommands')
|
||||||
@ -113,15 +113,21 @@ def process_avmt(projector, data):
|
|||||||
'31': {'shutter': True, 'mute': True}
|
'31': {'shutter': True, 'mute': True}
|
||||||
}
|
}
|
||||||
if data not in settings:
|
if data not in settings:
|
||||||
log.warning('({ip}) Invalid shutter response: {data}'.format(ip=projector.entry.name, data=data))
|
log.warning('({ip}) Invalid av mute response: {data}'.format(ip=projector.entry.name, data=data))
|
||||||
return
|
return
|
||||||
shutter = settings[data]['shutter']
|
shutter = settings[data]['shutter']
|
||||||
mute = settings[data]['mute']
|
mute = settings[data]['mute']
|
||||||
# Check if we need to update the icons
|
# Check if we need to update the icons
|
||||||
update_icons = (shutter != projector.shutter) or (mute != projector.mute)
|
update_icons = (shutter != projector.shutter) or (mute != projector.mute)
|
||||||
projector.shutter = shutter
|
|
||||||
projector.mute = mute
|
|
||||||
if update_icons:
|
if update_icons:
|
||||||
|
if projector.shutter != shutter:
|
||||||
|
projector.shutter = shutter
|
||||||
|
log.debug('({ip}) Setting shutter to {chk}'.format(ip=projector.entry.name,
|
||||||
|
chk='closed' if shutter else 'open'))
|
||||||
|
if projector.mute != mute:
|
||||||
|
projector.mute = mute
|
||||||
|
log.debug('({ip}) Setting speaker to {chk}'.format(ip=projector.entry.name,
|
||||||
|
chk='muted' if shutter else 'normal'))
|
||||||
if 'AVMT' in projector.status_timer_checks:
|
if 'AVMT' in projector.status_timer_checks:
|
||||||
projector.status_timer_delete('AVMT')
|
projector.status_timer_delete('AVMT')
|
||||||
projector.projectorUpdateIcons.emit()
|
projector.projectorUpdateIcons.emit()
|
||||||
@ -147,14 +153,14 @@ def process_clss(projector, data):
|
|||||||
# fix the class reply is to just remove all non-digit characters.
|
# fix the class reply is to just remove all non-digit characters.
|
||||||
chk = re.findall(r'\d', data)
|
chk = re.findall(r'\d', data)
|
||||||
if len(chk) < 1:
|
if len(chk) < 1:
|
||||||
log.error('({ip}) No numbers found in class version reply "{data}" - '
|
log.warning('({ip}) No numbers found in class version reply "{data}" - '
|
||||||
'defaulting to class "1"'.format(ip=projector.entry.name, data=data))
|
'defaulting to class "1"'.format(ip=projector.entry.name, data=data))
|
||||||
clss = '1'
|
clss = '1'
|
||||||
else:
|
else:
|
||||||
clss = chk[0] # Should only be the first match
|
clss = chk[0] # Should only be the first match
|
||||||
elif not data.isdigit():
|
elif not data.isdigit():
|
||||||
log.error('({ip}) NAN CLSS version reply "{data}" - '
|
log.warning('({ip}) NAN CLSS version reply "{data}" - '
|
||||||
'defaulting to class "1"'.format(ip=projector.entry.name, data=data))
|
'defaulting to class "1"'.format(ip=projector.entry.name, data=data))
|
||||||
clss = '1'
|
clss = '1'
|
||||||
else:
|
else:
|
||||||
clss = data
|
clss = data
|
||||||
@ -189,8 +195,7 @@ def process_erst(projector, data):
|
|||||||
# Bad data - ignore
|
# Bad data - ignore
|
||||||
log.warning('({ip}) Invalid error status response "{data}"'.format(ip=projector.entry.name, data=data))
|
log.warning('({ip}) Invalid error status response "{data}"'.format(ip=projector.entry.name, data=data))
|
||||||
return
|
return
|
||||||
datacheck = int(data)
|
if int(data) == 0:
|
||||||
if datacheck == 0:
|
|
||||||
projector.projector_errors = None
|
projector.projector_errors = None
|
||||||
# No errors
|
# No errors
|
||||||
return
|
return
|
||||||
@ -203,23 +208,17 @@ def process_erst(projector, data):
|
|||||||
data[PJLINK_ERST_DATA['FILTER']],
|
data[PJLINK_ERST_DATA['FILTER']],
|
||||||
data[PJLINK_ERST_DATA['OTHER']])
|
data[PJLINK_ERST_DATA['OTHER']])
|
||||||
if fan != PJLINK_ERST_STATUS[S_OK]:
|
if fan != PJLINK_ERST_STATUS[S_OK]:
|
||||||
projector.projector_errors[translate('OpenLP.ProjectorPJLink', 'Fan')] = \
|
projector.projector_errors[PJLINK_ERST_LIST['FAN']] = PJLINK_ERST_STATUS[fan]
|
||||||
PJLINK_ERST_STATUS[fan]
|
|
||||||
if lamp != PJLINK_ERST_STATUS[S_OK]:
|
if lamp != PJLINK_ERST_STATUS[S_OK]:
|
||||||
projector.projector_errors[translate('OpenLP.ProjectorPJLink', 'Lamp')] = \
|
projector.projector_errors[PJLINK_ERST_LIST['LAMP']] = PJLINK_ERST_STATUS[lamp]
|
||||||
PJLINK_ERST_STATUS[lamp]
|
|
||||||
if temp != PJLINK_ERST_STATUS[S_OK]:
|
if temp != PJLINK_ERST_STATUS[S_OK]:
|
||||||
projector.projector_errors[translate('OpenLP.ProjectorPJLink', 'Temperature')] = \
|
projector.projector_errors[PJLINK_ERST_LIST['TEMP']] = PJLINK_ERST_STATUS[temp]
|
||||||
PJLINK_ERST_STATUS[temp]
|
|
||||||
if cover != PJLINK_ERST_STATUS[S_OK]:
|
if cover != PJLINK_ERST_STATUS[S_OK]:
|
||||||
projector.projector_errors[translate('OpenLP.ProjectorPJLink', 'Cover')] = \
|
projector.projector_errors[PJLINK_ERST_LIST['COVER']] = PJLINK_ERST_STATUS[cover]
|
||||||
PJLINK_ERST_STATUS[cover]
|
|
||||||
if filt != PJLINK_ERST_STATUS[S_OK]:
|
if filt != PJLINK_ERST_STATUS[S_OK]:
|
||||||
projector.projector_errors[translate('OpenLP.ProjectorPJLink', 'Filter')] = \
|
projector.projector_errors[PJLINK_ERST_LIST['FILTER']] = PJLINK_ERST_STATUS[filt]
|
||||||
PJLINK_ERST_STATUS[filt]
|
|
||||||
if other != PJLINK_ERST_STATUS[S_OK]:
|
if other != PJLINK_ERST_STATUS[S_OK]:
|
||||||
projector.projector_errors[translate('OpenLP.ProjectorPJLink', 'Other')] = \
|
projector.projector_errors[PJLINK_ERST_LIST['OTHER']] = PJLINK_ERST_STATUS[other]
|
||||||
PJLINK_ERST_STATUS[other]
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@ -276,12 +275,13 @@ def process_inpt(projector, data):
|
|||||||
if projector.source_available is not None:
|
if projector.source_available is not None:
|
||||||
# We have available inputs, so verify it's in the list
|
# We have available inputs, so verify it's in the list
|
||||||
if data not in projector.source_available:
|
if data not in projector.source_available:
|
||||||
log.warn('({ip}) Input source not listed in available sources - ignoring'.format(ip=projector.entry.name))
|
log.warning('({ip}) Input source not listed in available sources - '
|
||||||
|
'ignoring'.format(ip=projector.entry.name))
|
||||||
return
|
return
|
||||||
elif data not in PJLINK_DEFAULT_CODES:
|
elif data not in PJLINK_DEFAULT_CODES:
|
||||||
# Hmm - no sources available yet, so check with PJLink defaults
|
# Hmm - no sources available yet, so check with PJLink defaults
|
||||||
log.warn('({ip}) Input source not listed as a PJLink available source '
|
log.warning('({ip}) Input source not listed as a PJLink valid source '
|
||||||
'- ignoring'.format(ip=projector.entry.name))
|
'- ignoring'.format(ip=projector.entry.name))
|
||||||
return
|
return
|
||||||
projector.source = data
|
projector.source = data
|
||||||
log.debug('({ip}) Setting current source to "{data}"'.format(ip=projector.entry.name, data=projector.source))
|
log.debug('({ip}) Setting current source to "{data}"'.format(ip=projector.entry.name, data=projector.source))
|
||||||
@ -320,7 +320,10 @@ def process_lamp(projector, data):
|
|||||||
lamps = []
|
lamps = []
|
||||||
lamp_list = data.split()
|
lamp_list = data.split()
|
||||||
if len(lamp_list) < 2:
|
if len(lamp_list) < 2:
|
||||||
lamps.append({'Hours': int(lamp_list[0]), 'On': None})
|
# Invalid data - not enough information
|
||||||
|
log.warning('({ip}) process_lamp(): Invalid data "{data}" - '
|
||||||
|
'Missing data'.format(ip=projector.entry.name, data=data))
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
while lamp_list:
|
while lamp_list:
|
||||||
if not lamp_list[0].isnumeric() or not lamp_list[1].isnumeric():
|
if not lamp_list[0].isnumeric() or not lamp_list[1].isnumeric():
|
||||||
@ -379,20 +382,29 @@ def process_pjlink(projector, data):
|
|||||||
if len(chk) > 1:
|
if len(chk) > 1:
|
||||||
# Invalid data - there should be nothing after a normal authentication scheme
|
# Invalid data - there should be nothing after a normal authentication scheme
|
||||||
log.error('({ip}) Normal connection with extra information - aborting'.format(ip=projector.entry.name))
|
log.error('({ip}) Normal connection with extra information - aborting'.format(ip=projector.entry.name))
|
||||||
return E_AUTHENTICATION
|
return E_NO_AUTHENTICATION
|
||||||
elif projector.pin:
|
elif projector.pin:
|
||||||
log.error('({ip}) Normal connection but PIN set - aborting'.format(ip=projector.entry.name))
|
log.error('({ip}) Normal connection but PIN set - aborting'.format(ip=projector.entry.name))
|
||||||
return E_AUTHENTICATION
|
return E_NO_AUTHENTICATION
|
||||||
log.debug('({ip}) PJLINK: Returning S_CONNECT'.format(ip=projector.entry.name))
|
log.debug('({ip}) PJLINK: Returning S_CONNECT'.format(ip=projector.entry.name))
|
||||||
return S_CONNECT
|
return S_CONNECT
|
||||||
elif chk[0] == '1':
|
elif chk[0] == '1':
|
||||||
if len(chk) < 2:
|
if len(chk) < 2:
|
||||||
# Not enough information for authenticated connection
|
# Not enough information for authenticated connection
|
||||||
log.error('({ip}) Authenticated connection but not enough info - aborting'.format(ip=projector.entry.name))
|
log.error('({ip}) Authenticated connection but not enough info - aborting'.format(ip=projector.entry.name))
|
||||||
return E_AUTHENTICATION
|
return E_NO_AUTHENTICATION
|
||||||
|
elif len(chk[-1]) != PJLINK_TOKEN_SIZE:
|
||||||
|
# Bad token - incorrect size
|
||||||
|
log.error('({ip}) Authentication token invalid (size) - aborting'.format(ip=projector.entry.name))
|
||||||
|
return E_NO_AUTHENTICATION
|
||||||
|
elif not all(c in string.hexdigits for c in chk[-1]):
|
||||||
|
# Bad token - not hexadecimal
|
||||||
|
log.error('({ip}) Authentication token invalid (not a hexadecimal number) '
|
||||||
|
'- aborting'.format(ip=projector.entry.name))
|
||||||
|
return E_NO_AUTHENTICATION
|
||||||
elif not projector.pin:
|
elif not projector.pin:
|
||||||
log.error('({ip}) Authenticate connection but no PIN - aborting'.format(ip=projector.entry.name))
|
log.error('({ip}) Authenticate connection but no PIN - aborting'.format(ip=projector.entry.name))
|
||||||
return E_AUTHENTICATION
|
return E_NO_AUTHENTICATION
|
||||||
log.debug('({ip}) PJLINK: Returning S_AUTHENTICATE'.format(ip=projector.entry.name))
|
log.debug('({ip}) PJLINK: Returning S_AUTHENTICATE'.format(ip=projector.entry.name))
|
||||||
return S_AUTHENTICATE
|
return S_AUTHENTICATE
|
||||||
|
|
||||||
@ -405,20 +417,22 @@ def process_powr(projector, data):
|
|||||||
:param projector: Projector instance
|
:param projector: Projector instance
|
||||||
:param data: Power status
|
:param data: Power status
|
||||||
"""
|
"""
|
||||||
log.debug('({ip}: Processing POWR command'.format(ip=projector.entry.name))
|
log.debug('({ip}) Processing POWR command'.format(ip=projector.entry.name))
|
||||||
if data in PJLINK_POWR_STATUS:
|
if data not in PJLINK_POWR_STATUS:
|
||||||
power = PJLINK_POWR_STATUS[data]
|
|
||||||
update_icons = projector.power != power
|
|
||||||
projector.power = power
|
|
||||||
projector.change_status(PJLINK_POWR_STATUS[data])
|
|
||||||
if update_icons:
|
|
||||||
projector.projectorUpdateIcons.emit()
|
|
||||||
# Update the input sources available
|
|
||||||
if power == S_ON:
|
|
||||||
projector.send_command('INST')
|
|
||||||
else:
|
|
||||||
# Log unknown status response
|
# Log unknown status response
|
||||||
log.warning('({ip}) Unknown power response: "{data}"'.format(ip=projector.entry.name, data=data))
|
log.warning('({ip}) Unknown power response: "{data}"'.format(ip=projector.entry.name, data=data))
|
||||||
|
return
|
||||||
|
|
||||||
|
power = PJLINK_POWR_STATUS[data]
|
||||||
|
update_icons = projector.power != power
|
||||||
|
if update_icons:
|
||||||
|
projector.power = power
|
||||||
|
projector.change_status(PJLINK_POWR_STATUS[data])
|
||||||
|
projector.projectorUpdateIcons.emit()
|
||||||
|
if power == S_ON:
|
||||||
|
# Input sources list should only be available after power on, so update here
|
||||||
|
projector.send_command('INST')
|
||||||
|
|
||||||
if projector.power in [S_ON, S_STANDBY, S_OFF] and 'POWR' in projector.status_timer_checks:
|
if projector.power in [S_ON, S_STANDBY, S_OFF] and 'POWR' in projector.status_timer_checks:
|
||||||
projector.status_timer_delete(cmd='POWR')
|
projector.status_timer_delete(cmd='POWR')
|
||||||
return
|
return
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
from PyQt5 import QtCore, QtNetwork
|
from PyQt5 import QtCore, QtNetwork
|
||||||
|
|
||||||
from openlp.core.common.mixins import LogMixin
|
from openlp.core.common.mixins import LogMixin
|
||||||
|
from openlp.core.common.path import Path
|
||||||
from openlp.core.common.registry import Registry
|
from openlp.core.common.registry import Registry
|
||||||
|
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ class Server(QtCore.QObject, LogMixin):
|
|||||||
msg = self.in_stream.readLine()
|
msg = self.in_stream.readLine()
|
||||||
if msg:
|
if msg:
|
||||||
self.log_debug("socket msg = " + msg)
|
self.log_debug("socket msg = " + msg)
|
||||||
Registry().get('service_manager').on_load_service_clicked(msg)
|
Registry().get('service_manager').load_service(Path(msg))
|
||||||
|
|
||||||
def close_server(self):
|
def close_server(self):
|
||||||
"""
|
"""
|
||||||
|
@ -93,4 +93,4 @@ class SingleColumnTableWidget(QtWidgets.QTableWidget):
|
|||||||
self.resizeRowsToContents()
|
self.resizeRowsToContents()
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['SingleColumnTableWidget']
|
__all__ = ['SingleColumnTableWidget', 'DisplayControllerType']
|
||||||
|
@ -117,6 +117,9 @@ class AdvancedTab(SettingsTab):
|
|||||||
self.enable_auto_close_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
self.enable_auto_close_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||||
self.enable_auto_close_check_box.setObjectName('enable_auto_close_check_box')
|
self.enable_auto_close_check_box.setObjectName('enable_auto_close_check_box')
|
||||||
self.ui_layout.addRow(self.enable_auto_close_check_box)
|
self.ui_layout.addRow(self.enable_auto_close_check_box)
|
||||||
|
self.experimental_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||||
|
self.experimental_check_box.setObjectName('experimental_check_box')
|
||||||
|
self.ui_layout.addRow(self.experimental_check_box)
|
||||||
self.left_layout.addWidget(self.ui_group_box)
|
self.left_layout.addWidget(self.ui_group_box)
|
||||||
if HAS_DARK_STYLE:
|
if HAS_DARK_STYLE:
|
||||||
self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box)
|
self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box)
|
||||||
@ -291,6 +294,8 @@ class AdvancedTab(SettingsTab):
|
|||||||
'Auto-scroll the next slide to bottom'))
|
'Auto-scroll the next slide to bottom'))
|
||||||
self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab',
|
self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab',
|
||||||
'Enable application exit confirmation'))
|
'Enable application exit confirmation'))
|
||||||
|
self.experimental_check_box.setText(translate('OpenLP.GeneralTab',
|
||||||
|
'Experimental features (use at your own risk)'))
|
||||||
if HAS_DARK_STYLE:
|
if HAS_DARK_STYLE:
|
||||||
self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)'))
|
self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)'))
|
||||||
self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name'))
|
self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name'))
|
||||||
@ -360,6 +365,7 @@ class AdvancedTab(SettingsTab):
|
|||||||
if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count():
|
if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count():
|
||||||
self.autoscroll_combo_box.setCurrentIndex(i)
|
self.autoscroll_combo_box.setCurrentIndex(i)
|
||||||
self.enable_auto_close_check_box.setChecked(settings.value('enable exit confirmation'))
|
self.enable_auto_close_check_box.setChecked(settings.value('enable exit confirmation'))
|
||||||
|
self.experimental_check_box.setChecked(settings.value('experimental'))
|
||||||
if HAS_DARK_STYLE:
|
if HAS_DARK_STYLE:
|
||||||
self.use_dark_style_checkbox.setChecked(settings.value('use_dark_style'))
|
self.use_dark_style_checkbox.setChecked(settings.value('use_dark_style'))
|
||||||
self.hide_mouse_check_box.setChecked(settings.value('hide mouse'))
|
self.hide_mouse_check_box.setChecked(settings.value('hide mouse'))
|
||||||
@ -423,6 +429,7 @@ class AdvancedTab(SettingsTab):
|
|||||||
slide_max_height_value = self.slide_max_height_combo_box.itemData(slide_max_height_index)
|
slide_max_height_value = self.slide_max_height_combo_box.itemData(slide_max_height_index)
|
||||||
settings.setValue('slide max height', slide_max_height_value)
|
settings.setValue('slide max height', slide_max_height_value)
|
||||||
settings.setValue('autoscrolling', self.autoscroll_map[self.autoscroll_combo_box.currentIndex()])
|
settings.setValue('autoscrolling', self.autoscroll_map[self.autoscroll_combo_box.currentIndex()])
|
||||||
|
settings.setValue('experimental', self.experimental_check_box.isChecked())
|
||||||
settings.setValue('enable exit confirmation', self.enable_auto_close_check_box.isChecked())
|
settings.setValue('enable exit confirmation', self.enable_auto_close_check_box.isChecked())
|
||||||
settings.setValue('hide mouse', self.hide_mouse_check_box.isChecked())
|
settings.setValue('hide mouse', self.hide_mouse_check_box.isChecked())
|
||||||
settings.setValue('alternate rows', self.alternate_rows_check_box.isChecked())
|
settings.setValue('alternate rows', self.alternate_rows_check_box.isChecked())
|
||||||
|
@ -78,7 +78,7 @@ class ThemeListWidget(QtWidgets.QListWidget):
|
|||||||
"""
|
"""
|
||||||
nominal_width = 141 # Icon width of 133 + 4 each side
|
nominal_width = 141 # Icon width of 133 + 4 each side
|
||||||
max_items_per_row = self.viewport().width() // nominal_width or 1 # or 1 to avoid divide by 0 errors
|
max_items_per_row = self.viewport().width() // nominal_width or 1 # or 1 to avoid divide by 0 errors
|
||||||
col_size = (self.viewport().width() - 1) / max_items_per_row
|
col_size = (self.viewport().width() - 1) // max_items_per_row
|
||||||
self.setGridSize(QtCore.QSize(col_size, 140))
|
self.setGridSize(QtCore.QSize(col_size, 140))
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,18 +83,6 @@ class GeneralTab(SettingsTab):
|
|||||||
self.password_edit.setObjectName('password_edit')
|
self.password_edit.setObjectName('password_edit')
|
||||||
self.ccli_layout.addRow(self.password_label, self.password_edit)
|
self.ccli_layout.addRow(self.password_label, self.password_edit)
|
||||||
self.left_layout.addWidget(self.ccli_group_box)
|
self.left_layout.addWidget(self.ccli_group_box)
|
||||||
# Background audio
|
|
||||||
self.audio_group_box = QtWidgets.QGroupBox(self.left_column)
|
|
||||||
self.audio_group_box.setObjectName('audio_group_box')
|
|
||||||
self.audio_layout = QtWidgets.QVBoxLayout(self.audio_group_box)
|
|
||||||
self.audio_layout.setObjectName('audio_layout')
|
|
||||||
self.start_paused_check_box = QtWidgets.QCheckBox(self.audio_group_box)
|
|
||||||
self.start_paused_check_box.setObjectName('start_paused_check_box')
|
|
||||||
self.audio_layout.addWidget(self.start_paused_check_box)
|
|
||||||
self.repeat_list_check_box = QtWidgets.QCheckBox(self.audio_group_box)
|
|
||||||
self.repeat_list_check_box.setObjectName('repeat_list_check_box')
|
|
||||||
self.audio_layout.addWidget(self.repeat_list_check_box)
|
|
||||||
self.left_layout.addWidget(self.audio_group_box)
|
|
||||||
self.left_layout.addStretch()
|
self.left_layout.addStretch()
|
||||||
# Application Startup
|
# Application Startup
|
||||||
self.startup_group_box = QtWidgets.QGroupBox(self.right_column)
|
self.startup_group_box = QtWidgets.QGroupBox(self.right_column)
|
||||||
@ -195,9 +183,7 @@ class GeneralTab(SettingsTab):
|
|||||||
self.number_label.setText(UiStrings().CCLINumberLabel)
|
self.number_label.setText(UiStrings().CCLINumberLabel)
|
||||||
self.username_label.setText(translate('OpenLP.GeneralTab', 'SongSelect username:'))
|
self.username_label.setText(translate('OpenLP.GeneralTab', 'SongSelect username:'))
|
||||||
self.password_label.setText(translate('OpenLP.GeneralTab', 'SongSelect password:'))
|
self.password_label.setText(translate('OpenLP.GeneralTab', 'SongSelect password:'))
|
||||||
self.audio_group_box.setTitle(translate('OpenLP.GeneralTab', 'Background Audio'))
|
self.logo_file_path_edit.dialog_caption = translate('OpenLP.AdvancedTab', 'Select Logo File')
|
||||||
self.start_paused_check_box.setText(translate('OpenLP.GeneralTab', 'Start background audio paused'))
|
|
||||||
self.repeat_list_check_box.setText(translate('OpenLP.GeneralTab', 'Repeat track list'))
|
|
||||||
self.logo_file_path_edit.dialog_caption = translate('OpenLP.AdvancedTab', 'Select Logo File')
|
self.logo_file_path_edit.dialog_caption = translate('OpenLP.AdvancedTab', 'Select Logo File')
|
||||||
self.logo_file_path_edit.filters = '{text};;{names} (*)'.format(
|
self.logo_file_path_edit.filters = '{text};;{names} (*)'.format(
|
||||||
text=get_images_filter(), names=UiStrings().AllFiles)
|
text=get_images_filter(), names=UiStrings().AllFiles)
|
||||||
@ -224,8 +210,6 @@ class GeneralTab(SettingsTab):
|
|||||||
self.check_for_updates_check_box.setChecked(settings.value('update check'))
|
self.check_for_updates_check_box.setChecked(settings.value('update check'))
|
||||||
self.auto_preview_check_box.setChecked(settings.value('auto preview'))
|
self.auto_preview_check_box.setChecked(settings.value('auto preview'))
|
||||||
self.timeout_spin_box.setValue(settings.value('loop delay'))
|
self.timeout_spin_box.setValue(settings.value('loop delay'))
|
||||||
self.start_paused_check_box.setChecked(settings.value('audio start paused'))
|
|
||||||
self.repeat_list_check_box.setChecked(settings.value('audio repeat list'))
|
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
@ -249,8 +233,6 @@ class GeneralTab(SettingsTab):
|
|||||||
settings.setValue('ccli number', self.number_edit.displayText())
|
settings.setValue('ccli number', self.number_edit.displayText())
|
||||||
settings.setValue('songselect username', self.username_edit.displayText())
|
settings.setValue('songselect username', self.username_edit.displayText())
|
||||||
settings.setValue('songselect password', self.password_edit.displayText())
|
settings.setValue('songselect password', self.password_edit.displayText())
|
||||||
settings.setValue('audio start paused', self.start_paused_check_box.isChecked())
|
|
||||||
settings.setValue('audio repeat list', self.repeat_list_check_box.isChecked())
|
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.post_set_up()
|
self.post_set_up()
|
||||||
|
|
||||||
|
@ -1338,7 +1338,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
|||||||
self.application.set_normal_cursor()
|
self.application.set_normal_cursor()
|
||||||
self.log_exception('Data copy failed {err}'.format(err=str(why)))
|
self.log_exception('Data copy failed {err}'.format(err=str(why)))
|
||||||
err_text = translate('OpenLP.MainWindow',
|
err_text = translate('OpenLP.MainWindow',
|
||||||
'OpenLP Data directory copy failed\n\n{err}').format(err=str(why)),
|
'OpenLP Data directory copy failed\n\n{err}').format(err=str(why))
|
||||||
QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'New Data Directory Error'),
|
QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'New Data Directory Error'),
|
||||||
err_text,
|
err_text,
|
||||||
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
||||||
@ -1356,6 +1356,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
|||||||
def open_cmd_line_files(self, args):
|
def open_cmd_line_files(self, args):
|
||||||
"""
|
"""
|
||||||
Open files passed in through command line arguments
|
Open files passed in through command line arguments
|
||||||
|
|
||||||
|
:param list[str] args: List of remaining positionall arguments
|
||||||
"""
|
"""
|
||||||
for arg in args:
|
for arg in args:
|
||||||
file_name = os.path.expanduser(arg)
|
file_name = os.path.expanduser(arg)
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
##########################################################################
|
##########################################################################
|
||||||
"""
|
"""
|
||||||
The :mod:`~openlp.core.ui.media.mediacontroller` module contains a base class for media components and other widgets
|
The :mod:`~openlp.core.ui.media.mediacontroller` module is the control module for all media playing.
|
||||||
related to playing media, such as sliders.
|
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -124,14 +123,14 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
self.setup()
|
self.setup()
|
||||||
self.vlc_player = VlcPlayer(self)
|
self.vlc_player = VlcPlayer(self)
|
||||||
State().add_service("mediacontroller", 0)
|
State().add_service('mediacontroller', 0)
|
||||||
State().add_service("media_live", 0, requires="mediacontroller")
|
State().add_service('media_live', 0)
|
||||||
if get_vlc() and pymediainfo_available:
|
if get_vlc() and pymediainfo_available:
|
||||||
State().update_pre_conditions("mediacontroller", True)
|
State().update_pre_conditions('mediacontroller', True)
|
||||||
State().update_pre_conditions('media_live', True)
|
State().update_pre_conditions('media_live', True)
|
||||||
else:
|
else:
|
||||||
State().missing_text("mediacontroller", translate('OpenLP.SlideController',
|
State().missing_text('media_live', translate('OpenLP.SlideController',
|
||||||
"VLC or pymediainfo are missing, so you are unable to play any media"))
|
'VLC or pymediainfo are missing, so you are unable to play any media'))
|
||||||
self._generate_extensions_lists()
|
self._generate_extensions_lists()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -140,11 +139,14 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
|||||||
Set up the controllers.
|
Set up the controllers.
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
try:
|
if State().check_preconditions('mediacontroller'):
|
||||||
self.setup_display(self.live_controller.display, False)
|
try:
|
||||||
except AttributeError:
|
self.setup_display(self.live_controller.display, False)
|
||||||
State().update_pre_conditions('media_live', False)
|
except AttributeError:
|
||||||
self.setup_display(self.preview_controller.preview_display, True)
|
State().update_pre_conditions('media_live', False)
|
||||||
|
State().missing_text('media_live', translate('OpenLP.SlideController',
|
||||||
|
'No Displays configure so Live Media has been disabled'))
|
||||||
|
self.setup_display(self.preview_controller.preview_display, True)
|
||||||
|
|
||||||
def display_controllers(self, controller_type):
|
def display_controllers(self, controller_type):
|
||||||
"""
|
"""
|
||||||
@ -215,9 +217,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
# Generic controls
|
# Generic controls
|
||||||
controller.mediabar.setVisible(value)
|
controller.mediabar.setVisible(value)
|
||||||
# if controller.is_live and controller.display:
|
|
||||||
# if self.current_media_players and value:
|
|
||||||
# controller.display.set_transparency(False)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def resize(display, player):
|
def resize(display, player):
|
||||||
@ -563,8 +562,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
|
|||||||
total_seconds = controller.media_info.length // 1000
|
total_seconds = controller.media_info.length // 1000
|
||||||
total_minutes = total_seconds // 60
|
total_minutes = total_seconds // 60
|
||||||
total_seconds %= 60
|
total_seconds %= 60
|
||||||
controller.position_label.setText(' %02d:%02d / %02d:%02d' %
|
controller.position_label.setText(' %02d:%02d / %02d:%02d' % (0, 0, total_minutes, total_seconds))
|
||||||
(0, 0, total_minutes, total_seconds))
|
|
||||||
controller.mediabar.actions['playbackPlay'].setVisible(True)
|
controller.mediabar.actions['playbackPlay'].setVisible(True)
|
||||||
controller.mediabar.actions['playbackStop'].setDisabled(True)
|
controller.mediabar.actions['playbackStop'].setDisabled(True)
|
||||||
controller.mediabar.actions['playbackPause'].setVisible(False)
|
controller.mediabar.actions['playbackPause'].setVisible(False)
|
||||||
|
@ -139,11 +139,12 @@ class MediaPlayer(RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def update_ui(self, display):
|
def update_ui(self, controller, output_display):
|
||||||
"""
|
"""
|
||||||
Do some ui related stuff (e.g. update the seek slider)
|
Do some ui related stuff (e.g. update the seek slider)
|
||||||
|
|
||||||
:param display: The display to be updated.
|
:param controller: Which Controller is running the show.
|
||||||
|
:param output_display: The display where the media is
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -20,11 +20,12 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
##########################################################################
|
##########################################################################
|
||||||
"""
|
"""
|
||||||
The :mod:`~openlp.core.ui.media.playertab` module holds the configuration tab for the media stuff.
|
The :mod:`~openlp.core.ui.media.mediatab` module holds the configuration tab for the media stuff.
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtWidgets
|
from PyQt5 import QtWidgets
|
||||||
# from PyQt5.QtMultimedia import QCameraInfo, QAudioDeviceInfo, QAudio
|
from PyQt5.QtMultimedia import QCameraInfo, QAudioDeviceInfo, QAudio
|
||||||
|
|
||||||
from openlp.core.common import is_linux, is_win
|
from openlp.core.common import is_linux, is_win
|
||||||
from openlp.core.common.i18n import translate
|
from openlp.core.common.i18n import translate
|
||||||
@ -32,8 +33,11 @@ from openlp.core.common.settings import Settings
|
|||||||
from openlp.core.lib.settingstab import SettingsTab
|
from openlp.core.lib.settingstab import SettingsTab
|
||||||
from openlp.core.ui.icons import UiIcons
|
from openlp.core.ui.icons import UiIcons
|
||||||
|
|
||||||
LINUX_STREAM = 'v4l2:///dev/video0'
|
LINUX_STREAM = 'v4l2://{video} :v4l2-standard= :input-slave={audio} :live-caching=300'
|
||||||
WIN_STREAM = 'dshow:// :dshow-vdev='
|
WIN_STREAM = 'dshow://:dshow-vdev={video} :dshow-adev={audio} :live-caching=300'
|
||||||
|
OSX_STREAM = 'avcapture://{video} :qtsound://{audio} :live-caching=300'
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MediaTab(SettingsTab):
|
class MediaTab(SettingsTab):
|
||||||
@ -44,8 +48,6 @@ class MediaTab(SettingsTab):
|
|||||||
"""
|
"""
|
||||||
Constructor
|
Constructor
|
||||||
"""
|
"""
|
||||||
# self.media_players = Registry().get('media_controller').media_players
|
|
||||||
# self.saved_used_players = None
|
|
||||||
self.icon_path = UiIcons().video
|
self.icon_path = UiIcons().video
|
||||||
player_translated = translate('OpenLP.MediaTab', 'Media')
|
player_translated = translate('OpenLP.MediaTab', 'Media')
|
||||||
super(MediaTab, self).__init__(parent, 'Media', player_translated)
|
super(MediaTab, self).__init__(parent, 'Media', player_translated)
|
||||||
@ -67,39 +69,52 @@ class MediaTab(SettingsTab):
|
|||||||
self.stream_media_group_box = QtWidgets.QGroupBox(self.left_column)
|
self.stream_media_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||||
self.stream_media_group_box.setObjectName('stream_media_group_box')
|
self.stream_media_group_box.setObjectName('stream_media_group_box')
|
||||||
self.stream_media_layout = QtWidgets.QHBoxLayout(self.stream_media_group_box)
|
self.stream_media_layout = QtWidgets.QHBoxLayout(self.stream_media_group_box)
|
||||||
self.stream_media_layout.setObjectName('live_media_layout')
|
self.stream_media_layout.setObjectName('stream_media_layout')
|
||||||
self.stream_media_layout.setContentsMargins(0, 0, 0, 0)
|
self.stream_media_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
self.stream_edit = QtWidgets.QPlainTextEdit(self)
|
self.stream_edit = QtWidgets.QLabel(self)
|
||||||
self.stream_media_layout.addWidget(self.stream_edit)
|
self.stream_media_layout.addWidget(self.stream_edit)
|
||||||
self.browse_button = QtWidgets.QToolButton(self)
|
|
||||||
self.browse_button.setIcon(UiIcons().undo)
|
|
||||||
self.stream_media_layout.addWidget(self.browse_button)
|
|
||||||
self.left_layout.addWidget(self.stream_media_group_box)
|
|
||||||
self.left_layout.addWidget(self.stream_media_group_box)
|
self.left_layout.addWidget(self.stream_media_group_box)
|
||||||
|
self.vlc_arguments_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||||
|
self.vlc_arguments_group_box.setObjectName('vlc_arguments_group_box')
|
||||||
|
self.vlc_arguments_layout = QtWidgets.QHBoxLayout(self.vlc_arguments_group_box)
|
||||||
|
self.vlc_arguments_layout.setObjectName('vlc_arguments_layout')
|
||||||
|
self.vlc_arguments_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.vlc_arguments_edit = QtWidgets.QPlainTextEdit(self)
|
||||||
|
self.vlc_arguments_layout.addWidget(self.vlc_arguments_edit)
|
||||||
|
self.left_layout.addWidget(self.vlc_arguments_group_box)
|
||||||
self.left_layout.addStretch()
|
self.left_layout.addStretch()
|
||||||
self.right_layout.addStretch()
|
self.right_layout.addStretch()
|
||||||
# # Signals and slots
|
# # Signals and slots
|
||||||
self.browse_button.clicked.connect(self.on_revert)
|
|
||||||
|
|
||||||
def retranslateUi(self):
|
def retranslate_ui(self):
|
||||||
"""
|
"""
|
||||||
Translate the UI on the fly
|
Translate the UI on the fly
|
||||||
"""
|
"""
|
||||||
self.live_media_group_box.setTitle(translate('MediaPlugin.MediaTab', 'Live Media'))
|
self.live_media_group_box.setTitle(translate('MediaPlugin.MediaTab', 'Live Media'))
|
||||||
self.stream_media_group_box.setTitle(translate('MediaPlugin.MediaTab', 'Stream Media Command'))
|
self.stream_media_group_box.setTitle(translate('MediaPlugin.MediaTab', 'Stream Media Command'))
|
||||||
self.auto_start_check_box.setText(translate('MediaPlugin.MediaTab', 'Start automatically'))
|
self.vlc_arguments_group_box.setTitle(translate('MediaPlugin.MediaTab', 'VLC arguments'))
|
||||||
|
self.auto_start_check_box.setText(translate('MediaPlugin.MediaTab', 'Start Live items automatically'))
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""
|
"""
|
||||||
Load the settings
|
Load the settings
|
||||||
"""
|
"""
|
||||||
self.auto_start_check_box.setChecked(Settings().value(self.settings_section + '/media auto start'))
|
self.auto_start_check_box.setChecked(Settings().value(self.settings_section + '/media auto start'))
|
||||||
self.stream_edit.setPlainText(Settings().value(self.settings_section + '/stream command'))
|
self.stream_edit.setText(Settings().value(self.settings_section + '/stream command'))
|
||||||
if not self.stream_edit.toPlainText():
|
if not self.stream_edit.text():
|
||||||
if is_linux:
|
if is_linux:
|
||||||
self.stream_edit.setPlainText(LINUX_STREAM)
|
self.stream_edit.setText(LINUX_STREAM)
|
||||||
elif is_win:
|
elif is_win:
|
||||||
self.stream_edit.setPlainText(WIN_STREAM)
|
self.stream_edit.setText(WIN_STREAM)
|
||||||
|
else:
|
||||||
|
self.stream_edit.setText(OSX_STREAM)
|
||||||
|
self.vlc_arguments_edit.setPlainText(Settings().value(self.settings_section + '/vlc arguments'))
|
||||||
|
if Settings().value('advanced/experimental'):
|
||||||
|
for cam in QCameraInfo.availableCameras():
|
||||||
|
log.debug(cam.deviceName())
|
||||||
|
log.debug(cam.description())
|
||||||
|
for au in QAudioDeviceInfo.availableDevices(QAudio.AudioInput):
|
||||||
|
log.debug(au.deviceName())
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""
|
"""
|
||||||
@ -108,17 +123,8 @@ class MediaTab(SettingsTab):
|
|||||||
setting_key = self.settings_section + '/media auto start'
|
setting_key = self.settings_section + '/media auto start'
|
||||||
if Settings().value(setting_key) != self.auto_start_check_box.checkState():
|
if Settings().value(setting_key) != self.auto_start_check_box.checkState():
|
||||||
Settings().setValue(setting_key, self.auto_start_check_box.checkState())
|
Settings().setValue(setting_key, self.auto_start_check_box.checkState())
|
||||||
# settings = Settings()
|
Settings().setValue(self.settings_section + '/stream command', self.stream_edit.text())
|
||||||
# settings.beginGroup(self.settings_section)
|
Settings().setValue(self.settings_section + '/vlc arguments', self.vlc_arguments_edit.toPlainText())
|
||||||
# settings.setValue('background color', self.background_color)
|
|
||||||
# settings.endGroup()
|
|
||||||
# old_players, override_player = get_media_players()
|
|
||||||
# if self.used_players != old_players:
|
|
||||||
# # clean old Media stuff
|
|
||||||
# set_media_players(self.used_players, override_player)
|
|
||||||
# self.settings_form.register_post_process('mediaitem_suffix_reset')
|
|
||||||
# self.settings_form.register_post_process('mediaitem_media_rebuild')
|
|
||||||
# self.settings_form.register_post_process('config_screen_changed')
|
|
||||||
|
|
||||||
def post_set_up(self, post_update=False):
|
def post_set_up(self, post_update=False):
|
||||||
"""
|
"""
|
||||||
@ -127,22 +133,6 @@ class MediaTab(SettingsTab):
|
|||||||
:param post_update: Indicates if called before or after updates.
|
:param post_update: Indicates if called before or after updates.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
# for key, player in self.media_players.items():
|
|
||||||
# player = self.media_players[key]
|
|
||||||
# checkbox = MediaQCheckBox(self.media_player_group_box)
|
|
||||||
# checkbox.setEnabled(player.available)
|
|
||||||
# checkbox.setObjectName(player.name + '_check_box')
|
|
||||||
# checkbox.setToolTip(player.get_info())
|
|
||||||
# checkbox.set_player_name(player.name)
|
|
||||||
# self.player_check_boxes[player.name] = checkbox
|
|
||||||
# checkbox.stateChanged.connect(self.on_player_check_box_changed)
|
|
||||||
# self.media_player_layout.addWidget(checkbox)
|
|
||||||
# if player.available and player.name in self.used_players:
|
|
||||||
# checkbox.setChecked(True)
|
|
||||||
# else:
|
|
||||||
# checkbox.setChecked(False)
|
|
||||||
# self.update_player_list()
|
|
||||||
# self.retranslate_players()
|
|
||||||
|
|
||||||
def on_revert(self):
|
def on_revert(self):
|
||||||
pass
|
pass
|
||||||
|
25
openlp/core/ui/media/vendor/__init__.py
vendored
25
openlp/core/ui/media/vendor/__init__.py
vendored
@ -1,25 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# OpenLP - Open Source Lyrics Projection #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# Copyright (c) 2008-2019 OpenLP Developers #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# This program is free software: you can redistribute it and/or modify #
|
|
||||||
# it under the terms of the GNU General Public License as published by #
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or #
|
|
||||||
# (at your option) any later version. #
|
|
||||||
# #
|
|
||||||
# This program is distributed in the hope that it will be useful, #
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
||||||
# GNU General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU General Public License #
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
||||||
##########################################################################
|
|
||||||
"""
|
|
||||||
The :mod:`~openlp.core.ui.media.vendor` module contains any scripts or libraries
|
|
||||||
from 3rd party vendors which are required to make certain media modules work.
|
|
||||||
"""
|
|
8775
openlp/core/ui/media/vendor/vlc.py
vendored
8775
openlp/core/ui/media/vendor/vlc.py
vendored
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from distutils.version import LooseVersion
|
import vlc
|
||||||
|
|
||||||
from PyQt5 import QtWidgets
|
from PyQt5 import QtWidgets
|
||||||
|
|
||||||
@ -65,59 +65,19 @@ def get_vlc():
|
|||||||
|
|
||||||
:return: The "vlc" module, or None
|
:return: The "vlc" module, or None
|
||||||
"""
|
"""
|
||||||
if 'openlp.core.ui.media.vendor.vlc' in sys.modules:
|
if 'vlc' in sys.modules:
|
||||||
# If VLC has already been imported, no need to do all the stuff below again
|
# If VLC has already been imported, no need to do all the stuff below again
|
||||||
is_vlc_available = False
|
is_vlc_available = False
|
||||||
try:
|
try:
|
||||||
is_vlc_available = bool(sys.modules['openlp.core.ui.media.vendor.vlc'].get_default_instance())
|
is_vlc_available = bool(sys.modules['vlc'].get_default_instance())
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
if is_vlc_available:
|
if is_vlc_available:
|
||||||
return sys.modules['openlp.core.ui.media.vendor.vlc']
|
return sys.modules['vlc']
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
is_vlc_available = False
|
|
||||||
try:
|
|
||||||
if is_macosx():
|
|
||||||
# Newer versions of VLC on OS X need this. See https://forum.videolan.org/viewtopic.php?t=124521
|
|
||||||
os.environ['VLC_PLUGIN_PATH'] = '/Applications/VLC.app/Contents/MacOS/plugins'
|
|
||||||
# On Windows when frozen in PyInstaller, we need to blank SetDllDirectoryW to allow loading of the VLC dll.
|
|
||||||
# This is due to limitations (by design) in PyInstaller. SetDllDirectoryW original value is restored once
|
|
||||||
# VLC has been imported.
|
|
||||||
if is_win():
|
|
||||||
buffer_size = 1024
|
|
||||||
dll_directory = ctypes.create_unicode_buffer(buffer_size)
|
|
||||||
new_buffer_size = ctypes.windll.kernel32.GetDllDirectoryW(buffer_size, dll_directory)
|
|
||||||
dll_directory = ''.join(dll_directory[:new_buffer_size]).replace('\0', '')
|
|
||||||
log.debug('Original DllDirectory: %s' % dll_directory)
|
|
||||||
ctypes.windll.kernel32.SetDllDirectoryW(None)
|
|
||||||
from openlp.core.ui.media.vendor import vlc
|
|
||||||
if is_win():
|
|
||||||
ctypes.windll.kernel32.SetDllDirectoryW(dll_directory)
|
|
||||||
is_vlc_available = bool(vlc.get_default_instance())
|
|
||||||
except (ImportError, NameError, NotImplementedError):
|
|
||||||
pass
|
|
||||||
except OSError as e:
|
|
||||||
# this will get raised the first time
|
|
||||||
if is_win():
|
|
||||||
if not isinstance(e, WindowsError) and e.winerror != 126:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
if is_vlc_available:
|
|
||||||
try:
|
|
||||||
VERSION = vlc.libvlc_get_version().decode('UTF-8')
|
|
||||||
except Exception:
|
|
||||||
VERSION = '0.0.0'
|
|
||||||
# LooseVersion does not work when a string contains letter and digits (e. g. 2.0.5 Twoflower).
|
|
||||||
# http://bugs.python.org/issue14894
|
|
||||||
if LooseVersion(VERSION.split()[0]) < LooseVersion('1.1.0'):
|
|
||||||
is_vlc_available = False
|
|
||||||
log.debug('VLC could not be loaded, because the vlc version is too old: %s' % VERSION)
|
|
||||||
if is_vlc_available:
|
|
||||||
return vlc
|
|
||||||
else:
|
else:
|
||||||
return None
|
return vlc
|
||||||
|
|
||||||
|
|
||||||
# On linux we need to initialise X threads, but not when running tests.
|
# On linux we need to initialise X threads, but not when running tests.
|
||||||
@ -161,35 +121,35 @@ class VlcPlayer(MediaPlayer):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
vlc = get_vlc()
|
vlc = get_vlc()
|
||||||
# Temporary workaround
|
output_display.vlc_widget = QtWidgets.QFrame(output_display)
|
||||||
if vlc:
|
output_display.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame)
|
||||||
output_display.vlc_widget = QtWidgets.QFrame(output_display)
|
# creating a basic vlc instance
|
||||||
output_display.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame)
|
command_line_options = '--no-video-title-show '
|
||||||
# creating a basic vlc instance
|
if Settings().value('advanced/hide mouse') and live_display:
|
||||||
command_line_options = '--no-video-title-show'
|
command_line_options += '--mouse-hide-timeout=0 '
|
||||||
if Settings().value('advanced/hide mouse') and live_display:
|
if Settings().value('media/vlc arguments'):
|
||||||
command_line_options += ' --mouse-hide-timeout=0'
|
command_line_options += Settings().value('media/vlc arguments')
|
||||||
output_display.vlc_instance = vlc.Instance(command_line_options)
|
output_display.vlc_instance = vlc.Instance(command_line_options)
|
||||||
# creating an empty vlc media player
|
# creating an empty vlc media player
|
||||||
output_display.vlc_media_player = output_display.vlc_instance.media_player_new()
|
output_display.vlc_media_player = output_display.vlc_instance.media_player_new()
|
||||||
output_display.vlc_widget.resize(output_display.size())
|
output_display.vlc_widget.resize(output_display.size())
|
||||||
output_display.vlc_widget.raise_()
|
output_display.vlc_widget.raise_()
|
||||||
output_display.vlc_widget.hide()
|
output_display.vlc_widget.hide()
|
||||||
# The media player has to be 'connected' to the QFrame.
|
# The media player has to be 'connected' to the QFrame.
|
||||||
# (otherwise a video would be displayed in it's own window)
|
# (otherwise a video would be displayed in it's own window)
|
||||||
# This is platform specific!
|
# This is platform specific!
|
||||||
# You have to give the id of the QFrame (or similar object)
|
# You have to give the id of the QFrame (or similar object)
|
||||||
# to vlc, different platforms have different functions for this.
|
# to vlc, different platforms have different functions for this.
|
||||||
win_id = int(output_display.vlc_widget.winId())
|
win_id = int(output_display.vlc_widget.winId())
|
||||||
if is_win():
|
if is_win():
|
||||||
output_display.vlc_media_player.set_hwnd(win_id)
|
output_display.vlc_media_player.set_hwnd(win_id)
|
||||||
elif is_macosx():
|
elif is_macosx():
|
||||||
# We have to use 'set_nsobject' since Qt5 on OSX uses Cocoa
|
# We have to use 'set_nsobject' since Qt5 on OSX uses Cocoa
|
||||||
# framework and not the old Carbon.
|
# framework and not the old Carbon.
|
||||||
output_display.vlc_media_player.set_nsobject(win_id)
|
output_display.vlc_media_player.set_nsobject(win_id)
|
||||||
else:
|
else:
|
||||||
# for Linux/*BSD using the X Server
|
# for Linux/*BSD using the X Server
|
||||||
output_display.vlc_media_player.set_xwindow(win_id)
|
output_display.vlc_media_player.set_xwindow(win_id)
|
||||||
self.has_own_widget = True
|
self.has_own_widget = True
|
||||||
|
|
||||||
def check_available(self):
|
def check_available(self):
|
||||||
@ -226,7 +186,8 @@ class VlcPlayer(MediaPlayer):
|
|||||||
return False
|
return False
|
||||||
output_display.vlc_media = audio_cd_tracks.item_at_index(controller.media_info.title_track)
|
output_display.vlc_media = audio_cd_tracks.item_at_index(controller.media_info.title_track)
|
||||||
elif controller.media_info.media_type == MediaType.Stream:
|
elif controller.media_info.media_type == MediaType.Stream:
|
||||||
output_display.vlc_media = output_display.vlc_instance.media_new_location('ZZZZZZ')
|
stream_cmd = Settings().value('media/stream command')
|
||||||
|
output_display.vlc_media = output_display.vlc_instance.media_new_location(stream_cmd)
|
||||||
else:
|
else:
|
||||||
output_display.vlc_media = output_display.vlc_instance.media_new_path(path)
|
output_display.vlc_media = output_display.vlc_instance.media_new_path(path)
|
||||||
# put the media in the media player
|
# put the media in the media player
|
||||||
@ -242,7 +203,7 @@ class VlcPlayer(MediaPlayer):
|
|||||||
Wait no longer than 60 seconds. (loading an iso file needs a long time)
|
Wait no longer than 60 seconds. (loading an iso file needs a long time)
|
||||||
|
|
||||||
:param media_state: The state of the playing media
|
:param media_state: The state of the playing media
|
||||||
:param display: The display where the media is
|
:param output_display: The display where the media is
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
vlc = get_vlc()
|
vlc = get_vlc()
|
||||||
@ -316,7 +277,7 @@ class VlcPlayer(MediaPlayer):
|
|||||||
self.volume(output_display, output_display.media_info.volume)
|
self.volume(output_display, output_display.media_info.volume)
|
||||||
if start_time > 0 and output_display.vlc_media_player.is_seekable():
|
if start_time > 0 and output_display.vlc_media_player.is_seekable():
|
||||||
output_display.vlc_media_player.set_time(int(start_time))
|
output_display.vlc_media_player.set_time(int(start_time))
|
||||||
controller.seek_slider.setMaximum(output_display.media_info.length)
|
controller.seek_slider.setMaximum(controller.media_info.length)
|
||||||
self.set_state(MediaState.Playing, output_display)
|
self.set_state(MediaState.Playing, output_display)
|
||||||
output_display.vlc_widget.raise_()
|
output_display.vlc_widget.raise_()
|
||||||
return True
|
return True
|
||||||
@ -363,9 +324,9 @@ class VlcPlayer(MediaPlayer):
|
|||||||
:param seek_value: The position of where a seek goes to
|
:param seek_value: The position of where a seek goes to
|
||||||
:param output_display: The display where the media is
|
:param output_display: The display where the media is
|
||||||
"""
|
"""
|
||||||
if output_display.controller.media_info.media_type == MediaType.CD \
|
if output_display.media_info.media_type == MediaType.CD \
|
||||||
or output_display.controller.media_info.media_type == MediaType.DVD:
|
or output_display.media_info.media_type == MediaType.DVD:
|
||||||
seek_value += int(output_display.controller.media_info.start_time)
|
seek_value += int(output_display.media_info.start_time)
|
||||||
if output_display.vlc_media_player.is_seekable():
|
if output_display.vlc_media_player.is_seekable():
|
||||||
output_display.vlc_media_player.set_time(seek_value)
|
output_display.vlc_media_player.set_time(seek_value)
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ from openlp.core.common.applocation import AppLocation
|
|||||||
from openlp.core.common.i18n import UiStrings, format_time, translate
|
from openlp.core.common.i18n import UiStrings, format_time, translate
|
||||||
from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder
|
from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder
|
||||||
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
||||||
from openlp.core.common.path import Path, str_to_path
|
from openlp.core.common.path import Path
|
||||||
from openlp.core.common.registry import Registry, RegistryBase
|
from openlp.core.common.registry import Registry, RegistryBase
|
||||||
from openlp.core.common.settings import Settings
|
from openlp.core.common.settings import Settings
|
||||||
from openlp.core.lib import build_icon
|
from openlp.core.lib import build_icon
|
||||||
@ -433,8 +433,8 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
|
|||||||
def on_load_service_clicked(self, checked):
|
def on_load_service_clicked(self, checked):
|
||||||
"""
|
"""
|
||||||
Handle the `fileOpenItem` action
|
Handle the `fileOpenItem` action
|
||||||
|
|
||||||
:param bool checked: Not used.
|
:param bool checked: Not used.
|
||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.load_service()
|
self.load_service()
|
||||||
|
@ -30,7 +30,6 @@ from openlp.core.state import State
|
|||||||
from openlp.core.api.tab import ApiTab
|
from openlp.core.api.tab import ApiTab
|
||||||
from openlp.core.common.mixins import RegistryProperties
|
from openlp.core.common.mixins import RegistryProperties
|
||||||
from openlp.core.common.registry import Registry
|
from openlp.core.common.registry import Registry
|
||||||
from openlp.core.common.settings import Settings
|
|
||||||
from openlp.core.lib import build_icon
|
from openlp.core.lib import build_icon
|
||||||
from openlp.core.projectors.tab import ProjectorTab
|
from openlp.core.projectors.tab import ProjectorTab
|
||||||
from openlp.core.ui.advancedtab import AdvancedTab
|
from openlp.core.ui.advancedtab import AdvancedTab
|
||||||
@ -61,6 +60,7 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
|
|||||||
self.setting_list_widget.currentRowChanged.connect(self.list_item_changed)
|
self.setting_list_widget.currentRowChanged.connect(self.list_item_changed)
|
||||||
self.general_tab = None
|
self.general_tab = None
|
||||||
self.themes_tab = None
|
self.themes_tab = None
|
||||||
|
self.player_tab = None
|
||||||
self.projector_tab = None
|
self.projector_tab = None
|
||||||
self.advanced_tab = None
|
self.advanced_tab = None
|
||||||
self.api_tab = None
|
self.api_tab = None
|
||||||
@ -79,8 +79,7 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
|
|||||||
self.insert_tab(self.advanced_tab)
|
self.insert_tab(self.advanced_tab)
|
||||||
self.insert_tab(self.screens_tab)
|
self.insert_tab(self.screens_tab)
|
||||||
self.insert_tab(self.themes_tab)
|
self.insert_tab(self.themes_tab)
|
||||||
if Settings().value('core/experimental'):
|
self.insert_tab(self.player_tab)
|
||||||
self.insert_tab(self.player_tab)
|
|
||||||
self.insert_tab(self.projector_tab)
|
self.insert_tab(self.projector_tab)
|
||||||
self.insert_tab(self.api_tab)
|
self.insert_tab(self.api_tab)
|
||||||
for plugin in State().list_plugins():
|
for plugin in State().list_plugins():
|
||||||
@ -161,8 +160,7 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
|
|||||||
self.themes_tab = ThemesTab(self)
|
self.themes_tab = ThemesTab(self)
|
||||||
self.projector_tab = ProjectorTab(self)
|
self.projector_tab = ProjectorTab(self)
|
||||||
self.advanced_tab = AdvancedTab(self)
|
self.advanced_tab = AdvancedTab(self)
|
||||||
if Settings().value('core/experimental'):
|
self.player_tab = MediaTab(self)
|
||||||
self.player_tab = MediaTab(self)
|
|
||||||
self.api_tab = ApiTab(self)
|
self.api_tab = ApiTab(self)
|
||||||
self.screens_tab = ScreensTab(self)
|
self.screens_tab = ScreensTab(self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -170,8 +168,7 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
|
|||||||
self.general_tab.post_set_up()
|
self.general_tab.post_set_up()
|
||||||
self.themes_tab.post_set_up()
|
self.themes_tab.post_set_up()
|
||||||
self.advanced_tab.post_set_up()
|
self.advanced_tab.post_set_up()
|
||||||
if Settings().value('core/experimental'):
|
self.player_tab.post_set_up()
|
||||||
self.player_tab.post_set_up()
|
|
||||||
self.api_tab.post_set_up()
|
self.api_tab.post_set_up()
|
||||||
for plugin in State().list_plugins():
|
for plugin in State().list_plugins():
|
||||||
if plugin.settings_tab:
|
if plugin.settings_tab:
|
||||||
|
@ -112,7 +112,7 @@ class MediaSlider(QtWidgets.QSlider):
|
|||||||
|
|
||||||
class InfoLabel(QtWidgets.QLabel):
|
class InfoLabel(QtWidgets.QLabel):
|
||||||
"""
|
"""
|
||||||
InfoLabel is a subclassed QLabel. Created to provide the ablilty to add a ellipsis if the text is cut off. Original
|
InfoLabel is a subclassed QLabel. Created to provide the ability to add a ellipsis if the text is cut off. Original
|
||||||
source: https://stackoverflow.com/questions/11446478/pyside-pyqt-truncate-text-in-qlabel-based-on-minimumsize
|
source: https://stackoverflow.com/questions/11446478/pyside-pyqt-truncate-text-in-qlabel-based-on-minimumsize
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -177,7 +177,6 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
if screen.is_display:
|
if screen.is_display:
|
||||||
display = DisplayWindow(self, screen)
|
display = DisplayWindow(self, screen)
|
||||||
self.displays.append(display)
|
self.displays.append(display)
|
||||||
# display.media_watcher.progress.connect(self.on_audio_time_remaining)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def display(self):
|
def display(self):
|
||||||
@ -381,7 +380,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
self.position_label.setMinimumSize(90, 0)
|
self.position_label.setMinimumSize(90, 0)
|
||||||
self.position_label.setObjectName('position_label')
|
self.position_label.setObjectName('position_label')
|
||||||
self.mediabar.add_toolbar_widget(self.position_label)
|
self.mediabar.add_toolbar_widget(self.position_label)
|
||||||
# Build the seek_slider.
|
# Build the media seek_slider.
|
||||||
self.seek_slider = MediaSlider(QtCore.Qt.Horizontal, self, self)
|
self.seek_slider = MediaSlider(QtCore.Qt.Horizontal, self, self)
|
||||||
self.seek_slider.setMaximum(1000)
|
self.seek_slider.setMaximum(1000)
|
||||||
self.seek_slider.setTracking(True)
|
self.seek_slider.setTracking(True)
|
||||||
@ -398,7 +397,6 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
|||||||
self.volume_slider.setMaximum(100)
|
self.volume_slider.setMaximum(100)
|
||||||
self.volume_slider.setTracking(True)
|
self.volume_slider.setTracking(True)
|
||||||
self.volume_slider.setToolTip(translate('OpenLP.SlideController', 'Audio Volume.'))
|
self.volume_slider.setToolTip(translate('OpenLP.SlideController', 'Audio Volume.'))
|
||||||
# self.volume_slider.setValue(self.media_info.volume)
|
|
||||||
self.volume_slider.setGeometry(QtCore.QRect(90, 160, 221, 24))
|
self.volume_slider.setGeometry(QtCore.QRect(90, 160, 221, 24))
|
||||||
self.volume_slider.setObjectName('volume_slider')
|
self.volume_slider.setObjectName('volume_slider')
|
||||||
self.mediabar.add_toolbar_widget(self.volume_slider)
|
self.mediabar.add_toolbar_widget(self.volume_slider)
|
||||||
|
@ -26,19 +26,18 @@ import os
|
|||||||
import zipfile
|
import zipfile
|
||||||
from xml.etree.ElementTree import XML, ElementTree
|
from xml.etree.ElementTree import XML, ElementTree
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtWidgets
|
||||||
|
|
||||||
from openlp.core.common import delete_file
|
from openlp.core.common import delete_file
|
||||||
from openlp.core.common.applocation import AppLocation
|
from openlp.core.common.applocation import AppLocation
|
||||||
from openlp.core.common.i18n import UiStrings, get_locale_key, translate
|
from openlp.core.common.i18n import UiStrings, get_locale_key, translate
|
||||||
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
||||||
from openlp.core.common.path import Path, copyfile, create_paths, path_to_str
|
from openlp.core.common.path import Path, copyfile, create_paths
|
||||||
from openlp.core.common.registry import Registry, RegistryBase
|
from openlp.core.common.registry import Registry, RegistryBase
|
||||||
from openlp.core.common.settings import Settings
|
from openlp.core.common.settings import Settings
|
||||||
from openlp.core.lib import ImageSource, build_icon, check_item_selected, create_thumb, get_text_file_string, \
|
from openlp.core.lib import build_icon, check_item_selected, create_thumb, get_text_file_string, validate_thumb
|
||||||
validate_thumb
|
|
||||||
from openlp.core.lib.exceptions import ValidationError
|
from openlp.core.lib.exceptions import ValidationError
|
||||||
from openlp.core.lib.theme import BackgroundType, Theme
|
from openlp.core.lib.theme import Theme
|
||||||
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
|
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
|
||||||
from openlp.core.ui.filerenameform import FileRenameForm
|
from openlp.core.ui.filerenameform import FileRenameForm
|
||||||
from openlp.core.ui.icons import UiIcons
|
from openlp.core.ui.icons import UiIcons
|
||||||
@ -648,11 +647,6 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
|||||||
:rtype: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self._write_theme(theme, image_source_path, image_destination_path)
|
self._write_theme(theme, image_source_path, image_destination_path)
|
||||||
if theme.background_type == BackgroundType.to_string(BackgroundType.Image):
|
|
||||||
self.image_manager.update_image_border(path_to_str(theme.background_filename),
|
|
||||||
ImageSource.Theme,
|
|
||||||
QtGui.QColor(theme.background_border_color))
|
|
||||||
self.image_manager.process_updates()
|
|
||||||
|
|
||||||
def _write_theme(self, theme, image_source_path=None, image_destination_path=None):
|
def _write_theme(self, theme, image_source_path=None, image_destination_path=None):
|
||||||
"""
|
"""
|
||||||
|
@ -35,7 +35,7 @@ class FileDialog(QtWidgets.QFileDialog):
|
|||||||
:type caption: str
|
:type caption: str
|
||||||
:type directory: openlp.core.common.path.Path
|
:type directory: openlp.core.common.path.Path
|
||||||
:type options: QtWidgets.QFileDialog.Options
|
:type options: QtWidgets.QFileDialog.Options
|
||||||
:rtype: tuple[openlp.core.common.path.Path, str]
|
:rtype: openlp.core.common.path.Path
|
||||||
"""
|
"""
|
||||||
args, kwargs = replace_params(args, kwargs, ((2, 'directory', path_to_str),))
|
args, kwargs = replace_params(args, kwargs, ((2, 'directory', path_to_str),))
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class AspectRatioLayout(QtWidgets.QLayout):
|
|||||||
"""
|
"""
|
||||||
Create a layout.
|
Create a layout.
|
||||||
|
|
||||||
:param PyQt5.QtWidgets.QWidget parent: The parent widget, can be None.
|
:param QtWidgets.QWidget | None parent: The parent widget
|
||||||
:param float aspect_ratio: The aspect ratio as a float (e.g. 16.0/9.0)
|
:param float aspect_ratio: The aspect ratio as a float (e.g. 16.0/9.0)
|
||||||
"""
|
"""
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
@ -39,7 +39,7 @@ def handle_mime_data_urls(mime_data):
|
|||||||
"""
|
"""
|
||||||
Process the data from a drag and drop operation.
|
Process the data from a drag and drop operation.
|
||||||
|
|
||||||
:param PyQt5.QtCore.QMimeData mime_data: The mime data from the drag and drop opperation.
|
:param QtCore.QMimeData mime_data: The mime data from the drag and drop opperation.
|
||||||
:return: A list of file paths that were dropped
|
:return: A list of file paths that were dropped
|
||||||
:rtype: list[openlp.core.common.path.Path]
|
:rtype: list[openlp.core.common.path.Path]
|
||||||
"""
|
"""
|
||||||
@ -297,7 +297,7 @@ class ListWidgetWithDnD(QtWidgets.QListWidget):
|
|||||||
"""
|
"""
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
|
self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
|
||||||
Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().load_file)
|
Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().handle_mime_data)
|
||||||
|
|
||||||
def clear(self, search_while_typing=False):
|
def clear(self, search_while_typing=False):
|
||||||
"""
|
"""
|
||||||
@ -412,7 +412,7 @@ class TreeWidgetWithDnD(QtWidgets.QTreeWidget):
|
|||||||
"""
|
"""
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
|
self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
|
||||||
Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().load_file)
|
Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().handle_mime_data)
|
||||||
Registry().register_function(('%s_dnd_internal' % self.mime_data_text), self.parent().dnd_move_internal)
|
Registry().register_function(('%s_dnd_internal' % self.mime_data_text), self.parent().dnd_move_internal)
|
||||||
|
|
||||||
def mouseMoveEvent(self, event):
|
def mouseMoveEvent(self, event):
|
||||||
|
@ -102,7 +102,7 @@ class CSVBible(BibleImport):
|
|||||||
:rtype: list[namedtuple]
|
:rtype: list[namedtuple]
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
encoding = get_file_encoding(file_path)['encoding']
|
encoding = get_file_encoding(file_path)
|
||||||
with file_path.open('r', encoding=encoding, newline='') as csv_file:
|
with file_path.open('r', encoding=encoding, newline='') as csv_file:
|
||||||
csv_reader = csv.reader(csv_file, delimiter=',', quotechar='"')
|
csv_reader = csv.reader(csv_file, delimiter=',', quotechar='"')
|
||||||
return [results_tuple(*line) for line in csv_reader]
|
return [results_tuple(*line) for line in csv_reader]
|
||||||
|
@ -401,10 +401,9 @@ class ImageMediaItem(MediaManagerItem):
|
|||||||
Process a list for files either from the File Dialog or from Drag and Drop.
|
Process a list for files either from the File Dialog or from Drag and Drop.
|
||||||
This method is overloaded from MediaManagerItem.
|
This method is overloaded from MediaManagerItem.
|
||||||
|
|
||||||
:param files: A List of strings containing the filenames of the files to be loaded
|
:param list[openlp.core.common.path.Path] file_paths: A List of paths to be loaded
|
||||||
:param target_group: The QTreeWidgetItem of the group that will be the parent of the added files
|
:param target_group: The QTreeWidgetItem of the group that will be the parent of the added files
|
||||||
"""
|
"""
|
||||||
file_paths = [Path(file) for file in file_paths]
|
|
||||||
self.application.set_normal_cursor()
|
self.application.set_normal_cursor()
|
||||||
self.load_list(file_paths, target_group)
|
self.load_list(file_paths, target_group)
|
||||||
last_dir = file_paths[0].parent
|
last_dir = file_paths[0].parent
|
||||||
|
@ -93,16 +93,6 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
|||||||
to another language.
|
to another language.
|
||||||
"""
|
"""
|
||||||
self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
|
self.on_new_prompt = translate('MediaPlugin.MediaItem', 'Select Media')
|
||||||
# self.replace_action.setText(UiStrings().ReplaceBG)
|
|
||||||
# self.replace_action_context.setText(UiStrings().ReplaceBG)
|
|
||||||
# self.replace_action.setToolTip(UiStrings().ReplaceLiveBGDisabled)
|
|
||||||
# self.replace_action_context.setToolTip(UiStrings().ReplaceLiveBGDisabled)
|
|
||||||
# self.reset_action.setText(UiStrings().ResetBG)
|
|
||||||
# self.reset_action.setToolTip(UiStrings().ResetLiveBG)
|
|
||||||
# self.reset_action_context.setText(UiStrings().ResetBG)
|
|
||||||
# self.reset_action_context.setToolTip(UiStrings().ResetLiveBG)
|
|
||||||
# self.automatic = UiStrings().Automatic
|
|
||||||
# self.display_type_label.setText(translate('MediaPlugin.MediaItem', 'Use Player:'))
|
|
||||||
|
|
||||||
def required_icons(self):
|
def required_icons(self):
|
||||||
"""
|
"""
|
||||||
@ -117,7 +107,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
|||||||
self.can_make_live = False
|
self.can_make_live = False
|
||||||
self.can_add_to_service = False
|
self.can_add_to_service = False
|
||||||
if State().check_preconditions('media_live'):
|
if State().check_preconditions('media_live'):
|
||||||
self.can_make_live = False
|
self.can_make_live = True
|
||||||
|
|
||||||
def add_list_view_to_toolbar(self):
|
def add_list_view_to_toolbar(self):
|
||||||
"""
|
"""
|
||||||
|
@ -24,7 +24,7 @@ import logging
|
|||||||
from PyQt5 import QtCore, QtWidgets
|
from PyQt5 import QtCore, QtWidgets
|
||||||
|
|
||||||
from openlp.core.common.i18n import UiStrings, get_natural_key, translate
|
from openlp.core.common.i18n import UiStrings, get_natural_key, translate
|
||||||
from openlp.core.common.path import path_to_str, str_to_path
|
from openlp.core.common.path import path_to_str
|
||||||
from openlp.core.common.registry import Registry
|
from openlp.core.common.registry import Registry
|
||||||
from openlp.core.common.settings import Settings
|
from openlp.core.common.settings import Settings
|
||||||
from openlp.core.lib import ServiceItemContext, build_icon, check_item_selected, create_thumb, validate_thumb
|
from openlp.core.lib import ServiceItemContext, build_icon, check_item_selected, create_thumb, validate_thumb
|
||||||
@ -127,7 +127,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
"""
|
"""
|
||||||
self.list_view.setIconSize(QtCore.QSize(88, 50))
|
self.list_view.setIconSize(QtCore.QSize(88, 50))
|
||||||
file_paths = Settings().value(self.settings_section + '/presentations files')
|
file_paths = Settings().value(self.settings_section + '/presentations files')
|
||||||
self.load_list([path_to_str(path) for path in file_paths], initial_load=True)
|
self.load_list(file_paths, initial_load=True)
|
||||||
self.populate_display_types()
|
self.populate_display_types()
|
||||||
|
|
||||||
def populate_display_types(self):
|
def populate_display_types(self):
|
||||||
@ -158,7 +158,6 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
|
|
||||||
:param list[openlp.core.common.path.Path] file_paths: List of file paths to add to the media manager.
|
:param list[openlp.core.common.path.Path] file_paths: List of file paths to add to the media manager.
|
||||||
"""
|
"""
|
||||||
file_paths = [str_to_path(filename) for filename in file_paths]
|
|
||||||
current_paths = self.get_file_list()
|
current_paths = self.get_file_list()
|
||||||
titles = [file_path.name for file_path in current_paths]
|
titles = [file_path.name for file_path in current_paths]
|
||||||
self.application.set_busy_cursor()
|
self.application.set_busy_cursor()
|
||||||
@ -175,7 +174,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
if not file_path.exists():
|
if not file_path.exists():
|
||||||
item_name = QtWidgets.QListWidgetItem(file_name)
|
item_name = QtWidgets.QListWidgetItem(file_name)
|
||||||
item_name.setIcon(UiIcons().delete)
|
item_name.setIcon(UiIcons().delete)
|
||||||
item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path))
|
item_name.setData(QtCore.Qt.UserRole, file_path)
|
||||||
item_name.setToolTip(str(file_path))
|
item_name.setToolTip(str(file_path))
|
||||||
self.list_view.addItem(item_name)
|
self.list_view.addItem(item_name)
|
||||||
else:
|
else:
|
||||||
@ -211,7 +210,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
'This type of presentation is not supported.'))
|
'This type of presentation is not supported.'))
|
||||||
continue
|
continue
|
||||||
item_name = QtWidgets.QListWidgetItem(file_name)
|
item_name = QtWidgets.QListWidgetItem(file_name)
|
||||||
item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path))
|
item_name.setData(QtCore.Qt.UserRole, file_path)
|
||||||
item_name.setIcon(icon)
|
item_name.setIcon(icon)
|
||||||
item_name.setToolTip(str(file_path))
|
item_name.setToolTip(str(file_path))
|
||||||
self.list_view.addItem(item_name)
|
self.list_view.addItem(item_name)
|
||||||
@ -230,8 +229,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
self.application.set_busy_cursor()
|
self.application.set_busy_cursor()
|
||||||
self.main_window.display_progress_bar(len(row_list))
|
self.main_window.display_progress_bar(len(row_list))
|
||||||
for item in items:
|
for item in items:
|
||||||
file_path = str_to_path(item.data(QtCore.Qt.UserRole))
|
self.clean_up_thumbnails(item.data(QtCore.Qt.UserRole))
|
||||||
self.clean_up_thumbnails(file_path)
|
|
||||||
self.main_window.increment_progress_bar()
|
self.main_window.increment_progress_bar()
|
||||||
self.main_window.finished_progress_bar()
|
self.main_window.finished_progress_bar()
|
||||||
for row in row_list:
|
for row in row_list:
|
||||||
@ -278,7 +276,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
if len(items) > 1:
|
if len(items) > 1:
|
||||||
return False
|
return False
|
||||||
if file_path is None:
|
if file_path is None:
|
||||||
file_path = str_to_path(items[0].data(QtCore.Qt.UserRole))
|
file_path = items[0].data(QtCore.Qt.UserRole)
|
||||||
file_type = file_path.suffix.lower()[1:]
|
file_type = file_path.suffix.lower()[1:]
|
||||||
if not self.display_type_combo_box.currentText():
|
if not self.display_type_combo_box.currentText():
|
||||||
return False
|
return False
|
||||||
@ -293,7 +291,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
service_item.theme = -1
|
service_item.theme = -1
|
||||||
for bitem in items:
|
for bitem in items:
|
||||||
if file_path is None:
|
if file_path is None:
|
||||||
file_path = str_to_path(bitem.data(QtCore.Qt.UserRole))
|
file_path = bitem.data(QtCore.Qt.UserRole)
|
||||||
path, file_name = file_path.parent, file_path.name
|
path, file_name = file_path.parent, file_path.name
|
||||||
service_item.title = file_name
|
service_item.title = file_name
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
@ -329,7 +327,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
service_item.processor = self.display_type_combo_box.currentText()
|
service_item.processor = self.display_type_combo_box.currentText()
|
||||||
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
|
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
|
||||||
for bitem in items:
|
for bitem in items:
|
||||||
file_path = str_to_path(bitem.data(QtCore.Qt.UserRole))
|
file_path = bitem.data(QtCore.Qt.UserRole)
|
||||||
path, file_name = file_path.parent, file_path.name
|
path, file_name = file_path.parent, file_path.name
|
||||||
service_item.title = file_name
|
service_item.title = file_name
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
|
@ -48,7 +48,7 @@ class PresentationManagerImport(SongImport):
|
|||||||
tree = etree.parse(str(file_path), parser=etree.XMLParser(recover=True))
|
tree = etree.parse(str(file_path), parser=etree.XMLParser(recover=True))
|
||||||
except etree.XMLSyntaxError:
|
except etree.XMLSyntaxError:
|
||||||
# Try to detect encoding and use it
|
# Try to detect encoding and use it
|
||||||
encoding = get_file_encoding(file_path)['encoding']
|
encoding = get_file_encoding(file_path)
|
||||||
# Open file with detected encoding and remove encoding declaration
|
# Open file with detected encoding and remove encoding declaration
|
||||||
text = file_path.read_text(encoding=encoding)
|
text = file_path.read_text(encoding=encoding)
|
||||||
text = re.sub(r'.+\?>\n', '', text)
|
text = re.sub(r'.+\?>\n', '', text)
|
||||||
|
@ -124,7 +124,7 @@ class SongBeamerImport(SongImport):
|
|||||||
self.chord_table = None
|
self.chord_table = None
|
||||||
if file_path.is_file():
|
if file_path.is_file():
|
||||||
# Detect the encoding
|
# Detect the encoding
|
||||||
self.input_file_encoding = get_file_encoding(file_path)['encoding']
|
self.input_file_encoding = get_file_encoding(file_path)
|
||||||
# The encoding should only be ANSI (cp1252), UTF-8, Unicode, Big-Endian-Unicode.
|
# The encoding should only be ANSI (cp1252), UTF-8, Unicode, Big-Endian-Unicode.
|
||||||
# So if it doesn't start with 'u' we default to cp1252. See:
|
# So if it doesn't start with 'u' we default to cp1252. See:
|
||||||
# https://forum.songbeamer.com/viewtopic.php?p=419&sid=ca4814924e37c11e4438b7272a98b6f2
|
# https://forum.songbeamer.com/viewtopic.php?p=419&sid=ca4814924e37c11e4438b7272a98b6f2
|
||||||
|
@ -82,7 +82,7 @@ class WorshipAssistantImport(SongImport):
|
|||||||
Receive a CSV file to import.
|
Receive a CSV file to import.
|
||||||
"""
|
"""
|
||||||
# Get encoding
|
# Get encoding
|
||||||
encoding = get_file_encoding(self.import_source)['encoding']
|
encoding = get_file_encoding(self.import_source)
|
||||||
with self.import_source.open('r', encoding=encoding) as songs_file:
|
with self.import_source.open('r', encoding=encoding) as songs_file:
|
||||||
songs_reader = csv.DictReader(songs_file, escapechar='\\')
|
songs_reader = csv.DictReader(songs_file, escapechar='\\')
|
||||||
try:
|
try:
|
||||||
|
@ -89,7 +89,8 @@ MODULES = [
|
|||||||
'webob',
|
'webob',
|
||||||
'requests',
|
'requests',
|
||||||
'qtawesome',
|
'qtawesome',
|
||||||
'pymediainfo'
|
'pymediainfo',
|
||||||
|
'vlc'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class TestCommonFunctions(TestCase):
|
|||||||
extension_loader('glob')
|
extension_loader('glob')
|
||||||
|
|
||||||
# THEN: The `ImportError` should be caught and logged
|
# THEN: The `ImportError` should be caught and logged
|
||||||
assert mocked_logger.warning.called
|
assert mocked_logger.exception.called
|
||||||
|
|
||||||
def test_extension_loader_os_error(self):
|
def test_extension_loader_os_error(self):
|
||||||
"""
|
"""
|
||||||
@ -106,7 +106,7 @@ class TestCommonFunctions(TestCase):
|
|||||||
extension_loader('glob')
|
extension_loader('glob')
|
||||||
|
|
||||||
# THEN: The `OSError` should be caught and logged
|
# THEN: The `OSError` should be caught and logged
|
||||||
assert mocked_logger.warning.called
|
assert mocked_logger.exception.called
|
||||||
|
|
||||||
def test_de_hump_conversion(self):
|
def test_de_hump_conversion(self):
|
||||||
"""
|
"""
|
||||||
|
@ -322,7 +322,7 @@ class TestInit(TestCase, TestMixin):
|
|||||||
mocked_open.assert_called_once_with('rb')
|
mocked_open.assert_called_once_with('rb')
|
||||||
assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256)]
|
assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256)]
|
||||||
mocked_universal_detector_inst.close.assert_called_once_with()
|
mocked_universal_detector_inst.close.assert_called_once_with()
|
||||||
assert result == encoding_result
|
assert result == 'UTF-8'
|
||||||
|
|
||||||
def test_get_file_encoding_eof(self):
|
def test_get_file_encoding_eof(self):
|
||||||
"""
|
"""
|
||||||
@ -344,7 +344,7 @@ class TestInit(TestCase, TestMixin):
|
|||||||
mocked_open.assert_called_once_with('rb')
|
mocked_open.assert_called_once_with('rb')
|
||||||
assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256), call(b'data' * 4)]
|
assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256), call(b'data' * 4)]
|
||||||
mocked_universal_detector_inst.close.assert_called_once_with()
|
mocked_universal_detector_inst.close.assert_called_once_with()
|
||||||
assert result == encoding_result
|
assert result == 'UTF-8'
|
||||||
|
|
||||||
def test_get_file_encoding_oserror(self):
|
def test_get_file_encoding_oserror(self):
|
||||||
"""
|
"""
|
||||||
@ -367,4 +367,4 @@ class TestInit(TestCase, TestMixin):
|
|||||||
mocked_log.exception.assert_called_once_with('Error detecting file encoding')
|
mocked_log.exception.assert_called_once_with('Error detecting file encoding')
|
||||||
mocked_universal_detector_inst.feed.assert_not_called()
|
mocked_universal_detector_inst.feed.assert_not_called()
|
||||||
mocked_universal_detector_inst.close.assert_called_once_with()
|
mocked_universal_detector_inst.close.assert_called_once_with()
|
||||||
assert result == encoding_result
|
assert result == 'UTF-8'
|
||||||
|
@ -138,7 +138,7 @@ def test_parse_options_file():
|
|||||||
assert args.loglevel == 'warning', 'The log level should be set to warning'
|
assert args.loglevel == 'warning', 'The log level should be set to warning'
|
||||||
assert args.no_error_form is False, 'The no_error_form should be set to False'
|
assert args.no_error_form is False, 'The no_error_form should be set to False'
|
||||||
assert args.portable is False, 'The portable flag should be set to false'
|
assert args.portable is False, 'The portable flag should be set to false'
|
||||||
assert args.rargs == 'dummy_temp', 'The service file should not be blank'
|
assert args.rargs == ['dummy_temp'], 'The service file should not be blank'
|
||||||
|
|
||||||
|
|
||||||
def test_parse_options_file_and_debug():
|
def test_parse_options_file_and_debug():
|
||||||
@ -155,7 +155,7 @@ def test_parse_options_file_and_debug():
|
|||||||
assert args.loglevel == ' debug', 'The log level should be set to debug'
|
assert args.loglevel == ' debug', 'The log level should be set to debug'
|
||||||
assert args.no_error_form is False, 'The no_error_form should be set to False'
|
assert args.no_error_form is False, 'The no_error_form should be set to False'
|
||||||
assert args.portable is False, 'The portable flag should be set to false'
|
assert args.portable is False, 'The portable flag should be set to false'
|
||||||
assert args.rargs == 'dummy_temp', 'The service file should not be blank'
|
assert args.rargs == ['dummy_temp'], 'The service file should not be blank'
|
||||||
|
|
||||||
|
|
||||||
@skip('Figure out why this is causing a segfault')
|
@skip('Figure out why this is causing a segfault')
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
from openlp.core.common.path import Path
|
||||||
from openlp.core.common.registry import Registry
|
from openlp.core.common.registry import Registry
|
||||||
from openlp.core.server import Server
|
from openlp.core.server import Server
|
||||||
from tests.helpers.testmixin import TestMixin
|
from tests.helpers.testmixin import TestMixin
|
||||||
@ -83,8 +84,8 @@ class TestServer(TestCase, TestMixin):
|
|||||||
self.server._on_ready_read()
|
self.server._on_ready_read()
|
||||||
|
|
||||||
# THEN: the service will be loaded
|
# THEN: the service will be loaded
|
||||||
assert service_manager.on_load_service_clicked.call_count == 1
|
assert service_manager.load_service.call_count == 1
|
||||||
service_manager.on_load_service_clicked.assert_called_once_with(file_name)
|
service_manager.load_service.assert_called_once_with(Path(file_name))
|
||||||
|
|
||||||
@patch("PyQt5.QtCore.QTextStream")
|
@patch("PyQt5.QtCore.QTextStream")
|
||||||
def test_post_to_server(self, mocked_stream):
|
def test_post_to_server(self, mocked_stream):
|
||||||
|
@ -65,21 +65,6 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
# THEN: The extra environment variable should be there
|
# THEN: The extra environment variable should be there
|
||||||
assert 'openlp.core.ui.media.vendor.vlc' not in sys.modules
|
assert 'openlp.core.ui.media.vendor.vlc' not in sys.modules
|
||||||
|
|
||||||
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
|
|
||||||
def test_fix_vlc_22_plugin_path(self, mocked_is_macosx):
|
|
||||||
"""
|
|
||||||
Test that on OS X we set the VLC plugin path to fix a bug in the VLC module
|
|
||||||
"""
|
|
||||||
# GIVEN: We're on OS X and we don't have the VLC plugin path set
|
|
||||||
mocked_is_macosx.return_value = True
|
|
||||||
|
|
||||||
# WHEN: An checking if the player is available
|
|
||||||
get_vlc()
|
|
||||||
|
|
||||||
# THEN: The extra environment variable should be there
|
|
||||||
assert 'VLC_PLUGIN_PATH' in os.environ, 'The plugin path should be in the environment variables'
|
|
||||||
assert '/Applications/VLC.app/Contents/MacOS/plugins' == os.environ['VLC_PLUGIN_PATH']
|
|
||||||
|
|
||||||
@patch.dict(os.environ)
|
@patch.dict(os.environ)
|
||||||
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
|
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
|
||||||
def test_not_osx_fix_vlc_22_plugin_path(self, mocked_is_macosx):
|
def test_not_osx_fix_vlc_22_plugin_path(self, mocked_is_macosx):
|
||||||
@ -126,7 +111,7 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
mocked_is_macosx.return_value = False
|
mocked_is_macosx.return_value = False
|
||||||
mocked_is_win.return_value = False
|
mocked_is_win.return_value = False
|
||||||
mocked_settings = MagicMock()
|
mocked_settings = MagicMock()
|
||||||
mocked_settings.value.return_value = True
|
mocked_settings.value.return_value = ''
|
||||||
MockedSettings.return_value = mocked_settings
|
MockedSettings.return_value = mocked_settings
|
||||||
mocked_qframe = MagicMock()
|
mocked_qframe = MagicMock()
|
||||||
mocked_qframe.winId.return_value = 2
|
mocked_qframe.winId.return_value = 2
|
||||||
@ -150,8 +135,9 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
# THEN: The VLC widget should be set up correctly
|
# THEN: The VLC widget should be set up correctly
|
||||||
assert mocked_output_display.vlc_widget == mocked_qframe
|
assert mocked_output_display.vlc_widget == mocked_qframe
|
||||||
mocked_qframe.setFrameStyle.assert_called_with(1)
|
mocked_qframe.setFrameStyle.assert_called_with(1)
|
||||||
mocked_settings.value.assert_called_with('advanced/hide mouse')
|
mocked_settings.value.assert_any_call('advanced/hide mouse')
|
||||||
mocked_vlc.Instance.assert_called_with('--no-video-title-show --mouse-hide-timeout=0')
|
mocked_settings.value.assert_any_call('media/vlc arguments')
|
||||||
|
mocked_vlc.Instance.assert_called_with('--no-video-title-show ')
|
||||||
assert mocked_output_display.vlc_instance == mocked_instance
|
assert mocked_output_display.vlc_instance == mocked_instance
|
||||||
mocked_instance.media_player_new.assert_called_with()
|
mocked_instance.media_player_new.assert_called_with()
|
||||||
assert mocked_output_display.vlc_media_player == mocked_media_player_new
|
assert mocked_output_display.vlc_media_player == mocked_media_player_new
|
||||||
@ -175,7 +161,7 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
mocked_is_macosx.return_value = False
|
mocked_is_macosx.return_value = False
|
||||||
mocked_is_win.return_value = False
|
mocked_is_win.return_value = False
|
||||||
mocked_settings = MagicMock()
|
mocked_settings = MagicMock()
|
||||||
mocked_settings.value.return_value = True
|
mocked_settings.value.return_value = ''
|
||||||
MockedSettings.return_value = mocked_settings
|
MockedSettings.return_value = mocked_settings
|
||||||
mocked_qframe = MagicMock()
|
mocked_qframe = MagicMock()
|
||||||
mocked_qframe.winId.return_value = 2
|
mocked_qframe.winId.return_value = 2
|
||||||
@ -197,7 +183,7 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
vlc_player.setup(mocked_output_display, mocked_controller)
|
vlc_player.setup(mocked_output_display, mocked_controller)
|
||||||
|
|
||||||
# THEN: The VLC instance should be created with the correct options
|
# THEN: The VLC instance should be created with the correct options
|
||||||
mocked_vlc.Instance.assert_called_with('--no-video-title-show --mouse-hide-timeout=0')
|
mocked_vlc.Instance.assert_called_with('--no-video-title-show ')
|
||||||
|
|
||||||
@patch('openlp.core.ui.media.vlcplayer.is_win')
|
@patch('openlp.core.ui.media.vlcplayer.is_win')
|
||||||
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
|
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
|
||||||
@ -213,7 +199,7 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
mocked_is_macosx.return_value = False
|
mocked_is_macosx.return_value = False
|
||||||
mocked_is_win.return_value = False
|
mocked_is_win.return_value = False
|
||||||
mocked_settings = MagicMock()
|
mocked_settings = MagicMock()
|
||||||
mocked_settings.value.return_value = False
|
mocked_settings.value.return_value = ''
|
||||||
MockedSettings.return_value = mocked_settings
|
MockedSettings.return_value = mocked_settings
|
||||||
mocked_qframe = MagicMock()
|
mocked_qframe = MagicMock()
|
||||||
mocked_qframe.winId.return_value = 2
|
mocked_qframe.winId.return_value = 2
|
||||||
@ -235,7 +221,7 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
vlc_player.setup(mocked_output_display, mocked_controller)
|
vlc_player.setup(mocked_output_display, mocked_controller)
|
||||||
|
|
||||||
# THEN: The VLC instance should be created with the correct options
|
# THEN: The VLC instance should be created with the correct options
|
||||||
mocked_vlc.Instance.assert_called_with('--no-video-title-show')
|
mocked_vlc.Instance.assert_called_with('--no-video-title-show ')
|
||||||
|
|
||||||
@patch('openlp.core.ui.media.vlcplayer.is_win')
|
@patch('openlp.core.ui.media.vlcplayer.is_win')
|
||||||
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
|
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
|
||||||
@ -863,7 +849,7 @@ class TestVLCPlayer(TestCase, TestMixin):
|
|||||||
|
|
||||||
# THEN: nothing should happen
|
# THEN: nothing should happen
|
||||||
mocked_display.vlc_media_player.is_seekable.assert_called_with()
|
mocked_display.vlc_media_player.is_seekable.assert_called_with()
|
||||||
mocked_display.vlc_media_player.set_time.assert_called_with(5000)
|
mocked_display.vlc_media_player.set_time.assert_called_with(2000)
|
||||||
|
|
||||||
def test_reset(self):
|
def test_reset(self):
|
||||||
"""
|
"""
|
||||||
|
@ -96,7 +96,7 @@ class TestMainWindow(TestCase, TestMixin):
|
|||||||
|
|
||||||
# WHEN the argument is processed
|
# WHEN the argument is processed
|
||||||
with patch.object(self.main_window.service_manager, 'load_file') as mocked_load_file:
|
with patch.object(self.main_window.service_manager, 'load_file') as mocked_load_file:
|
||||||
self.main_window.open_cmd_line_files(service)
|
self.main_window.open_cmd_line_files([service])
|
||||||
|
|
||||||
# THEN the service from the arguments is loaded
|
# THEN the service from the arguments is loaded
|
||||||
mocked_load_file.assert_called_with(Path(service))
|
mocked_load_file.assert_called_with(Path(service))
|
||||||
|
@ -143,7 +143,7 @@ class TestThemeManager(TestCase):
|
|||||||
mocked_theme.export_theme.return_value = "{}"
|
mocked_theme.export_theme.return_value = "{}"
|
||||||
|
|
||||||
# WHEN: Calling _write_theme with a theme with a name with special characters in it
|
# WHEN: Calling _write_theme with a theme with a name with special characters in it
|
||||||
theme_manager._write_theme(mocked_theme, None, None)
|
theme_manager._write_theme(mocked_theme)
|
||||||
|
|
||||||
# THEN: It should have been created
|
# THEN: It should have been created
|
||||||
assert os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.json')) is True, \
|
assert os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.json')) is True, \
|
||||||
@ -224,7 +224,7 @@ class TestThemeManager(TestCase):
|
|||||||
theme_manager = ThemeManager(None)
|
theme_manager = ThemeManager(None)
|
||||||
|
|
||||||
# WHEN: unzip_theme is called
|
# WHEN: unzip_theme is called
|
||||||
theme_manager.unzip_theme('theme.file', 'folder')
|
theme_manager.unzip_theme(Path('theme.file'), Path('folder'))
|
||||||
|
|
||||||
# THEN: The critical_error_message_box should have been called
|
# THEN: The critical_error_message_box should have been called
|
||||||
assert mocked_critical_error_message_box.call_count == 1, 'Should have been called once'
|
assert mocked_critical_error_message_box.call_count == 1, 'Should have been called once'
|
||||||
|
@ -136,8 +136,7 @@ class TestCSVImport(TestCase):
|
|||||||
mocked_enter_file = MagicMock()
|
mocked_enter_file = MagicMock()
|
||||||
mocked_csv_file.open.return_value.__enter__.return_value = mocked_enter_file
|
mocked_csv_file.open.return_value.__enter__.return_value = mocked_enter_file
|
||||||
|
|
||||||
with patch('openlp.plugins.bibles.lib.importers.csvbible.get_file_encoding',
|
with patch('openlp.plugins.bibles.lib.importers.csvbible.get_file_encoding', return_value='utf-8'), \
|
||||||
return_value={'encoding': 'utf-8', 'confidence': 0.99}), \
|
|
||||||
patch('openlp.plugins.bibles.lib.importers.csvbible.csv.reader',
|
patch('openlp.plugins.bibles.lib.importers.csvbible.csv.reader',
|
||||||
return_value=iter(test_data)) as mocked_reader:
|
return_value=iter(test_data)) as mocked_reader:
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@ from unittest.mock import call, patch
|
|||||||
|
|
||||||
import openlp.core.projectors.pjlink
|
import openlp.core.projectors.pjlink
|
||||||
from openlp.core.projectors.pjlinkcommands import process_command
|
from openlp.core.projectors.pjlinkcommands import process_command
|
||||||
from openlp.core.projectors.constants import E_UNDEFINED, S_DATA_OK
|
from openlp.core.projectors.constants import E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED, \
|
||||||
|
S_DATA_OK, PJLINK_ERRORS, STATUS_MSG
|
||||||
from openlp.core.projectors.db import Projector
|
from openlp.core.projectors.db import Projector
|
||||||
from openlp.core.projectors.pjlink import PJLink
|
from openlp.core.projectors.pjlink import PJLink
|
||||||
from tests.resources.projector.data import TEST1_DATA
|
from tests.resources.projector.data import TEST1_DATA
|
||||||
@ -114,19 +115,111 @@ class TestPJLinkRouting(TestCase):
|
|||||||
assert (chk == S_DATA_OK), 'Should have returned S_DATA_OK'
|
assert (chk == S_DATA_OK), 'Should have returned S_DATA_OK'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
def test_routing_pjink_errors(self, mock_log):
|
def test_routing_pjink_err1(self, mock_log):
|
||||||
"""
|
"""
|
||||||
Test rouing when PJLink error received (err1, err2, err3, err4, erra)
|
Test rouing when PJLink ERR1 received
|
||||||
"""
|
"""
|
||||||
# GIVEN: Test setup
|
# GIVEN: Test setup
|
||||||
log_error_text = [call('({ip}) CLSS: PJLink returned "ERR1: Undefined Command"'.format(ip=self.pjlink.name))]
|
|
||||||
log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR1"'.format(ip=self.pjlink.name))]
|
|
||||||
err_code = E_UNDEFINED
|
err_code = E_UNDEFINED
|
||||||
|
err_msg = STATUS_MSG[err_code]
|
||||||
|
err_str = PJLINK_ERRORS[err_code]
|
||||||
|
|
||||||
|
log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))]
|
||||||
|
log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name,
|
||||||
|
err=err_str))]
|
||||||
|
|
||||||
# WHEN: routing called
|
# WHEN: routing called
|
||||||
chk = process_command(projector=self.pjlink, cmd='CLSS', data='ERR1')
|
chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str)
|
||||||
|
|
||||||
# THEN: Appropriate log entries should have been made and methods called/not called
|
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||||
mock_log.error.assert_has_calls(log_error_text)
|
mock_log.error.assert_has_calls(log_error_text)
|
||||||
mock_log.debug.assert_has_calls(log_debug_text)
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
assert (chk == err_code), 'Should have returned E_UNDEFINED'
|
assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_routing_pjink_err2(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test rouing when PJLink ERR2 received
|
||||||
|
"""
|
||||||
|
# GIVEN: Test setup
|
||||||
|
err_code = E_PARAMETER
|
||||||
|
err_msg = STATUS_MSG[err_code]
|
||||||
|
err_str = PJLINK_ERRORS[err_code]
|
||||||
|
|
||||||
|
log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))]
|
||||||
|
log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name,
|
||||||
|
err=err_str))]
|
||||||
|
|
||||||
|
# WHEN: routing called
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str)
|
||||||
|
|
||||||
|
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||||
|
mock_log.error.assert_has_calls(log_error_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_routing_pjink_err3(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test rouing when PJLink ERR3 received
|
||||||
|
"""
|
||||||
|
# GIVEN: Test setup
|
||||||
|
err_code = E_UNAVAILABLE
|
||||||
|
err_msg = STATUS_MSG[err_code]
|
||||||
|
err_str = PJLINK_ERRORS[err_code]
|
||||||
|
|
||||||
|
log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))]
|
||||||
|
log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name,
|
||||||
|
err=err_str))]
|
||||||
|
|
||||||
|
# WHEN: routing called
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str)
|
||||||
|
|
||||||
|
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||||
|
mock_log.error.assert_has_calls(log_error_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_routing_pjink_err4(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test rouing when PJLink ERR4 received
|
||||||
|
"""
|
||||||
|
# GIVEN: Test setup
|
||||||
|
err_code = E_PROJECTOR
|
||||||
|
err_msg = STATUS_MSG[err_code]
|
||||||
|
err_str = PJLINK_ERRORS[err_code]
|
||||||
|
|
||||||
|
log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))]
|
||||||
|
log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name,
|
||||||
|
err=err_str))]
|
||||||
|
|
||||||
|
# WHEN: routing called
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str)
|
||||||
|
|
||||||
|
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||||
|
mock_log.error.assert_has_calls(log_error_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_routing_pjink_errA(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test rouing when PJLink ERRA received
|
||||||
|
"""
|
||||||
|
# GIVEN: Test setup
|
||||||
|
err_code = E_AUTHENTICATION
|
||||||
|
err_msg = STATUS_MSG[err_code]
|
||||||
|
err_str = PJLINK_ERRORS[err_code]
|
||||||
|
|
||||||
|
log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))]
|
||||||
|
log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name,
|
||||||
|
err=err_str))]
|
||||||
|
|
||||||
|
# WHEN: routing called
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str)
|
||||||
|
|
||||||
|
# THEN: Appropriate log entries should have been made and methods called/not called
|
||||||
|
mock_log.error.assert_has_calls(log_error_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code])
|
||||||
|
549
tests/openlp_core/projectors/test_projector_commands_01.py
Normal file
549
tests/openlp_core/projectors/test_projector_commands_01.py
Normal file
@ -0,0 +1,549 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2019 OpenLP Developers #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# This program is free software: you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the GNU General Public License as published by #
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or #
|
||||||
|
# (at your option) any later version. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, #
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||||
|
# GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License #
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
|
##########################################################################
|
||||||
|
"""
|
||||||
|
Package to test the openlp.core.projectors.pjlink commands package.
|
||||||
|
"""
|
||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
|
import openlp.core.projectors.pjlink
|
||||||
|
from openlp.core.projectors.pjlinkcommands import process_command
|
||||||
|
from openlp.core.projectors.constants import E_ERROR, E_WARN, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, S_OK
|
||||||
|
from openlp.core.projectors.db import Projector
|
||||||
|
from openlp.core.projectors.pjlink import PJLink
|
||||||
|
from tests.resources.projector.data import TEST1_DATA
|
||||||
|
|
||||||
|
|
||||||
|
class TestPJLinkCommands(TestCase):
|
||||||
|
"""
|
||||||
|
Tests PJLink commands part 1
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Initial test setup
|
||||||
|
"""
|
||||||
|
self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Test reset
|
||||||
|
"""
|
||||||
|
del(self.pjlink)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_avmt_audio_muted(self, mock_log, mock_UpdateIcons):
|
||||||
|
"""
|
||||||
|
Test avmt status shutter unchanged and mute on
|
||||||
|
"""
|
||||||
|
# GIVEN: Test setup
|
||||||
|
log_warning_text = []
|
||||||
|
log_debug_text = [call('({ip}) Processing command "AVMT" with data "21"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting speaker to muted'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.shutter = True
|
||||||
|
self.pjlink.mute = False
|
||||||
|
|
||||||
|
# WHEN: Called with setting shutter closed and mute on
|
||||||
|
process_command(projector=self.pjlink, cmd='AVMT', data='21')
|
||||||
|
|
||||||
|
# THEN: Shutter should be closed and mute should be True
|
||||||
|
assert self.pjlink.shutter, 'Shutter should not have changed'
|
||||||
|
assert self.pjlink.mute, 'Audio should be off'
|
||||||
|
assert mock_UpdateIcons.emit.called, 'Update icons should have been called'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_avmt_bad_data(self, mock_log, mock_UpdateIcons):
|
||||||
|
"""
|
||||||
|
Test avmt bad data fail
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_text = [call('({ip}) Invalid av mute response: 36'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_text = [call('({ip}) Processing command "AVMT" with data "36"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.shutter = True
|
||||||
|
self.pjlink.mute = True
|
||||||
|
|
||||||
|
# WHEN: Called with an invalid setting
|
||||||
|
process_command(projector=self.pjlink, cmd='AVMT', data='36')
|
||||||
|
|
||||||
|
# THEN: Shutter should be closed and mute should be True
|
||||||
|
assert self.pjlink.shutter, 'Shutter should changed'
|
||||||
|
assert self.pjlink.mute, 'Audio should not have changed'
|
||||||
|
assert not mock_UpdateIcons.emit.called, 'Update icons should NOT have been called'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_avmt_closed_muted(self, mock_log, mock_UpdateIcons):
|
||||||
|
"""
|
||||||
|
Test avmt status shutter closed and mute off
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_text = []
|
||||||
|
log_debug_text = [call('({ip}) Processing command "AVMT" with data "31"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting speaker to muted'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.shutter = False
|
||||||
|
self.pjlink.mute = False
|
||||||
|
|
||||||
|
# WHEN: Called with setting shutter to closed and mute on
|
||||||
|
process_command(projector=self.pjlink, cmd='AVMT', data='31')
|
||||||
|
|
||||||
|
# THEN: Shutter should be closed and mute should be True
|
||||||
|
assert self.pjlink.shutter, 'Shutter should have been set to closed'
|
||||||
|
assert self.pjlink.mute, 'Audio should be muted'
|
||||||
|
assert mock_UpdateIcons.emit.called, 'Update icons should have been called'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_avmt_open_unmuted(self, mock_log, mock_UpdateIcons):
|
||||||
|
"""
|
||||||
|
Test avmt status shutter open and mute off
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_text = []
|
||||||
|
log_debug_text = [call('({ip}) Processing command "AVMT" with data "30"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting shutter to open'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting speaker to normal'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.shutter = True
|
||||||
|
self.pjlink.mute = True
|
||||||
|
|
||||||
|
# WHEN: Called with setting shutter to closed and mute on
|
||||||
|
process_command(projector=self.pjlink, cmd='AVMT', data='30')
|
||||||
|
|
||||||
|
# THEN: Shutter should be closed and mute should be True
|
||||||
|
assert not self.pjlink.shutter, 'Shutter should have been set to off'
|
||||||
|
assert not self.pjlink.mute, 'Audio should be on'
|
||||||
|
assert mock_UpdateIcons.emit.called, 'Update icons should have been called'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_avmt_shutter_closed(self, mock_log, mock_UpdateIcons):
|
||||||
|
"""
|
||||||
|
Test avmt status shutter closed and audio unchanged
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_text = []
|
||||||
|
log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.shutter = False
|
||||||
|
self.pjlink.mute = True
|
||||||
|
|
||||||
|
# WHEN: Called with setting shutter closed and mute off
|
||||||
|
process_command(projector=self.pjlink, cmd='AVMT', data='11')
|
||||||
|
|
||||||
|
# THEN: Shutter should be True and mute should be False
|
||||||
|
assert self.pjlink.shutter, 'Shutter should have been set to closed'
|
||||||
|
assert self.pjlink.mute, 'Audio should not have changed'
|
||||||
|
assert mock_UpdateIcons.emit.called, 'Update icons should have been called'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_avmt_status_timer_check_delete(self, mock_log, mock_UpdateIcons):
|
||||||
|
"""
|
||||||
|
Test avmt deletes callback in projector.status_timer_check
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_text = []
|
||||||
|
log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.shutter = False
|
||||||
|
self.pjlink.mute = True
|
||||||
|
self.pjlink.status_timer_checks = {'AVMT': self.pjlink.get_av_mute_status}
|
||||||
|
|
||||||
|
# WHEN: Called with setting shutter closed and mute off
|
||||||
|
with patch.object(self.pjlink, 'status_timer') as mock_status_timer:
|
||||||
|
process_command(projector=self.pjlink, cmd='AVMT', data='11')
|
||||||
|
|
||||||
|
# THEN: Shutter should be True and mute should be False
|
||||||
|
assert self.pjlink.shutter, 'Shutter should have been set to closed'
|
||||||
|
assert self.pjlink.mute, 'Audio should not have changed'
|
||||||
|
assert mock_UpdateIcons.emit.called, 'Update icons should have been called'
|
||||||
|
assert 'AVMT' not in self.pjlink.status_timer_checks, 'Status timer list should not have AVMT callback'
|
||||||
|
assert mock_status_timer.stop.called, 'Projector status_timer.stop() should have been called'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_text)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_clss_1(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test CLSS request returns non-standard reply 1
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_error_calls = []
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "CLSS" with data "1"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: Process non-standard reply
|
||||||
|
process_command(projector=self.pjlink, cmd='CLSS', data='1')
|
||||||
|
|
||||||
|
# THEN: Projector class should be set with proper value
|
||||||
|
assert '1' == self.pjlink.pjlink_class, 'Should have set class=1'
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_clss_2(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test CLSS request returns non-standard reply 1
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_error_calls = []
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "CLSS" with data "2"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting pjlink_class for this projector to "2"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: Process non-standard reply
|
||||||
|
process_command(projector=self.pjlink, cmd='CLSS', data='2')
|
||||||
|
|
||||||
|
# THEN: Projector class should be set with proper value
|
||||||
|
assert '2' == self.pjlink.pjlink_class, 'Should have set class=2'
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_clss_invalid_nan(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test CLSS reply has no class number
|
||||||
|
"""
|
||||||
|
# GIVEN: Test setup
|
||||||
|
log_warning_calls = [call('({ip}) NAN CLSS version reply "Z" - '
|
||||||
|
'defaulting to class "1"'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Z"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: Process invalid reply
|
||||||
|
process_command(projector=self.pjlink, cmd='CLSS', data='Z')
|
||||||
|
|
||||||
|
# THEN: Projector class should be set with default value
|
||||||
|
assert self.pjlink.pjlink_class == '1', 'Invalid NaN class reply should have set class=1'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_clss_invalid_no_version(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test CLSS reply has no class number
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = [call('({ip}) No numbers found in class version reply "Invalid" '
|
||||||
|
'- defaulting to class "1"'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Invalid"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: Process invalid reply
|
||||||
|
process_command(projector=self.pjlink, cmd='CLSS', data='Invalid')
|
||||||
|
|
||||||
|
# THEN: Projector class should be set with default value
|
||||||
|
assert self.pjlink.pjlink_class == '1', 'Invalid class reply should have set class=1'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_clss_nonstandard_reply_1(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test CLSS request returns non-standard reply 1
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_error_calls = []
|
||||||
|
log_warning_calls = [call('({ip}) Non-standard CLSS reply: "Class 1"'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Class 1"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: Process non-standard reply
|
||||||
|
process_command(projector=self.pjlink, cmd='CLSS', data='Class 1')
|
||||||
|
|
||||||
|
# THEN: Projector class should be set with proper value
|
||||||
|
assert '1' == self.pjlink.pjlink_class, 'Non-standard class reply should have set class=1'
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_clss_nonstandard_reply_2(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test CLSS request returns non-standard reply 1
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = [call('({ip}) Non-standard CLSS reply: "Version2"'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Version2"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting pjlink_class for this projector to "2"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: Process non-standard reply
|
||||||
|
process_command(projector=self.pjlink, cmd='CLSS', data='Version2')
|
||||||
|
|
||||||
|
# THEN: Projector class should be set with proper value
|
||||||
|
assert '2' == self.pjlink.pjlink_class, 'Non-standard class reply should have set class=1'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_erst_all_error(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test test_projector_process_erst_all_error
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR],
|
||||||
|
lamp=PJLINK_ERST_STATUS[E_ERROR],
|
||||||
|
temp=PJLINK_ERST_STATUS[E_ERROR],
|
||||||
|
cover=PJLINK_ERST_STATUS[E_ERROR],
|
||||||
|
filt=PJLINK_ERST_STATUS[E_ERROR],
|
||||||
|
other=PJLINK_ERST_STATUS[E_ERROR])
|
||||||
|
chk_test = {'Fan': E_ERROR,
|
||||||
|
'Lamp': E_ERROR,
|
||||||
|
'Temperature': E_ERROR,
|
||||||
|
'Cover': E_ERROR,
|
||||||
|
'Filter': E_ERROR,
|
||||||
|
'Other': E_ERROR}
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name,
|
||||||
|
chk=chk_data)),
|
||||||
|
call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.projector_errors = None
|
||||||
|
|
||||||
|
# WHEN: process_erst with status set to WARN
|
||||||
|
process_command(projector=self.pjlink, cmd='ERST', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: PJLink instance errors should match chk_value
|
||||||
|
assert self.pjlink.projector_errors == chk_test, 'Projector errors should be all E_ERROR'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_erst_all_ok(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test to verify pjlink.projector_errors is set to None when no errors
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH']
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name,
|
||||||
|
chk=chk_data)),
|
||||||
|
call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: process_erst with no errors
|
||||||
|
process_command(projector=self.pjlink, cmd='ERST', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: PJLink instance errors should be None
|
||||||
|
assert self.pjlink.projector_errors is None, 'projector_errors should have been set to None'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_erst_all_warn(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test test_projector_process_erst_all_error
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN],
|
||||||
|
lamp=PJLINK_ERST_STATUS[E_WARN],
|
||||||
|
temp=PJLINK_ERST_STATUS[E_WARN],
|
||||||
|
cover=PJLINK_ERST_STATUS[E_WARN],
|
||||||
|
filt=PJLINK_ERST_STATUS[E_WARN],
|
||||||
|
other=PJLINK_ERST_STATUS[E_WARN])
|
||||||
|
chk_test = {'Fan': E_WARN,
|
||||||
|
'Lamp': E_WARN,
|
||||||
|
'Temperature': E_WARN,
|
||||||
|
'Cover': E_WARN,
|
||||||
|
'Filter': E_WARN,
|
||||||
|
'Other': E_WARN}
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name,
|
||||||
|
chk=chk_data)),
|
||||||
|
call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.projector_errors = None
|
||||||
|
|
||||||
|
# WHEN: process_erst with status set to WARN
|
||||||
|
process_command(projector=self.pjlink, cmd='ERST', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: PJLink instance errors should match chk_value
|
||||||
|
assert self.pjlink.projector_errors == chk_test, 'Projector errors should be all E_WARN'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_erst_data_invalid_length(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test test_projector_process_erst_data_invalid_length
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1)
|
||||||
|
log_warn_calls = [call('({ip}) Invalid error status response "{data}": '
|
||||||
|
'length != {chk}'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data, chk=PJLINK_ERST_DATA['DATA_LENGTH']))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data)),
|
||||||
|
call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.projector_errors = None
|
||||||
|
|
||||||
|
# WHEN: process_erst called with invalid data (too many values
|
||||||
|
process_command(self.pjlink, cmd='ERST', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: pjlink.projector_errors should be empty and warning logged
|
||||||
|
assert not self.pjlink.projector_errors, 'There should be no errors'
|
||||||
|
mock_log.warning.assert_has_calls(log_warn_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_erst_data_invalid_nan(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test ERST called with invalid data
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1))
|
||||||
|
log_warn_calls = [call('({ip}) Invalid error status response "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data)),
|
||||||
|
call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.projector_errors = None
|
||||||
|
|
||||||
|
# WHEN: process_erst called with invalid data (too many values
|
||||||
|
process_command(self.pjlink, cmd='ERST', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: pjlink.projector_errors should be empty and warning logged
|
||||||
|
assert not self.pjlink.projector_errors, 'There should be no errors'
|
||||||
|
mock_log.warning.assert_has_calls(log_warn_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_erst_warn_cover_only(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test test_projector_process_erst_warn_cover_only
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK],
|
||||||
|
lamp=PJLINK_ERST_STATUS[S_OK],
|
||||||
|
temp=PJLINK_ERST_STATUS[S_OK],
|
||||||
|
cover=PJLINK_ERST_STATUS[E_WARN],
|
||||||
|
filt=PJLINK_ERST_STATUS[S_OK],
|
||||||
|
other=PJLINK_ERST_STATUS[S_OK])
|
||||||
|
chk_test = {'Cover': E_WARN}
|
||||||
|
log_warn_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data)),
|
||||||
|
call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.projector_errors = None
|
||||||
|
|
||||||
|
# WHEN: process_erst with status set to WARN
|
||||||
|
process_command(projector=self.pjlink, cmd='ERST', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: PJLink instance errors should match only cover warning
|
||||||
|
assert 1 == len(self.pjlink.projector_errors), 'There should only be 1 error listed in projector_errors'
|
||||||
|
assert 'Cover' in self.pjlink.projector_errors, '"Cover" should be the only error listed'
|
||||||
|
assert self.pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error'
|
||||||
|
assert chk_test == self.pjlink.projector_errors, 'projector_errors should match test errors'
|
||||||
|
mock_log.warning.assert_has_calls(log_warn_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_inf1(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving INF1 data (manufacturer)
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = 'TEst INformation MultiCase'
|
||||||
|
log_warn_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "INF1" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data)),
|
||||||
|
call('({ip}) Calling function for INF1'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector manufacturer data to '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=chk_data))]
|
||||||
|
self.pjlink.manufacturer = None
|
||||||
|
|
||||||
|
# WHEN: process_inf called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='INF1', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: Data should be saved
|
||||||
|
assert self.pjlink.manufacturer == chk_data, 'Test data should have been saved'
|
||||||
|
mock_log.warning.assert_has_calls(log_warn_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_inf2(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving INF2 data (model)
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = 'TEst moDEl MultiCase'
|
||||||
|
log_warn_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "INF2" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data)),
|
||||||
|
call('({ip}) Calling function for INF2'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector model to "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data))]
|
||||||
|
self.pjlink.model = None
|
||||||
|
|
||||||
|
# WHEN: process_inf called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='INF2', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: Data should be saved
|
||||||
|
assert self.pjlink.model == chk_data, 'Test data should have been saved'
|
||||||
|
mock_log.warning.assert_has_calls(log_warn_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_info(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving INF2 data (model)
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
|
||||||
|
log_warn_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "INFO" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data)),
|
||||||
|
call('({ip}) Calling function for INFO'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector other_info to "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=chk_data))]
|
||||||
|
self.pjlink.other_info = None
|
||||||
|
|
||||||
|
# WHEN: process_inf called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='INFO', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: Data should be saved
|
||||||
|
assert self.pjlink.other_info == chk_data, 'Test data should have been saved'
|
||||||
|
mock_log.warning.assert_has_calls(log_warn_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
550
tests/openlp_core/projectors/test_projector_commands_02.py
Normal file
550
tests/openlp_core/projectors/test_projector_commands_02.py
Normal file
@ -0,0 +1,550 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2019 OpenLP Developers #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# This program is free software: you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the GNU General Public License as published by #
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or #
|
||||||
|
# (at your option) any later version. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, #
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||||
|
# GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License #
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
|
##########################################################################
|
||||||
|
"""
|
||||||
|
Package to test the openlp.core.projectors.pjlink commands package.
|
||||||
|
"""
|
||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
|
import openlp.core.projectors.pjlink
|
||||||
|
from openlp.core.projectors.pjlinkcommands import process_command
|
||||||
|
from openlp.core.projectors.constants import PJLINK_POWR_STATUS, S_ON, S_STANDBY
|
||||||
|
from openlp.core.projectors.db import Projector
|
||||||
|
from openlp.core.projectors.pjlink import PJLink
|
||||||
|
from tests.resources.projector.data import TEST1_DATA
|
||||||
|
|
||||||
|
|
||||||
|
class TestPJLinkCommands(TestCase):
|
||||||
|
"""
|
||||||
|
Tests PJLink commands part 2
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Initial test setup
|
||||||
|
"""
|
||||||
|
self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Test reset
|
||||||
|
"""
|
||||||
|
del(self.pjlink)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_inpt_good(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test input source status shows current input
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
self.pjlink.source = '11'
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "INPT" with data "21"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for INPT'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting current source to "21"'.format(ip=self.pjlink.name))]
|
||||||
|
chk_source_available = ['11', '12', '21', '22', '31', '32']
|
||||||
|
self.pjlink.source_available = chk_source_available
|
||||||
|
|
||||||
|
# WHEN: Called with input source
|
||||||
|
process_command(projector=self.pjlink, cmd='INPT', data='21')
|
||||||
|
|
||||||
|
# THEN: Input selected should reflect current input
|
||||||
|
assert '21' == self.pjlink.source, 'Input source should be set to "21"'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_inpt_invalid(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test input source returned not valid according to standard
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = [call('({ip}) Input source not listed as a PJLink valid source - '
|
||||||
|
'ignoring'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "INPT" with data "91"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for INPT'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.source = None
|
||||||
|
self.pjlink.source_available = None
|
||||||
|
|
||||||
|
# WHEN: Called with input source
|
||||||
|
process_command(projector=self.pjlink, cmd='INPT', data='91')
|
||||||
|
|
||||||
|
# THEN: Input selected should reflect current input
|
||||||
|
assert not self.pjlink.source, 'Input source should not have changed'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_inpt_not_in_list(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test input source not listed in available sources
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = [call('({ip}) Input source not listed in available sources - '
|
||||||
|
'ignoring'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "INPT" with data "25"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for INPT'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.source = '11'
|
||||||
|
chk_source_available = ['11', '12', '21', '22', '31', '32']
|
||||||
|
self.pjlink.source_available = chk_source_available
|
||||||
|
|
||||||
|
# WHEN: Called with input source
|
||||||
|
process_command(projector=self.pjlink, cmd='INPT', data='25')
|
||||||
|
|
||||||
|
# THEN: Input selected should reflect current input
|
||||||
|
assert '11' == self.pjlink.source, 'Input source should not have changed'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_inst_class_1(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving video source available information
|
||||||
|
"""
|
||||||
|
|
||||||
|
# GIVEN: Test object
|
||||||
|
self.pjlink.source_available = []
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "INST" with data '
|
||||||
|
'"21 12 11 22 32 31"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for INST'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector source_available to '
|
||||||
|
'"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to check method
|
||||||
|
chk_test = ['11', '12', '21', '22', '31', '32']
|
||||||
|
|
||||||
|
# WHEN: process_inst called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='INST', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: Data should have been sorted and saved properly
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert self.pjlink.source_available == chk_test, "Sources should have been sorted and saved"
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_lamp_invalid_missing_data(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test process lamp with 1 lamp reply hours only and no on/off status
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = [call('({ip}) process_lamp(): Invalid data "45" - '
|
||||||
|
'Missing data'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "LAMP" with data "45"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.lamp = None
|
||||||
|
|
||||||
|
# WHEN: Call process_command with 3 lamps
|
||||||
|
process_command(projector=self.pjlink, cmd='LAMP', data='45')
|
||||||
|
|
||||||
|
# THEN: Lamp should have been set with proper lamp status
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert not self.pjlink.lamp, 'Projector lamp info should not have changed'
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_lamp_invalid_nan(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test status multiple lamp on/off and hours
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
self.pjlink.lamp = [{'Hours': 00000, 'On': True},
|
||||||
|
{'Hours': 11111, 'On': False}]
|
||||||
|
log_warning_calls = [call('({ip}) process_lamp(): Invalid data "11111 1 22222 0 '
|
||||||
|
'333A3 1"'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "LAMP" with data "11111 1 22222 0 '
|
||||||
|
'333A3 1"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: Call process_command with invalid lamp data
|
||||||
|
process_command(projector=self.pjlink, cmd='LAMP', data='11111 1 22222 0 333A3 1')
|
||||||
|
|
||||||
|
# THEN: lamps should not have changed
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert 2 == len(self.pjlink.lamp), 'Projector lamp list should not have changed'
|
||||||
|
assert self.pjlink.lamp[0]['On'], 'Lamp 1 power status should not have changed'
|
||||||
|
assert 0 == self.pjlink.lamp[0]['Hours'], 'Lamp 1 hours should not have changed'
|
||||||
|
assert not self.pjlink.lamp[1]['On'], 'Lamp 2 power status should not have changed'
|
||||||
|
assert 11111 == self.pjlink.lamp[1]['Hours'], 'Lamp 2 hours should not have changed'
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_lamp_multiple(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test status multiple lamp on/off and hours
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "LAMP" with data "11111 1 22222 0 '
|
||||||
|
'33333 1"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.lamp = None
|
||||||
|
|
||||||
|
# WHEN: Call process_command with 3 lamps
|
||||||
|
process_command(projector=self.pjlink, cmd='LAMP', data='11111 1 22222 0 33333 1')
|
||||||
|
|
||||||
|
# THEN: Lamp should have been set with proper lamp status
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert 3 == len(self.pjlink.lamp), 'Projector should have 3 lamps specified'
|
||||||
|
assert self.pjlink.lamp[0]['On'], 'Lamp 1 power status should have been set to TRUE'
|
||||||
|
assert 11111 == self.pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been set to 11111'
|
||||||
|
assert not self.pjlink.lamp[1]['On'], 'Lamp 2 power status should have been set to FALSE'
|
||||||
|
assert 22222 == self.pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been set to 22222'
|
||||||
|
assert self.pjlink.lamp[2]['On'], 'Lamp 3 power status should have been set to TRUE'
|
||||||
|
assert 33333 == self.pjlink.lamp[2]['Hours'], 'Lamp 3 hours should have been set to 33333'
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_lamp_single(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test status lamp on/off and hours
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "LAMP" with data "11111 1"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.lamp = None
|
||||||
|
|
||||||
|
# WHEN: Call process_command with 3 lamps
|
||||||
|
process_command(projector=self.pjlink, cmd='LAMP', data='11111 1')
|
||||||
|
|
||||||
|
# THEN: Lamp should have been set with proper lamp status
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert 1 == len(self.pjlink.lamp), 'Projector should have 1 lamp specified'
|
||||||
|
assert self.pjlink.lamp[0]['On'], 'Lamp 1 power status should have been set to TRUE'
|
||||||
|
assert 11111 == self.pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been set to 11111'
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_name(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving NAME data from projector
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
chk_data = "Some Name the End-User Set IN Projector"
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "NAME" with data '
|
||||||
|
'"Some Name the End-User Set IN Projector"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for NAME'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector PJLink name to '
|
||||||
|
'"Some Name the End-User Set IN Projector"'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: process_name called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='NAME', data=chk_data)
|
||||||
|
|
||||||
|
# THEN: name should be set and logged
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert self.pjlink.pjlink_name == chk_data, 'Name test data should have been saved'
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command')
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status')
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_powr_invalid(self, mock_log, mock_UpdateIcons, mock_change_status, mock_send_command):
|
||||||
|
"""
|
||||||
|
Test process_powr invalid call
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
self.pjlink.power = S_STANDBY
|
||||||
|
log_warning_calls = [call('({ip}) Unknown power response: "99"'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "POWR" with data "99"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for POWR'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing POWR command'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# WHEN: process_command called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='POWR', data='99')
|
||||||
|
|
||||||
|
# THEN: Projector power should not have changed
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert S_STANDBY == self.pjlink.power, 'Power should not have changed'
|
||||||
|
mock_UpdateIcons.emit.assert_not_called()
|
||||||
|
mock_change_status.assert_not_called()
|
||||||
|
mock_send_command.assert_not_called()
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command')
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status')
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_powr_off(self, mock_log, mock_UpdateIcons, mock_change_status, mock_send_command):
|
||||||
|
"""
|
||||||
|
Test status power to OFF
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "POWR" with data "0"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for POWR'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing POWR command'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.power = S_ON
|
||||||
|
|
||||||
|
# WHEN: process_name called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='POWR', data=PJLINK_POWR_STATUS[S_STANDBY])
|
||||||
|
|
||||||
|
# THEN: Power should be set to ON
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert S_STANDBY == self.pjlink.power, 'Power should have been set to OFF'
|
||||||
|
assert mock_UpdateIcons.emit.called, 'projectorUpdateIcons should have been called'
|
||||||
|
assert not mock_send_command.called, 'send_command should not have been called'
|
||||||
|
mock_change_status.assert_called_once_with(S_STANDBY)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command')
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status')
|
||||||
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons')
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_powr_on(self, mock_log, mock_UpdateIcons, mock_change_status, mock_send_command):
|
||||||
|
"""
|
||||||
|
Test status power to ON
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "POWR" with data "1"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for POWR'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing POWR command'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.power = S_STANDBY
|
||||||
|
|
||||||
|
# WHEN: process_name called with test data
|
||||||
|
process_command(projector=self.pjlink, cmd='POWR', data=PJLINK_POWR_STATUS[S_ON])
|
||||||
|
|
||||||
|
# THEN: Power should be set to ON
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert S_ON == self.pjlink.power, 'Power should have been set to ON'
|
||||||
|
assert mock_UpdateIcons.emit.called, 'projectorUpdateIcons should have been called'
|
||||||
|
mock_send_command.assert_called_once_with('INST')
|
||||||
|
mock_change_status.assert_called_once_with(S_ON)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_rfil_save(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving filter type
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
new_data = 'Filter Type Test'
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "RFIL" with data '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Calling function for RFIL'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.model_filter = None
|
||||||
|
|
||||||
|
# WHEN: Filter model is received
|
||||||
|
process_command(projector=self.pjlink, cmd='RFIL', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Filter model number should be saved
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert self.pjlink.model_filter == new_data, 'Filter model should have been saved'
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_rfil_nosave(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving filter type previously saved
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
old_data = 'Old filter type'
|
||||||
|
new_data = 'Filter Type Test'
|
||||||
|
log_warning_calls = [call('({ip}) Filter model already set'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Saved model: "{data}"'.format(ip=self.pjlink.name, data=old_data)),
|
||||||
|
call('({ip}) New model: "{data}"'.format(ip=self.pjlink.name, data=new_data))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "RFIL" with data '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Calling function for RFIL'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.model_filter = old_data
|
||||||
|
|
||||||
|
# WHEN: Filter model is received
|
||||||
|
process_command(projector=self.pjlink, cmd='RFIL', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Filter model number should be saved
|
||||||
|
assert self.pjlink.model_filter != new_data, 'Filter model should NOT have been saved'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_rlmp_save(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving lamp type
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
new_data = 'Lamp Type Test'
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "RLMP" with data '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Calling function for RLMP'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.model_lamp = None
|
||||||
|
|
||||||
|
# WHEN: Filter model is received
|
||||||
|
process_command(projector=self.pjlink, cmd='RLMP', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Filter model number should be saved
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert self.pjlink.model_lamp == new_data, 'Lamp model should have been saved'
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_rlmp_nosave(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving lamp type previously saved
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
old_data = 'Old filter type'
|
||||||
|
new_data = 'Filter Type Test'
|
||||||
|
log_warning_calls = [call('({ip}) Lamp model already set'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Saved lamp: "{data}"'.format(ip=self.pjlink.name, data=old_data)),
|
||||||
|
call('({ip}) New lamp: "{data}"'.format(ip=self.pjlink.name, data=new_data))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "RLMP" with data '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Calling function for RLMP'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.model_lamp = old_data
|
||||||
|
|
||||||
|
# WHEN: Filter model is received
|
||||||
|
process_command(projector=self.pjlink, cmd='RLMP', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Filter model number should be saved
|
||||||
|
assert self.pjlink.model_lamp != new_data, 'Lamp model should NOT have been saved'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_snum_different(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test projector serial number different than saved serial number
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
new_data = 'Test Serial Number'
|
||||||
|
old_data = 'Previous serial number'
|
||||||
|
log_warning_calls = [call('({ip}) Projector serial number does not match '
|
||||||
|
'saved serial number'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Saved: "{data}"'.format(ip=self.pjlink.name, data=old_data)),
|
||||||
|
call('({ip}) Received: "{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) NOT saving serial number'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "SNUM" with data '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Calling function for SNUM'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.serial_no = old_data
|
||||||
|
|
||||||
|
# WHEN: No serial number is set and we receive serial number command
|
||||||
|
process_command(projector=self.pjlink, cmd='SNUM', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Serial number should be set
|
||||||
|
assert self.pjlink.serial_no != new_data, 'Projector serial number should NOT have been set'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_snum_set(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test saving serial number from projector
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
new_data = 'Test Serial Number'
|
||||||
|
self.pjlink.serial_no = None
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "SNUM" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=new_data)),
|
||||||
|
call('({ip}) Calling function for SNUM'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector serial number to '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data))]
|
||||||
|
|
||||||
|
# WHEN: No serial number is set and we receive serial number command
|
||||||
|
process_command(projector=self.pjlink, cmd='SNUM', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Serial number should be set
|
||||||
|
assert self.pjlink.serial_no == new_data, 'Projector serial number should have been set'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_sver_changed(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test invalid software version information - Received different than saved
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
old_data = 'Test 1 Subtest 1'
|
||||||
|
new_data = 'Test 1 Subtest 2'
|
||||||
|
log_warning_calls = [call('({ip}) Projector software version does not match '
|
||||||
|
'saved software version'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Saved: "{data}"'.format(ip=self.pjlink.name, data=old_data)),
|
||||||
|
call('({ip}) Received: "{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Updating software version'.format(ip=self.pjlink.name))]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "SVER" with data '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Calling function for SVER'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector software version to '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data))]
|
||||||
|
self.pjlink.sw_version = old_data
|
||||||
|
|
||||||
|
# WHEN: process_sver called with invalid data
|
||||||
|
process_command(self.pjlink, cmd='SVER', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Version information should change
|
||||||
|
assert self.pjlink.sw_version == new_data, 'Software version should have changed'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_sver_invalid(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test invalid software version information - too long
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
new_data = 'This is a test software version line that is too long based on PJLink version 2 specs'
|
||||||
|
log_warning_calls = [call('Invalid software version - too long')]
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "SVER" with data "{data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=new_data)),
|
||||||
|
call('({ip}) Calling function for SVER'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.sw_version = None
|
||||||
|
self.pjlink.sw_version_received = None
|
||||||
|
|
||||||
|
# WHEN: process_sver called with invalid data
|
||||||
|
process_command(projector=self.pjlink, cmd='SVER', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Version information should not change
|
||||||
|
assert not self.pjlink.sw_version, 'Software version should not have changed'
|
||||||
|
assert not self.pjlink.sw_version_received, 'Received software version should not have changed'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_projector_sver_save(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test invalid software version information - too long
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
new_data = 'Test 1 Subtest 1'
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "SVER" with data '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data)),
|
||||||
|
call('({ip}) Calling function for SVER'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Setting projector software version to '
|
||||||
|
'"{data}"'.format(ip=self.pjlink.name, data=new_data))]
|
||||||
|
self.pjlink.sw_version = None
|
||||||
|
self.pjlink.sw_version_received = None
|
||||||
|
|
||||||
|
# WHEN: process_sver called with invalid data
|
||||||
|
process_command(projector=self.pjlink, cmd='SVER', data=new_data)
|
||||||
|
|
||||||
|
# THEN: Version information should not change
|
||||||
|
assert self.pjlink.sw_version == new_data, 'Software version should have been updated'
|
||||||
|
assert not self.pjlink.sw_version_received, 'Received version field should not have changed'
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
253
tests/openlp_core/projectors/test_projector_commands_03.py
Normal file
253
tests/openlp_core/projectors/test_projector_commands_03.py
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2019 OpenLP Developers #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# This program is free software: you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the GNU General Public License as published by #
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or #
|
||||||
|
# (at your option) any later version. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, #
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||||
|
# GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License #
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
|
##########################################################################
|
||||||
|
"""
|
||||||
|
Package to test the openlp.core.projectors.pjlink commands package.
|
||||||
|
"""
|
||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
|
import openlp.core.projectors.pjlink
|
||||||
|
from openlp.core.projectors.constants import E_NO_AUTHENTICATION, STATUS_CODE, S_AUTHENTICATE, S_CONNECT
|
||||||
|
from openlp.core.projectors.db import Projector
|
||||||
|
from openlp.core.projectors.pjlink import PJLink
|
||||||
|
from openlp.core.projectors.pjlinkcommands import process_command
|
||||||
|
from tests.resources.projector.data import TEST1_DATA, TEST_PIN, TEST_SALT
|
||||||
|
|
||||||
|
|
||||||
|
class TestPJLinkCommands(TestCase):
|
||||||
|
"""
|
||||||
|
Tests PJLink commands part 3
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Initialize test state(s)
|
||||||
|
"""
|
||||||
|
# Default PJLink instance for tests
|
||||||
|
self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Cleanup test state(s)
|
||||||
|
"""
|
||||||
|
del(self.pjlink)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_authenticate(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test initial connection prompt with authentication
|
||||||
|
"""
|
||||||
|
# GIVEN: Initial mocks and data
|
||||||
|
log_error_calls = []
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "1 {data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=TEST_SALT)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) PJLINK: Returning {data}'.format(ip=self.pjlink.name,
|
||||||
|
data=STATUS_CODE[S_AUTHENTICATE]))]
|
||||||
|
|
||||||
|
self.pjlink.pin = TEST_PIN
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with no authentication required
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data='1 {salt}'.format(salt=TEST_SALT))
|
||||||
|
|
||||||
|
# THEN: proper processing should have occured
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == S_AUTHENTICATE, 'Should have returned {data}'.format(data=STATUS_CODE[S_AUTHENTICATE])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_authenticate_pin_not_set_error(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test initial connection prompt with authentication and no pin set
|
||||||
|
"""
|
||||||
|
# GIVEN: Initial mocks and data
|
||||||
|
log_error_calls = [call('({ip}) Authenticate connection but no PIN - aborting'.format(ip=self.pjlink.name))]
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "1 {data}"'.format(ip=self.pjlink.name,
|
||||||
|
data=TEST_SALT)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
self.pjlink.pin = None
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with no authentication required
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data='1 {salt}'.format(salt=TEST_SALT))
|
||||||
|
|
||||||
|
# THEN: proper processing should have occured
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == E_NO_AUTHENTICATION, \
|
||||||
|
'Should have returned {data}'.format(data=STATUS_CODE[E_NO_AUTHENTICATION])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_authenticate_token_invalid(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test initial connection prompt with authentication and bad token
|
||||||
|
"""
|
||||||
|
# GIVEN: Initial mocks and data
|
||||||
|
bad_token = 'abcdefgh'
|
||||||
|
log_error_calls = [call('({ip}) Authentication token invalid (not a hexadecimal number) - '
|
||||||
|
'aborting'.format(ip=self.pjlink.name))]
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data '
|
||||||
|
'"1 {data}"'.format(ip=self.pjlink.name, data=bad_token)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.pin = TEST_SALT
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with bad token
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data='1 {data}'.format(data=bad_token))
|
||||||
|
|
||||||
|
# THEN: proper processing should have occured
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == E_NO_AUTHENTICATION, \
|
||||||
|
'Should have returned {data}'.format(data=STATUS_CODE[E_NO_AUTHENTICATION])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_authenticate_token_length(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test initial connection prompt with authentication and bad token
|
||||||
|
"""
|
||||||
|
# GIVEN: Initial mocks and data
|
||||||
|
bad_token = '1234abcde' # Length should be 8, this is 9
|
||||||
|
log_error_calls = [call('({ip}) Authentication token invalid (size) - '
|
||||||
|
'aborting'.format(ip=self.pjlink.name))]
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data '
|
||||||
|
'"1 {data}"'.format(ip=self.pjlink.name, data=bad_token)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.pin = TEST_SALT
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with bad token
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data='1 {data}'.format(data=bad_token))
|
||||||
|
|
||||||
|
# THEN: proper processing should have occured
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == E_NO_AUTHENTICATION, \
|
||||||
|
'Should have returned {data}'.format(data=STATUS_CODE[E_NO_AUTHENTICATION])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_authenticate_token_missing(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test initial connection prompt with authentication and missing token
|
||||||
|
"""
|
||||||
|
# GIVEN: Initial mocks and data
|
||||||
|
log_error_calls = [call('({ip}) Authenticated connection but not enough info - '
|
||||||
|
'aborting'.format(ip=self.pjlink.name))]
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "1"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
self.pjlink.pin = TEST_SALT
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with bad token
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data='1')
|
||||||
|
|
||||||
|
# THEN: proper processing should have occured
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == E_NO_AUTHENTICATION, \
|
||||||
|
'Should have returned {data}'.format(data=STATUS_CODE[E_NO_AUTHENTICATION])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_normal(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test processing PJLINK initial prompt
|
||||||
|
"""
|
||||||
|
# GIVEN: Mocks and data
|
||||||
|
log_error_calls = []
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "0"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) PJLINK: Returning {data}'.format(ip=self.pjlink.name,
|
||||||
|
data=STATUS_CODE[S_CONNECT]))]
|
||||||
|
|
||||||
|
self.pjlink.pin = None
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with no authentication required
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data="0")
|
||||||
|
|
||||||
|
# THEN: proper processing should have occured
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == S_CONNECT, 'Should have returned {data}'.format(data=STATUS_CODE[S_CONNECT])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_normal_pin_set_error(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test process_pjlinnk called with no authentication but pin is set
|
||||||
|
"""
|
||||||
|
# GIVEN: Initial mocks and data
|
||||||
|
log_error_calls = [call('({ip}) Normal connection but PIN set - '
|
||||||
|
'aborting'.format(ip=self.pjlink.name))]
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "0"'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.pin = TEST_PIN
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with invalid authentication scheme
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data='0')
|
||||||
|
|
||||||
|
# THEN: Proper calls should be made
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == E_NO_AUTHENTICATION, \
|
||||||
|
'Should have returned {data}'.format(data=STATUS_CODE[E_NO_AUTHENTICATION])
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlinkcommands, 'log')
|
||||||
|
def test_process_pjlink_normal_with_token(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test process_pjlinnk called with no authentication but pin is set
|
||||||
|
"""
|
||||||
|
# GIVEN: Initial mocks and data
|
||||||
|
log_error_calls = [call('({ip}) Normal connection with extra information - '
|
||||||
|
'aborting'.format(ip=self.pjlink.name))]
|
||||||
|
log_warning_calls = []
|
||||||
|
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data '
|
||||||
|
'"0 {data}"'.format(ip=self.pjlink.name, data=TEST_SALT)),
|
||||||
|
call('({ip}) Calling function for PJLINK'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}) Processing PJLINK command'.format(ip=self.pjlink.name))]
|
||||||
|
self.pjlink.pin = TEST_PIN
|
||||||
|
|
||||||
|
# WHEN: process_pjlink called with invalid authentication scheme
|
||||||
|
chk = process_command(projector=self.pjlink, cmd='PJLINK', data='0 {data}'.format(data=TEST_SALT))
|
||||||
|
|
||||||
|
# THEN: Proper calls should be made
|
||||||
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert chk == E_NO_AUTHENTICATION, \
|
||||||
|
'Should have returned {data}'.format(data=STATUS_CODE[E_NO_AUTHENTICATION])
|
@ -20,7 +20,7 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
##########################################################################
|
##########################################################################
|
||||||
"""
|
"""
|
||||||
Package to test the openlp.core.projectors.pjlink base package.
|
Package to test the openlp.core.projectors.pjlink base package part 1.
|
||||||
"""
|
"""
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import MagicMock, call, patch
|
from unittest.mock import MagicMock, call, patch
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
##########################################################################
|
##########################################################################
|
||||||
"""
|
"""
|
||||||
Package to test the openlp.core.projectors.pjlink base package.
|
Package to test the openlp.core.projectors.pjlink base package part 2.
|
||||||
"""
|
"""
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import call, patch
|
from unittest.mock import call, patch
|
||||||
@ -96,10 +96,10 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
mock_change_status.called_with(E_NETWORK, 'Error while sending data to projector')
|
mock_change_status.called_with(E_NETWORK, 'Error while sending data to projector')
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert mock_timer.start.called, 'Timer should have been called'
|
assert mock_timer.start.called, 'Timer should have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not should have been called'
|
assert not mock_reset.called, 'reset_information() should not should have been called'
|
||||||
assert mock_disconnect.called, 'disconnect_from_host() should have been called'
|
assert mock_disconnect.called, 'disconnect_from_host() should have been called'
|
||||||
assert self.pjlink.send_busy, 'send_busy should be True'
|
assert self.pjlink.send_busy, 'send_busy should be True'
|
||||||
|
|
||||||
@ -127,41 +127,10 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert (not mock_timer.called), 'Timer should not have been called'
|
assert not mock_timer.called, 'Timer should not have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
|
|
||||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
|
||||||
def test_local_send_command_no_data_queue_check(self, mock_log, mock_reset, mock_state):
|
|
||||||
"""
|
|
||||||
Test _underscore_send_command last queue length check
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
log_error_calls = []
|
|
||||||
log_warning_calls = [call('({ip}) _send_command(): No data to send'.format(ip=self.pjlink.name))]
|
|
||||||
log_debug_calls = []
|
|
||||||
mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
|
|
||||||
self.pjlink.priority_queue = []
|
|
||||||
|
|
||||||
# WHEN: _send_command called with no data and queue's emtpy
|
|
||||||
# Patch some attributes here since they are not available until after instantiation
|
|
||||||
with patch.object(self.pjlink, 'socket_timer') as mock_timer, \
|
|
||||||
patch.object(self.pjlink, 'send_queue') as mock_queue:
|
|
||||||
# Unlikely case of send_queue not really empty, but len(send_queue) returns 0
|
|
||||||
mock_queue.return_value = ['test']
|
|
||||||
mock_queue.__len__.return_value = 0
|
|
||||||
self.pjlink._send_command(data=None)
|
|
||||||
|
|
||||||
# THEN:
|
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
|
||||||
assert (not mock_timer.called), 'Timer should not have been called'
|
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
|
||||||
@ -204,11 +173,11 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert mock_timer.start.called, 'Timer should have been called'
|
assert mock_timer.start.called, 'Timer should have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert (not mock_disconnect.called), 'disconnect_from_host() should not have been called'
|
assert not mock_disconnect.called, 'disconnect_from_host() should not have been called'
|
||||||
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
|
||||||
@ -242,12 +211,12 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
assert (self.pjlink.send_queue == [test_command]), 'Send queue should have one entry'
|
assert self.pjlink.send_queue == [test_command], 'Send queue should have one entry'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert (not mock_timer.called), 'Timer should not have been called'
|
assert not mock_timer.called, 'Timer should not have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert mock_disconnect.called, 'disconnect_from_host() should have been called'
|
assert mock_disconnect.called, 'disconnect_from_host() should have been called'
|
||||||
assert (not self.pjlink.send_busy), 'send_busy flag should be False'
|
assert not self.pjlink.send_busy, 'send_busy flag should be False'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
|
||||||
@ -292,11 +261,11 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert mock_timer.start.called, 'Timer should have been called'
|
assert mock_timer.start.called, 'Timer should have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert (not mock_disconnect.called), 'disconnect_from_host() should not have been called'
|
assert not mock_disconnect.called, 'disconnect_from_host() should not have been called'
|
||||||
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
|
||||||
@ -345,10 +314,10 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
assert self.pjlink.send_queue, 'Send queue should have one entry'
|
assert self.pjlink.send_queue, 'Send queue should have one entry'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert mock_timer.start.called, 'Timer should have been called'
|
assert mock_timer.start.called, 'Timer should have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert (not mock_disconnect.called), 'disconnect_from_host() should not have been called'
|
assert not mock_disconnect.called, 'disconnect_from_host() should not have been called'
|
||||||
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -389,9 +358,9 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
assert self.pjlink.send_queue, 'Send queue should have one entry'
|
assert self.pjlink.send_queue, 'Send queue should have one entry'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert (not mock_timer.start.called), 'Timer should not have been called'
|
assert not mock_timer.start.called, 'Timer should not have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -433,10 +402,10 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert self.pjlink.priority_queue, 'Priority queue should have one entry'
|
assert self.pjlink.priority_queue, 'Priority queue should have one entry'
|
||||||
assert (not mock_timer.start.called), 'Timer should not have been called'
|
assert not mock_timer.start.called, 'Timer should not have been called'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
assert self.pjlink.send_busy, 'send_busy flag should be True'
|
||||||
|
|
||||||
# ------------ Test PJLink.send_command ----------
|
# ------------ Test PJLink.send_command ----------
|
||||||
@ -471,7 +440,7 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -504,8 +473,8 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
mock_priority.append.assert_called_with(test_command)
|
mock_priority.append.assert_called_with(test_command)
|
||||||
assert (not mock_send.append.called), 'send_queue should not have changed'
|
assert not mock_send.append.called, 'send_queue should not have changed'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -537,9 +506,9 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
assert (self.pjlink.send_queue == [test_command]), 'Send queue should have one entry'
|
assert self.pjlink.send_queue == [test_command], 'Send queue should have one entry'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -571,9 +540,9 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert (self.pjlink.priority_queue == [test_command]), 'Priority queue should have one entry'
|
assert self.pjlink.priority_queue == [test_command], 'Priority queue should have one entry'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -600,10 +569,10 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert (not mock_send_command.called), '_underscore_send_command() should not have been called'
|
assert not mock_send_command.called, '_underscore_send_command() should not have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
|
||||||
@ -633,8 +602,8 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
assert self.pjlink.send_queue, 'Send queue should have one entry'
|
assert self.pjlink.send_queue, 'Send queue should have one entry'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -664,9 +633,9 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert self.pjlink.priority_queue, 'Priority queue should have one entry'
|
assert self.pjlink.priority_queue, 'Priority queue should have one entry'
|
||||||
assert (not mock_reset.called), 'reset_information() should not have been called'
|
assert not mock_reset.called, 'reset_information() should not have been called'
|
||||||
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
assert mock_send_command.called, '_underscore_send_command() should have been called'
|
||||||
|
|
||||||
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
@patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
|
||||||
@ -692,7 +661,7 @@ class TestPJLinkBase(TestCase):
|
|||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
mock_log.warning.assert_has_calls(log_warning_calls)
|
mock_log.warning.assert_has_calls(log_warning_calls)
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
mock_log.error.assert_has_calls(log_error_calls)
|
||||||
assert (not self.pjlink.send_queue), 'Send queue should be empty'
|
assert not self.pjlink.send_queue, 'Send queue should be empty'
|
||||||
assert (not self.pjlink.priority_queue), 'Priority queue should be empty'
|
assert not self.pjlink.priority_queue, 'Priority queue should be empty'
|
||||||
assert mock_reset.called, 'reset_information() should have been called'
|
assert mock_reset.called, 'reset_information() should have been called'
|
||||||
assert (not mock_send_command.called), '_underscore_send_command() should not have been called'
|
assert not mock_send_command.called, '_underscore_send_command() should not have been called'
|
||||||
|
130
tests/openlp_core/projectors/test_projector_pjlink_base_03.py
Normal file
130
tests/openlp_core/projectors/test_projector_pjlink_base_03.py
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2019 OpenLP Developers #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# This program is free software: you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the GNU General Public License as published by #
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or #
|
||||||
|
# (at your option) any later version. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, #
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||||
|
# GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License #
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
|
##########################################################################
|
||||||
|
"""
|
||||||
|
Package to test the openlp.core.projectors.pjlink base package part 3.
|
||||||
|
"""
|
||||||
|
from unittest import TestCase
|
||||||
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
|
import openlp.core.projectors.pjlink
|
||||||
|
from openlp.core.projectors.constants import PJLINK_CLASS, STATUS_CODE, \
|
||||||
|
S_NOT_CONNECTED, S_OFF, S_ON, QSOCKET_STATE
|
||||||
|
from openlp.core.projectors.db import Projector
|
||||||
|
from openlp.core.projectors.pjlink import PJLink
|
||||||
|
from tests.resources.projector.data import TEST1_DATA
|
||||||
|
|
||||||
|
|
||||||
|
class TestPJLinkBase(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for the PJLink module
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Initialize test state(s)
|
||||||
|
"""
|
||||||
|
# Default PJLink instance for tests
|
||||||
|
self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Cleanup test state(s)
|
||||||
|
"""
|
||||||
|
del(self.pjlink)
|
||||||
|
|
||||||
|
@patch.object(openlp.core.projectors.pjlink, 'log')
|
||||||
|
def test_projector_reset_information(self, mock_log):
|
||||||
|
"""
|
||||||
|
Test reset_information() resets all information and stops timers
|
||||||
|
"""
|
||||||
|
# GIVEN: Test object
|
||||||
|
log_debug_calls = [call('({ip}) reset_information() connect status is '
|
||||||
|
'S_NOT_CONNECTED'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}): Calling poll_timer.stop()'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}): Calling socket_timer.stop()'.format(ip=self.pjlink.name)),
|
||||||
|
call('({ip}): Calling status_timer.stop()'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
|
# Attributes not available until instantiation, so mock here
|
||||||
|
with patch.object(self.pjlink, 'socket_timer') as mock_socket_timer, \
|
||||||
|
patch.object(self.pjlink, 'status_timer') as mock_status_timer, \
|
||||||
|
patch.object(self.pjlink, 'poll_timer') as mock_poll_timer, \
|
||||||
|
patch.object(self.pjlink, 'state') as mock_state:
|
||||||
|
mock_state.return_value = QSOCKET_STATE[S_NOT_CONNECTED]
|
||||||
|
# Set attributes to something other than None or {} or []
|
||||||
|
self.pjlink.fan = True
|
||||||
|
self.pjlink.filter_time = True
|
||||||
|
self.pjlink.lamp = True
|
||||||
|
self.pjlink.mac_adx_received = 'Some random MAC'
|
||||||
|
self.pjlink.manufacturer = 'PJLINK'
|
||||||
|
self.pjlink.model = '1'
|
||||||
|
self.pjlink.model_filter = 'Filter'
|
||||||
|
self.pjlink.model_lamp = 'Lamp'
|
||||||
|
self.pjlink.mute = True
|
||||||
|
self.pjlink.other_info = 'Another Test'
|
||||||
|
self.pjlink.pjlink_class = 2
|
||||||
|
self.pjlink.pjlink_name = 'OPENLPTEST'
|
||||||
|
self.pjlink.power = S_ON
|
||||||
|
self.pjlink.projector_errors = {'test1': True, 'test2': False}
|
||||||
|
self.pjlink.serial_no = 'Some Number'
|
||||||
|
self.pjlink.serial_no_received = 'Some Other Number'
|
||||||
|
self.pjlink.sw_version = 'Some Version'
|
||||||
|
self.pjlink.sw_version_received = 'Some Other Version'
|
||||||
|
self.pjlink.shutter = True
|
||||||
|
self.pjlink.source_available = True
|
||||||
|
self.pjlink.source = True
|
||||||
|
self.pjlink.status_timer_checks = {'test1': object(), 'test2': object()}
|
||||||
|
self.pjlink.send_busy = False
|
||||||
|
self.pjlink.send_queue = ['test1', 'test2']
|
||||||
|
self.pjlink.priority_queue = ['test1', 'test2']
|
||||||
|
|
||||||
|
# WHEN: reset_information() is called
|
||||||
|
self.pjlink.reset_information()
|
||||||
|
|
||||||
|
# THEN: All information should be reset and timers stopped
|
||||||
|
mock_log.debug.assert_has_calls(log_debug_calls)
|
||||||
|
assert self.pjlink.fan is None, 'fan should be None'
|
||||||
|
assert self.pjlink.filter_time is None, 'filter_time should be None'
|
||||||
|
assert self.pjlink.lamp is None, 'lamp should be None'
|
||||||
|
assert self.pjlink.mac_adx_received is None, 'mac_adx_received should be None'
|
||||||
|
assert self.pjlink.manufacturer is None, 'manufacturer should be None'
|
||||||
|
assert self.pjlink.model is None, 'model should be None'
|
||||||
|
assert self.pjlink.model_filter is None, 'model_filter should be None'
|
||||||
|
assert self.pjlink.model_lamp is None, 'model_lamp should be None'
|
||||||
|
assert not self.pjlink.mute, 'mute should be False'
|
||||||
|
assert self.pjlink.other_info is None, 'other should be None'
|
||||||
|
assert self.pjlink.pjlink_class == PJLINK_CLASS, 'pjlink_class should be {cls}'.format(cls=PJLINK_CLASS)
|
||||||
|
assert self.pjlink.pjlink_name is None, 'pjlink_name should be None'
|
||||||
|
assert self.pjlink.power == S_OFF, 'power should be {data}'.format(data=STATUS_CODE[S_OFF])
|
||||||
|
assert self.pjlink.projector_errors == {}, 'projector_errors should be an empty dict'
|
||||||
|
assert self.pjlink.serial_no is None, 'serial_no should be None'
|
||||||
|
assert self.pjlink.serial_no_received is None, 'serial_no_received should be None'
|
||||||
|
assert self.pjlink.sw_version is None, 'sw_version should be None'
|
||||||
|
assert self.pjlink.sw_version_received is None, 'sw_version_received should be None'
|
||||||
|
assert not self.pjlink.shutter, 'shutter should be False'
|
||||||
|
assert self.pjlink.source_available is None, 'source_available should be None'
|
||||||
|
assert self.pjlink.source is None, 'source should be None'
|
||||||
|
assert self.pjlink.status_timer_checks == {}, 'status_timer_checks should be an empty dict'
|
||||||
|
assert not self.pjlink.send_busy, 'send_busy should be False'
|
||||||
|
assert self.pjlink.send_queue == [], 'send_queue should be an empty list'
|
||||||
|
assert self.pjlink.priority_queue == [], 'priority_queue should be an empty list'
|
||||||
|
assert mock_socket_timer.stop.called, 'socket_timer.stop() should have been called'
|
||||||
|
assert mock_status_timer.stop.called, 'status_timer.stop() should have been called'
|
||||||
|
assert mock_poll_timer.stop.called, 'poll_timer.stop() should have been called'
|
@ -23,12 +23,11 @@
|
|||||||
Package to test the openlp.core.projectors.pjlink command routing.
|
Package to test the openlp.core.projectors.pjlink command routing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from unittest import TestCase, skip
|
from unittest import TestCase
|
||||||
from unittest.mock import call, patch
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
import openlp.core.projectors.pjlink
|
import openlp.core.projectors.pjlink
|
||||||
from openlp.core.projectors.constants import E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED, \
|
from openlp.core.projectors.constants import PJLINK_PREFIX
|
||||||
PJLINK_ERRORS, PJLINK_PREFIX, STATUS_MSG
|
|
||||||
from openlp.core.projectors.db import Projector
|
from openlp.core.projectors.db import Projector
|
||||||
from openlp.core.projectors.pjlink import PJLink
|
from openlp.core.projectors.pjlink import PJLink
|
||||||
from tests.resources.projector.data import TEST1_DATA
|
from tests.resources.projector.data import TEST1_DATA
|
||||||
@ -57,9 +56,9 @@ class TestPJLinkRouting(TestCase):
|
|||||||
Test projector received valid command invalid version
|
Test projector received valid command invalid version
|
||||||
"""
|
"""
|
||||||
# GIVEN: Test object
|
# GIVEN: Test object
|
||||||
log_warning_text = [call('({ip}) get_data() Command reply version does not match '
|
log_warning_text = [call('({ip}) _send_command(): Nothing to send - returning'.format(ip=self.pjlink.name)),
|
||||||
'a valid command version'.format(ip=self.pjlink.name)),
|
call('({ip}) get_data() Command reply version does not match '
|
||||||
call('({ip}) _send_command(): Nothing to send - returning'.format(ip=self.pjlink.name))]
|
'a valid command version'.format(ip=self.pjlink.name))]
|
||||||
log_debug_text = [call('({ip}) get_data(buffer="{pre}XCLSS=X"'.format(ip=self.pjlink.name, pre=PJLINK_PREFIX)),
|
log_debug_text = [call('({ip}) get_data(buffer="{pre}XCLSS=X"'.format(ip=self.pjlink.name, pre=PJLINK_PREFIX)),
|
||||||
call('({ip}) get_data(): Checking new data "{pre}XCLSS=X"'.format(ip=self.pjlink.name,
|
call('({ip}) get_data(): Checking new data "{pre}XCLSS=X"'.format(ip=self.pjlink.name,
|
||||||
pre=PJLINK_PREFIX)),
|
pre=PJLINK_PREFIX)),
|
||||||
@ -84,10 +83,10 @@ class TestPJLinkRouting(TestCase):
|
|||||||
Test projector receiving invalid command
|
Test projector receiving invalid command
|
||||||
"""
|
"""
|
||||||
# GIVEN: Test object
|
# GIVEN: Test object
|
||||||
log_warning_text = [call('({ip}) get_data(): Invalid packet - '
|
log_warning_text = [call('({ip}) _send_command(): Nothing to send - '
|
||||||
'unknown command "UNKN"'.format(ip=self.pjlink.name)),
|
'returning'.format(ip=self.pjlink.name)),
|
||||||
call('({ip}) _send_command(): Nothing to send - '
|
call('({ip}) get_data(): Invalid packet - '
|
||||||
'returning'.format(ip=self.pjlink.name))]
|
'unknown command "UNKN"'.format(ip=self.pjlink.name))]
|
||||||
log_debug_text = [call('({ip}) get_data(buffer="{pre}1UNKN=Huh?"'.format(ip=self.pjlink.name,
|
log_debug_text = [call('({ip}) get_data(buffer="{pre}1UNKN=Huh?"'.format(ip=self.pjlink.name,
|
||||||
pre=PJLINK_PREFIX)),
|
pre=PJLINK_PREFIX)),
|
||||||
call('({ip}) get_data(): Checking new data "{pre}1UNKN=Huh?"'.format(ip=self.pjlink.name,
|
call('({ip}) get_data(): Checking new data "{pre}1UNKN=Huh?"'.format(ip=self.pjlink.name,
|
||||||
@ -114,9 +113,9 @@ class TestPJLinkRouting(TestCase):
|
|||||||
Test projector received valid command with command version higher than projector
|
Test projector received valid command with command version higher than projector
|
||||||
"""
|
"""
|
||||||
# GIVEN: Test object
|
# GIVEN: Test object
|
||||||
log_warning_text = [call('({ip}) get_data(): Projector returned class reply higher than projector '
|
log_warning_text = [call('({ip}) _send_command(): Nothing to send - returning'.format(ip=self.pjlink.name)),
|
||||||
'stated class'.format(ip=self.pjlink.name)),
|
call('({ip}) get_data(): Projector returned class reply higher than projector '
|
||||||
call('({ip}) _send_command(): Nothing to send - returning'.format(ip=self.pjlink.name))]
|
'stated class'.format(ip=self.pjlink.name))]
|
||||||
|
|
||||||
log_debug_text = [call('({ip}) get_data(buffer="{pre}2ACKN=X"'.format(ip=self.pjlink.name,
|
log_debug_text = [call('({ip}) get_data(buffer="{pre}2ACKN=X"'.format(ip=self.pjlink.name,
|
||||||
pre=PJLINK_PREFIX)),
|
pre=PJLINK_PREFIX)),
|
||||||
@ -134,119 +133,3 @@ class TestPJLinkRouting(TestCase):
|
|||||||
mock_log.warning.assert_has_calls(log_warning_text)
|
mock_log.warning.assert_has_calls(log_warning_text)
|
||||||
mock_log.debug.assert_has_calls(log_debug_text)
|
mock_log.debug.assert_has_calls(log_debug_text)
|
||||||
assert (mock_process_cmd.call_count == 0), 'process_command should not have been called'
|
assert (mock_process_cmd.call_count == 0), 'process_command should not have been called'
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_routing_err1(self):
|
|
||||||
"""
|
|
||||||
Test ERR1 - Undefined projector function
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=self.pjlink.name, msg=STATUS_MSG[E_UNDEFINED]))]
|
|
||||||
log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR1"'.format(ip=self.pjlink.name)),
|
|
||||||
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_command called with ERR1
|
|
||||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
|
|
||||||
|
|
||||||
# THEN: Appropriate log entries should have been made and methods called
|
|
||||||
mock_log.error.assert_has_calls(log_error_text)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_text)
|
|
||||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNDEFINED])
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_routing_err2(self):
|
|
||||||
"""
|
|
||||||
Test ERR2 - Parameter Error
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=self.pjlink.name, msg=STATUS_MSG[E_PARAMETER]))]
|
|
||||||
log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR2"'.format(ip=self.pjlink.name)),
|
|
||||||
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_command called with ERR2
|
|
||||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
|
|
||||||
|
|
||||||
# THEN: Appropriate log entries should have been made and methods called/not called
|
|
||||||
mock_log.error.assert_has_calls(log_error_text)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_text)
|
|
||||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PARAMETER])
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_routing_err3(self):
|
|
||||||
"""
|
|
||||||
Test ERR3 - Unavailable error
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=self.pjlink.name, msg=STATUS_MSG[E_UNAVAILABLE]))]
|
|
||||||
log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR3"'.format(ip=self.pjlink.name)),
|
|
||||||
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_command called with ERR3
|
|
||||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
|
|
||||||
|
|
||||||
# THEN: Appropriate log entries should have been made and methods called
|
|
||||||
mock_log.error.assert_has_calls(log_error_text)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_text)
|
|
||||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNAVAILABLE])
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_routing_err4(self):
|
|
||||||
"""
|
|
||||||
Test ERR3 - Unavailable error
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=self.pjlink.name, msg=STATUS_MSG[E_PROJECTOR]))]
|
|
||||||
log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR4"'.format(ip=self.pjlink.name)),
|
|
||||||
call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_command called with ERR4
|
|
||||||
pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
|
|
||||||
|
|
||||||
# THEN: Appropriate log entries should have been made and methods called
|
|
||||||
mock_log.error.assert_has_calls(log_error_text)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_text)
|
|
||||||
mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PROJECTOR])
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_routing_erra(self):
|
|
||||||
"""
|
|
||||||
Test ERRA - Authentication Error
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'process_pjlink') as mock_process_pjlink, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') as mock_disconnect, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorAuthentication') as mock_authentication:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_error_calls = [call('({ip}) PJLINK: {msg}'.format(ip=self.pjlink.name,
|
|
||||||
msg=STATUS_MSG[E_AUTHENTICATION]))]
|
|
||||||
log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "ERRA"'.format(ip=self.pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_command called with ERRA
|
|
||||||
pjlink.process_command(cmd='PJLINK', data=PJLINK_ERRORS[E_AUTHENTICATION])
|
|
||||||
|
|
||||||
# THEN: Appropriate log entries should have been made and methods called/not called
|
|
||||||
assert mock_disconnect.called is True, 'disconnect_from_host should have been called'
|
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
mock_change_status.assert_called_once_with(status=E_AUTHENTICATION)
|
|
||||||
mock_authentication.emit.assert_called_once_with(pjlink.name)
|
|
||||||
mock_process_pjlink.assert_not_called()
|
|
||||||
|
@ -1,853 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# OpenLP - Open Source Lyrics Projection #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# Copyright (c) 2008-2019 OpenLP Developers #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# This program is free software: you can redistribute it and/or modify #
|
|
||||||
# it under the terms of the GNU General Public License as published by #
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or #
|
|
||||||
# (at your option) any later version. #
|
|
||||||
# #
|
|
||||||
# This program is distributed in the hope that it will be useful, #
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
||||||
# GNU General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU General Public License #
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
||||||
##########################################################################
|
|
||||||
"""
|
|
||||||
Package to test the openlp.core.projectors.pjlink commands package.
|
|
||||||
"""
|
|
||||||
from unittest import TestCase, skip
|
|
||||||
from unittest.mock import call, patch
|
|
||||||
|
|
||||||
import openlp.core.projectors.pjlink
|
|
||||||
from openlp.core.projectors.constants import E_ERROR, E_WARN, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
|
|
||||||
PJLINK_POWR_STATUS, S_NOT_CONNECTED, S_OK, S_ON, S_STANDBY, STATUS_CODE
|
|
||||||
from openlp.core.projectors.db import Projector
|
|
||||||
from openlp.core.projectors.pjlink import PJLink
|
|
||||||
from tests.resources.projector.data import TEST1_DATA
|
|
||||||
|
|
||||||
|
|
||||||
class TestPJLinkCommands(TestCase):
|
|
||||||
"""
|
|
||||||
Tests for the PJLinkCommands class part 1
|
|
||||||
"""
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_inf1(self):
|
|
||||||
"""
|
|
||||||
Test saving INF1 data (manufacturer)
|
|
||||||
"""
|
|
||||||
test_data = 'TEst INformation MultiCase'
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.manufacturer = None
|
|
||||||
|
|
||||||
# WHEN: process_inf called with test data
|
|
||||||
pjlink.process_inf1(data=test_data)
|
|
||||||
|
|
||||||
# THEN: Data should be saved
|
|
||||||
assert pjlink.manufacturer == test_data, 'Test data should have been saved'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_inf2(self):
|
|
||||||
"""
|
|
||||||
Test saving INF2 data (model)
|
|
||||||
"""
|
|
||||||
test_data = 'TEst moDEl MultiCase'
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.model = None
|
|
||||||
|
|
||||||
# WHEN: process_inf called with test data
|
|
||||||
pjlink.process_inf2(data=test_data)
|
|
||||||
|
|
||||||
# THEN: Data should be saved
|
|
||||||
assert pjlink.model == test_data, 'Test data should have been saved'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_info(self):
|
|
||||||
"""
|
|
||||||
Test saving INFO data (other information)
|
|
||||||
"""
|
|
||||||
test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.other_info = None
|
|
||||||
|
|
||||||
# WHEN: process_inf called with test data
|
|
||||||
pjlink.process_info(data=test_data)
|
|
||||||
|
|
||||||
# THEN: Data should be saved
|
|
||||||
assert pjlink.other_info == test_data, 'Test data should have been saved'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_avmt_bad_data(self):
|
|
||||||
"""
|
|
||||||
Test avmt bad data fail
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.shutter = True
|
|
||||||
pjlink.mute = True
|
|
||||||
|
|
||||||
# WHEN: Called with an invalid setting
|
|
||||||
pjlink.process_avmt('36')
|
|
||||||
|
|
||||||
# THEN: Shutter should be closed and mute should be True
|
|
||||||
assert pjlink.shutter is True, 'Shutter should changed'
|
|
||||||
assert pjlink.mute is True, 'Audio should not have changed'
|
|
||||||
assert mock_UpdateIcons.emit.called is False, 'Update icons should NOT have been called'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_avmt_closed_muted(self):
|
|
||||||
"""
|
|
||||||
Test avmt status shutter closed and mute off
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.shutter = False
|
|
||||||
pjlink.mute = False
|
|
||||||
|
|
||||||
# WHEN: Called with setting shutter to closed and mute on
|
|
||||||
pjlink.process_avmt('31')
|
|
||||||
|
|
||||||
# THEN: Shutter should be closed and mute should be True
|
|
||||||
assert pjlink.shutter is True, 'Shutter should have been set to closed'
|
|
||||||
assert pjlink.mute is True, 'Audio should be muted'
|
|
||||||
assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_avmt_shutter_closed(self):
|
|
||||||
"""
|
|
||||||
Test avmt status shutter closed and audio unchanged
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.shutter = False
|
|
||||||
pjlink.mute = True
|
|
||||||
|
|
||||||
# WHEN: Called with setting shutter closed and mute off
|
|
||||||
pjlink.process_avmt('11')
|
|
||||||
|
|
||||||
# THEN: Shutter should be True and mute should be False
|
|
||||||
assert pjlink.shutter is True, 'Shutter should have been set to closed'
|
|
||||||
assert pjlink.mute is True, 'Audio should not have changed'
|
|
||||||
assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_avmt_audio_muted(self):
|
|
||||||
"""
|
|
||||||
Test avmt status shutter unchanged and mute on
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.shutter = True
|
|
||||||
pjlink.mute = False
|
|
||||||
|
|
||||||
# WHEN: Called with setting shutter closed and mute on
|
|
||||||
pjlink.process_avmt('21')
|
|
||||||
|
|
||||||
# THEN: Shutter should be closed and mute should be True
|
|
||||||
assert pjlink.shutter is True, 'Shutter should not have changed'
|
|
||||||
assert pjlink.mute is True, 'Audio should be off'
|
|
||||||
assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_avmt_open_unmuted(self):
|
|
||||||
"""
|
|
||||||
Test avmt status shutter open and mute off
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.shutter = True
|
|
||||||
pjlink.mute = True
|
|
||||||
|
|
||||||
# WHEN: Called with setting shutter to closed and mute on
|
|
||||||
pjlink.process_avmt('30')
|
|
||||||
|
|
||||||
# THEN: Shutter should be closed and mute should be True
|
|
||||||
assert pjlink.shutter is False, 'Shutter should have been set to open'
|
|
||||||
assert pjlink.mute is False, 'Audio should be on'
|
|
||||||
assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_clss_one(self):
|
|
||||||
"""
|
|
||||||
Test class 1 sent from projector
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
|
|
||||||
# WHEN: Process class response
|
|
||||||
pjlink.process_clss('1')
|
|
||||||
|
|
||||||
# THEN: Projector class should be set to 1
|
|
||||||
assert pjlink.pjlink_class == '1', 'Projector should have set class=1'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_clss_two(self):
|
|
||||||
"""
|
|
||||||
Test class 2 sent from projector
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
|
|
||||||
# WHEN: Process class response
|
|
||||||
pjlink.process_clss('2')
|
|
||||||
|
|
||||||
# THEN: Projector class should be set to 1
|
|
||||||
assert pjlink.pjlink_class == '2', 'Projector should have set class=2'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_clss_invalid_nan(self):
|
|
||||||
"""
|
|
||||||
Test CLSS reply has no class number
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_debug_calls = [call('({ip}) reset_information() connect status is '
|
|
||||||
'{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])),
|
|
||||||
call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=pjlink.name))]
|
|
||||||
log_error_calls = [call('({ip}) NAN CLSS version reply "Z" - '
|
|
||||||
'defaulting to class "1"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: Process invalid reply
|
|
||||||
pjlink.process_clss('Z')
|
|
||||||
|
|
||||||
# THEN: Projector class should be set with default value
|
|
||||||
assert pjlink.pjlink_class == '1', 'Invalid NaN class reply should have set class=1'
|
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_clss_invalid_no_version(self):
|
|
||||||
"""
|
|
||||||
Test CLSS reply has no class number
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_debug_calls = [call('({ip}) reset_information() connect status is '
|
|
||||||
'{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])),
|
|
||||||
call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=pjlink.name))]
|
|
||||||
log_error_calls = [call('({ip}) No numbers found in class version reply "Invalid" '
|
|
||||||
'- defaulting to class "1"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: Process invalid reply
|
|
||||||
pjlink.process_clss('Invalid')
|
|
||||||
|
|
||||||
# THEN: Projector class should be set with default value
|
|
||||||
assert pjlink.pjlink_class == '1', 'Invalid class reply should have set class=1'
|
|
||||||
mock_log.error.assert_has_calls(log_error_calls)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_clss_nonstandard_reply_1(self):
|
|
||||||
"""
|
|
||||||
Test CLSS request returns non-standard reply 1
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
|
|
||||||
# WHEN: Process non-standard reply
|
|
||||||
pjlink.process_clss('Class 1')
|
|
||||||
|
|
||||||
# THEN: Projector class should be set with proper value
|
|
||||||
assert '1' == pjlink.pjlink_class, 'Non-standard class reply should have set class=1'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_clss_nonstandard_reply_2(self):
|
|
||||||
"""
|
|
||||||
Test CLSS request returns non-standard reply 2
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
|
|
||||||
# WHEN: Process non-standard reply
|
|
||||||
pjlink.process_clss('Version2')
|
|
||||||
|
|
||||||
# THEN: Projector class should be set with proper value
|
|
||||||
assert '2' == pjlink.pjlink_class, 'Non-standard class reply should have set class=2'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_erst_all_ok(self):
|
|
||||||
"""
|
|
||||||
Test to verify pjlink.projector_errors is set to None when no errors
|
|
||||||
"""
|
|
||||||
chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH']
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
|
|
||||||
# WHEN: process_erst with no errors
|
|
||||||
pjlink.process_erst(chk_data)
|
|
||||||
|
|
||||||
# THEN: PJLink instance errors should be None
|
|
||||||
assert pjlink.projector_errors is None, 'projector_errors should have been set to None'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_erst_data_invalid_length(self):
|
|
||||||
"""
|
|
||||||
Test test_projector_process_erst_data_invalid_length
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.projector_errors = None
|
|
||||||
chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1)
|
|
||||||
log_debug_calls = [call('({ip}) reset_information() connect status is '
|
|
||||||
'{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED]))]
|
|
||||||
log_warn_calls = [call('({ip}) Invalid error status response "0000000": '
|
|
||||||
'length != {chk}'.format(ip=pjlink.name, chk=PJLINK_ERST_DATA['DATA_LENGTH']))]
|
|
||||||
|
|
||||||
# WHEN: process_erst called with invalid data (too many values
|
|
||||||
pjlink.process_erst(chk_data)
|
|
||||||
|
|
||||||
# THEN: pjlink.projector_errors should be empty and warning logged
|
|
||||||
assert pjlink.projector_errors is None, 'There should be no errors'
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_erst_data_invalid_nan(self):
|
|
||||||
"""
|
|
||||||
Test test_projector_process_erst_data_invalid_nan
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.projector_errors = None
|
|
||||||
chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1))
|
|
||||||
log_debug_calls = [call('({ip}) reset_information() connect status is '
|
|
||||||
'{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED]))]
|
|
||||||
log_warn_calls = [call('({ip}) Invalid error status response "Z00000"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_erst called with invalid data (too many values
|
|
||||||
pjlink.process_erst(chk_data)
|
|
||||||
|
|
||||||
# THEN: pjlink.projector_errors should be empty and warning logged
|
|
||||||
assert pjlink.projector_errors is None, 'There should be no errors'
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_erst_all_warn(self):
|
|
||||||
"""
|
|
||||||
Test test_projector_process_erst_all_warn
|
|
||||||
"""
|
|
||||||
chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN],
|
|
||||||
lamp=PJLINK_ERST_STATUS[E_WARN],
|
|
||||||
temp=PJLINK_ERST_STATUS[E_WARN],
|
|
||||||
cover=PJLINK_ERST_STATUS[E_WARN],
|
|
||||||
filt=PJLINK_ERST_STATUS[E_WARN],
|
|
||||||
other=PJLINK_ERST_STATUS[E_WARN])
|
|
||||||
chk_test = {'Fan': E_WARN,
|
|
||||||
'Lamp': E_WARN,
|
|
||||||
'Temperature': E_WARN,
|
|
||||||
'Cover': E_WARN,
|
|
||||||
'Filter': E_WARN,
|
|
||||||
'Other': E_WARN}
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.projector_errors = None
|
|
||||||
|
|
||||||
# WHEN: process_erst with status set to WARN
|
|
||||||
pjlink.process_erst(chk_data)
|
|
||||||
|
|
||||||
# THEN: PJLink instance errors should match chk_value
|
|
||||||
assert pjlink.projector_errors == chk_test, 'Projector errors should be all E_WARN'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_erst_all_error(self):
|
|
||||||
"""
|
|
||||||
Test test_projector_process_erst_all_error
|
|
||||||
"""
|
|
||||||
chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR],
|
|
||||||
lamp=PJLINK_ERST_STATUS[E_ERROR],
|
|
||||||
temp=PJLINK_ERST_STATUS[E_ERROR],
|
|
||||||
cover=PJLINK_ERST_STATUS[E_ERROR],
|
|
||||||
filt=PJLINK_ERST_STATUS[E_ERROR],
|
|
||||||
other=PJLINK_ERST_STATUS[E_ERROR])
|
|
||||||
chk_test = {'Fan': E_ERROR,
|
|
||||||
'Lamp': E_ERROR,
|
|
||||||
'Temperature': E_ERROR,
|
|
||||||
'Cover': E_ERROR,
|
|
||||||
'Filter': E_ERROR,
|
|
||||||
'Other': E_ERROR}
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.projector_errors = None
|
|
||||||
|
|
||||||
# WHEN: process_erst with status set to WARN
|
|
||||||
pjlink.process_erst(chk_data)
|
|
||||||
|
|
||||||
# THEN: PJLink instance errors should match chk_value
|
|
||||||
assert pjlink.projector_errors == chk_test, 'Projector errors should be all E_ERROR'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_erst_warn_cover_only(self):
|
|
||||||
"""
|
|
||||||
Test test_projector_process_erst_warn_cover_only
|
|
||||||
"""
|
|
||||||
chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK],
|
|
||||||
lamp=PJLINK_ERST_STATUS[S_OK],
|
|
||||||
temp=PJLINK_ERST_STATUS[S_OK],
|
|
||||||
cover=PJLINK_ERST_STATUS[E_WARN],
|
|
||||||
filt=PJLINK_ERST_STATUS[S_OK],
|
|
||||||
other=PJLINK_ERST_STATUS[S_OK])
|
|
||||||
chk_test = {'Cover': E_WARN}
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.projector_errors = None
|
|
||||||
|
|
||||||
# WHEN: process_erst with status set to WARN
|
|
||||||
pjlink.process_erst(chk_data)
|
|
||||||
|
|
||||||
# THEN: PJLink instance errors should match only cover warning
|
|
||||||
assert 1 == len(pjlink.projector_errors), 'There should only be 1 error listed in projector_errors'
|
|
||||||
assert 'Cover' in pjlink.projector_errors, '"Cover" should be the only error listed'
|
|
||||||
assert pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error'
|
|
||||||
assert chk_test == pjlink.projector_errors, 'projector_errors should match test errors'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_inpt_valid(self):
|
|
||||||
"""
|
|
||||||
Test input source status shows current input
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.source = '11'
|
|
||||||
log_debug_calls = [call('({ip}) reset_information() connect status is '
|
|
||||||
'S_NOT_CONNECTED'.format(ip=pjlink.name))]
|
|
||||||
chk_source_available = ['11', '12', '21', '22', '31', '32']
|
|
||||||
pjlink.source_available = chk_source_available
|
|
||||||
|
|
||||||
# WHEN: Called with input source
|
|
||||||
pjlink.process_inpt('21')
|
|
||||||
|
|
||||||
# THEN: Input selected should reflect current input
|
|
||||||
assert pjlink.source == '21', 'Input source should be set to "21"'
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_input_not_in_list(self):
|
|
||||||
"""
|
|
||||||
Test setting input outside of available inputs
|
|
||||||
|
|
||||||
TODO: Future test
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_input_not_in_default(self):
|
|
||||||
"""
|
|
||||||
Test setting input with no sources available
|
|
||||||
TODO: Future test
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_input_invalid(self):
|
|
||||||
"""
|
|
||||||
Test setting input with an invalid value
|
|
||||||
|
|
||||||
TODO: Future test
|
|
||||||
"""
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_inst_class_1(self):
|
|
||||||
"""
|
|
||||||
Test saving video source available information
|
|
||||||
"""
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.source_available = []
|
|
||||||
log_debug_calls = [call('({ip}) reset_information() connect status is '
|
|
||||||
'S_NOT_CONNECTED'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Setting projector source_available to '
|
|
||||||
'"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to verify method
|
|
||||||
chk_test = ['11', '12', '21', '22', '31', '32']
|
|
||||||
|
|
||||||
# WHEN: process_inst called with test data
|
|
||||||
pjlink.process_inst(data=chk_data)
|
|
||||||
|
|
||||||
# THEN: Data should have been sorted and saved properly
|
|
||||||
assert pjlink.source_available == chk_test, "Sources should have been sorted and saved"
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_lamp_invalid(self):
|
|
||||||
"""
|
|
||||||
Test status multiple lamp on/off and hours
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.lamp = [{'Hours': 00000, 'On': True},
|
|
||||||
{'Hours': 11111, 'On': False}]
|
|
||||||
log_data = [call('({ip}) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: Call process_command with invalid lamp data
|
|
||||||
pjlink.process_lamp('11111 1 22222 0 333A3 1')
|
|
||||||
|
|
||||||
# THEN: lamps should not have changed
|
|
||||||
assert 2 == len(pjlink.lamp), 'Projector should have kept 2 lamps specified'
|
|
||||||
assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have stayed TRUE'
|
|
||||||
assert 00000 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been left at 00000'
|
|
||||||
assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have stayed FALSE'
|
|
||||||
assert 11111 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been left at 11111'
|
|
||||||
mock_log.warning.assert_has_calls(log_data)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_lamp_multiple(self):
|
|
||||||
"""
|
|
||||||
Test status multiple lamp on/off and hours
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.lamp = []
|
|
||||||
|
|
||||||
# WHEN: Call process_command with invalid lamp data
|
|
||||||
pjlink.process_lamp('11111 1 22222 0 33333 1')
|
|
||||||
|
|
||||||
# THEN: Lamp should have been set with proper lamp status
|
|
||||||
assert 3 == len(pjlink.lamp), 'Projector should have 3 lamps specified'
|
|
||||||
assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have been set to TRUE'
|
|
||||||
assert 11111 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been set to 11111'
|
|
||||||
assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have been set to FALSE'
|
|
||||||
assert 22222 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been set to 22222'
|
|
||||||
assert pjlink.lamp[2]['On'] is True, 'Lamp 3 power status should have been set to TRUE'
|
|
||||||
assert 33333 == pjlink.lamp[2]['Hours'], 'Lamp 3 hours should have been set to 33333'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_lamp_single(self):
|
|
||||||
"""
|
|
||||||
Test status lamp on/off and hours
|
|
||||||
"""
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.lamp = []
|
|
||||||
|
|
||||||
# WHEN: Call process_command with invalid lamp data
|
|
||||||
pjlink.process_lamp('22222 1')
|
|
||||||
|
|
||||||
# THEN: Lamp should have been set with status=ON and hours=22222
|
|
||||||
assert 1 == len(pjlink.lamp), 'Projector should have only 1 lamp'
|
|
||||||
assert pjlink.lamp[0]['On'] is True, 'Lamp power status should have been set to TRUE'
|
|
||||||
assert 22222 == pjlink.lamp[0]['Hours'], 'Lamp hours should have been set to 22222'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_lamp_single_hours_only(self):
|
|
||||||
"""
|
|
||||||
Test process lamp with 1 lamp reply hours only and no on/off status
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.lamp = []
|
|
||||||
|
|
||||||
# WHEN: Process lamp command called with only hours and no lamp power state
|
|
||||||
pjlink.process_lamp("45")
|
|
||||||
|
|
||||||
# THEN: Lamp should show hours as 45 and lamp power as Unavailable
|
|
||||||
assert 1 == len(pjlink.lamp), 'There should only be 1 lamp available'
|
|
||||||
assert 45 == pjlink.lamp[0]['Hours'], 'Lamp hours should have equalled 45'
|
|
||||||
assert pjlink.lamp[0]['On'] is None, 'Lamp power should be "None"'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_name(self):
|
|
||||||
"""
|
|
||||||
Test saving NAME data from projector
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
chk_data = "Some Name the End-User Set IN Projector"
|
|
||||||
log_debug_calls = [call('({ip}) Setting projector PJLink name to '
|
|
||||||
'"Some Name the End-User Set IN Projector"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_name called with test data
|
|
||||||
pjlink.process_name(data=chk_data)
|
|
||||||
|
|
||||||
# THEN: name should be set and logged
|
|
||||||
assert pjlink.pjlink_name == chk_data, 'Name test data should have been saved'
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_powr_on(self):
|
|
||||||
"""
|
|
||||||
Test status power to ON
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.power = S_STANDBY
|
|
||||||
|
|
||||||
# WHEN: process_name called with test data
|
|
||||||
pjlink.process_powr(data=PJLINK_POWR_STATUS[S_ON])
|
|
||||||
|
|
||||||
# THEN: Power should be set to ON
|
|
||||||
assert pjlink.power == S_ON, 'Power should have been set to ON'
|
|
||||||
assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called'
|
|
||||||
mock_send_command.assert_called_once_with('INST')
|
|
||||||
mock_change_status.assert_called_once_with(S_ON)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_powr_invalid(self):
|
|
||||||
"""
|
|
||||||
Test process_powr invalid call
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.power = S_STANDBY
|
|
||||||
log_warn_calls = [call('({ip}) Unknown power response: "99"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_name called with test data
|
|
||||||
pjlink.process_powr(data='99')
|
|
||||||
|
|
||||||
# THEN: Power should be set to ON
|
|
||||||
assert pjlink.power == S_STANDBY, 'Power should not have changed'
|
|
||||||
mock_UpdateIcons.emit.assert_not_called()
|
|
||||||
mock_change_status.assert_not_called()
|
|
||||||
mock_send_command.assert_not_called()
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_powr_off(self):
|
|
||||||
"""
|
|
||||||
Test status power to STANDBY
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
|
|
||||||
patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.power = S_ON
|
|
||||||
|
|
||||||
# WHEN: process_name called with test data
|
|
||||||
pjlink.process_powr(data=PJLINK_POWR_STATUS[S_STANDBY])
|
|
||||||
|
|
||||||
# THEN: Power should be set to ON
|
|
||||||
assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY'
|
|
||||||
mock_UpdateIcons.emit.assert_called_with()
|
|
||||||
mock_change_status.assert_called_with(313)
|
|
||||||
mock_send_command.assert_not_called()
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_rfil_save(self):
|
|
||||||
"""
|
|
||||||
Test saving filter type
|
|
||||||
"""
|
|
||||||
filter_model = 'Filter Type Test'
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.model_filter = None
|
|
||||||
|
|
||||||
# WHEN: Filter model is received
|
|
||||||
pjlink.process_rfil(data=filter_model)
|
|
||||||
|
|
||||||
# THEN: Filter model number should be saved
|
|
||||||
assert pjlink.model_filter == filter_model, 'Filter type should have been saved'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_rfil_nosave(self):
|
|
||||||
"""
|
|
||||||
Test saving filter type previously saved
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.model_filter = 'Old filter type'
|
|
||||||
filter_model = 'Filter Type Test'
|
|
||||||
log_warn_calls = [call('({ip}) Filter model already set'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Saved model: "Old filter type"'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) New model: "Filter Type Test"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: Filter model is received
|
|
||||||
pjlink.process_rfil(data=filter_model)
|
|
||||||
|
|
||||||
# THEN: Filter model number should be saved
|
|
||||||
assert pjlink.model_filter != filter_model, 'Filter type should NOT have been saved'
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_rlmp_save(self):
|
|
||||||
"""
|
|
||||||
Test saving lamp type
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
# GIVEN: Test object
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.model_lamp = None
|
|
||||||
lamp_model = 'Lamp Type Test'
|
|
||||||
|
|
||||||
# WHEN: Filter model is received
|
|
||||||
pjlink.process_rlmp(data=lamp_model)
|
|
||||||
|
|
||||||
# THEN: Filter model number should be saved
|
|
||||||
assert pjlink.model_lamp == lamp_model, 'Lamp type should have been saved'
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_rlmp_nosave(self):
|
|
||||||
"""
|
|
||||||
Test saving lamp type previously saved
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.model_lamp = 'Old lamp type'
|
|
||||||
lamp_model = 'Lamp Type Test'
|
|
||||||
log_warn_calls = [call('({ip}) Lamp model already set'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Saved lamp: "Old lamp type"'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) New lamp: "Lamp Type Test"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: Filter model is received
|
|
||||||
pjlink.process_rlmp(data=lamp_model)
|
|
||||||
|
|
||||||
# THEN: Filter model number should be saved
|
|
||||||
assert pjlink.model_lamp != lamp_model, 'Lamp type should NOT have been saved'
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_snum_set(self):
|
|
||||||
"""
|
|
||||||
Test saving serial number from projector
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.serial_no = None
|
|
||||||
log_debug_calls = [call('({ip}) Setting projector serial number to '
|
|
||||||
'"Test Serial Number"'.format(ip=pjlink.name))]
|
|
||||||
test_number = 'Test Serial Number'
|
|
||||||
|
|
||||||
# WHEN: No serial number is set and we receive serial number command
|
|
||||||
pjlink.process_snum(data=test_number)
|
|
||||||
|
|
||||||
# THEN: Serial number should be set
|
|
||||||
assert pjlink.serial_no == test_number, 'Projector serial number should have been set'
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_snum_different(self):
|
|
||||||
"""
|
|
||||||
Test projector serial number different than saved serial number
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.serial_no = 'Previous serial number'
|
|
||||||
log_warn_calls = [call('({ip}) Projector serial number does not match '
|
|
||||||
'saved serial number'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Saved: "Previous serial number"'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Received: "Test Serial Number"'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) NOT saving serial number'.format(ip=pjlink.name))]
|
|
||||||
test_number = 'Test Serial Number'
|
|
||||||
|
|
||||||
# WHEN: No serial number is set and we receive serial number command
|
|
||||||
pjlink.process_snum(data=test_number)
|
|
||||||
|
|
||||||
# THEN: Serial number should be set
|
|
||||||
assert pjlink.serial_no != test_number, 'Projector serial number should NOT have been set'
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_sver(self):
|
|
||||||
"""
|
|
||||||
Test invalid software version information - too long
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.sw_version = None
|
|
||||||
pjlink.sw_version_received = None
|
|
||||||
test_data = 'Test 1 Subtest 1'
|
|
||||||
log_debug_calls = [call('({ip}) Setting projector software version to '
|
|
||||||
'"Test 1 Subtest 1"'.format(ip=pjlink.name))]
|
|
||||||
|
|
||||||
# WHEN: process_sver called with invalid data
|
|
||||||
pjlink.process_sver(data=test_data)
|
|
||||||
|
|
||||||
# THEN: Version information should not change
|
|
||||||
assert pjlink.sw_version == test_data, 'Software version should have been updated'
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_sver_changed(self):
|
|
||||||
"""
|
|
||||||
Test invalid software version information - Received different than saved
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
test_data_old = 'Test 1 Subtest 1'
|
|
||||||
test_data_new = 'Test 1 Subtest 2'
|
|
||||||
log_warn_calls = [call('({ip}) Projector software version does not match '
|
|
||||||
'saved software version'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Saved: "Test 1 Subtest 1"'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Received: "Test 1 Subtest 2"'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}) Updating software version'.format(ip=pjlink.name))]
|
|
||||||
pjlink.sw_version = test_data_old
|
|
||||||
|
|
||||||
# WHEN: process_sver called with invalid data
|
|
||||||
pjlink.process_sver(data=test_data_new)
|
|
||||||
|
|
||||||
# THEN: Version information should not change
|
|
||||||
assert pjlink.sw_version == test_data_new, 'Software version should have changed'
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_process_sver_invalid(self):
|
|
||||||
"""
|
|
||||||
Test invalid software version information - too long
|
|
||||||
"""
|
|
||||||
test_data = 'This is a test software version line that is too long based on PJLink version 2 specs'
|
|
||||||
log_warn_calls = [call('Invalid software version - too long')]
|
|
||||||
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.sw_version = None
|
|
||||||
|
|
||||||
# WHEN: process_sver called with invalid data
|
|
||||||
pjlink.process_sver(data=test_data)
|
|
||||||
|
|
||||||
# THEN: Version information should not change
|
|
||||||
assert pjlink.sw_version is None, 'Software version should not have changed'
|
|
||||||
assert pjlink.sw_version_received is None, 'Received software version should not have changed'
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
@ -1,356 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# OpenLP - Open Source Lyrics Projection #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# Copyright (c) 2008-2019 OpenLP Developers #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# This program is free software: you can redistribute it and/or modify #
|
|
||||||
# it under the terms of the GNU General Public License as published by #
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or #
|
|
||||||
# (at your option) any later version. #
|
|
||||||
# #
|
|
||||||
# This program is distributed in the hope that it will be useful, #
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
||||||
# GNU General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU General Public License #
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
||||||
##########################################################################
|
|
||||||
"""
|
|
||||||
Package to test the openlp.core.projectors.pjlink commands package.
|
|
||||||
"""
|
|
||||||
from unittest import TestCase, skip
|
|
||||||
from unittest.mock import call, patch
|
|
||||||
|
|
||||||
import openlp.core.projectors.pjlink
|
|
||||||
from openlp.core.projectors.constants import PJLINK_PORT, S_CONNECTED, S_OFF, S_ON
|
|
||||||
from openlp.core.projectors.db import Projector
|
|
||||||
from openlp.core.projectors.pjlink import PJLink, PJLinkUDP
|
|
||||||
from tests.resources.projector.data import TEST1_DATA, TEST2_DATA, TEST_HASH, TEST_PIN, TEST_SALT
|
|
||||||
|
|
||||||
|
|
||||||
class TestPJLinkCommands(TestCase):
|
|
||||||
"""
|
|
||||||
Tests for the PJLinkCommands class part 2
|
|
||||||
"""
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_projector_reset_information(self):
|
|
||||||
"""
|
|
||||||
Test reset_information() resets all information and stops timers
|
|
||||||
"""
|
|
||||||
# GIVEN: Test object
|
|
||||||
with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_debug_calls = [call('({ip}): Calling poll_timer.stop()'.format(ip=pjlink.name)),
|
|
||||||
call('({ip}): Calling socket_timer.stop()'.format(ip=pjlink.name))]
|
|
||||||
# timer and socket_timer not available until instantiation, so mock here
|
|
||||||
with patch.object(pjlink, 'socket_timer') as mock_socket_timer, \
|
|
||||||
patch.object(pjlink, 'poll_timer') as mock_timer:
|
|
||||||
|
|
||||||
pjlink.power = S_ON
|
|
||||||
pjlink.pjlink_name = 'OPENLPTEST'
|
|
||||||
pjlink.manufacturer = 'PJLINK'
|
|
||||||
pjlink.model = '1'
|
|
||||||
pjlink.shutter = True
|
|
||||||
pjlink.mute = True
|
|
||||||
pjlink.lamp = True
|
|
||||||
pjlink.fan = True
|
|
||||||
pjlink.source_available = True
|
|
||||||
pjlink.other_info = 'ANOTHER TEST'
|
|
||||||
pjlink.send_queue = True
|
|
||||||
pjlink.send_busy = True
|
|
||||||
|
|
||||||
# WHEN: reset_information() is called
|
|
||||||
pjlink.reset_information()
|
|
||||||
|
|
||||||
# THEN: All information should be reset and timers stopped
|
|
||||||
assert pjlink.power == S_OFF, 'Projector power should be OFF'
|
|
||||||
assert pjlink.pjlink_name is None, 'Projector pjlink_name should be None'
|
|
||||||
assert pjlink.manufacturer is None, 'Projector manufacturer should be None'
|
|
||||||
assert pjlink.model is None, 'Projector model should be None'
|
|
||||||
assert pjlink.shutter is None, 'Projector shutter should be None'
|
|
||||||
assert pjlink.mute is None, 'Projector shuttter should be None'
|
|
||||||
assert pjlink.lamp is None, 'Projector lamp should be None'
|
|
||||||
assert pjlink.fan is None, 'Projector fan should be None'
|
|
||||||
assert pjlink.source_available is None, 'Projector source_available should be None'
|
|
||||||
assert pjlink.source is None, 'Projector source should be None'
|
|
||||||
assert pjlink.other_info is None, 'Projector other_info should be None'
|
|
||||||
assert pjlink.send_queue == [], 'Projector send_queue should be an empty list'
|
|
||||||
assert pjlink.send_busy is False, 'Projector send_busy should be False'
|
|
||||||
assert mock_timer.stop.called is True, 'Projector timer.stop() should have been called'
|
|
||||||
assert mock_socket_timer.stop.called is True, 'Projector socket_timer.stop() should have been called'
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_process_pjlink_normal(self):
|
|
||||||
"""
|
|
||||||
Test initial connection prompt with no authentication
|
|
||||||
"""
|
|
||||||
# GIVEN: Initial mocks and data
|
|
||||||
mock_log = patch.object(openlp.core.projectors.pjlink, "log").start()
|
|
||||||
mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
|
|
||||||
mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
|
|
||||||
mock_readyRead = patch('openlp.core.projectors.pjlink.PJLink.readyRead').start()
|
|
||||||
mock_change_status = patch('openlp.core.projectors.pjlink.PJLink.change_status').start()
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.pin = None
|
|
||||||
log_check = [call('({ip}) process_pjlink(): Sending "CLSS" initial command'.format(ip=pjlink.name)), ]
|
|
||||||
|
|
||||||
# WHEN: process_pjlink called with no authentication required
|
|
||||||
pjlink.process_pjlink(data="0")
|
|
||||||
|
|
||||||
# THEN: proper processing should have occured
|
|
||||||
mock_log.debug.has_calls(log_check)
|
|
||||||
mock_disconnect_from_host.assert_not_called()
|
|
||||||
assert 1 == mock_readyRead.connect.call_count, 'Should have only been called once'
|
|
||||||
mock_change_status.assert_called_once_with(S_CONNECTED)
|
|
||||||
mock_send_command.assert_called_with(cmd='CLSS', priority=True, salt=None)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_process_pjlink_authenticate(self):
|
|
||||||
"""
|
|
||||||
Test initial connection prompt with authentication
|
|
||||||
"""
|
|
||||||
# GIVEN: Initial mocks and data
|
|
||||||
mock_log = patch.object(openlp.core.projectors.pjlink, "log").start()
|
|
||||||
mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
|
|
||||||
mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
|
|
||||||
mock_readyRead = patch('openlp.core.projectors.pjlink.PJLink.readyRead').start()
|
|
||||||
mock_change_status = patch('openlp.core.projectors.pjlink.PJLink.change_status').start()
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.pin = TEST_PIN
|
|
||||||
log_check = [call('({ip}) process_pjlink(): Sending "CLSS" initial command'.format(ip=pjlink.name)), ]
|
|
||||||
|
|
||||||
# WHEN: process_pjlink called with no authentication required
|
|
||||||
pjlink.process_pjlink(data='1 {salt}'.format(salt=TEST_SALT))
|
|
||||||
|
|
||||||
# THEN: proper processing should have occured
|
|
||||||
mock_log.debug.has_calls(log_check)
|
|
||||||
mock_disconnect_from_host.assert_not_called()
|
|
||||||
assert 1 == mock_readyRead.connect.call_count, 'Should have only been called once'
|
|
||||||
mock_change_status.assert_called_once_with(S_CONNECTED)
|
|
||||||
mock_send_command.assert_called_with(cmd='CLSS', priority=True, salt=TEST_HASH)
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_process_pjlink_normal_pin_set_error(self):
|
|
||||||
"""
|
|
||||||
Test process_pjlinnk called with no authentication but pin is set
|
|
||||||
"""
|
|
||||||
# GIVEN: Initial mocks and data
|
|
||||||
mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
|
|
||||||
mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
|
|
||||||
mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.pin = TEST_PIN
|
|
||||||
log_check = [call('({ip}) Normal connection but PIN set - aborting'.format(ip=pjlink.name)), ]
|
|
||||||
|
|
||||||
# WHEN: process_pjlink called with invalid authentication scheme
|
|
||||||
pjlink.process_pjlink(data='0')
|
|
||||||
|
|
||||||
# THEN: Proper calls should be made
|
|
||||||
mock_log.error.assert_has_calls(log_check)
|
|
||||||
assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
|
|
||||||
mock_send_command.assert_not_called()
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_process_pjlink_normal_with_salt_error(self):
|
|
||||||
"""
|
|
||||||
Test process_pjlinnk called with no authentication but pin is set
|
|
||||||
"""
|
|
||||||
# GIVEN: Initial mocks and data
|
|
||||||
mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
|
|
||||||
mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
|
|
||||||
mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.pin = TEST_PIN
|
|
||||||
log_check = [call('({ip}) Normal connection with extra information - aborting'.format(ip=pjlink.name)), ]
|
|
||||||
|
|
||||||
# WHEN: process_pjlink called with invalid authentication scheme
|
|
||||||
pjlink.process_pjlink(data='0 {salt}'.format(salt=TEST_SALT))
|
|
||||||
|
|
||||||
# THEN: Proper calls should be made
|
|
||||||
mock_log.error.assert_has_calls(log_check)
|
|
||||||
assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
|
|
||||||
mock_send_command.assert_not_called()
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_process_pjlink_invalid_authentication_scheme_length_error(self):
|
|
||||||
"""
|
|
||||||
Test initial connection prompt with authentication scheme longer than 1 character
|
|
||||||
"""
|
|
||||||
# GIVEN: Initial mocks and data
|
|
||||||
mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
|
|
||||||
mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
|
|
||||||
mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_check = [call('({ip}) Invalid initial authentication scheme - aborting'.format(ip=pjlink.name)), ]
|
|
||||||
|
|
||||||
# WHEN: process_pjlink called with invalid authentication scheme
|
|
||||||
pjlink.process_pjlink(data='01')
|
|
||||||
|
|
||||||
# THEN: socket should be closed and invalid data logged
|
|
||||||
mock_log.error.assert_has_calls(log_check)
|
|
||||||
assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
|
|
||||||
mock_send_command.assert_not_called()
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_process_pjlink_invalid_authentication_data_length_error(self):
|
|
||||||
"""
|
|
||||||
Test initial connection prompt with authentication no salt
|
|
||||||
"""
|
|
||||||
# GIVEN: Initial mocks and data
|
|
||||||
mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
|
|
||||||
mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
|
|
||||||
mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
log_check = [call('({ip}) Authenticated connection but not enough info - aborting'.format(ip=pjlink.name)), ]
|
|
||||||
|
|
||||||
# WHEN: process_pjlink called with no salt
|
|
||||||
pjlink.process_pjlink(data='1')
|
|
||||||
|
|
||||||
# THEN: socket should be closed and invalid data logged
|
|
||||||
mock_log.error.assert_has_calls(log_check)
|
|
||||||
assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
|
|
||||||
mock_send_command.assert_not_called()
|
|
||||||
|
|
||||||
@skip('Needs update to new setup')
|
|
||||||
def test_process_pjlink_authenticate_pin_not_set_error(self):
|
|
||||||
"""
|
|
||||||
Test process_pjlink authentication but pin not set
|
|
||||||
"""
|
|
||||||
# GIVEN: Initial mocks and data
|
|
||||||
mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
|
|
||||||
mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
|
|
||||||
mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
|
|
||||||
|
|
||||||
pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
|
|
||||||
pjlink.pin = None
|
|
||||||
log_check = [call('({ip}) Authenticate connection but no PIN - aborting'.format(ip=pjlink.name)), ]
|
|
||||||
|
|
||||||
# WHEN: process_pjlink called with no salt
|
|
||||||
pjlink.process_pjlink(data='1 {salt}'.format(salt=TEST_SALT))
|
|
||||||
|
|
||||||
# THEN: socket should be closed and invalid data logged
|
|
||||||
mock_log.error.assert_has_calls(log_check)
|
|
||||||
assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
|
|
||||||
mock_send_command.assert_not_called()
|
|
||||||
|
|
||||||
@skip('Change to pjlink_udp.get_datagram() call')
|
|
||||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
|
||||||
def test_process_ackn_duplicate(self, mock_log):
|
|
||||||
"""
|
|
||||||
Test process_ackn method with multiple calls with same data
|
|
||||||
"""
|
|
||||||
# TODO: Change this to call pjlink_udp.get_datagram() so ACKN can be processed properly
|
|
||||||
|
|
||||||
# GIVEN: Test setup
|
|
||||||
pjlink = PJLink(projector=self.test_list[0])
|
|
||||||
check_list = {TEST1_DATA['ip']: {'data': TEST1_DATA['mac_adx'], 'port': PJLINK_PORT}}
|
|
||||||
log_warn_calls = [call('(___TEST_ONE___) Host {host} already replied - '
|
|
||||||
'ignoring'.format(host=TEST1_DATA['ip']))]
|
|
||||||
log_debug_calls = [call('PJlinkCommands(args=() kwargs={})'),
|
|
||||||
call('(___TEST_ONE___) reset_information() connect status is S_NOT_CONNECTED'),
|
|
||||||
call('(___TEST_ONE___) Processing ACKN packet'),
|
|
||||||
call('(___TEST_ONE___) Adding {host} to ACKN list'.format(host=TEST1_DATA['ip'])),
|
|
||||||
call('(___TEST_ONE___) Processing ACKN packet')]
|
|
||||||
|
|
||||||
# WHEN: process_ackn called twice with same data
|
|
||||||
pjlink.process_ackn(data=TEST1_DATA['mac_adx'], host=TEST1_DATA['ip'], port=PJLINK_PORT)
|
|
||||||
pjlink.process_ackn(data=TEST1_DATA['mac_adx'], host=TEST1_DATA['ip'], port=PJLINK_PORT)
|
|
||||||
|
|
||||||
# THEN: pjlink_udp.ack_list should equal test_list
|
|
||||||
# NOTE: This assert only returns AssertionError - does not list differences. Maybe add a compare function?
|
|
||||||
if pjlink.ackn_list != check_list:
|
|
||||||
# Check this way so we can print differences to stdout
|
|
||||||
print('\nackn_list: ', pjlink.ackn_list)
|
|
||||||
print('test_list: ', check_list, '\n')
|
|
||||||
assert pjlink.ackn_list == check_list
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
|
|
||||||
@skip('Change to pjlink_udp.get_datagram() call')
|
|
||||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
|
||||||
def test_process_ackn_multiple(self, mock_log):
|
|
||||||
"""
|
|
||||||
Test process_ackn method with multiple calls
|
|
||||||
"""
|
|
||||||
# TODO: Change this to call pjlink_udp.get_datagram() so ACKN can be processed properly
|
|
||||||
|
|
||||||
# GIVEN: Test setup
|
|
||||||
pjlink_udp = PJLinkUDP(projector_list=self.test_list)
|
|
||||||
check_list = {TEST1_DATA['ip']: {'data': TEST1_DATA['mac_adx'], 'port': PJLINK_PORT},
|
|
||||||
TEST2_DATA['ip']: {'data': TEST2_DATA['mac_adx'], 'port': PJLINK_PORT}}
|
|
||||||
log_debug_calls = [call('(UDP) PJLinkUDP() Initialized'),
|
|
||||||
call('(UDP) Processing ACKN packet'),
|
|
||||||
call('(UDP) Adding {host} to ACKN list'.format(host=TEST1_DATA['ip'])),
|
|
||||||
call('(UDP) Processing ACKN packet'),
|
|
||||||
call('(UDP) Adding {host} to ACKN list'.format(host=TEST2_DATA['ip']))]
|
|
||||||
|
|
||||||
# WHEN: process_ackn called twice with different data
|
|
||||||
pjlink_udp.process_ackn(data=TEST1_DATA['mac_adx'], host=TEST1_DATA['ip'], port=PJLINK_PORT)
|
|
||||||
pjlink_udp.process_ackn(data=TEST2_DATA['mac_adx'], host=TEST2_DATA['ip'], port=PJLINK_PORT)
|
|
||||||
|
|
||||||
# THEN: pjlink_udp.ack_list should equal test_list
|
|
||||||
# NOTE: This assert only returns AssertionError - does not list differences. Maybe add a compare function?
|
|
||||||
if pjlink_udp.ackn_list != check_list:
|
|
||||||
# Check this way so we can print differences to stdout
|
|
||||||
print('\nackn_list: ', pjlink_udp.ackn_list)
|
|
||||||
print('test_list: ', check_list)
|
|
||||||
assert pjlink_udp.ackn_list == check_list
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Change to pjlink_udp.get_datagram() call')
|
|
||||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
|
||||||
def test_process_ackn_single(self, mock_log):
|
|
||||||
"""
|
|
||||||
Test process_ackn method with single call
|
|
||||||
"""
|
|
||||||
# TODO: Change this to call pjlink_udp.get_datagram() so ACKN can be processed properly
|
|
||||||
|
|
||||||
# GIVEN: Test setup
|
|
||||||
pjlink_udp = PJLinkUDP(projector_list=self.test_list)
|
|
||||||
check_list = {TEST1_DATA['ip']: {'data': TEST1_DATA['mac_adx'], 'port': PJLINK_PORT}}
|
|
||||||
log_debug_calls = [call('(UDP) PJLinkUDP() Initialized'),
|
|
||||||
call('(UDP) Processing ACKN packet'),
|
|
||||||
call('(UDP) Adding {host} to ACKN list'.format(host=TEST1_DATA['ip']))]
|
|
||||||
|
|
||||||
# WHEN: process_ackn called twice with different data
|
|
||||||
pjlink_udp.process_ackn(data=TEST1_DATA['mac_adx'], host=TEST1_DATA['ip'], port=PJLINK_PORT)
|
|
||||||
|
|
||||||
# THEN: pjlink_udp.ack_list should equal test_list
|
|
||||||
# NOTE: This assert only returns AssertionError - does not list differences. Maybe add a compare function?
|
|
||||||
if pjlink_udp.ackn_list != check_list:
|
|
||||||
# Check this way so we can print differences to stdout
|
|
||||||
print('\nackn_list: ', pjlink_udp.ackn_list)
|
|
||||||
print('test_list: ', check_list)
|
|
||||||
assert pjlink_udp.ackn_list == check_list
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
||||||
|
|
||||||
@skip('Change to pjlink_udp.get_datagram() call')
|
|
||||||
@patch.object(openlp.core.projectors.pjlink, 'log')
|
|
||||||
def test_process_srch(self, mock_log):
|
|
||||||
"""
|
|
||||||
Test process_srch method
|
|
||||||
"""
|
|
||||||
# TODO: Change this to call pjlink_udp.get_datagram() so ACKN can be processed properly
|
|
||||||
|
|
||||||
# GIVEN: Test setup
|
|
||||||
log_warn_calls = [call('(UDP) SRCH packet received from {ip} - ignoring'.format(ip=TEST1_DATA['ip'])), ]
|
|
||||||
log_debug_calls = [call('(UDP) PJLinkUDP() Initialized'), ]
|
|
||||||
pjlink_udp = PJLinkUDP(projector_list=self.test_list)
|
|
||||||
|
|
||||||
# WHEN: process_srch called
|
|
||||||
pjlink_udp.process_srch(data=None, host=TEST1_DATA['ip'], port=PJLINK_PORT)
|
|
||||||
|
|
||||||
# THEN: log entries should be entered
|
|
||||||
mock_log.warning.assert_has_calls(log_warn_calls)
|
|
||||||
mock_log.debug.assert_has_calls(log_debug_calls)
|
|
Loading…
Reference in New Issue
Block a user