openlp/openlp/core/projectors/db.py

470 lines
20 KiB
Python
Raw Normal View History

2014-10-06 19:10:03 +00:00
# -*- coding: utf-8 -*-
2019-04-13 13:00:22 +00:00
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
2022-02-01 10:10:57 +00:00
# Copyright (c) 2008-2022 OpenLP Developers #
2019-04-13 13:00:22 +00:00
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
2014-10-06 19:10:03 +00:00
"""
:mod:`openlp.core.lib.projector.db` module
2014-10-17 17:28:12 +00:00
Provides the database functions for the Projector module.
2014-10-17 17:28:12 +00:00
The Manufacturer, Model, Source tables keep track of the video source
strings used for display of input sources. The Source table maps
manufacturer-defined or user-defined strings from PJLink default strings
to end-user readable strings; ex: PJLink code 11 would map "RGB 1"
default string to "RGB PC (analog)" string.
(Future feature).
2014-10-17 17:28:12 +00:00
The Projector table keeps track of entries for controlled projectors.
2014-10-06 19:10:03 +00:00
"""
import logging
2014-10-23 02:21:26 +00:00
from sqlalchemy import Column, ForeignKey, Integer, MetaData, String, and_
from sqlalchemy.ext.declarative import declarative_base
2016-07-01 21:17:20 +00:00
from sqlalchemy.orm import relationship
2014-10-06 19:10:03 +00:00
from openlp.core.lib.db import CommonMixin, Manager, init_db, init_url
2017-11-10 11:59:38 +00:00
from openlp.core.projectors import upgrade
2018-10-02 04:39:42 +00:00
from openlp.core.projectors.constants import PJLINK_DEFAULT_CODES
log = logging.getLogger(__name__)
log.debug('projector.lib.db module loaded')
2016-07-01 21:17:20 +00:00
Base = declarative_base(MetaData())
2014-10-06 19:10:03 +00:00
2017-10-23 22:09:57 +00:00
class Manufacturer(Base, CommonMixin):
2014-10-06 19:10:03 +00:00
"""
2014-10-17 17:28:12 +00:00
Projector manufacturer table.
Manufacturer:
name: Column(String(30))
models: Relationship(Model.id)
2014-10-06 19:10:03 +00:00
Model table is related.
"""
def __repr__(self):
2014-10-17 17:28:12 +00:00
"""
Returns a basic representation of a Manufacturer table entry.
"""
2016-04-16 08:08:45 +00:00
return '<Manufacturer(name="{name}")>'.format(name=self.name)
2014-10-17 17:28:12 +00:00
2014-10-06 19:10:03 +00:00
name = Column(String(30))
models = relationship('Model',
order_by='Model.name',
backref='manufacturer',
cascade='all, delete-orphan',
primaryjoin='Manufacturer.id==Model.manufacturer_id',
lazy='joined')
2017-10-23 22:09:57 +00:00
class Model(Base, CommonMixin):
2014-10-06 19:10:03 +00:00
"""
2014-10-17 17:28:12 +00:00
Projector model table.
Model:
name: Column(String(20))
sources: Relationship(Source.id)
manufacturer_id: Foreign_key(Manufacturer.id)
2014-10-06 19:10:03 +00:00
Manufacturer table links here.
Source table is related.
"""
def __repr__(self):
2014-10-17 17:28:12 +00:00
"""
Returns a basic representation of a Model table entry.
"""
2016-04-16 08:08:45 +00:00
return '<Model(name={name})>'.format(name=self.name)
2014-10-17 17:28:12 +00:00
2014-10-06 19:10:03 +00:00
manufacturer_id = Column(Integer, ForeignKey('manufacturer.id'))
name = Column(String(20))
sources = relationship('Source',
order_by='Source.pjlink_name',
backref='model',
cascade='all, delete-orphan',
primaryjoin='Model.id==Source.model_id',
lazy='joined')
2017-10-23 22:09:57 +00:00
class Source(Base, CommonMixin):
2014-10-06 19:10:03 +00:00
"""
2014-10-17 17:28:12 +00:00
Projector video source table.
Source:
pjlink_name: Column(String(15))
pjlink_code: Column(String(2))
text: Column(String(30))
model_id: Foreign_key(Model.id)
2014-10-06 19:10:03 +00:00
Model table links here.
2014-10-17 17:28:12 +00:00
These entries map PJLink input video source codes to text strings.
2014-10-06 19:10:03 +00:00
"""
def __repr__(self):
2014-10-17 17:28:12 +00:00
"""
Return basic representation of Source table entry.
"""
2016-05-20 16:22:06 +00:00
return '<Source(pjlink_name="{name}", pjlink_code="{code}", text="{text}")>'.format(name=self.pjlink_name,
2016-04-16 08:08:45 +00:00
code=self.pjlink_code,
text=self.text)
2014-10-06 19:10:03 +00:00
model_id = Column(Integer, ForeignKey('model.id'))
pjlink_name = Column(String(15))
pjlink_code = Column(String(2))
text = Column(String(30))
2017-10-23 22:09:57 +00:00
class Projector(Base, CommonMixin):
2014-10-06 19:10:03 +00:00
"""
Projector table.
2014-10-17 17:28:12 +00:00
Projector:
ip: Column(String(100)) # Allow for IPv6 or FQDN
port: Column(String(8))
pin: Column(String(20)) # Allow for test strings
name: Column(String(20))
location: Column(String(30))
notes: Column(String(200))
2017-05-20 05:51:58 +00:00
pjlink_name: Column(String(128)) # From projector
2018-01-13 07:17:15 +00:00
pjlink_class Column(String(5)) # From projector
2017-05-20 05:51:58 +00:00
manufacturer: Column(String(128)) # From projector
model: Column(String(128)) # From projector
other: Column(String(128)) # From projector
sources: Column(String(128)) # From projector
serial_no: Column(String(30)) # From projector (Class 2)
sw_version: Column(String(30)) # From projector (Class 2)
model_filter: Column(String(30)) # From projector (Class 2)
model_lamp: Column(String(30)) # From projector (Class 2)
2014-10-21 22:47:25 +00:00
ProjectorSource relates
2014-10-06 19:10:03 +00:00
"""
2014-10-23 02:21:26 +00:00
def __repr__(self):
"""
Return basic representation of Source table entry.
"""
2017-06-01 22:35:57 +00:00
return '< Projector(id="{data}", ip="{ip}", port="{port}", mac_adx="{mac}", pin="{pin}", name="{name}", ' \
2018-01-13 05:41:42 +00:00
'location="{location}", notes="{notes}", pjlink_name="{pjlink_name}", pjlink_class="{pjlink_class}", ' \
2017-05-20 05:51:58 +00:00
'manufacturer="{manufacturer}", model="{model}", serial_no="{serial}", other="{other}", ' \
'sources="{sources}", source_list="{source_list}", model_filter="{mfilter}", ' \
'model_lamp="{mlamp}", sw_version="{sw_ver}") >'.format(data=self.id,
ip=self.ip,
port=self.port,
2017-06-01 22:35:57 +00:00
mac=self.mac_adx,
2017-05-20 05:51:58 +00:00
pin=self.pin,
name=self.name,
location=self.location,
notes=self.notes,
pjlink_name=self.pjlink_name,
2018-01-13 05:41:42 +00:00
pjlink_class=self.pjlink_class,
2017-05-20 05:51:58 +00:00
manufacturer=self.manufacturer,
model=self.model,
other=self.other,
sources=self.sources,
source_list=self.source_list,
serial=self.serial_no,
mfilter=self.model_filter,
mlamp=self.model_lamp,
sw_ver=self.sw_version)
2014-10-06 19:10:03 +00:00
ip = Column(String(100))
port = Column(String(8))
2017-06-01 22:35:57 +00:00
mac_adx = Column(String(18))
2014-10-13 15:11:55 +00:00
pin = Column(String(20))
2014-10-06 19:10:03 +00:00
name = Column(String(20))
location = Column(String(30))
notes = Column(String(200))
pjlink_name = Column(String(128))
2018-01-13 07:17:15 +00:00
pjlink_class = Column(String(5))
2014-10-06 19:10:03 +00:00
manufacturer = Column(String(128))
model = Column(String(128))
other = Column(String(128))
sources = Column(String(128))
2017-05-20 05:51:58 +00:00
serial_no = Column(String(30))
sw_version = Column(String(30))
model_filter = Column(String(30))
model_lamp = Column(String(30))
2014-10-21 22:47:25 +00:00
source_list = relationship('ProjectorSource',
order_by='ProjectorSource.code',
backref='projector',
cascade='all, delete-orphan',
primaryjoin='Projector.id==ProjectorSource.projector_id',
lazy='joined')
2014-10-06 19:10:03 +00:00
2017-10-23 22:09:57 +00:00
class ProjectorSource(Base, CommonMixin):
2014-10-21 20:05:35 +00:00
"""
Projector local source table
This table allows mapping specific projector source input to a local
connection; i.e., '11': 'DVD Player'
Projector Source:
projector_id: Foreign_key(Column(Projector.id))
code: Column(String(3)) # PJLink source code
text: Column(String(20)) # Text to display
2014-10-21 21:24:16 +00:00
Projector table links here
2014-10-21 20:05:35 +00:00
"""
2014-10-23 02:21:26 +00:00
def __repr__(self):
"""
Return basic representation of Source table entry.
"""
2016-04-16 08:08:45 +00:00
return '<ProjectorSource(id="{data}", code="{code}", text="{text}", ' \
'projector_id="{projector_id}")>'.format(data=self.id,
code=self.code,
text=self.text,
projector_id=self.projector_id)
2014-10-21 20:05:35 +00:00
code = Column(String(3))
text = Column(String(20))
2014-10-21 22:47:25 +00:00
projector_id = Column(Integer, ForeignKey('projector.id'))
2014-10-21 20:05:35 +00:00
2014-10-06 19:10:03 +00:00
class ProjectorDB(Manager):
"""
Class to access the projector database.
"""
def __init__(self, *args, **kwargs):
2016-04-16 21:32:56 +00:00
log.debug('ProjectorDB().__init__(args="{arg}", kwargs="{kwarg}")'.format(arg=args, kwarg=kwargs))
2017-06-01 22:35:57 +00:00
super().__init__(plugin_name='projector',
init_schema=self.init_schema,
upgrade_mod=upgrade)
2016-04-16 08:08:45 +00:00
log.debug('ProjectorDB() Initialized using db url {db}'.format(db=self.db_url))
log.debug('Session: {session}'.format(session=self.session))
2014-10-06 19:10:03 +00:00
def init_schema(self, *args, **kwargs):
2014-10-06 19:10:03 +00:00
"""
Setup the projector database and initialize the schema.
2014-10-17 17:28:12 +00:00
Declarative uses table classes to define schema.
2014-10-06 19:10:03 +00:00
"""
self.db_url = init_url('projector')
session, metadata = init_db(self.db_url, base=Base)
metadata.create_all(checkfirst=True)
2014-10-06 19:10:03 +00:00
return session
2014-10-13 20:16:03 +00:00
def get_projector_by_id(self, dbid):
"""
Locate a DB record by record ID.
2014-10-17 17:28:12 +00:00
:param dbid: DB record id
2014-10-13 20:16:03 +00:00
:returns: Projector() instance
"""
2016-04-16 08:08:45 +00:00
log.debug('get_projector_by_id(id="{data}")'.format(data=dbid))
2014-10-13 20:16:03 +00:00
projector = self.get_object_filtered(Projector, Projector.id == dbid)
if projector is None:
# Not found
2016-07-01 21:17:20 +00:00
log.warning('get_projector_by_id() did not find {data}'.format(data=id))
2014-10-13 20:16:03 +00:00
return None
2016-04-16 08:08:45 +00:00
log.debug('get_projectorby_id() returning 1 entry for "{entry}" id="{data}"'.format(entry=dbid,
data=projector.id))
2014-10-13 20:16:03 +00:00
return projector
2014-10-06 19:10:03 +00:00
def get_projector_all(self):
"""
2014-10-17 17:28:12 +00:00
Retrieve all projector entries.
:returns: List with Projector() instances used in Manager() QListWidget.
2014-10-06 19:10:03 +00:00
"""
log.debug('get_all() called')
return_list = []
new_list = self.get_all_objects(Projector)
if new_list is None or new_list.count == 0:
return return_list
for new_projector in new_list:
return_list.append(new_projector)
2016-04-16 08:08:45 +00:00
log.debug('get_all() returning {items} item(s)'.format(items=len(return_list)))
2014-10-06 19:10:03 +00:00
return return_list
def get_projector_by_ip(self, ip):
"""
Locate a projector by host IP/Name.
:param ip: Host IP/Name
2014-10-09 20:30:07 +00:00
:returns: Projector() instance
2014-10-06 19:10:03 +00:00
"""
2017-06-25 02:21:07 +00:00
log.debug('get_projector_by_ip(ip="{ip}")'.format(ip=ip))
2014-10-06 19:10:03 +00:00
projector = self.get_object_filtered(Projector, Projector.ip == ip)
if projector is None:
# Not found
2016-07-01 21:17:20 +00:00
log.warning('get_projector_by_ip() did not find {ip}'.format(ip=ip))
2014-10-06 19:10:03 +00:00
return None
2016-04-16 08:08:45 +00:00
log.debug('get_projectorby_ip() returning 1 entry for "{ip}" id="{data}"'.format(ip=ip,
data=projector.id))
2014-10-06 19:10:03 +00:00
return projector
def get_projector_by_name(self, name):
"""
Locate a projector by name field
:param name: Name of projector
2014-10-09 20:30:07 +00:00
:returns: Projector() instance
2014-10-06 19:10:03 +00:00
"""
2016-04-16 08:08:45 +00:00
log.debug('get_projector_by_name(name="{name}")'.format(name=name))
2014-10-06 19:10:03 +00:00
projector = self.get_object_filtered(Projector, Projector.name == name)
if projector is None:
# Not found
2016-07-01 21:17:20 +00:00
log.warning('get_projector_by_name() did not find "{name}"'.format(name=name))
2014-10-06 19:10:03 +00:00
return None
2016-04-16 08:08:45 +00:00
log.debug('get_projector_by_name() returning one entry for "{name}" id="{data}"'.format(name=name,
data=projector.id))
2014-10-06 19:10:03 +00:00
return projector
def add_projector(self, projector):
"""
Add a new projector entry
2014-10-09 20:30:07 +00:00
:param projector: Projector() instance to add
2014-10-06 19:10:03 +00:00
:returns: bool
2014-10-17 17:28:12 +00:00
True if entry added
False if entry already in DB or db error
2014-10-06 19:10:03 +00:00
"""
old_projector = self.get_object_filtered(Projector, Projector.ip == projector.ip)
if old_projector is not None:
2017-09-22 12:03:28 +00:00
log.warning('add_projector() skipping entry ip="{ip}" (Already saved)'.format(ip=old_projector.ip))
2014-10-06 19:10:03 +00:00
return False
2017-09-22 12:03:28 +00:00
log.debug('add_projector() saving new entry')
2016-04-16 08:08:45 +00:00
log.debug('ip="{ip}", name="{name}", location="{location}"'.format(ip=projector.ip,
name=projector.name,
location=projector.location))
log.debug('notes="{notes}"'.format(notes=projector.notes))
2014-10-06 19:10:03 +00:00
return self.save_object(projector)
def update_projector(self, projector=None):
"""
Update projector entry
:param projector: Projector() instance with new information
:returns: bool
2014-10-17 17:28:12 +00:00
True if DB record updated
False if entry not in DB or DB error
2014-10-06 19:10:03 +00:00
"""
if projector is None:
log.error('No Projector() instance to update - cancelled')
return False
old_projector = self.get_object_filtered(Projector, Projector.id == projector.id)
if old_projector is None:
log.error('Edit called on projector instance not in database - cancelled')
return False
2016-04-16 08:08:45 +00:00
log.debug('({ip}) Updating projector with dbid={dbid}'.format(ip=projector.ip, dbid=projector.id))
2014-10-06 19:10:03 +00:00
old_projector.ip = projector.ip
old_projector.name = projector.name
old_projector.location = projector.location
old_projector.pin = projector.pin
old_projector.port = projector.port
old_projector.pjlink_name = projector.pjlink_name
old_projector.manufacturer = projector.manufacturer
old_projector.model = projector.model
old_projector.other = projector.other
old_projector.sources = projector.sources
2017-05-20 05:51:58 +00:00
old_projector.serial_no = projector.serial_no
old_projector.sw_version = projector.sw_version
old_projector.model_filter = projector.model_filter
old_projector.model_lamp = projector.model_lamp
2014-10-06 19:10:03 +00:00
return self.save_object(old_projector)
def delete_projector(self, projector):
"""
Delete an entry by record id
:param projector: Projector() instance to delete
:returns: bool
2014-10-17 17:28:12 +00:00
True if record deleted
False if DB error
2014-10-06 19:10:03 +00:00
"""
deleted = self.delete_object(Projector, projector.id)
if deleted:
2016-04-16 08:08:45 +00:00
log.debug('delete_by_id() Removed entry id="{data}"'.format(data=projector.id))
2014-10-06 19:10:03 +00:00
else:
2016-04-16 08:08:45 +00:00
log.error('delete_by_id() Entry id="{data}" not deleted for some reason'.format(data=projector.id))
2014-10-06 19:10:03 +00:00
return deleted
2014-10-21 20:05:35 +00:00
def get_source_list(self, projector):
2014-10-06 19:10:03 +00:00
"""
Retrieves the source inputs pjlink code-to-text if available based on
manufacturer and model.
If not available, then returns the PJLink code to default text.
2014-10-21 20:05:35 +00:00
:param projector: Projector instance
2014-10-06 19:10:03 +00:00
:returns: dict
2014-10-17 17:28:12 +00:00
key: (str) PJLink code for source
2014-10-21 20:05:35 +00:00
value: (str) From ProjectorSource, Sources tables or PJLink default code list
2014-10-06 19:10:03 +00:00
"""
2014-10-21 20:05:35 +00:00
source_dict = {}
2019-03-08 15:19:57 +00:00
# Apparently, there was a change to the projector object. Test for which object has db id
if hasattr(projector, 'entry') and hasattr(projector.entry, 'id'):
2019-03-08 15:19:57 +00:00
chk = projector.entry.id
else:
chk = projector.id
2019-03-08 15:19:57 +00:00
2014-10-23 02:21:26 +00:00
# Get default list first
for key in projector.source_available:
item = self.get_object_filtered(ProjectorSource,
and_(ProjectorSource.code == key,
2019-03-08 15:19:57 +00:00
ProjectorSource.projector_id == chk))
2014-10-23 02:21:26 +00:00
if item is None:
source_dict[key] = PJLINK_DEFAULT_CODES[key]
2014-10-21 20:05:35 +00:00
else:
2014-10-23 02:21:26 +00:00
source_dict[key] = item.text
2014-10-06 19:10:03 +00:00
return source_dict
2014-10-23 02:21:26 +00:00
def get_source_by_id(self, source):
"""
Retrieves the ProjectorSource by ProjectorSource.id
:param source: ProjectorSource id
:returns: ProjetorSource instance or None
"""
2016-07-01 21:17:20 +00:00
source_entry = self.get_object_filtered(ProjectorSource, ProjectorSource.id == source)
2014-10-23 02:21:26 +00:00
if source_entry is None:
# Not found
2016-07-01 21:17:20 +00:00
log.warning('get_source_by_id() did not find "{source}"'.format(source=source))
2014-10-23 02:21:26 +00:00
return None
2016-04-16 08:08:45 +00:00
log.debug('get_source_by_id() returning one entry for "{source}""'.format(source=source))
2014-10-23 02:21:26 +00:00
return source_entry
def get_source_by_code(self, code, projector_id):
"""
Retrieves the ProjectorSource by ProjectorSource.id
:param source: PJLink ID
:param projector_id: Projector.id
:returns: ProjetorSource instance or None
"""
source_entry = self.get_object_filtered(ProjectorSource,
and_(ProjectorSource.code == code,
ProjectorSource.projector_id == projector_id))
2016-04-16 08:08:45 +00:00
2014-10-23 02:21:26 +00:00
if source_entry is None:
# Not found
2016-07-01 21:17:20 +00:00
log.warning('get_source_by_id() not found')
log.warning('code="{code}" projector_id="{data}"'.format(code=code, data=projector_id))
2014-10-23 02:21:26 +00:00
return None
2016-04-16 08:08:45 +00:00
log.debug('get_source_by_id() returning one entry')
log.debug('code="{code}" projector_id="{data}"'.format(code=code, data=projector_id))
2014-10-23 02:21:26 +00:00
return source_entry
def add_source(self, source):
"""
Add a new ProjectorSource record
:param source: ProjectorSource() instance to add
"""
2016-04-16 08:08:45 +00:00
log.debug('Saving ProjectorSource(projector_id="{data}" '
2016-04-16 21:32:56 +00:00
'code="{code}" text="{text}")'.format(data=source.projector_id, code=source.code, text=source.text))
2014-10-23 02:21:26 +00:00
return self.save_object(source)