forked from openlp/openlp
Merge 2.4 base - fix conflicts
This commit is contained in:
commit
319870aa83
@ -219,7 +219,8 @@ def qmd5_hash(salt, data=None):
|
||||
log.debug('qmd5_hash(salt="%s"' % salt)
|
||||
hash_obj = QHash(QHash.Md5)
|
||||
hash_obj.addData(salt)
|
||||
hash_obj.addData(data)
|
||||
if data:
|
||||
hash_obj.addData(data)
|
||||
hash_value = hash_obj.result().toHex()
|
||||
log.debug('qmd5_hash() returning "%s"' % hash_value)
|
||||
return hash_value.data()
|
||||
|
@ -297,7 +297,11 @@ PJLINK_ERST_STATUS = {'0': ERROR_STRING[E_OK],
|
||||
PJLINK_POWR_STATUS = {'0': S_STANDBY,
|
||||
'1': S_ON,
|
||||
'2': S_COOLDOWN,
|
||||
'3': S_WARMUP}
|
||||
'3': S_WARMUP,
|
||||
S_STANDBY: '0',
|
||||
S_ON: '1',
|
||||
S_COOLDOWN: '2',
|
||||
S_WARMUP: '3'}
|
||||
|
||||
PJLINK_DEFAULT_SOURCES = {'1': translate('OpenLP.DB', 'RGB'),
|
||||
'2': translate('OpenLP.DB', 'Video'),
|
||||
|
@ -49,7 +49,7 @@ from codecs import decode
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtNetwork import QAbstractSocket, QTcpSocket
|
||||
|
||||
from openlp.core.common import translate, qmd5_hash
|
||||
from openlp.core.common import translate, md5_hash
|
||||
from openlp.core.lib.projector.constants import *
|
||||
|
||||
# Shortcuts
|
||||
@ -58,7 +58,7 @@ SocketSTate = QAbstractSocket.SocketState
|
||||
|
||||
PJLINK_PREFIX = '%'
|
||||
PJLINK_CLASS = '1'
|
||||
PJLINK_HEADER = '%s%s' % (PJLINK_PREFIX, PJLINK_CLASS)
|
||||
PJLINK_HEADER = '{prefix}{linkclass}'.format(prefix=PJLINK_PREFIX, linkclass=PJLINK_CLASS)
|
||||
PJLINK_SUFFIX = CR
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ class PJLink1(QTcpSocket):
|
||||
:param poll_time: Time (in seconds) to poll connected projector
|
||||
:param socket_timeout: Time (in seconds) to abort the connection if no response
|
||||
"""
|
||||
log.debug('PJlink(args="%s" kwargs="%s")' % (args, kwargs))
|
||||
log.debug('PJlink(args={args} kwargs={kwargs})'.format(args=args, kwargs=kwargs))
|
||||
self.name = name
|
||||
self.ip = ip
|
||||
self.port = port
|
||||
@ -147,7 +147,7 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Reset projector-specific information to default
|
||||
"""
|
||||
log.debug('(%s) reset_information() connect status is %s' % (self.ip, self.state()))
|
||||
log.debug('({ip}) reset_information() connect status is {state}'.format(ip=self.ip, state=self.state()))
|
||||
self.power = S_OFF
|
||||
self.pjlink_name = None
|
||||
self.manufacturer = None
|
||||
@ -160,8 +160,10 @@ class PJLink1(QTcpSocket):
|
||||
self.source = None
|
||||
self.other_info = None
|
||||
if hasattr(self, 'timer'):
|
||||
log.debug('({ip}): Calling timer.stop()'.format(ip=self.ip))
|
||||
self.timer.stop()
|
||||
if hasattr(self, 'socket_timer'):
|
||||
log.debug('({ip}): Calling socket_timer.stop()'.format(ip=self.ip))
|
||||
self.socket_timer.stop()
|
||||
self.send_queue = []
|
||||
self.send_busy = False
|
||||
@ -170,7 +172,7 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Connects signals to methods when thread is started.
|
||||
"""
|
||||
log.debug('(%s) Thread starting' % self.ip)
|
||||
log.debug('({ip}) Thread starting'.format(ip=self.ip))
|
||||
self.i_am_running = True
|
||||
self.connected.connect(self.check_login)
|
||||
self.disconnected.connect(self.disconnect_from_host)
|
||||
@ -180,7 +182,7 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Cleanups when thread is stopped.
|
||||
"""
|
||||
log.debug('(%s) Thread stopped' % self.ip)
|
||||
log.debug('({ip}) Thread stopped'.format(ip=self.ip))
|
||||
try:
|
||||
self.connected.disconnect(self.check_login)
|
||||
except TypeError:
|
||||
@ -206,7 +208,7 @@ class PJLink1(QTcpSocket):
|
||||
Aborts connection and closes socket in case of brain-dead projectors.
|
||||
Should normally be called by socket_timer().
|
||||
"""
|
||||
log.debug('(%s) socket_abort() - Killing connection' % self.ip)
|
||||
log.debug('({ip}) socket_abort() - Killing connection'.format(ip=self.ip))
|
||||
self.disconnect_from_host(abort=True)
|
||||
|
||||
def poll_loop(self):
|
||||
@ -216,7 +218,7 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
if self.state() != self.ConnectedState:
|
||||
return
|
||||
log.debug('(%s) Updating projector status' % self.ip)
|
||||
log.debug('({ip}) Updating projector status'.format(ip=self.ip))
|
||||
# Reset timer in case we were called from a set command
|
||||
if self.timer.interval() < self.poll_time:
|
||||
# Reset timer to 5 seconds
|
||||
@ -276,11 +278,17 @@ class PJLink1(QTcpSocket):
|
||||
self.status_connect = S_CONNECTED
|
||||
self.projector_status = status
|
||||
(status_code, status_message) = self._get_status(self.status_connect)
|
||||
log.debug('(%s) status_connect: %s: %s' % (self.ip, status_code, status_message if msg is None else msg))
|
||||
log.debug('({ip}) status_connect: {code}: "{message}"'.format(ip=self.ip,
|
||||
code=status_code,
|
||||
message=status_message if msg is None else msg))
|
||||
(status_code, status_message) = self._get_status(self.projector_status)
|
||||
log.debug('(%s) projector_status: %s: %s' % (self.ip, status_code, status_message if msg is None else msg))
|
||||
log.debug('({ip}) projector_status: {code}: "{message}"'.format(ip=self.ip,
|
||||
code=status_code,
|
||||
message=status_message if msg is None else msg))
|
||||
(status_code, status_message) = self._get_status(self.error_status)
|
||||
log.debug('(%s) error_status: %s: %s' % (self.ip, status_code, status_message if msg is None else msg))
|
||||
log.debug('({ip}) error_status: {code}: "{message}"'.format(ip=self.ip,
|
||||
code=status_code,
|
||||
message=status_message if msg is None else msg))
|
||||
self.changeStatus.emit(self.ip, status, message)
|
||||
|
||||
@pyqtSlot()
|
||||
@ -289,29 +297,31 @@ class PJLink1(QTcpSocket):
|
||||
Processes the initial connection and authentication (if needed).
|
||||
Starts poll timer if connection is established.
|
||||
|
||||
NOTE: Qt md5 hash function doesn't work with projector authentication. Use the python md5 hash function.
|
||||
|
||||
:param data: Optional data if called from another routine
|
||||
"""
|
||||
log.debug('(%s) check_login(data="%s")' % (self.ip, data))
|
||||
log.debug('({ip}) check_login(data="{data}")'.format(ip=self.ip, data=data))
|
||||
if data is None:
|
||||
# Reconnected setup?
|
||||
if not self.waitForReadyRead(2000):
|
||||
# Possible timeout issue
|
||||
log.error('(%s) Socket timeout waiting for login' % self.ip)
|
||||
log.error('({ip}) Socket timeout waiting for login'.format(ip=self.ip))
|
||||
self.change_status(E_SOCKET_TIMEOUT)
|
||||
return
|
||||
read = self.readLine(self.maxSize)
|
||||
dontcare = self.readLine(self.maxSize) # Clean out the trailing \r\n
|
||||
if read is None:
|
||||
log.warn('(%s) read is None - socket error?' % self.ip)
|
||||
log.warn('({ip}) read is None - socket error?'.format(ip=self.ip))
|
||||
return
|
||||
elif len(read) < 8:
|
||||
log.warn('(%s) Not enough data read)' % self.ip)
|
||||
log.warn('({ip}) Not enough data read)'.format(ip=self.ip))
|
||||
return
|
||||
data = decode(read, 'ascii')
|
||||
# Possibility of extraneous data on input when reading.
|
||||
# Clean out extraneous characters in buffer.
|
||||
dontcare = self.readLine(self.maxSize)
|
||||
log.debug('(%s) check_login() read "%s"' % (self.ip, data.strip()))
|
||||
log.debug('({ip}) check_login() read "{data}"'.format(ip=self.ip, data=data.strip()))
|
||||
# At this point, we should only have the initial login prompt with
|
||||
# possible authentication
|
||||
# PJLink initial login will be:
|
||||
@ -326,26 +336,35 @@ class PJLink1(QTcpSocket):
|
||||
else:
|
||||
# Process initial connection
|
||||
data_check = data.strip().split(' ')
|
||||
log.debug('(%s) data_check="%s"' % (self.ip, data_check))
|
||||
log.debug('({ip}) data_check="{data}"'.format(ip=self.ip, data=data_check))
|
||||
# Check for projector reporting an error
|
||||
if data_check[1].upper() == 'ERRA':
|
||||
# Authentication error
|
||||
self.disconnect_from_host()
|
||||
self.change_status(E_AUTHENTICATION)
|
||||
log.debug('(%s) emitting projectorAuthentication() signal' % self.name)
|
||||
log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.name))
|
||||
return
|
||||
elif data_check[1] == '0' and self.pin is not None:
|
||||
# Pin set and no authentication needed
|
||||
log.warning('({ip}) Regular connection but PIN set'.format(ip=self.name))
|
||||
self.disconnect_from_host()
|
||||
self.change_status(E_AUTHENTICATION)
|
||||
log.debug('(%s) emitting projectorNoAuthentication() signal' % self.name)
|
||||
log.debug('({ip}) Emitting projectorNoAuthentication() signal'.format(ip=self.name))
|
||||
self.projectorNoAuthentication.emit(self.name)
|
||||
return
|
||||
elif data_check[1] == '1':
|
||||
# Authenticated login with salt
|
||||
log.debug('(%s) Setting hash with salt="%s"' % (self.ip, data_check[2]))
|
||||
log.debug('(%s) pin="%s"' % (self.ip, self.pin))
|
||||
salt = qmd5_hash(salt=data_check[2].encode('ascii'), data=self.pin.encode('ascii'))
|
||||
if self.pin is None:
|
||||
log.warning('({ip}) Authenticated connection but no pin set'.format(ip=self.name))
|
||||
self.disconnect_from_host()
|
||||
self.change_status(E_AUTHENTICATION)
|
||||
log.debug('({ip}) Emitting projectorAuthentication() signal'.format(ip=self.name))
|
||||
self.projectorAuthentication.emit(self.name)
|
||||
return
|
||||
else:
|
||||
log.debug('({ip}) Setting hash with salt="{data}"'.format(ip=self.ip, data=data_check[2]))
|
||||
log.debug('({ip}) pin="{data}"'.format(ip=self.ip, data=self.pin))
|
||||
salt = md5_hash(salt=data_check[2].encode('ascii'), data=self.pin.encode('ascii'))
|
||||
else:
|
||||
salt = None
|
||||
# We're connected at this point, so go ahead and do regular I/O
|
||||
@ -355,7 +374,7 @@ class PJLink1(QTcpSocket):
|
||||
self.send_command(cmd='CLSS', salt=salt)
|
||||
self.waitForReadyRead()
|
||||
if (not self.no_poll) and (self.state() == self.ConnectedState):
|
||||
log.debug('(%s) Starting timer' % self.ip)
|
||||
log.debug('({ip}) Starting timer'.format(ip=self.ip))
|
||||
self.timer.setInterval(2000) # Set 2 seconds for initial information
|
||||
self.timer.start()
|
||||
|
||||
@ -364,15 +383,15 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Socket interface to retrieve data.
|
||||
"""
|
||||
log.debug('(%s) get_data(): Reading data' % self.ip)
|
||||
log.debug('({ip}) get_data(): Reading data'.format(ip=self.ip))
|
||||
if self.state() != self.ConnectedState:
|
||||
log.debug('(%s) get_data(): Not connected - returning' % self.ip)
|
||||
log.debug('({ip}) get_data(): Not connected - returning'.format(ip=self.ip))
|
||||
self.send_busy = False
|
||||
return
|
||||
read = self.readLine(self.maxSize)
|
||||
if read == -1:
|
||||
# No data available
|
||||
log.debug('(%s) get_data(): No data available (-1)' % self.ip)
|
||||
log.debug('({ip}) get_data(): No data available (-1)'.format(ip=self.ip))
|
||||
self.send_busy = False
|
||||
self.projectorReceivedData.emit()
|
||||
return
|
||||
@ -382,11 +401,11 @@ class PJLink1(QTcpSocket):
|
||||
data = data_in.strip()
|
||||
if len(data) < 7:
|
||||
# Not enough data for a packet
|
||||
log.debug('(%s) get_data(): Packet length < 7: "%s"' % (self.ip, data))
|
||||
log.debug('({ip}) get_data(): Packet length < 7: "{data}"'.format(ip=self.ip, data=data))
|
||||
self.send_busy = False
|
||||
self.projectorReceivedData.emit()
|
||||
return
|
||||
log.debug('(%s) get_data(): Checking new data "%s"' % (self.ip, data))
|
||||
log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data))
|
||||
if data.upper().startswith('PJLINK'):
|
||||
# Reconnected from remote host disconnect ?
|
||||
self.check_login(data)
|
||||
@ -394,7 +413,7 @@ class PJLink1(QTcpSocket):
|
||||
self.projectorReceivedData.emit()
|
||||
return
|
||||
elif '=' not in data:
|
||||
log.warn('(%s) get_data(): Invalid packet received' % self.ip)
|
||||
log.warn('({ip}) get_data(): Invalid packet received'.format(ip=self.ip))
|
||||
self.send_busy = False
|
||||
self.projectorReceivedData.emit()
|
||||
return
|
||||
@ -402,15 +421,15 @@ class PJLink1(QTcpSocket):
|
||||
try:
|
||||
(prefix, class_, cmd, data) = (data_split[0][0], data_split[0][1], data_split[0][2:], data_split[1])
|
||||
except ValueError as e:
|
||||
log.warn('(%s) get_data(): Invalid packet - expected header + command + data' % self.ip)
|
||||
log.warn('(%s) get_data(): Received data: "%s"' % (self.ip, read))
|
||||
log.warn('({ip}) get_data(): Invalid packet - expected header + command + data'.format(ip=self.ip))
|
||||
log.warn('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in.strip()))
|
||||
self.change_status(E_INVALID_DATA)
|
||||
self.send_busy = False
|
||||
self.projectorReceivedData.emit()
|
||||
return
|
||||
|
||||
if not (self.pjlink_class in PJLINK_VALID_CMD and cmd in PJLINK_VALID_CMD[self.pjlink_class]):
|
||||
log.warn('(%s) get_data(): Invalid packet - unknown command "%s"' % (self.ip, cmd))
|
||||
log.warn('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
|
||||
self.send_busy = False
|
||||
self.projectorReceivedData.emit()
|
||||
return
|
||||
@ -424,7 +443,7 @@ class PJLink1(QTcpSocket):
|
||||
|
||||
:param err: Error code
|
||||
"""
|
||||
log.debug('(%s) get_error(err=%s): %s' % (self.ip, err, self.errorString()))
|
||||
log.debug('({ip}) get_error(err={error}): {data}'.format(ip=self.ip, error=err, data=self.errorString()))
|
||||
if err <= 18:
|
||||
# QSocket errors. Redefined in projector.constants so we don't mistake
|
||||
# them for system errors
|
||||
@ -453,7 +472,7 @@ class PJLink1(QTcpSocket):
|
||||
:param queue: Option to force add to queue rather than sending directly
|
||||
"""
|
||||
if self.state() != self.ConnectedState:
|
||||
log.warn('(%s) send_command(): Not connected - returning' % self.ip)
|
||||
log.warn('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
|
||||
self.send_queue = []
|
||||
return
|
||||
self.projectorNetwork.emit(self.ip, S_NETWORK_SENDING)
|
||||
@ -467,18 +486,19 @@ class PJLink1(QTcpSocket):
|
||||
out = '%s%s%s %s%s' % (salt, PJLINK_HEADER, cmd, opts, CR)
|
||||
if out in self.send_queue:
|
||||
# Already there, so don't add
|
||||
log.debug('(%s) send_command(out="%s") Already in queue - skipping' % (self.ip, out.strip()))
|
||||
log.debug('({ip}) send_command(out="{data}") Already in queue - skipping'.format(ip=self.ip,
|
||||
data=out.strip()))
|
||||
elif not queue and len(self.send_queue) == 0:
|
||||
# Nothing waiting to send, so just send it
|
||||
log.debug('(%s) send_command(out="%s") Sending data' % (self.ip, out.strip()))
|
||||
log.debug('({ip}) send_command(out="{data}") Sending data'.format(ip=self.ip, data=out.strip()))
|
||||
return self._send_command(data=out)
|
||||
else:
|
||||
log.debug('(%s) send_command(out="%s") adding to queue' % (self.ip, out.strip()))
|
||||
log.debug('({ip}) send_command(out="{data}") adding to queue'.format(ip=self.ip, data=out.strip()))
|
||||
self.send_queue.append(out)
|
||||
self.projectorReceivedData.emit()
|
||||
log.debug('(%s) send_command(): send_busy is %s' % (self.ip, self.send_busy))
|
||||
log.debug('({ip}) send_command(): send_busy is {data}'.format(ip=self.ip, data=self.send_busy))
|
||||
if not self.send_busy:
|
||||
log.debug('(%s) send_command() calling _send_string()')
|
||||
log.debug('({ip}) send_command() calling _send_string()'.format(ip=self.ip))
|
||||
self._send_command()
|
||||
|
||||
@pyqtSlot()
|
||||
@ -488,10 +508,10 @@ class PJLink1(QTcpSocket):
|
||||
|
||||
:param data: Immediate data to send
|
||||
"""
|
||||
log.debug('(%s) _send_string()' % self.ip)
|
||||
log.debug('(%s) _send_string(): Connection status: %s' % (self.ip, self.state()))
|
||||
log.debug('({ip}) _send_string()'.format(ip=self.ip))
|
||||
log.debug('({ip}) _send_string(): Connection status: {data}'.format(ip=self.ip, data=self.state()))
|
||||
if self.state() != self.ConnectedState:
|
||||
log.debug('(%s) _send_string() Not connected - abort' % self.ip)
|
||||
log.debug('({ip}) _send_string() Not connected - abort'.format(ip=self.ip))
|
||||
self.send_queue = []
|
||||
self.send_busy = False
|
||||
return
|
||||
@ -500,18 +520,18 @@ class PJLink1(QTcpSocket):
|
||||
return
|
||||
if data is not None:
|
||||
out = data
|
||||
log.debug('(%s) _send_string(data=%s)' % (self.ip, out.strip()))
|
||||
log.debug('({ip}) _send_string(data="{data}")'.format(ip=self.ip, data=out.strip()))
|
||||
elif len(self.send_queue) != 0:
|
||||
out = self.send_queue.pop(0)
|
||||
log.debug('(%s) _send_string(queued data=%s)' % (self.ip, out.strip()))
|
||||
log.debug('({ip}) _send_string(queued data="{data}"%s)'.format(ip=self.ip, data=out.strip()))
|
||||
else:
|
||||
# No data to send
|
||||
log.debug('(%s) _send_string(): No data to send' % self.ip)
|
||||
log.debug('({ip}) _send_string(): No data to send'.format(ip=self.ip))
|
||||
self.send_busy = False
|
||||
return
|
||||
self.send_busy = True
|
||||
log.debug('(%s) _send_string(): Sending "%s"' % (self.ip, out.strip()))
|
||||
log.debug('(%s) _send_string(): Queue = %s' % (self.ip, self.send_queue))
|
||||
log.debug('({ip}) _send_string(): Sending "{data}"'.format(ip=self.ip, data=out.strip()))
|
||||
log.debug('({ip}) _send_string(): Queue = {data}'.format(ip=self.ip, data=self.send_queue))
|
||||
self.socket_timer.start()
|
||||
try:
|
||||
self.projectorNetwork.emit(self.ip, S_NETWORK_SENDING)
|
||||
@ -523,7 +543,9 @@ class PJLink1(QTcpSocket):
|
||||
translate('OpenLP.PJLink1', 'Error while sending data to projector'))
|
||||
except SocketError as e:
|
||||
self.disconnect_from_host(abort=True)
|
||||
self.changeStatus(E_NETWORK, '%s : %s' % (e.error(), e.errorString()))
|
||||
self.changeStatus(E_NETWORK,
|
||||
translate('OpenLP.PJLink1', '{code} : {string}').format(code=e.error(),
|
||||
string=e.errorString()))
|
||||
|
||||
def process_command(self, cmd, data):
|
||||
"""
|
||||
@ -532,19 +554,21 @@ class PJLink1(QTcpSocket):
|
||||
:param cmd: Command to process
|
||||
:param data: Data being processed
|
||||
"""
|
||||
log.debug('(%s) Processing command "%s"' % (self.ip, cmd))
|
||||
log.debug('({ip}) Processing command "{data}"'.format(ip=self.ip, data=cmd))
|
||||
if data in PJLINK_ERRORS:
|
||||
# Oops - projector error
|
||||
log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))
|
||||
if data.upper() == 'ERRA':
|
||||
# Authentication error
|
||||
self.disconnect_from_host()
|
||||
self.change_status(E_AUTHENTICATION)
|
||||
log.debug('(%s) emitting projectorAuthentication() signal' % self.ip)
|
||||
log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.ip))
|
||||
self.projectorAuthentication.emit(self.name)
|
||||
elif data.upper() == 'ERR1':
|
||||
# Undefined command
|
||||
self.change_status(E_UNDEFINED, '%s "%s"' %
|
||||
(translate('OpenLP.PJLink1', 'Undefined command:'), cmd))
|
||||
self.change_status(E_UNDEFINED, '{error} "{data}"'.format(error=translate('OpenLP.PJLink1',
|
||||
'Undefined command:'),
|
||||
data=cmd))
|
||||
elif data.upper() == 'ERR2':
|
||||
# Invalid parameter
|
||||
self.change_status(E_PARAMETER)
|
||||
@ -559,7 +583,7 @@ class PJLink1(QTcpSocket):
|
||||
return
|
||||
# Command succeeded - no extra information
|
||||
elif data.upper() == 'OK':
|
||||
log.debug('(%s) Command returned OK' % self.ip)
|
||||
log.debug('({ip}) Command returned OK'.format(ip=self.ip))
|
||||
# A command returned successfully, recheck data
|
||||
self.send_busy = False
|
||||
self.projectorReceivedData.emit()
|
||||
@ -568,7 +592,7 @@ class PJLink1(QTcpSocket):
|
||||
if cmd in self.PJLINK1_FUNC:
|
||||
self.PJLINK1_FUNC[cmd](data)
|
||||
else:
|
||||
log.warn('(%s) Invalid command %s' % (self.ip, cmd))
|
||||
log.warn('({ip}) Invalid command {data}'.format(ip=self.ip, data=cmd))
|
||||
self.send_busy = False
|
||||
self.projectorReceivedData.emit()
|
||||
|
||||
@ -587,7 +611,7 @@ class PJLink1(QTcpSocket):
|
||||
fill = {'Hours': int(data_dict[0]), 'On': False if data_dict[1] == '0' else True}
|
||||
except ValueError:
|
||||
# In case of invalid entry
|
||||
log.warn('(%s) process_lamp(): Invalid data "%s"' % (self.ip, data))
|
||||
log.warn('({ip}) process_lamp(): Invalid data "{data}"'.format(ip=self.ip, data=data))
|
||||
return
|
||||
lamps.append(fill)
|
||||
data_dict.pop(0) # Remove lamp hours
|
||||
@ -614,7 +638,7 @@ class PJLink1(QTcpSocket):
|
||||
self.send_command('INST')
|
||||
else:
|
||||
# Log unknown status response
|
||||
log.warn('Unknown power response: %s' % data)
|
||||
log.warn('({ip}) Unknown power response: {data}'.format(ip=self.ip, data=data))
|
||||
return
|
||||
|
||||
def process_avmt(self, data):
|
||||
@ -639,7 +663,7 @@ class PJLink1(QTcpSocket):
|
||||
shutter = True
|
||||
mute = True
|
||||
else:
|
||||
log.warn('Unknown shutter response: %s' % data)
|
||||
log.warn('({ip}) Unknown shutter response: {data}'.format(ip=self.ip, data=data))
|
||||
update_icons = shutter != self.shutter
|
||||
update_icons = update_icons or mute != self.mute
|
||||
self.shutter = shutter
|
||||
@ -656,6 +680,7 @@ class PJLink1(QTcpSocket):
|
||||
:param data: Currently selected source
|
||||
"""
|
||||
self.source = data
|
||||
log.info('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source))
|
||||
return
|
||||
|
||||
def process_clss(self, data):
|
||||
@ -674,7 +699,8 @@ class PJLink1(QTcpSocket):
|
||||
else:
|
||||
clss = data
|
||||
self.pjlink_class = clss
|
||||
log.debug('(%s) Setting pjlink_class for this projector to "%s"' % (self.ip, self.pjlink_class))
|
||||
log.debug('({ip}) Setting pjlink_class for this projector to "{data}"'.format(ip=self.ip,
|
||||
data=self.pjlink_class))
|
||||
return
|
||||
|
||||
def process_name(self, data):
|
||||
@ -685,6 +711,7 @@ class PJLink1(QTcpSocket):
|
||||
:param data: Projector name
|
||||
"""
|
||||
self.pjlink_name = data
|
||||
log.debug('({ip}) Setting projector PJLink name to "{data}"'.format(ip=self.ip, data=self.pjlink_name))
|
||||
return
|
||||
|
||||
def process_inf1(self, data):
|
||||
@ -695,6 +722,7 @@ class PJLink1(QTcpSocket):
|
||||
:param data: Projector manufacturer
|
||||
"""
|
||||
self.manufacturer = data
|
||||
log.debug('({ip}) Setting projector manufacturer data to "{data}"'.format(ip=self.ip, data=self.manufacturer))
|
||||
return
|
||||
|
||||
def process_inf2(self, data):
|
||||
@ -705,6 +733,7 @@ class PJLink1(QTcpSocket):
|
||||
:param data: Model name
|
||||
"""
|
||||
self.model = data
|
||||
log.debug('({ip}) Setting projector model to "{data}"'.format(ip=self.ip, data=self.model))
|
||||
return
|
||||
|
||||
def process_info(self, data):
|
||||
@ -715,6 +744,7 @@ class PJLink1(QTcpSocket):
|
||||
:param data: Projector other info
|
||||
"""
|
||||
self.other_info = data
|
||||
log.debug('({ip}) Setting projector other_info to "{data}"'.format(ip=self.ip, data=self.other_info))
|
||||
return
|
||||
|
||||
def process_inst(self, data):
|
||||
@ -731,6 +761,8 @@ class PJLink1(QTcpSocket):
|
||||
sources.sort()
|
||||
self.source_available = sources
|
||||
self.projectorUpdateIcons.emit()
|
||||
log.debug('({ip}) Setting projector sources_available to "{data}"'.format(ip=self.ip,
|
||||
data=self.source_available))
|
||||
return
|
||||
|
||||
def process_erst(self, data):
|
||||
@ -780,7 +812,7 @@ class PJLink1(QTcpSocket):
|
||||
Initiate connection to projector.
|
||||
"""
|
||||
if self.state() == self.ConnectedState:
|
||||
log.warn('(%s) connect_to_host(): Already connected - returning' % self.ip)
|
||||
log.warn('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.ip))
|
||||
return
|
||||
self.change_status(S_CONNECTING)
|
||||
self.connectToHost(self.ip, self.port if type(self.port) is int else int(self.port))
|
||||
@ -792,9 +824,9 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
if abort or self.state() != self.ConnectedState:
|
||||
if abort:
|
||||
log.warn('(%s) disconnect_from_host(): Aborting connection' % self.ip)
|
||||
log.warn('({ip}) disconnect_from_host(): Aborting connection'.format(ip=self.ip))
|
||||
else:
|
||||
log.warn('(%s) disconnect_from_host(): Not connected - returning' % self.ip)
|
||||
log.warn('({ip}) disconnect_from_host(): Not connected - returning'.format(ip=self.ip))
|
||||
self.reset_information()
|
||||
self.disconnectFromHost()
|
||||
try:
|
||||
@ -804,8 +836,8 @@ class PJLink1(QTcpSocket):
|
||||
if abort:
|
||||
self.change_status(E_NOT_CONNECTED)
|
||||
else:
|
||||
log.debug('(%s) disconnect_from_host() Current status %s' % (self.ip,
|
||||
self._get_status(self.status_connect)[0]))
|
||||
log.debug('({ip}) disconnect_from_host() '
|
||||
'Current status {data}'.format(ip=self.ip, data=self._get_status(self.status_connect)[0]))
|
||||
if self.status_connect != E_NOT_CONNECTED:
|
||||
self.change_status(S_NOT_CONNECTED)
|
||||
self.reset_information()
|
||||
@ -815,60 +847,70 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Send command to retrieve available source inputs.
|
||||
"""
|
||||
log.debug('({ip}) Sending INST command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='INST')
|
||||
|
||||
def get_error_status(self):
|
||||
"""
|
||||
Send command to retrieve currently known errors.
|
||||
"""
|
||||
log.debug('({ip}) Sending ERST command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='ERST')
|
||||
|
||||
def get_input_source(self):
|
||||
"""
|
||||
Send command to retrieve currently selected source input.
|
||||
"""
|
||||
log.debug('({ip}) Sending INPT command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='INPT')
|
||||
|
||||
def get_lamp_status(self):
|
||||
"""
|
||||
Send command to return the lap status.
|
||||
"""
|
||||
log.debug('({ip}) Sending LAMP command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='LAMP')
|
||||
|
||||
def get_manufacturer(self):
|
||||
"""
|
||||
Send command to retrieve manufacturer name.
|
||||
"""
|
||||
log.debug('({ip}) Sending INF1 command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='INF1')
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Send command to retrieve the model name.
|
||||
"""
|
||||
log.debug('({ip}) Sending INF2 command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='INF2')
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Send command to retrieve name as set by end-user (if set).
|
||||
"""
|
||||
log.debug('({ip}) Sending NAME command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='NAME')
|
||||
|
||||
def get_other_info(self):
|
||||
"""
|
||||
Send command to retrieve extra info set by manufacturer.
|
||||
"""
|
||||
log.debug('({ip}) Sending INFO command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='INFO')
|
||||
|
||||
def get_power_status(self):
|
||||
"""
|
||||
Send command to retrieve power status.
|
||||
"""
|
||||
log.debug('({ip}) Sending POWR command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='POWR')
|
||||
|
||||
def get_shutter_status(self):
|
||||
"""
|
||||
Send command to retrieve shutter status.
|
||||
"""
|
||||
log.debug('({ip}) Sending AVMT command'.format(ip=self.ip))
|
||||
return self.send_command(cmd='AVMT')
|
||||
|
||||
def set_input_source(self, src=None):
|
||||
@ -878,12 +920,12 @@ class PJLink1(QTcpSocket):
|
||||
|
||||
:param src: Video source to select in projector
|
||||
"""
|
||||
log.debug('(%s) set_input_source(src=%s)' % (self.ip, src))
|
||||
log.debug('({ip}) set_input_source(src="{data}")'.format(ip=self.ip, data=src))
|
||||
if self.source_available is None:
|
||||
return
|
||||
elif src not in self.source_available:
|
||||
return
|
||||
log.debug('(%s) Setting input source to %s' % (self.ip, src))
|
||||
log.debug('({ip}) Setting input source to "{data}"'.format(ip=self.ip, data=src))
|
||||
self.send_command(cmd='INPT', opts=src)
|
||||
self.poll_loop()
|
||||
|
||||
@ -891,6 +933,7 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Send command to turn power to on.
|
||||
"""
|
||||
log.debug('({ip}) Setting POWR to 1 (on)'.format(ip=self.ip))
|
||||
self.send_command(cmd='POWR', opts='1')
|
||||
self.poll_loop()
|
||||
|
||||
@ -898,6 +941,7 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Send command to turn power to standby.
|
||||
"""
|
||||
log.debug('({ip}) Setting POWR to 0 (standby)'.format(ip=self.ip))
|
||||
self.send_command(cmd='POWR', opts='0')
|
||||
self.poll_loop()
|
||||
|
||||
@ -905,6 +949,7 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Send command to set shutter to closed position.
|
||||
"""
|
||||
log.debug('({ip}) Setting AVMT to 11 (shutter closed)'.format(ip=self.ip))
|
||||
self.send_command(cmd='AVMT', opts='11')
|
||||
self.poll_loop()
|
||||
|
||||
@ -912,5 +957,6 @@ class PJLink1(QTcpSocket):
|
||||
"""
|
||||
Send command to set shutter to open position.
|
||||
"""
|
||||
log.debug('({ip}) Setting AVMT to "10" (shutter open)'.format(ip=self.ip))
|
||||
self.send_command(cmd='AVMT', opts='10')
|
||||
self.poll_loop()
|
||||
|
@ -59,6 +59,7 @@ class MediaShoutImport(SongImport):
|
||||
songs = cursor.fetchall()
|
||||
self.import_wizard.progress_bar.setMaximum(len(songs))
|
||||
for song in songs:
|
||||
topics = []
|
||||
if self.stop_import_flag:
|
||||
break
|
||||
cursor.execute('SELECT Type, Number, Text FROM Verses WHERE Record = %s ORDER BY Type, Number'
|
||||
@ -66,9 +67,10 @@ class MediaShoutImport(SongImport):
|
||||
verses = cursor.fetchall()
|
||||
cursor.execute('SELECT Type, Number, POrder FROM PlayOrder WHERE Record = %s ORDER BY POrder' % song.Record)
|
||||
verse_order = cursor.fetchall()
|
||||
cursor.execute('SELECT Name FROM Themes INNER JOIN SongThemes ON SongThemes.ThemeId = Themes.ThemeId '
|
||||
'WHERE SongThemes.Record = %s' % song.Record)
|
||||
topics = cursor.fetchall()
|
||||
if cursor.tables(table='TableName', tableType='TABLE').fetchone():
|
||||
cursor.execute('SELECT Name FROM Themes INNER JOIN SongThemes ON SongThemes.ThemeId = Themes.ThemeId '
|
||||
'WHERE SongThemes.Record = %s' % song.Record)
|
||||
topics = cursor.fetchall()
|
||||
cursor.execute('SELECT Name FROM Groups INNER JOIN SongGroups ON SongGroups.GroupId = Groups.GroupId '
|
||||
'WHERE SongGroups.Record = %s' % song.Record)
|
||||
topics += cursor.fetchall()
|
||||
|
@ -156,8 +156,8 @@ class OpenSongImport(SongImport):
|
||||
ustring = str(root.__getattr__(attr))
|
||||
if isinstance(fn_or_string, str):
|
||||
if attr in ['ccli']:
|
||||
ustring = ''.join(re.findall('\d+', ustring))
|
||||
if ustring:
|
||||
ustring = ''.join(re.findall('\d+', ustring))
|
||||
setattr(self, fn_or_string, int(ustring))
|
||||
else:
|
||||
setattr(self, fn_or_string, None)
|
||||
|
@ -54,7 +54,13 @@ class PresentationManagerImport(SongImport):
|
||||
# Open file with detected encoding and remove encoding declaration
|
||||
text = open(file_path, mode='r', encoding=encoding).read()
|
||||
text = re.sub('.+\?>\n', '', text)
|
||||
tree = etree.fromstring(text, parser=etree.XMLParser(recover=True))
|
||||
try:
|
||||
tree = etree.fromstring(text, parser=etree.XMLParser(recover=True))
|
||||
except ValueError:
|
||||
self.log_error(file_path,
|
||||
translate('SongsPlugin.PresentationManagerImport',
|
||||
'File is not in XML-format, which is the only format supported.'))
|
||||
continue
|
||||
root = objectify.fromstring(etree.tostring(tree))
|
||||
self.process_song(root)
|
||||
|
||||
|
@ -116,7 +116,13 @@ class SongShowPlusImport(SongImport):
|
||||
null, verse_name_length, = struct.unpack("BB", song_data.read(2))
|
||||
verse_name = self.decode(song_data.read(verse_name_length))
|
||||
length_descriptor_size, = struct.unpack("B", song_data.read(1))
|
||||
log.debug(length_descriptor_size)
|
||||
log.debug('length_descriptor_size: %d' % length_descriptor_size)
|
||||
# In the case of song_numbers the number is in the data from the
|
||||
# current position to the next block starts
|
||||
if block_key == SONG_NUMBER:
|
||||
sn_bytes = song_data.read(length_descriptor_size - 1)
|
||||
self.song_number = int.from_bytes(sn_bytes, byteorder='little')
|
||||
continue
|
||||
# Detect if/how long the length descriptor is
|
||||
if length_descriptor_size == 12 or length_descriptor_size == 20:
|
||||
length_descriptor, = struct.unpack("I", song_data.read(4))
|
||||
|
@ -73,6 +73,14 @@ class VideoPsalmImport(SongImport):
|
||||
processed_content += c
|
||||
c = next(file_content_it)
|
||||
processed_content += '"' + c
|
||||
# Remove control characters
|
||||
elif (c < chr(32)):
|
||||
processed_content += ' '
|
||||
# Handle escaped characters
|
||||
elif c == '\\':
|
||||
processed_content += c
|
||||
c = next(file_content_it)
|
||||
processed_content += c
|
||||
else:
|
||||
processed_content += c
|
||||
songbook = json.loads(processed_content.strip())
|
||||
@ -117,6 +125,6 @@ class VideoPsalmImport(SongImport):
|
||||
if not self.finish():
|
||||
self.log_error('Could not import %s' % self.title)
|
||||
except Exception as e:
|
||||
self.log_error(translate('SongsPlugin.VideoPsalmImport', 'File %s' % file.name),
|
||||
self.log_error(self.import_source,
|
||||
translate('SongsPlugin.VideoPsalmImport', 'Error: %s') % e)
|
||||
song_file.close()
|
||||
|
@ -4548,7 +4548,7 @@ Dateiendung nicht unterstützt.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/mediaitem.py" line="109"/>
|
||||
<source>&Clone</source>
|
||||
<translation>&Klonen</translation>
|
||||
<translation>&Duplizieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/lib/mediamanageritem.py" line="379"/>
|
||||
|
@ -1592,7 +1592,8 @@ Complete</source>
|
||||
<location filename="../../openlp/plugins/bibles/forms/bibleupgradeform.py" line="549"/>
|
||||
<source>Upgrading Bible(s): %(success)d successful%(failed_text)s
|
||||
Please note that verses from Web Bibles will be downloaded on demand and so an Internet connection is required.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Aktualizowanie Biblii: %(success)d z powodzeniem %(failed_text)s
|
||||
Należy pamiętać, że wersety z Biblii online będą pobierane na żądnie, więc połączenie z internetem jest wymagane.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1772,7 +1773,7 @@ Wtyczka Slajdu Tekstowego umożliwia umieszczanie zwykłych ciągów znaków na
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/custom/lib/mediaitem.py" line="190"/>
|
||||
<source>Are you sure you want to delete the "%d" selected custom slide(s)?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Czy na pewno chcesz usunąć %n zaznaczonych slajdów niestandardowych?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1998,7 +1999,7 @@ Czy mimo to chcesz dodać inne?</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/media/systemplayer.py" line="249"/>
|
||||
<source>This media player uses your operating system to provide media capabilities.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Ten odtwarzacz multimediów wykorzystuje twój system operacyjny dla zapewnienia zdolności multimedialnych</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2426,147 +2427,147 @@ OpenLP jest pisany i wspierany przez wolontariuszy. Jeśli chciałbyś, aby pows
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="157"/>
|
||||
<source>Project Lead</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Prowadzenie projektu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="158"/>
|
||||
<source>Developers</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Deweloperzy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="159"/>
|
||||
<source>Contributors</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Uczestnicy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="160"/>
|
||||
<source>Packagers</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Paczki</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="161"/>
|
||||
<source>Testers</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Testerzy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="162"/>
|
||||
<source>Translators</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Tłumacze</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="163"/>
|
||||
<source>Afrikaans (af)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Afrykanerski (af)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="164"/>
|
||||
<source>Czech (cs)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Czeski (cs)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="165"/>
|
||||
<source>Danish (da)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Duński (da)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="166"/>
|
||||
<source>German (de)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Niemiecki (de)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="167"/>
|
||||
<source>Greek (el)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Grecki (el)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="168"/>
|
||||
<source>English, United Kingdom (en_GB)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Angielski, UK (en_GB)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="169"/>
|
||||
<source>English, South Africa (en_ZA)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Angielski, RPA (en_ZA)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="170"/>
|
||||
<source>Spanish (es)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Hiszpański (es)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="171"/>
|
||||
<source>Estonian (et)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Estoński (et)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="172"/>
|
||||
<source>Finnish (fi)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Fiński (fi)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="173"/>
|
||||
<source>French (fr)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Francuski (fr)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="174"/>
|
||||
<source>Hungarian (hu)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Węgierski (hu)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="175"/>
|
||||
<source>Indonesian (id)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Indonezyjski (id)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="176"/>
|
||||
<source>Japanese (ja)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Japoński (ja)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="177"/>
|
||||
<source>Norwegian Bokmål (nb)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Norweski (nb)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="178"/>
|
||||
<source>Dutch (nl)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Holenderski (nl)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="179"/>
|
||||
<source>Polish (pl)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Polski (pl)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="180"/>
|
||||
<source>Portuguese, Brazil (pt_BR)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Portugalski (pt_BR)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="181"/>
|
||||
<source>Russian (ru)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Rosyjski (ru)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="182"/>
|
||||
<source>Swedish (sv)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Szwedzki (sv)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="183"/>
|
||||
<source>Tamil(Sri-Lanka) (ta_LK)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Tamilski (Sri-Lanka) (ta_LK)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="184"/>
|
||||
<source>Chinese(China) (zh_CN)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Chiński(Chiny) (zh_CN)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="185"/>
|
||||
<source>Documentation</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Dokumentacja</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="186"/>
|
||||
@ -2577,7 +2578,12 @@ OpenLP jest pisany i wspierany przez wolontariuszy. Jeśli chciałbyś, aby pows
|
||||
Oxygen Icons: http://techbase.kde.org/Projects/Oxygen/
|
||||
MuPDF: http://www.mupdf.com/
|
||||
</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Stworzono przy użyciu:
|
||||
Python: http://www.python.org/
|
||||
Qt5: http://qt.io
|
||||
PyQt5: http://www.riverbankcomputing.co.uk/software/pyqt/intro
|
||||
Oxygen Icons: http://techbase.kde.org/Projects/Oxygen/
|
||||
MuPDF: http://www.mupdf.com/</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="192"/>
|
||||
@ -2592,13 +2598,19 @@ OpenLP jest pisany i wspierany przez wolontariuszy. Jeśli chciałbyś, aby pows
|
||||
on the cross, setting us free from sin. We
|
||||
bring this software to you for free because
|
||||
He has set us free.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Końcowe podziękowanie:
|
||||
"Dla Boga, który tak umiłował świat, że Syna swego, jednorodzonego dał, aby każdy, kto w niego wierzy, nie zginął, ale miał życie wieczne" J 3,16
|
||||
|
||||
Na koniec ale nie mniej ważnie, końcowe podziękowania dla Boga, naszego Ojca, za zesłanie nam swego Syna, by umarł za nas na krzyżu i uczynił nas wolnymi od grzechu.
|
||||
Dostarczamy to oprogramowanie za darmo, ponieważ On uczynił nas wolnymi.
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/aboutdialog.py" line="303"/>
|
||||
<source>Copyright © 2004-2016 %s
|
||||
Portions copyright © 2004-2016 %s</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Copyright © 2004-2016 %s
|
||||
Portions copyright © 2004-2016 %s</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3221,12 +3233,12 @@ Katalog z danymi zostanie przywrucony jak OpenLP zostanie zamknięty.</translati
|
||||
<location filename="../../openlp/core/ui/exceptiondialog.py" line="92"/>
|
||||
<source>Please enter a description of what you were doing to cause this error. If possible, write in English.
|
||||
(Minimum 20 characters)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Proszę opisać czynności wykonywane bezpośrednio przed wystąpieniem błędu. Jeśli to możliwe, napisz w języku angielskim (min. 20 znaków).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/exceptiondialog.py" line="96"/>
|
||||
<source>Oops! OpenLP hit a problem, and couldn't recover. The text in the box below contains information that might be helpful to the OpenLP developers, so please e-mail it to bugs@openlp.org, along with a detailed description of what you were doing when the problem occurred. Also attach any files that triggered the problem.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Oops! OpenLP napotkał problem i już nie wstał... Poniższe pole tekstowe zawiera informacje, które mogą być pomocne dla programistów OpenLP. Proszę wysłać e-mail na adres bugs@openlp.org wraz z dokładnym opisem czynności jakie były wykonywane w momencie wystąpienia błędu.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3629,7 +3641,7 @@ By anulować kreatora pierwszego uruchomienia całkowicie (i nie uruchamiać Ope
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/formattingtagcontroller.py" line="168"/>
|
||||
<source>End tag %(end)s does not match end tag for start tag %(start)s</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Końcowy znacznik %s nie pasuje do początkowego %s</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -4409,47 +4421,47 @@ Proces został zatrzymany i nie wykonano żadnych zmian.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="393"/>
|
||||
<source>&Recent Services</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Ostatnio &używane</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="404"/>
|
||||
<source>&New Service</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Nowy plan nabożeństwa</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="407"/>
|
||||
<source>&Open Service</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Otwórz plan nabożeństwa.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="410"/>
|
||||
<source>&Save Service</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zapisz plan nabożeństwa</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="413"/>
|
||||
<source>Save Service &As...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zapisz plan nabożeństwa jako</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="460"/>
|
||||
<source>&Manage Plugins</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zarządzaj profilami</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="1101"/>
|
||||
<source>Exit OpenLP</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Wyjdź z OpenLP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="1101"/>
|
||||
<source>Are you sure you want to exit OpenLP?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Czy na pewno chcesz zamknąć OpenLP?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="1108"/>
|
||||
<source>&Exit OpenLP</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Wyjdź z OpenLP</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -4620,7 +4632,7 @@ Nieobsługiwany przyrostek.</translation>
|
||||
<location filename="../../openlp/core/ui/media/playertab.py" line="256"/>
|
||||
<source>NOTE: To use VLC you must install the %s version</source>
|
||||
<comment>Will insert "32bit" or "64bit"</comment>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Uwaga: By używać VLC musisz zainstalować %s wersję</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -4663,7 +4675,7 @@ Nieobsługiwany przyrostek.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/plugindialog.py" line="81"/>
|
||||
<source>Manage Plugins</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zarządzaj wtyczkami </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -5291,7 +5303,7 @@ Nieobsługiwany przyrostek.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/projector/manager.py" line="653"/>
|
||||
<source>Shutter is</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Przesłona</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/projector/manager.py" line="653"/>
|
||||
@ -5351,12 +5363,12 @@ Nieobsługiwany przyrostek.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/projector/manager.py" line="476"/>
|
||||
<source>Delete projector (%s) %s?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Usunąć projektor (%s) %s?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/projector/manager.py" line="478"/>
|
||||
<source>Are you sure you want to delete this projector?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Czy napewno chcesz usunąć ten projektor?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -5379,7 +5391,7 @@ Nieobsługiwany przyrostek.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/lib/projector/pjlink1.py" line="767"/>
|
||||
<source>Cover</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Osłona</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/lib/projector/pjlink1.py" line="771"/>
|
||||
@ -6456,14 +6468,15 @@ Zostaną one usunięte, jeśli będziesz kontynuował/</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/thememanager.py" line="768"/>
|
||||
<source>Unable to delete theme</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Nie można usunąć motywu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/thememanager.py" line="768"/>
|
||||
<source>Theme is currently used
|
||||
|
||||
%s</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Motyw, który jest obecnie używany
|
||||
%s</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -7510,19 +7523,19 @@ Proszę zaznaczyć go ręcznie.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/common/uistrings.py" line="125"/>
|
||||
<source>Replace live background is not available when the WebKit player is disabled.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zastępowanie tła live jest niedostępne gdy odtwarzacz WebKit jest zablokowany</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/ui.py" line="38"/>
|
||||
<source>Songbook</source>
|
||||
<comment>Singular</comment>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Śpiewnik</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/ui.py" line="39"/>
|
||||
<source>Songbooks</source>
|
||||
<comment>Plural</comment>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Śpiewniki</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -7970,12 +7983,12 @@ Proszę zaznaczyć go ręcznie.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/remotes/lib/remotetab.py" line="198"/>
|
||||
<source>iOS App</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Aplikacja iOS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/remotes/lib/remotetab.py" line="199"/>
|
||||
<source>Scan the QR code or click <a href="%s">download</a> to install the iOS app from the App Store.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zeskanuj kod QR lub kliknij <a href="%s">pobierz</a>, aby zainstalować aplikację z App Store.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -8712,42 +8725,43 @@ Proszę, wpisz zwrotki oddzielając je spacją.</translation>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongform.py" line="189"/>
|
||||
<source>There are no verses corresponding to "%(invalid)s". Valid entries are %(valid)s.
|
||||
Please enter the verses separated by spaces.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Nie ma zwrotek o oznaczeniu "%(invalid)s". Właściwymi oznaczeniami są %(valid)s.
|
||||
Proszę, wpisz zwrotki oddzielając je spacją.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="317"/>
|
||||
<source>&Manage Authors, Topics, Songbooks</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zarządzaj autorami, &tematami, śpiewnikami</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="322"/>
|
||||
<source>Add &to Song</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Dodaj do &pieśni</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="323"/>
|
||||
<source>Re&move</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Usuń</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="324"/>
|
||||
<source>Authors, Topics && Songbooks</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Autorzy, tematy i śpiewniki</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongform.py" line="683"/>
|
||||
<source>Add Songbook</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Dodaj Śpiewnik</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongform.py" line="683"/>
|
||||
<source>This Songbook does not exist, do you want to add it?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Ten śpiewnik nie istnieje, czy chcesz go dodać?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongform.py" line="700"/>
|
||||
<source>This Songbook is already in the list.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Ten Śpiewnik już jest na liście</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongform.py" line="707"/>
|
||||
@ -8764,7 +8778,9 @@ Please enter the verses separated by spaces.</source>
|
||||
<source>Unable to find the following file:
|
||||
%s
|
||||
Do you want to remove the entry from the song?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Nie można znaleźć pliku:
|
||||
%s
|
||||
Czy chcesz usunąć wpis z pieśni?</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9094,37 +9110,37 @@ Do you want to remove the entry from the song?</source>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importer.py" line="194"/>
|
||||
<source>OpenLyrics or OpenLP 2 Exported Song</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>OpenLyrics lub wyeksportowane pieśni OpenLP 2.0</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importer.py" line="201"/>
|
||||
<source>OpenLP 2 Databases</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Bazy danych OpenLP 2.0</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importer.py" line="255"/>
|
||||
<source>LyriX Files</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Pliki LyriX</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importer.py" line="256"/>
|
||||
<source>LyriX (Exported TXT-files)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>LyriX (Eksportowane pliki txt)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importer.py" line="343"/>
|
||||
<source>VideoPsalm Files</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>pliki VideoPsalm</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importer.py" line="344"/>
|
||||
<source>VideoPsalm</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>VideoPsalm</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importer.py" line="345"/>
|
||||
<source>The VideoPsalm songbooks are normally located in %s</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Śpiewniki VideoPsalm są normalnie zlokalizowane w %s</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9132,7 +9148,7 @@ Do you want to remove the entry from the song?</source>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importers/lyrix.py" line="109"/>
|
||||
<source>Error: %s</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Błąd: %s</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9204,12 +9220,12 @@ Do you want to remove the entry from the song?</source>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/mediaitem.py" line="364"/>
|
||||
<source>Are you sure you want to delete the "%d" selected song(s)?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Czy na pewno chcesz usunąć "%d" wybranych pieśn(i)?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/mediaitem.py" line="142"/>
|
||||
<source>Search Songbooks...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Szukaj Śpiewników</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9225,7 +9241,7 @@ Do you want to remove the entry from the song?</source>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importers/openlp.py" line="102"/>
|
||||
<source>Not a valid OpenLP 2 song database.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Niewłaściwa baza pieśni Openlp 2.0.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9297,7 +9313,7 @@ Do you want to remove the entry from the song?</source>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/songbookdialog.py" line="66"/>
|
||||
<source>Songbook Maintenance</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Zarządzanie pieśniami</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9605,7 +9621,7 @@ Zapisywanie nazwy użytkownika i hasła jest NIEBEZPIECZNE, twoje hasło jest za
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/songselectdialog.py" line="244"/>
|
||||
<source>Stop</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Stop</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9702,7 +9718,7 @@ Zapisywanie nazwy użytkownika i hasła jest NIEBEZPIECZNE, twoje hasło jest za
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importers/videopsalm.py" line="121"/>
|
||||
<source>Error: %s</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Błąd: %s</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -9710,7 +9726,7 @@ Zapisywanie nazwy użytkownika i hasła jest NIEBEZPIECZNE, twoje hasło jest za
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importers/wordsofworship.py" line="109"/>
|
||||
<source>Invalid Words of Worship song file. Missing "%s" header.WoW File\nSong Words</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Niewłaściwy plik pieśni Words of Worship. Brakujący "%s" nagłówek. WoW File\nSong Words </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importers/wordsofworship.py" line="119"/>
|
||||
|
@ -2329,7 +2329,7 @@ Deseja continuar adicionando as outras imagens mesmo assim?</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/core/ui/mainwindow.py" line="435"/>
|
||||
<source>&Projector Manager</source>
|
||||
<translation>Gerenciador de projetor</translation>
|
||||
<translation>Gerenciador de &Projetor</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -7122,7 +7122,7 @@ See http://docs.python.org/library/datetime.html#strftime-strptime-behavior for
|
||||
<message>
|
||||
<location filename="../../openlp/core/common/uistrings.py" line="73"/>
|
||||
<source>&Delete</source>
|
||||
<translation>&Excluir</translation>
|
||||
<translation>E&xcluir</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/core/common/uistrings.py" line="74"/>
|
||||
@ -7989,7 +7989,7 @@ Por favor, tente selecionar individualmente.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/remotes/lib/remotetab.py" line="198"/>
|
||||
<source>iOS App</source>
|
||||
<translation>iOS App</translation>
|
||||
<translation>Aplicativo iOS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/remotes/lib/remotetab.py" line="199"/>
|
||||
@ -8027,12 +8027,12 @@ Por favor, tente selecionar individualmente.</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songusage/songusageplugin.py" line="103"/>
|
||||
<source>Toggle Tracking</source>
|
||||
<translation>Alternar Registro</translation>
|
||||
<translation>Liga/Desliga Registro</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songusage/songusageplugin.py" line="117"/>
|
||||
<source>Toggle the tracking of song usage.</source>
|
||||
<translation>Alternar o registro de uso das músicas.</translation>
|
||||
<translation>Liga/Desliga o registro de uso das músicas.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songusage/songusageplugin.py" line="237"/>
|
||||
@ -8043,19 +8043,19 @@ Por favor, tente selecionar individualmente.</translation>
|
||||
<location filename="../../openlp/plugins/songusage/songusageplugin.py" line="248"/>
|
||||
<source>SongUsage</source>
|
||||
<comment>name singular</comment>
|
||||
<translation>UsoDaMúsica</translation>
|
||||
<translation>Música Utilizada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songusage/songusageplugin.py" line="249"/>
|
||||
<source>SongUsage</source>
|
||||
<comment>name plural</comment>
|
||||
<translation>UsoDaMúsica</translation>
|
||||
<translation>Músicas Utilizadas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songusage/songusageplugin.py" line="253"/>
|
||||
<source>SongUsage</source>
|
||||
<comment>container title</comment>
|
||||
<translation>UsoDaMúsica</translation>
|
||||
<translation>Música Utilizada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songusage/songusageplugin.py" line="153"/>
|
||||
@ -8548,7 +8548,7 @@ A codificação é responsável pela correta representação dos caracteres.</tr
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="304"/>
|
||||
<source>Alt&ernate title:</source>
|
||||
<translation>Título &Alternativo:</translation>
|
||||
<translation>Tít&ulo Alternativo:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="305"/>
|
||||
@ -8558,12 +8558,12 @@ A codificação é responsável pela correta representação dos caracteres.</tr
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="306"/>
|
||||
<source>&Verse order:</source>
|
||||
<translation>Ordem das &estrofes:</translation>
|
||||
<translation>&Ordem das estrofes:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="309"/>
|
||||
<source>Ed&it All</source>
|
||||
<translation>&Editar Todos</translation>
|
||||
<translation>Ed&itar Todos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="311"/>
|
||||
@ -8573,7 +8573,7 @@ A codificação é responsável pela correta representação dos caracteres.</tr
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="314"/>
|
||||
<source>&Add to Song</source>
|
||||
<translation>&Adicionar à Música</translation>
|
||||
<translation>&Adicionar Autor</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="338"/>
|
||||
@ -8583,7 +8583,7 @@ A codificação é responsável pela correta representação dos caracteres.</tr
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="319"/>
|
||||
<source>A&dd to Song</source>
|
||||
<translation>A&dicionar uma Música</translation>
|
||||
<translation>Adicionar &Tópico</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/forms/editsongdialog.py" line="320"/>
|
||||
@ -9247,7 +9247,7 @@ Você deseja remover a entrada da música?</translation>
|
||||
<message>
|
||||
<location filename="../../openlp/plugins/songs/lib/importers/openlp.py" line="102"/>
|
||||
<source>Not a valid OpenLP 2 song database.</source>
|
||||
<translation>Não é uma base de dados de músicas válida do OpenLP 2.</translation>
|
||||
<translation>Não é uma base de dados de músicas válido do OpenLP 2.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -23,13 +23,12 @@
|
||||
Package to test the openlp.core.ui.projector.networkutils package.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.common import verify_ip_address, md5_hash, qmd5_hash
|
||||
|
||||
from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_HASH
|
||||
|
||||
salt = TEST_SALT
|
||||
pin = TEST_PIN
|
||||
test_hash = TEST_HASH
|
||||
@ -148,7 +147,7 @@ class testProjectorUtilities(TestCase):
|
||||
hash_ = qmd5_hash(salt=salt.encode('ascii'), data=pin.encode('ascii'))
|
||||
|
||||
# THEN: Validate return has is same
|
||||
self.assertEquals(hash_.decode('ascii'), test_hash, 'Qt-MD5 should have returned a good hash')
|
||||
self.assertEquals(hash_, test_hash.encode('ascii'), 'Qt-MD5 should have returned a good hash')
|
||||
|
||||
def test_qmd5_hash_bad(self):
|
||||
"""
|
||||
@ -158,7 +157,7 @@ class testProjectorUtilities(TestCase):
|
||||
hash_ = qmd5_hash(salt=pin.encode('ascii'), data=salt.encode('ascii'))
|
||||
|
||||
# THEN: return data is different
|
||||
self.assertNotEquals(hash_.decode('ascii'), test_hash, 'Qt-MD5 should have returned a bad hash')
|
||||
self.assertNotEquals(hash_, test_hash, 'Qt-MD5 should have returned a bad hash')
|
||||
|
||||
def test_md5_non_ascii_string(self):
|
||||
"""
|
||||
|
@ -26,13 +26,29 @@ Package to test the openlp.core.lib.projector.pjlink1 package.
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.lib.projector.pjlink1 import PJLink1
|
||||
from openlp.core.lib.projector.constants import E_PARAMETER, ERROR_STRING, S_OFF, S_STANDBY, S_WARMUP, S_ON, \
|
||||
S_COOLDOWN, PJLINK_POWR_STATUS
|
||||
|
||||
from tests.functional import patch
|
||||
from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE
|
||||
from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST_HASH
|
||||
|
||||
pjlink_test = PJLink1(name='test', ip='127.0.0.1', pin=TEST_PIN, no_poll=True)
|
||||
|
||||
|
||||
class DummyTimer(object):
|
||||
'''
|
||||
Dummy class to fake timers
|
||||
'''
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def start(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def stop(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class TestPJLink(TestCase):
|
||||
"""
|
||||
Tests for the PJLink module
|
||||
@ -41,13 +57,10 @@ class TestPJLink(TestCase):
|
||||
@patch.object(pjlink_test, 'send_command')
|
||||
@patch.object(pjlink_test, 'waitForReadyRead')
|
||||
@patch('openlp.core.common.qmd5_hash')
|
||||
def authenticated_connection_call_test(self,
|
||||
mock_qmd5_hash,
|
||||
mock_waitForReadyRead,
|
||||
mock_send_command,
|
||||
def test_authenticated_connection_call(self, mock_qmd5_hash, mock_waitForReadyRead, mock_send_command,
|
||||
mock_readyRead):
|
||||
"""
|
||||
Fix for projector connect with PJLink authentication exception. Ticket 92187.
|
||||
Ticket 92187: Fix for projector connect with PJLink authentication exception.
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
@ -61,9 +74,23 @@ class TestPJLink(TestCase):
|
||||
self.assertTrue(mock_qmd5_hash.called_with(TEST_PIN,
|
||||
"Connection request should have been called with TEST_PIN"))
|
||||
|
||||
def non_standard_class_reply_test(self):
|
||||
def test_projector_class(self):
|
||||
"""
|
||||
bugfix 1550891 - CLSS request returns non-standard 'Class N' reply
|
||||
Test class version from projector
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
|
||||
# WHEN: Process class response
|
||||
pjlink.process_clss('1')
|
||||
|
||||
# THEN: Projector class should be set to 1
|
||||
self.assertEquals(pjlink.pjlink_class, '1',
|
||||
'Projector should have returned class=1')
|
||||
|
||||
def test_non_standard_class_reply(self):
|
||||
"""
|
||||
Bugfix 1550891: CLSS request returns non-standard 'Class N' reply
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
@ -88,3 +115,284 @@ class TestPJLink(TestCase):
|
||||
# THEN: Projector class should be set to 1
|
||||
self.assertEquals(pjlink.pjlink_class, '1',
|
||||
'Projector should have returned class=1')
|
||||
|
||||
@patch.object(pjlink_test, 'change_status')
|
||||
def test_status_change(self, mock_change_status):
|
||||
"""
|
||||
Test process_command call with ERR2 (Parameter) status
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
|
||||
# WHEN: process_command is called with "ERR2" status from projector
|
||||
pjlink.process_command('POWR', 'ERR2')
|
||||
|
||||
# THEN: change_status should have called change_status with E_UNDEFINED
|
||||
# as first parameter
|
||||
mock_change_status.called_with(E_PARAMETER,
|
||||
'change_status should have been called with "{}"'.format(
|
||||
ERROR_STRING[E_PARAMETER]))
|
||||
|
||||
@patch.object(pjlink_test, 'process_inpt')
|
||||
def test_projector_return_ok(self, mock_process_inpt):
|
||||
"""
|
||||
Test projector calls process_inpt command when process_command is called with INPT option
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
|
||||
# WHEN: process_command is called with INST command and 31 input:
|
||||
pjlink.process_command('INPT', '31')
|
||||
|
||||
# THEN: process_inpt method should have been called with 31
|
||||
mock_process_inpt.called_with('31',
|
||||
"process_inpt should have been called with 31")
|
||||
|
||||
@patch.object(pjlink_test, 'projectorReceivedData')
|
||||
def test_projector_process_lamp(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test status lamp on/off and hours
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
|
||||
# WHEN: Call process_command with lamp data
|
||||
pjlink.process_command('LAMP', '22222 1')
|
||||
|
||||
# THEN: Lamp should have been set with status=ON and hours=22222
|
||||
self.assertEquals(pjlink.lamp[0]['On'], True,
|
||||
'Lamp power status should have been set to TRUE')
|
||||
self.assertEquals(pjlink.lamp[0]['Hours'], 22222,
|
||||
'Lamp hours should have been set to 22222')
|
||||
|
||||
@patch.object(pjlink_test, 'projectorReceivedData')
|
||||
def test_projector_process_multiple_lamp(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test status multiple lamp on/off and hours
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
|
||||
# WHEN: Call process_command with lamp data
|
||||
pjlink.process_command('LAMP', '11111 1 22222 0 33333 1')
|
||||
|
||||
# THEN: Lamp should have been set with proper lamp status
|
||||
self.assertEquals(len(pjlink.lamp), 3,
|
||||
'Projector should have 3 lamps specified')
|
||||
self.assertEquals(pjlink.lamp[0]['On'], True,
|
||||
'Lamp 1 power status should have been set to TRUE')
|
||||
self.assertEquals(pjlink.lamp[0]['Hours'], 11111,
|
||||
'Lamp 1 hours should have been set to 11111')
|
||||
self.assertEquals(pjlink.lamp[1]['On'], False,
|
||||
'Lamp 2 power status should have been set to FALSE')
|
||||
self.assertEquals(pjlink.lamp[1]['Hours'], 22222,
|
||||
'Lamp 2 hours should have been set to 22222')
|
||||
self.assertEquals(pjlink.lamp[2]['On'], True,
|
||||
'Lamp 3 power status should have been set to TRUE')
|
||||
self.assertEquals(pjlink.lamp[2]['Hours'], 33333,
|
||||
'Lamp 3 hours should have been set to 33333')
|
||||
|
||||
@patch.object(pjlink_test, 'projectorReceivedData')
|
||||
def test_projector_process_power_on(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test status power to ON
|
||||
"""
|
||||
# GIVEN: Test object and preset
|
||||
pjlink = pjlink_test
|
||||
pjlink.power = S_STANDBY
|
||||
|
||||
# WHEN: Call process_command with turn power on command
|
||||
pjlink.process_command('POWR', PJLINK_POWR_STATUS[S_ON])
|
||||
|
||||
# THEN: Power should be set to ON
|
||||
self.assertEquals(pjlink.power, S_ON, 'Power should have been set to ON')
|
||||
|
||||
@patch.object(pjlink_test, 'projectorReceivedData')
|
||||
def test_projector_process_power_off(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test status power to STANDBY
|
||||
"""
|
||||
# GIVEN: Test object and preset
|
||||
pjlink = pjlink_test
|
||||
pjlink.power = S_ON
|
||||
|
||||
# WHEN: Call process_command with turn power on command
|
||||
pjlink.process_command('POWR', PJLINK_POWR_STATUS[S_STANDBY])
|
||||
|
||||
# THEN: Power should be set to STANDBY
|
||||
self.assertEquals(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')
|
||||
|
||||
@patch.object(pjlink_test, 'projectorUpdateIcons')
|
||||
def test_projector_process_avmt_closed_unmuted(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test avmt status shutter closed and audio muted
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
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
|
||||
self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
|
||||
self.assertFalse(pjlink.mute, 'Audio should be off')
|
||||
|
||||
@patch.object(pjlink_test, 'projectorUpdateIcons')
|
||||
def test_projector_process_avmt_open_muted(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test avmt status shutter open and mute on
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
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
|
||||
self.assertFalse(pjlink.shutter, 'Shutter should have been set to closed')
|
||||
self.assertTrue(pjlink.mute, 'Audio should be off')
|
||||
|
||||
@patch.object(pjlink_test, 'projectorUpdateIcons')
|
||||
def test_projector_process_avmt_open_unmuted(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test avmt status shutter open and mute off off
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
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
|
||||
self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')
|
||||
self.assertFalse(pjlink.mute, 'Audio should be on')
|
||||
|
||||
@patch.object(pjlink_test, 'projectorUpdateIcons')
|
||||
def test_projector_process_avmt_closed_muted(self, mock_projectorReceivedData):
|
||||
"""
|
||||
Test avmt status shutter closed and mute off
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
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
|
||||
self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
|
||||
self.assertTrue(pjlink.mute, 'Audio should be on')
|
||||
|
||||
def test_projector_process_input(self):
|
||||
"""
|
||||
Test input source status shows current input
|
||||
"""
|
||||
# GIVEN: Test object
|
||||
pjlink = pjlink_test
|
||||
pjlink.source = '0'
|
||||
|
||||
# WHEN: Called with input source
|
||||
pjlink.process_inpt('1')
|
||||
|
||||
# THEN: Input selected should reflect current input
|
||||
self.assertEquals(pjlink.source, '1', 'Input source should be set to "1"')
|
||||
|
||||
def test_projector_reset_information(self):
|
||||
"""
|
||||
Test reset_information() resets all information and stops timers
|
||||
"""
|
||||
# GIVEN: Test object and test data
|
||||
pjlink = pjlink_test
|
||||
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
|
||||
pjlink.timer = DummyTimer()
|
||||
pjlink.socket_timer = DummyTimer()
|
||||
|
||||
# WHEN: reset_information() is called
|
||||
with patch.object(pjlink.timer, 'stop') as mock_timer:
|
||||
with patch.object(pjlink.socket_timer, 'stop') as mock_socket_timer:
|
||||
pjlink.reset_information()
|
||||
|
||||
# THEN: All information should be reset and timers stopped
|
||||
self.assertEquals(pjlink.power, S_OFF, 'Projector power should be OFF')
|
||||
self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')
|
||||
self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')
|
||||
self.assertIsNone(pjlink.model, 'Projector model should be None')
|
||||
self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')
|
||||
self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')
|
||||
self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')
|
||||
self.assertIsNone(pjlink.fan, 'Projector fan should be None')
|
||||
self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')
|
||||
self.assertIsNone(pjlink.source, 'Projector source should be None')
|
||||
self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')
|
||||
self.assertEquals(pjlink.send_queue, [], 'Projector send_queue should be an empty list')
|
||||
self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')
|
||||
self.assertTrue(mock_timer.called, 'Projector timer.stop() should have been called')
|
||||
self.assertTrue(mock_socket_timer.called, 'Projector socket_timer.stop() should have been called')
|
||||
|
||||
@patch.object(pjlink_test, 'send_command')
|
||||
@patch.object(pjlink_test, 'waitForReadyRead')
|
||||
@patch.object(pjlink_test, 'projectorAuthentication')
|
||||
@patch.object(pjlink_test, 'timer')
|
||||
@patch.object(pjlink_test, 'socket_timer')
|
||||
def test_bug_1593882_no_pin_authenticated_connection(self, mock_socket_timer,
|
||||
mock_timer,
|
||||
mock_authentication,
|
||||
mock_ready_read,
|
||||
mock_send_command):
|
||||
"""
|
||||
Test bug 1593882 no pin and authenticated request exception
|
||||
"""
|
||||
# GIVEN: Test object and mocks
|
||||
pjlink = pjlink_test
|
||||
pjlink.pin = None
|
||||
mock_ready_read.return_value = True
|
||||
|
||||
# WHEN: call with authentication request and pin not set
|
||||
pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
|
||||
|
||||
# THEN: No Authentication signal should have been sent
|
||||
mock_authentication.emit.assert_called_with(pjlink.name)
|
||||
|
||||
@patch.object(pjlink_test, 'waitForReadyRead')
|
||||
@patch.object(pjlink_test, 'state')
|
||||
@patch.object(pjlink_test, '_send_command')
|
||||
@patch.object(pjlink_test, 'timer')
|
||||
@patch.object(pjlink_test, 'socket_timer')
|
||||
def test_bug_1593883_pjlink_authentication(self, mock_socket_timer,
|
||||
mock_timer,
|
||||
mock_send_command,
|
||||
mock_state,
|
||||
mock_waitForReadyRead):
|
||||
"""
|
||||
Test bugfix 1593883 pjlink authentication
|
||||
"""
|
||||
# GIVEN: Test object and data
|
||||
pjlink = pjlink_test
|
||||
pjlink.pin = TEST_PIN
|
||||
mock_state.return_value = pjlink.ConnectedState
|
||||
mock_waitForReadyRead.return_value = True
|
||||
|
||||
# WHEN: Athenticated connection is called
|
||||
pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
|
||||
|
||||
# THEN: send_command should have the proper authentication
|
||||
self.assertEquals("{test}".format(test=mock_send_command.call_args),
|
||||
"call(data='{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
|
||||
|
@ -22,13 +22,13 @@
|
||||
"""
|
||||
This module contains tests for the OpenSong song importer.
|
||||
"""
|
||||
|
||||
import os
|
||||
from unittest import TestCase
|
||||
|
||||
from tests.helpers.songfileimport import SongImportTestHelper
|
||||
from openlp.plugins.songs.lib.importers.opensong import OpenSongImport
|
||||
from openlp.core.common import Registry
|
||||
|
||||
from tests.helpers.songfileimport import SongImportTestHelper
|
||||
from tests.functional import patch, MagicMock
|
||||
|
||||
TEST_PATH = os.path.abspath(
|
||||
@ -54,6 +54,8 @@ class TestOpenSongFileImport(SongImportTestHelper):
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five.json')))
|
||||
self.file_import([os.path.join(TEST_PATH, 'Amazing Grace2')],
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
|
||||
self.file_import([os.path.join(TEST_PATH, 'Amazing Grace with bad CCLI')],
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace without CCLI.json')))
|
||||
|
||||
|
||||
class TestOpenSongImport(TestCase):
|
||||
|
@ -52,6 +52,8 @@ class TestSongShowPlusFileImport(SongImportTestHelper):
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json')))
|
||||
self.file_import([os.path.join(TEST_PATH, 'a mighty fortress is our god.sbsong')],
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'a mighty fortress is our god.json')))
|
||||
self.file_import([os.path.join(TEST_PATH, 'cleanse-me.sbsong')],
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'cleanse-me.json')))
|
||||
|
||||
|
||||
class TestSongShowPlusImport(TestCase):
|
||||
|
@ -46,3 +46,5 @@ class TestVideoPsalmFileImport(SongImportTestHelper):
|
||||
"""
|
||||
self.file_import(os.path.join(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'),
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold.json')))
|
||||
self.file_import(os.path.join(TEST_PATH, 'videopsalm-as-safe-a-stronghold2.json'),
|
||||
self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold2.json')))
|
||||
|
@ -29,6 +29,7 @@ from unittest import TestCase
|
||||
|
||||
from openlp.plugins.songs.lib.importers.opensong import OpenSongImport
|
||||
from openlp.core.common import Registry
|
||||
|
||||
from tests.functional import patch, MagicMock, call
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -36,7 +37,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class SongImportTestHelper(TestCase):
|
||||
"""
|
||||
This class is designed to be a helper class to reduce repition when testing the import of song files.
|
||||
This class is designed to be a helper class to reduce repetition when testing the import of song files.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SongImportTestHelper, self).__init__(*args, **kwargs)
|
||||
|
@ -53,4 +53,4 @@
|
||||
<key_line></key_line>
|
||||
<time_sig></time_sig>
|
||||
<style index="default_style"></style>
|
||||
</song>
|
||||
</song>
|
||||
|
56
tests/resources/opensongsongs/Amazing Grace with bad CCLI
Normal file
56
tests/resources/opensongsongs/Amazing Grace with bad CCLI
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<song>
|
||||
<title>Amazing Grace (Demonstration)</title>
|
||||
<author>John Newton, Edwin Excell & John P. Rees</author>
|
||||
<copyright>Public Domain </copyright>
|
||||
<presentation>V1 V2 V3 V4 V5</presentation>
|
||||
<capo print="false"></capo>
|
||||
<tempo></tempo>
|
||||
<ccli>GE</ccli>
|
||||
<theme>God: Assurance/Grace/Salvation</theme>
|
||||
<alttheme>Worship: Praise</alttheme>
|
||||
<user1> </user1>
|
||||
<user2> </user2>
|
||||
<user3> </user3>
|
||||
<lyrics>[V]
|
||||
;Test the chords format
|
||||
;Chords beging with .
|
||||
;Verses begin with their verse number
|
||||
;Link words with _
|
||||
;Comments begin with ;
|
||||
. D D7 G D
|
||||
1A______ma________zing grace! How sweet the sound!
|
||||
2'Twas grace that taught my heart to fear,
|
||||
3The Lord has pro____mised good to me,
|
||||
4Thro' ma________ny dan____gers, toils and snares
|
||||
5When we've been there ten thou__sand years,
|
||||
|
||||
. Bm E A A7
|
||||
1That saved a wretch like me!
|
||||
2And grace my fears re___lieved.
|
||||
3His Word my hope se___cures.
|
||||
4I have al___rea____dy come.
|
||||
5Bright shi___ning as the sun,
|
||||
|
||||
. D D7 G D
|
||||
1I once was lost, but now am found;
|
||||
2How pre___cious did that grace ap____pear,
|
||||
3He will my shield and por___tion be
|
||||
4'Tis grace that brought me safe thus far,
|
||||
5We've no less days to sing God's praise,
|
||||
|
||||
. Bm A G D
|
||||
1Was blind, but now I see.
|
||||
2The hour I first be_lieved.
|
||||
3As long as life en_dures.
|
||||
4And grace will lead me home.
|
||||
5Than when we first be_gun.
|
||||
|
||||
</lyrics>
|
||||
<hymn_number>Demonstration Songs 0</hymn_number>
|
||||
<key></key>
|
||||
<aka></aka>
|
||||
<key_line></key_line>
|
||||
<time_sig></time_sig>
|
||||
<style index="default_style"></style>
|
||||
</song>
|
@ -0,0 +1,42 @@
|
||||
{
|
||||
"authors": [
|
||||
"John Newton",
|
||||
"Edwin Excell",
|
||||
"John P. Rees"
|
||||
],
|
||||
"ccli_number": null,
|
||||
"comments": "\n\n\n",
|
||||
"copyright": "Public Domain ",
|
||||
"song_book_name": "Demonstration Songs",
|
||||
"song_number": 0,
|
||||
"title": "Amazing Grace (Demonstration)",
|
||||
"topics": [
|
||||
"Assurance",
|
||||
"Grace",
|
||||
"Praise",
|
||||
"Salvation"
|
||||
],
|
||||
"verse_order_list": [],
|
||||
"verses": [
|
||||
[
|
||||
"Amazing grace! How sweet the sound!\nThat saved a wretch like me!\nI once was lost, but now am found;\nWas blind, but now I see.",
|
||||
"v1"
|
||||
],
|
||||
[
|
||||
"'Twas grace that taught my heart to fear,\nAnd grace my fears relieved.\nHow precious did that grace appear,\nThe hour I first believed.",
|
||||
"v2"
|
||||
],
|
||||
[
|
||||
"The Lord has promised good to me,\nHis Word my hope secures.\nHe will my shield and portion be\nAs long as life endures.",
|
||||
"v3"
|
||||
],
|
||||
[
|
||||
"Thro' many dangers, toils and snares\nI have already come.\n'Tis grace that brought me safe thus far,\nAnd grace will lead me home.",
|
||||
"v4"
|
||||
],
|
||||
[
|
||||
"When we've been there ten thousand years,\nBright shining as the sun,\nWe've no less days to sing God's praise,\nThan when we first begun.",
|
||||
"v5"
|
||||
]
|
||||
]
|
||||
}
|
38
tests/resources/songshowplussongs/cleanse-me.json
Normal file
38
tests/resources/songshowplussongs/cleanse-me.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"authors": [
|
||||
"J. Edwin Orr"
|
||||
],
|
||||
"ccli_number": 56307,
|
||||
"comments": "",
|
||||
"copyright": "Public Domain ",
|
||||
"song_book_name": "",
|
||||
"song_number": 438,
|
||||
"title": "Cleanse Me [438]",
|
||||
"topics": [
|
||||
"Cleansing",
|
||||
"Communion",
|
||||
"Consecration",
|
||||
"Holiness",
|
||||
"Holy Spirit",
|
||||
"Revival"
|
||||
],
|
||||
"verse_order_list": [],
|
||||
"verses": [
|
||||
[
|
||||
"Search me, O God,\r\nAnd know my heart today;\r\nTry me, O Savior,\r\nKnow my thoughts, I pray.\r\nSee if there be\r\nSome wicked way in me;\r\nCleanse me from every sin\r\nAnd set me free.",
|
||||
"v1"
|
||||
],
|
||||
[
|
||||
"I praise Thee, Lord,\r\nFor cleansing me from sin;\r\nFulfill Thy Word,\r\nAnd make me pure within.\r\nFill me with fire\r\nWhere once I burned with shame;\r\nGrant my desire\r\nTo magnify Thy name.",
|
||||
"v2"
|
||||
],
|
||||
[
|
||||
"Lord, take my life,\r\nAnd make it wholly Thine;\r\nFill my poor heart\r\nWith Thy great love divine.\r\nTake all my will,\r\nMy passion, self and pride;\r\nI now surrender, Lord\r\nIn me abide.",
|
||||
"v3"
|
||||
],
|
||||
[
|
||||
"O Holy Ghost,\r\nRevival comes from Thee;\r\nSend a revival,\r\nStart the work in me.\r\nThy Word declares\r\nThou wilt supply our need;\r\nFor blessings now,\r\nO Lord, I humbly plead.",
|
||||
"v4"
|
||||
]
|
||||
]
|
||||
}
|
BIN
tests/resources/songshowplussongs/cleanse-me.sbsong
Normal file
BIN
tests/resources/songshowplussongs/cleanse-me.sbsong
Normal file
Binary file not shown.
35
tests/resources/videopsalmsongs/as-safe-a-stronghold2.json
Normal file
35
tests/resources/videopsalmsongs/as-safe-a-stronghold2.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"authors": [
|
||||
["Martin Luther", "words"],
|
||||
["Unknown", "music"]
|
||||
],
|
||||
"ccli_number": "12345",
|
||||
"comments": "This is\nthe first comment\nThis is\nthe second comment\nThis is\nthe third comment\n",
|
||||
"copyright": "Public Domain",
|
||||
"song_book_name": "SongBook1",
|
||||
"song_number": 0,
|
||||
"title": "A Safe Stronghold Our God is Still",
|
||||
"topics": [
|
||||
"tema1",
|
||||
"tema2"
|
||||
],
|
||||
"verse_order_list": [],
|
||||
"verses": [
|
||||
[
|
||||
"As safe a stronghold our God is still,\nA trusty shield and weapon;\nHe’ll help us clear from all the ill\nThat hath us now o’ertaken.\nThe ancient prince of hell\nHath risen with purpose fell;\nStrong mail of craft and power\nHe weareth in this hour;\nOn earth is not His fellow.",
|
||||
"v"
|
||||
],
|
||||
[
|
||||
"With \"force\" of arms we nothing can,\nFull soon were we down-ridden;\nBut for us fights \\ the proper Man,\nWhom God Himself hath bidden.\nAsk ye: Who is this same?\nChrist Jesus is His name,\nThe Lord Sabaoth’s Son;\nHe, and no other one,\nShall conquer in the battle.",
|
||||
"v"
|
||||
],
|
||||
[
|
||||
"And were this world all devils o’er,\nAnd watching to devour us,\nWe lay it not to heart so sore;\nNot they can overpower us.\nAnd let the prince of ill\nLook grim as e’er he will,\nHe harms us not a whit;\nFor why? his doom is writ;\nA word shall quickly slay him.",
|
||||
"v"
|
||||
],
|
||||
[
|
||||
"God’s word, for all their craft and force,\nOne moment will not linger,\nBut, spite of hell, shall have its course;\n’Tis written by His finger.\nAnd though they take our life,\nGoods, honour, children, wife,\nYet is their profit small:\nThese things shall vanish all;\nThe city of God remaineth.",
|
||||
"v"
|
||||
]
|
||||
]
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
{Abbreviation:"SB1",Copyright:"Public domain",Songs:[{ID:3,Composer:"Unknown",Author:"Martin Luther",Copyright:"Public
|
||||
Domain",Theme:"tema1
|
||||
tema2",CCLI:"12345",Alias:"A safe stronghold",Memo1:"This is
|
||||
the first comment
|
||||
",Memo2:"This is
|
||||
the second comment
|
||||
",Memo3:"This is
|
||||
the third comment
|
||||
",Reference:"reference",Guid:"jtCkrJdPIUOmECjaQylg/g",Verses:[{
|
||||
Text:"As safe a stronghold our God is still,
|
||||
A trusty shield and weapon;
|
||||
He’ll help us clear from all the ill
|
||||
That hath us now o’ertaken.
|
||||
The ancient prince of hell
|
||||
Hath risen with purpose fell;
|
||||
Strong mail of craft and power
|
||||
He weareth in this hour;
|
||||
On earth is not His fellow."},{ID:2,
|
||||
Text:"With \"force\" of arms we nothing can,
|
||||
Full soon were we down-ridden;
|
||||
But for us fights \\ the proper Man,
|
||||
Whom God Himself hath bidden.
|
||||
Ask ye: Who is this same?
|
||||
Christ Jesus is His name,
|
||||
The Lord Sabaoth’s Son;
|
||||
He, and no other one,
|
||||
Shall conquer in the battle."},{ID:3,
|
||||
Text:"And were this world all devils o’er,
|
||||
And watching to devour us,
|
||||
We lay it not to heart so sore;
|
||||
Not they can overpower us.
|
||||
And let the prince of ill
|
||||
Look grim as e’er he will,
|
||||
He harms us not a whit;
|
||||
For why? his doom is writ;
|
||||
A word shall quickly slay him."},{ID:4,
|
||||
Text:"God’s word, for all their craft and force,
|
||||
One moment will not linger,
|
||||
But, spite of hell, shall have its course;
|
||||
’Tis written by His finger.
|
||||
And though they take our life,
|
||||
Goods, honour, children, wife,
|
||||
Yet is their profit small:
|
||||
These things shall vanish all;
|
||||
The city of God remaineth."}],AudioFile:"282.mp3",IsAudioFileEnabled:1,
|
||||
Text:"A Safe Stronghold Our God is Still"}],Guid:"khiHU2blX0Kb41dGdbDLhA",VersionDate:"20121012000000",
|
||||
Text:"SongBook1"}
|
Loading…
Reference in New Issue
Block a user