From 077327d92078ff3019f165e5cbe4ef01675d861c Mon Sep 17 00:00:00 2001 From: Peter Bennett Date: Mon, 9 Dec 2024 10:15:39 -0500 Subject: [PATCH] Remove old service API code from backend Service APIs have all been rewritten in services v2. Change soapclient code that is used with upnp to find backend the first time. This was still using the old API. Refs #915 --- mythtv/libs/libmythupnp/mythxmlclient.cpp | 2 +- mythtv/libs/libmythupnp/soapclient.cpp | 106 +- mythtv/programs/mythbackend/CMakeLists.txt | 29 - mythtv/programs/mythbackend/mediaserver.cpp | 44 - mythtv/programs/mythbackend/mythbackend.pro | 16 - .../serviceHosts/captureServiceHost.h | 57 - .../serviceHosts/channelIconServiceHost.h | 59 - .../serviceHosts/channelServiceHost.h | 57 - .../serviceHosts/contentServiceHost.h | 57 - .../mythbackend/serviceHosts/dvrServiceHost.h | 57 - .../serviceHosts/guideServiceHost.h | 57 - .../serviceHosts/imageServiceHost.h | 47 - .../serviceHosts/musicServiceHost.h | 40 - .../serviceHosts/mythServiceHost.h | 57 - .../serviceHosts/videoServiceHost.h | 57 - .../programs/mythbackend/services/capture.cpp | 359 --- .../programs/mythbackend/services/capture.h | 190 -- .../programs/mythbackend/services/channel.cpp | 809 ------- .../programs/mythbackend/services/channel.h | 372 --- .../mythbackend/services/channelicon.cpp | 132 -- .../mythbackend/services/channelicon.h | 101 - .../programs/mythbackend/services/content.cpp | 1143 --------- .../programs/mythbackend/services/content.h | 271 --- mythtv/programs/mythbackend/services/dvr.cpp | 2104 ----------------- mythtv/programs/mythbackend/services/dvr.h | 707 ------ .../programs/mythbackend/services/guide.cpp | 616 ----- mythtv/programs/mythbackend/services/guide.h | 226 -- .../programs/mythbackend/services/image.cpp | 225 -- mythtv/programs/mythbackend/services/image.h | 155 -- .../programs/mythbackend/services/music.cpp | 118 - mythtv/programs/mythbackend/services/music.h | 94 - mythtv/programs/mythbackend/services/myth.cpp | 1160 --------- mythtv/programs/mythbackend/services/myth.h | 447 ---- .../mythbackend/services/serviceUtil.cpp | 790 ------- .../mythbackend/services/serviceUtil.h | 111 - .../programs/mythbackend/services/video.cpp | 923 -------- mythtv/programs/mythbackend/services/video.h | 305 --- 37 files changed, 14 insertions(+), 12086 deletions(-) delete mode 100644 mythtv/programs/mythbackend/serviceHosts/captureServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/channelIconServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/channelServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/contentServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/dvrServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/guideServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/imageServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/musicServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/mythServiceHost.h delete mode 100644 mythtv/programs/mythbackend/serviceHosts/videoServiceHost.h delete mode 100644 mythtv/programs/mythbackend/services/capture.cpp delete mode 100644 mythtv/programs/mythbackend/services/capture.h delete mode 100644 mythtv/programs/mythbackend/services/channel.cpp delete mode 100644 mythtv/programs/mythbackend/services/channel.h delete mode 100644 mythtv/programs/mythbackend/services/channelicon.cpp delete mode 100644 mythtv/programs/mythbackend/services/channelicon.h delete mode 100644 mythtv/programs/mythbackend/services/content.cpp delete mode 100644 mythtv/programs/mythbackend/services/content.h delete mode 100644 mythtv/programs/mythbackend/services/dvr.cpp delete mode 100644 mythtv/programs/mythbackend/services/dvr.h delete mode 100644 mythtv/programs/mythbackend/services/guide.cpp delete mode 100644 mythtv/programs/mythbackend/services/guide.h delete mode 100644 mythtv/programs/mythbackend/services/image.cpp delete mode 100644 mythtv/programs/mythbackend/services/image.h delete mode 100644 mythtv/programs/mythbackend/services/music.cpp delete mode 100644 mythtv/programs/mythbackend/services/music.h delete mode 100644 mythtv/programs/mythbackend/services/myth.cpp delete mode 100644 mythtv/programs/mythbackend/services/myth.h delete mode 100644 mythtv/programs/mythbackend/services/serviceUtil.cpp delete mode 100644 mythtv/programs/mythbackend/services/serviceUtil.h delete mode 100644 mythtv/programs/mythbackend/services/video.cpp delete mode 100644 mythtv/programs/mythbackend/services/video.h diff --git a/mythtv/libs/libmythupnp/mythxmlclient.cpp b/mythtv/libs/libmythupnp/mythxmlclient.cpp index 71d7cc026b8..7740e24f306 100644 --- a/mythtv/libs/libmythupnp/mythxmlclient.cpp +++ b/mythtv/libs/libmythupnp/mythxmlclient.cpp @@ -52,7 +52,7 @@ UPnPResultCode MythXMLClient::GetConnectionInfo( const QString &sPin, DatabasePa // Is this a valid response? // -------------------------------------------------------------- - QDomNode oNode = xmlResults.namedItem( "GetConnectionInfoResult" ); + QDomNode oNode = xmlResults.namedItem( "ConnectionInfo" ); if (UPnPResult_Success == nErrCode && !oNode.isNull()) { diff --git a/mythtv/libs/libmythupnp/soapclient.cpp b/mythtv/libs/libmythupnp/soapclient.cpp index 06d9fa9064b..1440d638215 100644 --- a/mythtv/libs/libmythupnp/soapclient.cpp +++ b/mythtv/libs/libmythupnp/soapclient.cpp @@ -187,7 +187,12 @@ QDomDocument SOAPClient::SendSOAPRequest(const QString &sMethod, { QUrl url(m_url); - url.setPath(m_sControlPath); + QString path = m_sControlPath; + path.append("/"); + path.append(sMethod); + + // Service url port is 6 less than upnp port (see MediaServer::Init) + url.setPort(m_url.port() - 6); nErrCode = UPnPResult_Success; sErrDesc = ""; @@ -215,44 +220,21 @@ QDomDocument SOAPClient::SendSOAPRequest(const QString &sMethod, // -------------------------------------------------------------- QByteArray aBuffer; - QTextStream os( &aBuffer ); - -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - os.setCodec("UTF-8"); -#else - os.setEncoding(QStringConverter::Utf8); -#endif - - os << "\r\n"; - os << "\r\n"; - os << " \r\n"; - os << " \r\n"; - - // -------------------------------------------------------------- - // Add parameters from list - // -------------------------------------------------------------- - + QUrlQuery query; for (QStringMap::iterator it = list.begin(); it != list.end(); ++it) - { - os << " <" << it.key() << ">"; - os << HTTPRequest::Encode( *it ); - os << "\r\n"; + { + query.addQueryItem(it.key(),*it); } - os << " \r\n"; - os << " \r\n"; - os << "\r\n"; - - os.flush(); + url.setPath(path); + url.setQuery(query); // -------------------------------------------------------------- // Perform Request // -------------------------------------------------------------- LOG(VB_UPNP, LOG_DEBUG, - QString("SOAPClient(%1) sending:\n %2").arg(url.toString(), aBuffer.constData())); + QString("SOAPClient(%1) sending:\n %2").arg(url.toString() /*, aBuffer.constData()*/ )); QString sXml; @@ -289,68 +271,6 @@ QDomDocument SOAPClient::SendSOAPRequest(const QString &sMethod, QString::number(nErrCode), sErrDesc, sXml)); return xmlResult; } - - // -------------------------------------------------------------- - // Is this a valid response? - // -------------------------------------------------------------- - - QString sResponseName = sMethod + "Response"; - QDomNodeList oNodeList = - doc.elementsByTagNameNS(m_sNamespace, sResponseName); - - if (oNodeList.count() == 0) - { - // -------------------------------------------------------------- - // Must be a fault... parse it to return reason - // -------------------------------------------------------------- - - nErrCode = GetNodeValue( - doc, "Envelope/Body/Fault/detail/UPnPResult/errorCode", 500); - sErrDesc = GetNodeValue( - doc, "Envelope/Body/Fault/detail/UPnPResult/errorDescription", ""); - if (sErrDesc.isEmpty()) - sErrDesc = QString("Unknown #%1").arg(nErrCode); - - QDomNode oNode = FindNode( "Envelope/Body/Fault", doc ); - - oNode = xmlResult.importNode( oNode, true ); - xmlResult.appendChild( oNode ); - - return xmlResult; - } - - QDomNode oMethod = oNodeList.item(0); - if (oMethod.isNull()) - return xmlResult; - - QDomNode oNode = oMethod.firstChild(); - for (; !oNode.isNull(); oNode = oNode.nextSibling()) - { - QDomElement e = oNode.toElement(); - if (e.isNull()) - continue; - - QString sName = e.tagName(); - QString sValue = ""; - - QDomText oText = oNode.firstChild().toText(); - - if (!oText.isNull()) - sValue = oText.nodeValue(); - - list.insert(QUrl::fromPercentEncoding(sName.toUtf8()), - QUrl::fromPercentEncoding(sValue.toUtf8())); - } - - // Create copy of oMethod that can be used with xmlResult. - - oMethod = xmlResult.importNode( oMethod.firstChild(), true ); - - // importNode does not attach the new nodes to the document, - // do it here. - - xmlResult.appendChild( oMethod ); - - return xmlResult; + return doc; } diff --git a/mythtv/programs/mythbackend/CMakeLists.txt b/mythtv/programs/mythbackend/CMakeLists.txt index 104202ff050..a7b83e5bcd7 100644 --- a/mythtv/programs/mythbackend/CMakeLists.txt +++ b/mythtv/programs/mythbackend/CMakeLists.txt @@ -43,35 +43,6 @@ add_executable( recordingextender.h scheduler.cpp scheduler.h - serviceHosts/captureServiceHost.h - serviceHosts/channelServiceHost.h - serviceHosts/contentServiceHost.h - serviceHosts/dvrServiceHost.h - serviceHosts/guideServiceHost.h - serviceHosts/imageServiceHost.h - serviceHosts/musicServiceHost.h - serviceHosts/mythServiceHost.h - serviceHosts/videoServiceHost.h - services/capture.cpp - services/capture.h - services/channel.cpp - services/channel.h - services/content.cpp - services/content.h - services/dvr.cpp - services/dvr.h - services/guide.cpp - services/guide.h - services/image.cpp - services/image.h - services/music.cpp - services/music.h - services/myth.cpp - services/myth.h - services/serviceUtil.cpp - services/serviceUtil.h - services/video.cpp - services/video.h servicesv2/preformat.h servicesv2/v2artworkInfo.h servicesv2/v2artworkInfoList.h diff --git a/mythtv/programs/mythbackend/mediaserver.cpp b/mythtv/programs/mythbackend/mediaserver.cpp index 8c6040e37ba..5e528284920 100644 --- a/mythtv/programs/mythbackend/mediaserver.cpp +++ b/mythtv/programs/mythbackend/mediaserver.cpp @@ -33,15 +33,6 @@ #include "upnpcdstv.h" #include "upnpcdsvideo.h" -#include "serviceHosts/mythServiceHost.h" -#include "serviceHosts/guideServiceHost.h" -#include "serviceHosts/contentServiceHost.h" -#include "serviceHosts/dvrServiceHost.h" -#include "serviceHosts/channelServiceHost.h" -#include "serviceHosts/videoServiceHost.h" -#include "serviceHosts/musicServiceHost.h" -#include "serviceHosts/captureServiceHost.h" -#include "serviceHosts/imageServiceHost.h" ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -133,17 +124,6 @@ void MediaServer::Init(bool bIsMaster, bool bDisableUPnp /* = false */) pHttpServer->RegisterExtension( new HttpConfig() ); pHttpServer->RegisterExtension( new InternetContent ( m_sSharePath )); - pHttpServer->RegisterExtension( new MythServiceHost ( m_sSharePath )); - pHttpServer->RegisterExtension( new GuideServiceHost ( m_sSharePath )); - pHttpServer->RegisterExtension( new ContentServiceHost( m_sSharePath )); - pHttpServer->RegisterExtension( new DvrServiceHost ( m_sSharePath )); - pHttpServer->RegisterExtension( new ChannelServiceHost( m_sSharePath )); - pHttpServer->RegisterExtension( new VideoServiceHost ( m_sSharePath )); - pHttpServer->RegisterExtension( new MusicServiceHost ( m_sSharePath )); - pHttpServer->RegisterExtension( new CaptureServiceHost( m_sSharePath )); - pHttpServer->RegisterExtension( new ImageServiceHost ( m_sSharePath )); - - // ------------------------------------------------------------------ // Register Service Types with Scripting Engine // @@ -153,30 +133,6 @@ void MediaServer::Init(bool bIsMaster, bool bDisableUPnp /* = false */) // classes. - dblain // ------------------------------------------------------------------ -#if CONFIG_QTSCRIPT - QScriptEngine* pEngine = pHtmlServer->ScriptEngine(); - - pEngine->globalObject().setProperty("Myth" , - pEngine->scriptValueFromQMetaObject< ScriptableMyth >() ); - pEngine->globalObject().setProperty("Guide" , - pEngine->scriptValueFromQMetaObject< ScriptableGuide >() ); - pEngine->globalObject().setProperty("Content", - pEngine->scriptValueFromQMetaObject< ScriptableContent >() ); - pEngine->globalObject().setProperty("Dvr" , - pEngine->scriptValueFromQMetaObject< ScriptableDvr >() ); - pEngine->globalObject().setProperty("Channel", - pEngine->scriptValueFromQMetaObject< ScriptableChannel >() ); - pEngine->globalObject().setProperty("Video" , - pEngine->scriptValueFromQMetaObject< ScriptableVideo >() ); - pEngine->globalObject().setProperty("Music" , - pEngine->scriptValueFromQMetaObject< ScriptableVideo >() ); - pEngine->globalObject().setProperty("Capture" , - pEngine->scriptValueFromQMetaObject< ScriptableCapture >() ); - pEngine->globalObject().setProperty("Image" , - pEngine->scriptValueFromQMetaObject< ScriptableImage >() ); -#endif - - // ------------------------------------------------------------------ if (bDisableUPnp) { diff --git a/mythtv/programs/mythbackend/mythbackend.pro b/mythtv/programs/mythbackend/mythbackend.pro index 4c06196c01f..2dfa4f23e2b 100644 --- a/mythtv/programs/mythbackend/mythbackend.pro +++ b/mythtv/programs/mythbackend/mythbackend.pro @@ -30,17 +30,6 @@ HEADERS += internetContent.h mythbackend_main_helpers.h backendcontext.h HEADERS += httpconfig.h mythsettings.h mythbackend_commandlineparser.h HEADERS += recordingextender.h -HEADERS += serviceHosts/mythServiceHost.h serviceHosts/guideServiceHost.h -HEADERS += serviceHosts/contentServiceHost.h serviceHosts/dvrServiceHost.h -HEADERS += serviceHosts/channelServiceHost.h serviceHosts/videoServiceHost.h -HEADERS += serviceHosts/captureServiceHost.h serviceHosts/imageServiceHost.h -HEADERS += serviceHosts/musicServiceHost.h - -HEADERS += services/myth.h services/guide.h services/content.h services/dvr.h -HEADERS += services/serviceUtil.h services/channel.h services/video.h -HEADERS += services/capture.h services/image.h services/music.h - - SOURCES += autoexpire.cpp encoderlink.cpp filetransfer.cpp httpstatus.cpp SOURCES += mythbackend.cpp mainserver.cpp playbacksock.cpp scheduler.cpp SOURCES += backendhousekeeper.cpp @@ -49,11 +38,6 @@ SOURCES += internetContent.cpp mythbackend_main_helpers.cpp backendcontext.cpp SOURCES += httpconfig.cpp mythsettings.cpp mythbackend_commandlineparser.cpp SOURCES += recordingextender.cpp -SOURCES += services/myth.cpp services/guide.cpp services/content.cpp -SOURCES += services/dvr.cpp services/channel.cpp services/video.cpp -SOURCES += services/serviceUtil.cpp services/capture.cpp -SOURCES += services/image.cpp services/music.cpp - HEADERS += servicesv2/v2myth.h servicesv2/v2connectionInfo.h servicesv2/v2wolInfo.h HEADERS += servicesv2/v2databaseInfo.h servicesv2/v2versionInfo.h HEADERS += servicesv2/v2storageGroupDir.h servicesv2/v2storageGroupDirList.h diff --git a/mythtv/programs/mythbackend/serviceHosts/captureServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/captureServiceHost.h deleted file mode 100644 index 3df8363a814..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/captureServiceHost.h +++ /dev/null @@ -1,57 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: captureServiceHost.h -// Created : Sep. 21, 2011 -// -// Purpose - Capture Device Service Host -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CAPTURESERVICEHOST_H_ -#define CAPTURESERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/capture.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class CaptureServiceHost : public ServiceHost -{ - public: - - explicit CaptureServiceHost( const QString &sSharePath ) - : ServiceHost( Capture::staticMetaObject, - "Capture", - "/Capture", - sSharePath ) - { - } - - ~CaptureServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/channelIconServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/channelIconServiceHost.h deleted file mode 100644 index d895c53b63c..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/channelIconServiceHost.h +++ /dev/null @@ -1,59 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: channelIconServiceHost.h -// Created : Jun. 22, 2014 -// -// Purpose - Channel Icon Service Host -// -// Copyright (c) 2014 The MythTV Team -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CHANNELICONSERVICEHOST_H_ -#define CHANNELICONSERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/channelicon.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class ChannelIconServiceHost : public ServiceHost -{ - public: - - ChannelIconServiceHost( const QString &sSharePath ) - : ServiceHost( ChannelIcon::staticMetaObject, - "ChannelIcon", - "/ChannelIcon", - sSharePath ) - { - } - - virtual ~ChannelIconServiceHost() - { - } -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/channelServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/channelServiceHost.h deleted file mode 100644 index 6d297270b95..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/channelServiceHost.h +++ /dev/null @@ -1,57 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: channelServiceHost.h -// Created : Apr. 8, 2011 -// -// Purpose - Channel Service Host -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CHANNELSERVICEHOST_H_ -#define CHANNELSERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/channel.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class ChannelServiceHost : public ServiceHost -{ - public: - - explicit ChannelServiceHost( const QString &sSharePath ) - : ServiceHost( Channel::staticMetaObject, - "Channel", - "/Channel", - sSharePath ) - { - } - - ~ChannelServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/contentServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/contentServiceHost.h deleted file mode 100644 index 52b2a228a03..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/contentServiceHost.h +++ /dev/null @@ -1,57 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: contentServiceHost.h -// Created : Mar. 7, 2011 -// -// Purpose - Content Service Host -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CONTENTSERVICEHOST_H_ -#define CONTENTSERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/content.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class ContentServiceHost : public ServiceHost -{ - public: - - explicit ContentServiceHost( const QString &sSharePath ) - : ServiceHost( Content::staticMetaObject, - "Content", - "/Content", - sSharePath ) - { - } - - ~ContentServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/dvrServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/dvrServiceHost.h deleted file mode 100644 index 95ee0e5e6df..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/dvrServiceHost.h +++ /dev/null @@ -1,57 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: dvrServiceHost.h -// Created : Mar. 7, 2011 -// -// Purpose - DVR Service Host -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef DVRSERVICEHOST_H_ -#define DVRSERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/dvr.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class DvrServiceHost : public ServiceHost -{ - public: - - explicit DvrServiceHost( const QString &sSharePath ) - : ServiceHost( Dvr::staticMetaObject, - "Dvr", - "/Dvr", - sSharePath ) - { - } - - ~DvrServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/guideServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/guideServiceHost.h deleted file mode 100644 index 4eaa3f9e1ed..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/guideServiceHost.h +++ /dev/null @@ -1,57 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: guideServiceHost.h -// Created : Mar. 7, 2011 -// -// Purpose - Guide Data Service Host -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef GUIDESERVICEHOST_H_ -#define GUIDESERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/guide.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class GuideServiceHost : public ServiceHost -{ - public: - - explicit GuideServiceHost( const QString &sSharePath ) - : ServiceHost( Guide::staticMetaObject, - "Guide", - "/Guide", - sSharePath ) - { - } - - ~GuideServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/imageServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/imageServiceHost.h deleted file mode 100644 index 8f5f3fb0588..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/imageServiceHost.h +++ /dev/null @@ -1,47 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: contentServiceHost.h -// Created : Jul. 27, 2012 -// -// Purpose - Content Service Host -// -// Copyright (c) 2012 Robert Siebert -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or at your option any later version of the LGPL. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef IMAGESERVICEHOST_H_ -#define IMAGESERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/image.h" - - - -class ImageServiceHost : public ServiceHost -{ - public: - - explicit ImageServiceHost( const QString &sSharePath ) - : ServiceHost( Image::staticMetaObject, - "Image", - "/Image", - sSharePath ) - { - } - - ~ImageServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/musicServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/musicServiceHost.h deleted file mode 100644 index ddf91445b91..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/musicServiceHost.h +++ /dev/null @@ -1,40 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: musicServiceHost.h -// Created : July 20, 2017 -// -// Copyright (c) 2017 Paul Harrison -// -// Licensed under the GPL v2 or later, see LICENSE for details -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef MUSICSERVICEHOST_H_ -#define MUSICSERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/music.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class MusicServiceHost : public ServiceHost -{ - public: - - explicit MusicServiceHost( const QString &sSharePath ) - : ServiceHost( Music::staticMetaObject, - "Music", - "/Music", - sSharePath ) - { - } - - ~MusicServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/mythServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/mythServiceHost.h deleted file mode 100644 index 3cdf6afaf1a..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/mythServiceHost.h +++ /dev/null @@ -1,57 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: mythServiceHost.h -// Created : Mar. 7, 2011 -// -// Purpose - Myth Service Host -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef MYTHSERVICEHOST_H_ -#define MYTHSERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/myth.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class MythServiceHost : public ServiceHost -{ - public: - - explicit MythServiceHost( const QString &sSharePath ) - : ServiceHost( Myth::staticMetaObject, - "Myth", - "/Myth", - sSharePath ) - { - } - - ~MythServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/serviceHosts/videoServiceHost.h b/mythtv/programs/mythbackend/serviceHosts/videoServiceHost.h deleted file mode 100644 index 76e27bd1022..00000000000 --- a/mythtv/programs/mythbackend/serviceHosts/videoServiceHost.h +++ /dev/null @@ -1,57 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: videoServiceHost.h -// Created : Apr. 21, 2011 -// -// Purpose - Imported Video Service Host -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef VIDEOSERVICEHOST_H_ -#define VIDEOSERVICEHOST_H_ - -#include "libmythupnp/servicehost.h" -#include "services/video.h" - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -// -// -// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -class VideoServiceHost : public ServiceHost -{ - public: - - explicit VideoServiceHost( const QString &sSharePath ) - : ServiceHost( Video::staticMetaObject, - "Video", - "/Video", - sSharePath ) - { - } - - ~VideoServiceHost() override = default; -}; - -#endif diff --git a/mythtv/programs/mythbackend/services/capture.cpp b/mythtv/programs/mythbackend/services/capture.cpp deleted file mode 100644 index 47000155f85..00000000000 --- a/mythtv/programs/mythbackend/services/capture.cpp +++ /dev/null @@ -1,359 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: capture.cpp -// Created : Sep. 21, 2011 -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// Qt -#include -#include -#include - -// MythTV -#include "libmythbase/compat.h" -#include "libmythbase/mythcorecontext.h" -#include "libmythbase/mythdate.h" -#include "libmythbase/mythversion.h" -#include "libmythtv/cardutil.h" - -// MythBackend -#include "capture.h" -#include "serviceUtil.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::CaptureCardList* Capture::GetCaptureCardList( const QString &sHostName, - const QString &sCardType ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to list " - "Capture Cards.")); - - QString str = "SELECT cardid, parentid, videodevice, audiodevice, vbidevice, " - "cardtype, defaultinput, audioratelimit, hostname, " - "dvb_swfilter, dvb_sat_type, dvb_wait_for_seqstart, " - "skipbtaudio, dvb_on_demand, dvb_diseqc_type, " - "firewire_speed, firewire_model, firewire_connection, " - "signal_timeout, channel_timeout, dvb_tuning_delay, " - "contrast, brightness, colour, hue, diseqcid, dvb_eitscan, " - "inputname, sourceid, externalcommand, changer_device, " - "changer_model, tunechan, startchan, displayname, " - "dishnet_eit, recpriority, quicktune, schedorder, " - "livetvorder, reclimit, schedgroup " - "from capturecard"; - - if (!sHostName.isEmpty()) - str += " WHERE hostname = :HOSTNAME"; - else if (!sCardType.isEmpty()) - str += " WHERE cardtype = :CARDTYPE"; - - if (!sHostName.isEmpty() && !sCardType.isEmpty()) - str += " AND cardtype = :CARDTYPE"; - - query.prepare(str); - - if (!sHostName.isEmpty()) - query.bindValue(":HOSTNAME", sHostName); - if (!sCardType.isEmpty()) - query.bindValue(":CARDTYPE", sCardType); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetCaptureCardList()", query); - throw( QString( "Database Error executing query." )); - } - - // ---------------------------------------------------------------------- - // return the results of the query - // ---------------------------------------------------------------------- - - auto* pList = new DTC::CaptureCardList(); - - while (query.next()) - { - - DTC::CaptureCard *pCaptureCard = pList->AddNewCaptureCard(); - - pCaptureCard->setCardId ( query.value(0).toInt() ); - pCaptureCard->setParentId ( query.value(1).toInt() ); - pCaptureCard->setVideoDevice ( query.value(2).toString() ); - pCaptureCard->setAudioDevice ( query.value(3).toString() ); - pCaptureCard->setVBIDevice ( query.value(4).toString() ); - pCaptureCard->setCardType ( query.value(5).toString() ); - pCaptureCard->setDefaultInput ( query.value(6).toString() ); - pCaptureCard->setAudioRateLimit ( query.value(7).toUInt() ); - pCaptureCard->setHostName ( query.value(8).toString() ); - pCaptureCard->setDVBSWFilter ( query.value(9).toUInt() ); - pCaptureCard->setDVBSatType ( query.value(10).toUInt() ); - pCaptureCard->setDVBWaitForSeqStart( query.value(11).toBool() ); - pCaptureCard->setSkipBTAudio ( query.value(12).toBool() ); - pCaptureCard->setDVBOnDemand ( query.value(13).toBool() ); - pCaptureCard->setDVBDiSEqCType ( query.value(14).toUInt() ); - pCaptureCard->setFirewireSpeed ( query.value(15).toUInt() ); - pCaptureCard->setFirewireModel ( query.value(16).toString() ); - pCaptureCard->setFirewireConnection( query.value(17).toUInt() ); - pCaptureCard->setSignalTimeout ( query.value(18).toUInt() ); - pCaptureCard->setChannelTimeout ( query.value(19).toUInt() ); - pCaptureCard->setDVBTuningDelay ( query.value(20).toUInt() ); - pCaptureCard->setContrast ( query.value(21).toUInt() ); - pCaptureCard->setBrightness ( query.value(22).toUInt() ); - pCaptureCard->setColour ( query.value(23).toUInt() ); - pCaptureCard->setHue ( query.value(24).toUInt() ); - pCaptureCard->setDiSEqCId ( query.value(25).toUInt() ); - pCaptureCard->setDVBEITScan ( query.value(26).toBool() ); - pCaptureCard->setInputName ( query.value(27).toString() ); - pCaptureCard->setSourceId ( query.value(28).toInt() ); - pCaptureCard->setExternalCommand ( query.value(29).toString() ); - pCaptureCard->setChangerDevice ( query.value(30).toString() ); - pCaptureCard->setChangerModel ( query.value(31).toString() ); - pCaptureCard->setTuneChannel ( query.value(32).toString() ); - pCaptureCard->setStartChannel ( query.value(33).toString() ); - pCaptureCard->setDisplayName ( query.value(34).toString() ); - pCaptureCard->setDishnetEit ( query.value(35).toBool() ); - pCaptureCard->setRecPriority ( query.value(36).toInt() ); - pCaptureCard->setQuickTune ( query.value(37).toBool() ); - pCaptureCard->setSchedOrder ( query.value(38).toUInt() ); - pCaptureCard->setLiveTVOrder ( query.value(39).toUInt() ); - pCaptureCard->setRecLimit ( query.value(40).toUInt() ); - pCaptureCard->setSchedGroup ( query.value(41).toBool() ); - } - - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::CaptureCard* Capture::GetCaptureCard( int nCardId ) -{ - if ( nCardId < 1 ) - throw( QString( "The Card ID is invalid.")); - - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to list " - "Capture Cards.")); - - QString str = "SELECT cardid, parentid, videodevice, audiodevice, vbidevice, " - "cardtype, defaultinput, audioratelimit, hostname, " - "dvb_swfilter, dvb_sat_type, dvb_wait_for_seqstart, " - "skipbtaudio, dvb_on_demand, dvb_diseqc_type, " - "firewire_speed, firewire_model, firewire_connection, " - "signal_timeout, channel_timeout, dvb_tuning_delay, " - "contrast, brightness, colour, hue, diseqcid, dvb_eitscan, " - "inputname, sourceid, externalcommand, changer_device, " - "changer_model, tunechan, startchan, displayname, " - "dishnet_eit, recpriority, quicktune, schedorder, " - "livetvorder, reclimit, schedgroup " - "from capturecard WHERE cardid = :CARDID"; - - query.prepare(str); - query.bindValue(":CARDID", nCardId); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetCaptureCard()", query); - throw( QString( "Database Error executing query." )); - } - - auto* pCaptureCard = new DTC::CaptureCard(); - - if (query.next()) - { - pCaptureCard->setCardId ( query.value(0).toInt() ); - pCaptureCard->setParentId ( query.value(1).toInt() ); - pCaptureCard->setVideoDevice ( query.value(2).toString() ); - pCaptureCard->setAudioDevice ( query.value(3).toString() ); - pCaptureCard->setVBIDevice ( query.value(4).toString() ); - pCaptureCard->setCardType ( query.value(5).toString() ); - pCaptureCard->setDefaultInput ( query.value(6).toString() ); - pCaptureCard->setAudioRateLimit ( query.value(7).toUInt() ); - pCaptureCard->setHostName ( query.value(8).toString() ); - pCaptureCard->setDVBSWFilter ( query.value(9).toUInt() ); - pCaptureCard->setDVBSatType ( query.value(10).toUInt() ); - pCaptureCard->setDVBWaitForSeqStart( query.value(11).toBool() ); - pCaptureCard->setSkipBTAudio ( query.value(12).toBool() ); - pCaptureCard->setDVBOnDemand ( query.value(13).toBool() ); - pCaptureCard->setDVBDiSEqCType ( query.value(14).toUInt() ); - pCaptureCard->setFirewireSpeed ( query.value(15).toUInt() ); - pCaptureCard->setFirewireModel ( query.value(16).toString() ); - pCaptureCard->setFirewireConnection( query.value(17).toUInt() ); - pCaptureCard->setSignalTimeout ( query.value(18).toUInt() ); - pCaptureCard->setChannelTimeout ( query.value(19).toUInt() ); - pCaptureCard->setDVBTuningDelay ( query.value(20).toUInt() ); - pCaptureCard->setContrast ( query.value(21).toUInt() ); - pCaptureCard->setBrightness ( query.value(22).toUInt() ); - pCaptureCard->setColour ( query.value(23).toUInt() ); - pCaptureCard->setHue ( query.value(24).toUInt() ); - pCaptureCard->setDiSEqCId ( query.value(25).toUInt() ); - pCaptureCard->setDVBEITScan ( query.value(26).toBool() ); - pCaptureCard->setInputName ( query.value(27).toString() ); - pCaptureCard->setSourceId ( query.value(28).toInt() ); - pCaptureCard->setExternalCommand ( query.value(29).toString() ); - pCaptureCard->setChangerDevice ( query.value(30).toString() ); - pCaptureCard->setChangerModel ( query.value(31).toString() ); - pCaptureCard->setTuneChannel ( query.value(32).toString() ); - pCaptureCard->setStartChannel ( query.value(33).toString() ); - pCaptureCard->setDisplayName ( query.value(34).toString() ); - pCaptureCard->setDishnetEit ( query.value(35).toBool() ); - pCaptureCard->setRecPriority ( query.value(36).toInt() ); - pCaptureCard->setQuickTune ( query.value(37).toBool() ); - pCaptureCard->setSchedOrder ( query.value(38).toUInt() ); - pCaptureCard->setLiveTVOrder ( query.value(39).toUInt() ); - pCaptureCard->setRecLimit ( query.value(40).toUInt() ); - pCaptureCard->setSchedGroup ( query.value(41).toBool() ); - } - - return pCaptureCard; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Capture::RemoveCaptureCard( int nCardId ) -{ - if ( nCardId < 1 ) - throw( QString( "The Card ID is invalid.")); - - bool bResult = CardUtil::DeleteInput(nCardId); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -int Capture::AddCaptureCard ( const QString &sVideoDevice, - const QString &sAudioDevice, - const QString &sVBIDevice, - const QString &sCardType, - const uint nAudioRateLimit, - const QString &sHostName, - const uint nDVBSWFilter, - const uint nDVBSatType, - bool bDVBWaitForSeqStart, - bool bSkipBTAudio, - bool bDVBOnDemand, - const uint nDVBDiSEqCType, - const uint nFirewireSpeed, - const QString &sFirewireModel, - const uint nFirewireConnection, - const uint nSignalTimeout, - const uint nChannelTimeout, - const uint nDVBTuningDelay, - const uint nContrast, - const uint nBrightness, - const uint nColour, - const uint nHue, - const uint nDiSEqCId, - bool bDVBEITScan) -{ - if ( sVideoDevice.isEmpty() || sCardType.isEmpty() || sHostName.isEmpty() ) - throw( QString( "This API requires at least a video device node, a card type, " - "and a hostname." )); - - int nResult = CardUtil::CreateCaptureCard(sVideoDevice, sAudioDevice, - sVBIDevice, sCardType, nAudioRateLimit, - sHostName, nDVBSWFilter, nDVBSatType, bDVBWaitForSeqStart, - bSkipBTAudio, bDVBOnDemand, nDVBDiSEqCType, nFirewireSpeed, - sFirewireModel, nFirewireConnection, std::chrono::milliseconds(nSignalTimeout), - std::chrono::milliseconds(nChannelTimeout), nDVBTuningDelay, nContrast, nBrightness, - nColour, nHue, nDiSEqCId, bDVBEITScan); - - if ( nResult < 1 ) - throw( QString( "Unable to create capture device." )); - - return nResult; -} - -bool Capture::UpdateCaptureCard ( int nCardId, - const QString &sSetting, - const QString &sValue ) -{ - if ( nCardId < 1 || sSetting.isEmpty() || sValue.isEmpty() ) - throw( QString( "Card ID, Setting Name, and Value are required." )); - - return set_on_input(sSetting, nCardId, sValue); -} - -// Card Inputs - -bool Capture::RemoveCardInput( int nCardInputId ) -{ - if ( nCardInputId < 1 ) - throw( QString( "The Input ID is invalid.")); - - bool bResult = CardUtil::DeleteInput(nCardInputId); - - return bResult; -} - -int Capture::AddCardInput ( const uint nCardId, - const uint nSourceId, - const QString &sInputName, - const QString &sExternalCommand, - const QString &sChangerDevice, - const QString &sChangerModel, - const QString &sHostName, - const QString &sTuneChan, - const QString &sStartChan, - const QString &sDisplayName, - bool bDishnetEIT, - const uint nRecPriority, - const uint nQuicktune, - const uint nSchedOrder, - const uint nLiveTVOrder) -{ - if ( nCardId < 1 || nSourceId < 1 || - sInputName.isEmpty() || sInputName == "None" ) - throw( QString( "This API requires at least a card ID, a source ID, " - "and an input name." )); - - if ( !CardUtil::IsUniqueDisplayName(sDisplayName, 0 )) - throw QString(" DisplayName is not set or is not unique."); - - int nResult = CardUtil::CreateCardInput(nCardId, nSourceId, sInputName, - sExternalCommand, sChangerDevice, sChangerModel, - sHostName, sTuneChan, sStartChan, sDisplayName, - bDishnetEIT, nRecPriority, nQuicktune, nSchedOrder, - nLiveTVOrder); - - return nResult; -} - -bool Capture::UpdateCardInput ( int nCardInputId, - const QString &sSetting, - const QString &sValue ) -{ - if ( nCardInputId < 1 || sSetting.isEmpty() || sValue.isEmpty() ) - throw( QString( "Input ID, Setting Name, and Value are required." )); - - return set_on_input(sSetting, nCardInputId, sValue); -} diff --git a/mythtv/programs/mythbackend/services/capture.h b/mythtv/programs/mythbackend/services/capture.h deleted file mode 100644 index 7aacb7d2d4f..00000000000 --- a/mythtv/programs/mythbackend/services/capture.h +++ /dev/null @@ -1,190 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: capture.h -// Created : Sep. 21, 2011 -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CAPTURE_H -#define CAPTURE_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -#include "libmythservicecontracts/services/captureServices.h" - -class Capture : public CaptureServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Capture( QObject */*parent*/ = nullptr ) {} - - public: - - DTC::CaptureCardList* GetCaptureCardList ( const QString &HostName, - const QString &CardType ) override; // CaptureServices - - DTC::CaptureCard* GetCaptureCard ( int CardId ) override; // CaptureServices - - bool RemoveCaptureCard ( int CardId ) override; // CaptureServices - - int AddCaptureCard ( const QString &VideoDevice, - const QString &AudioDevice, - const QString &VBIDevice, - const QString &CardType, - uint AudioRateLimit, - const QString &HostName, - uint DVBSWFilter, - uint DVBSatType, - bool DVBWaitForSeqStart, - bool SkipBTAudio, - bool DVBOnDemand, - uint DVBDiSEqCType, - uint FirewireSpeed, - const QString &FirewireModel, - uint FirewireConnection, - uint SignalTimeout, - uint ChannelTimeout, - uint DVBTuningDelay, - uint Contrast, - uint Brightness, - uint Colour, - uint Hue, - uint DiSEqCId, - bool DVBEITScan) override; // CaptureServices - - bool UpdateCaptureCard ( int CardId, - const QString &Setting, - const QString &Value ) override; // CaptureServices - - // Card Inputs - - bool RemoveCardInput ( int CardInputId) override; // CaptureServices - - int AddCardInput ( uint CardId, - uint SourceId, - const QString &InputName, - const QString &ExternalCommand, - const QString &ChangerDevice, - const QString &ChangerModel, - const QString &HostName, - const QString &TuneChan, - const QString &StartChan, - const QString &DisplayName, - bool DishnetEIT, - uint RecPriority, - uint Quicktune, - uint SchedOrder, - uint LiveTVOrder) override; // CaptureServices - - bool UpdateCardInput ( int CardInputId, - const QString &Setting, - const QString &Value ) override; // CaptureServices - -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableCapture : public QObject -{ - Q_OBJECT - - private: - - Capture m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableCapture( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - bool RemoveCaptureCard ( int Id ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveCaptureCard( Id ); - ) - } - - bool AddCaptureCard ( const QString &VideoDevice, - const QString &AudioDevice, - const QString &VBIDevice, - const QString &CardType, - const uint AudioRateLimit, - const QString &HostName, - const uint DVBSWFilter, - const uint DVBSatType, - bool DVBWaitForSeqStart, - bool SkipBTAudio, - bool DVBOnDemand, - const uint DVBDiSEqCType, - const uint FirewireSpeed, - const QString &FirewireModel, - const uint FirewireConnection, - const uint SignalTimeout, - const uint ChannelTimeout, - const uint DVBTuningDelay, - const uint Contrast, - const uint Brightness, - const uint Colour, - const uint Hue, - const uint DiSEqCId, - bool DVBEITScan) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.AddCaptureCard( VideoDevice, AudioDevice, VBIDevice, CardType, - AudioRateLimit, HostName, DVBSWFilter, - DVBSatType, DVBWaitForSeqStart, SkipBTAudio, DVBOnDemand, - DVBDiSEqCType, FirewireSpeed, FirewireModel, FirewireConnection, - SignalTimeout, ChannelTimeout, DVBTuningDelay, Contrast, Brightness, - Colour, Hue, DiSEqCId, DVBEITScan); - ) - } -}; - - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableCapture, QObject*); -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/channel.cpp b/mythtv/programs/mythbackend/services/channel.cpp deleted file mode 100644 index f22a7e425bd..00000000000 --- a/mythtv/programs/mythbackend/services/channel.cpp +++ /dev/null @@ -1,809 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: channel.cpp -// Created : Apr. 8, 2011 -// -// Copyright (c) 2011 Robert McNamara -// Copyright (c) 2013 MythTV Developers -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// C++ -#include - -// Qt -#include - -// MythTV -#include "libmythbase/compat.h" -#include "libmythbase/mythcorecontext.h" -#include "libmythbase/mythdate.h" -#include "libmythbase/mythdbcon.h" -#include "libmythbase/mythdirs.h" -#include "libmythbase/mythversion.h" -#include "libmythtv/cardutil.h" -#include "libmythtv/channelutil.h" -#include "libmythtv/sourceutil.h" - -// MythBackend -#include "channel.h" -#include "serviceUtil.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ChannelInfoList* Channel::GetChannelInfoList( uint nSourceID, - uint nChannelGroupID, - uint nStartIndex, - uint nCount, - bool bOnlyVisible, - bool bDetails, - bool bOrderByName, - bool bGroupByCallsign, - bool bOnlyTunable ) -{ - ChannelInfoList chanList; - - uint nTotalAvailable = 0; - - chanList = ChannelUtil::LoadChannels( 0, 0, nTotalAvailable, bOnlyVisible, - bOrderByName ? ChannelUtil::kChanOrderByName : ChannelUtil::kChanOrderByChanNum, - bGroupByCallsign ? ChannelUtil::kChanGroupByCallsign : ChannelUtil::kChanGroupByChanid, - nSourceID, nChannelGroupID, false, "", - "", bOnlyTunable); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pChannelInfos = new DTC::ChannelInfoList(); - - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, nTotalAvailable ) : 0; - nCount = (nCount > 0) ? std::min(nCount, (nTotalAvailable - nStartIndex)) : - (nTotalAvailable - nStartIndex); - - ChannelInfoList::iterator chanIt; - auto chanItBegin = chanList.begin() + nStartIndex; - auto chanItEnd = chanItBegin + nCount; - - for( chanIt = chanItBegin; chanIt < chanItEnd; ++chanIt ) - { - DTC::ChannelInfo *pChannelInfo = pChannelInfos->AddNewChannelInfo(); - - const ChannelInfo& channelInfo = (*chanIt); - - if (!FillChannelInfo(pChannelInfo, channelInfo, bDetails)) - { - delete pChannelInfo; - delete pChannelInfos; - throw( QString("Channel ID appears invalid.")); - } - } - - int nCurPage = 0; - int nTotalPages = 0; - if (nCount == 0) - nTotalPages = 1; - else - nTotalPages = (int)std::ceil((float)nTotalAvailable / nCount); - - if (nTotalPages == 1) - nCurPage = 1; - else - { - nCurPage = (int)std::ceil((float)nStartIndex / nCount) + 1; - } - - pChannelInfos->setStartIndex ( nStartIndex ); - pChannelInfos->setCount ( nCount ); - pChannelInfos->setCurrentPage ( nCurPage ); - pChannelInfos->setTotalPages ( nTotalPages ); - pChannelInfos->setTotalAvailable( nTotalAvailable ); - pChannelInfos->setAsOf ( MythDate::current() ); - pChannelInfos->setVersion ( MYTH_BINARY_VERSION ); - pChannelInfos->setProtoVer ( MYTH_PROTO_VERSION ); - - return pChannelInfos; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ChannelInfo* Channel::GetChannelInfo( uint nChanID ) -{ - if (nChanID == 0) - throw( QString("Channel ID appears invalid.")); - - auto *pChannelInfo = new DTC::ChannelInfo(); - - if (!FillChannelInfo(pChannelInfo, nChanID, true)) - { - // throw causes a crash on linux and we can't know in advance - // that a channel id from an old recording rule is invalid - //throw( QString("Channel ID appears invalid.")); - } - - return pChannelInfo; -} - -bool Channel::UpdateDBChannel( uint MplexID, - uint SourceID, - uint ChannelID, - const QString &CallSign, - const QString &ChannelName, - const QString &ChannelNumber, - uint ServiceID, - uint ATSCMajorChannel, - uint ATSCMinorChannel, - bool UseEIT, - bool Visible, - [[maybe_unused]] const QString &ExtendedVisible, - const QString &FrequencyID, - const QString &Icon, - const QString &Format, - const QString &XMLTVID, - const QString &DefaultAuthority, - uint ServiceType ) -{ - if (!HAS_PARAM("channelid")) - throw QString("ChannelId is required"); - - if (m_parsedParams.size() < 2 ) - throw QString("Nothing to update"); - - ChannelInfo channel; - if (!channel.Load(ChannelID)) - throw QString("ChannelId %1 doesn't exist"); - - if (HAS_PARAM("mplexid")) - channel.m_mplexId = MplexID; - if (HAS_PARAM("sourceid")) - channel.m_sourceId = SourceID; - if (HAS_PARAM("callsign")) - channel.m_callSign = CallSign; - if (HAS_PARAM("channelname")) - channel.m_name = ChannelName; - if (HAS_PARAM("channelnumber")) - channel.m_chanNum = ChannelNumber; - if (HAS_PARAM("serviceid")) - channel.m_serviceId = ServiceID; - if (HAS_PARAM("atscmajorchannel")) - channel.m_atscMajorChan = ATSCMajorChannel; - if (HAS_PARAM("atscminorchannel")) - channel.m_atscMinorChan = ATSCMinorChannel; - if (HAS_PARAM("useeit")) - channel.m_useOnAirGuide = UseEIT; - - if (HAS_PARAM("extendedvisible")) - { -#ifndef _WIN32 // TODO Does not compile on Windows - channel.m_visible = channelVisibleTypeFromString(ExtendedVisible); -#endif - } - else if (HAS_PARAM("visible")) - { - if (channel.m_visible == kChannelVisible || - channel.m_visible == kChannelNotVisible) - { - channel.m_visible = - (Visible ? kChannelVisible : kChannelNotVisible); - } - else if ((channel.m_visible == kChannelAlwaysVisible && !Visible) || - (channel.m_visible == kChannelNeverVisible && Visible)) - { - throw QString("Can't override Always/NeverVisible"); - } - } - if (HAS_PARAM("frequencyid")) - channel.m_freqId = FrequencyID; - if (HAS_PARAM("icon")) - channel.m_icon = Icon; - if (HAS_PARAM("format")) - channel.m_tvFormat = Format; - if (HAS_PARAM("xmltvid")) - channel.m_xmltvId = XMLTVID; - if (HAS_PARAM("defaultauthority")) - channel.m_defaultAuthority = DefaultAuthority; - if (HAS_PARAM("servicetype")) - channel.m_serviceType = ServiceType; - - bool bResult = ChannelUtil::UpdateChannel( - channel.m_mplexId, channel.m_sourceId, channel.m_chanId, - channel.m_callSign, channel.m_name, channel.m_chanNum, - channel.m_serviceId, channel.m_atscMajorChan, - channel.m_atscMinorChan, channel.m_useOnAirGuide, - channel.m_visible, channel.m_freqId, - channel.m_icon, channel.m_tvFormat, channel.m_xmltvId, - channel.m_defaultAuthority, channel.m_serviceType ); - - return bResult; -} - -bool Channel::AddDBChannel( uint MplexID, - uint SourceID, - uint ChannelID, - const QString &CallSign, - const QString &ChannelName, - const QString &ChannelNumber, - uint ServiceID, - uint ATSCMajorChannel, - uint ATSCMinorChannel, - bool UseEIT, - bool Visible, - [[maybe_unused]] const QString &ExtendedVisible, - const QString &FrequencyID, - const QString &Icon, - const QString &Format, - const QString &XMLTVID, - const QString &DefaultAuthority, - uint ServiceType ) -{ - ChannelVisibleType chan_visible = kChannelVisible; - - #ifdef _WIN32 // TODO Needs fixing for Windows - chan_visible = (Visible ? kChannelVisible : kChannelNotVisible); - #else - if (HAS_PARAM("extendedvisible")) - chan_visible = channelVisibleTypeFromString(ExtendedVisible); - else if (HAS_PARAM("visible")) - chan_visible = (Visible ? kChannelVisible : kChannelNotVisible); - #endif - - - bool bResult = ChannelUtil::CreateChannel( MplexID, SourceID, ChannelID, - CallSign, ChannelName, ChannelNumber, - ServiceID, ATSCMajorChannel, ATSCMinorChannel, - UseEIT, chan_visible, FrequencyID, - Icon, Format, XMLTVID, DefaultAuthority, - ServiceType ); - - return bResult; -} - -bool Channel::RemoveDBChannel( uint nChannelID ) -{ - bool bResult = ChannelUtil::DeleteChannel( nChannelID ); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoSourceList* Channel::GetVideoSourceList() -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to list " - "Video Sources.")); - - query.prepare("SELECT sourceid, name, xmltvgrabber, userid, " - "freqtable, lineupid, password, useeit, configpath, " - "dvb_nit_id, bouquet_id, region_id, scanfrequency, " - "lcnoffset FROM videosource " - "ORDER BY sourceid" ); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetVideoSourceList()", query); - - throw( QString( "Database Error executing query." )); - } - - // ---------------------------------------------------------------------- - // return the results of the query - // ---------------------------------------------------------------------- - - auto* pList = new DTC::VideoSourceList(); - - while (query.next()) - { - - DTC::VideoSource *pVideoSource = pList->AddNewVideoSource(); - - pVideoSource->setId ( query.value(0).toInt() ); - pVideoSource->setSourceName ( query.value(1).toString() ); - pVideoSource->setGrabber ( query.value(2).toString() ); - pVideoSource->setUserId ( query.value(3).toString() ); - pVideoSource->setFreqTable ( query.value(4).toString() ); - pVideoSource->setLineupId ( query.value(5).toString() ); - pVideoSource->setPassword ( query.value(6).toString() ); - pVideoSource->setUseEIT ( query.value(7).toBool() ); - pVideoSource->setConfigPath ( query.value(8).toString() ); - pVideoSource->setNITId ( query.value(9).toInt() ); - pVideoSource->setBouquetId ( query.value(10).toUInt() ); - pVideoSource->setRegionId ( query.value(11).toUInt() ); - pVideoSource->setScanFrequency ( query.value(12).toUInt() ); - pVideoSource->setLCNOffset ( query.value(13).toUInt() ); - } - - pList->setAsOf ( MythDate::current() ); - pList->setVersion ( MYTH_BINARY_VERSION ); - pList->setProtoVer ( MYTH_PROTO_VERSION ); - - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoSource* Channel::GetVideoSource( uint nSourceID ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to list " - "Video Sources.")); - - query.prepare("SELECT name, xmltvgrabber, userid, " - "freqtable, lineupid, password, useeit, configpath, " - "dvb_nit_id, bouquet_id, region_id, scanfrequency, " - "lcnoffset " - "FROM videosource WHERE sourceid = :SOURCEID " - "ORDER BY sourceid" ); - query.bindValue(":SOURCEID", nSourceID); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetVideoSource()", query); - - throw( QString( "Database Error executing query." )); - } - - // ---------------------------------------------------------------------- - // return the results of the query - // ---------------------------------------------------------------------- - - auto *pVideoSource = new DTC::VideoSource(); - - if (query.next()) - { - pVideoSource->setId ( nSourceID ); - pVideoSource->setSourceName ( query.value(0).toString() ); - pVideoSource->setGrabber ( query.value(1).toString() ); - pVideoSource->setUserId ( query.value(2).toString() ); - pVideoSource->setFreqTable ( query.value(3).toString() ); - pVideoSource->setLineupId ( query.value(4).toString() ); - pVideoSource->setPassword ( query.value(5).toString() ); - pVideoSource->setUseEIT ( query.value(6).toBool() ); - pVideoSource->setConfigPath ( query.value(7).toString() ); - pVideoSource->setNITId ( query.value(8).toInt() ); - pVideoSource->setBouquetId ( query.value(9).toUInt() ); - pVideoSource->setRegionId ( query.value(10).toUInt() ); - pVideoSource->setScanFrequency ( query.value(11).toUInt() ); - pVideoSource->setLCNOffset ( query.value(12).toUInt() ); - } - - return pVideoSource; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Channel::UpdateVideoSource( uint nSourceId, - const QString &sSourceName, - const QString &sGrabber, - const QString &sUserId, - const QString &sFreqTable, - const QString &sLineupId, - const QString &sPassword, - bool bUseEIT, - const QString &sConfigPath, - int nNITId, - uint nBouquetId, - uint nRegionId, - uint nScanFrequency, - uint nLCNOffset ) -{ - - if (!HAS_PARAM("sourceid")) - { - LOG(VB_GENERAL, LOG_ERR, "SourceId is required"); - return false; - } - - if (!SourceUtil::IsSourceIDValid(nSourceId)) - { - LOG(VB_GENERAL, LOG_ERR, QString("SourceId %1 doesn't exist") - .arg(nSourceId)); - return false; - } - - if (m_parsedParams.size() < 2 ) - { - LOG(VB_GENERAL, LOG_ERR, QString("SourceId=%1 was the only parameter") - .arg(nSourceId)); - return false; - } - - MSqlBindings bindings; - MSqlBindings::const_iterator it; - QString settings; - - if ( HAS_PARAM("sourcename") ) - ADD_SQL(settings, bindings, "name", "SourceName", sSourceName); - - if ( HAS_PARAM("grabber") ) - ADD_SQL(settings, bindings, "xmltvgrabber", "Grabber", sGrabber); - - if ( HAS_PARAM("userid") ) - ADD_SQL(settings, bindings, "userid", "UserId", sUserId); - - if ( HAS_PARAM("freqtable") ) - ADD_SQL(settings, bindings, "freqtable", "FreqTable", sFreqTable); - - if ( HAS_PARAM("lineupid") ) - ADD_SQL(settings, bindings, "lineupid", "LineupId", sLineupId); - - if ( HAS_PARAM("password") ) - ADD_SQL(settings, bindings, "password", "Password", sPassword); - - if ( HAS_PARAM("useeit") ) - ADD_SQL(settings, bindings, "useeit", "UseEIT", bUseEIT); - - if (HAS_PARAM("configpath")) - { - if (sConfigPath.isEmpty()) - settings += "configpath=NULL, "; // mythfilldatabase grabber requirement - else - ADD_SQL(settings, bindings, "configpath", "ConfigPath", sConfigPath); - } - - if ( HAS_PARAM("nitid") ) - ADD_SQL(settings, bindings, "dvb_nit_id", "NITId", nNITId); - - if ( HAS_PARAM("bouquetid") ) - ADD_SQL(settings, bindings, "bouquet_id", "BouquetId", nBouquetId); - - if ( HAS_PARAM("regionid") ) - ADD_SQL(settings, bindings, "region_id", "RegionId", nRegionId); - - if ( HAS_PARAM("scanfrequency") ) - ADD_SQL(settings, bindings, "scanfrequency", "ScanFrequency", nScanFrequency); - - if ( HAS_PARAM("lcnoffset") ) - ADD_SQL(settings, bindings, "lcnoffset", "LCNOffset", nLCNOffset); - - if ( settings.isEmpty() ) - { - LOG(VB_GENERAL, LOG_ERR, "No valid parameters were passed"); - return false; - } - - settings.chop(2); - - MSqlQuery query(MSqlQuery::InitCon()); - - query.prepare(QString("UPDATE videosource SET %1 WHERE sourceid=:SOURCEID") - .arg(settings)); - bindings[":SOURCEID"] = nSourceId; - - for (it = bindings.cbegin(); it != bindings.cend(); ++it) - query.bindValue(it.key(), it.value()); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::UpdateVideoSource()", query); - - throw( QString( "Database Error executing query." )); - } - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -int Channel::AddVideoSource( const QString &sSourceName, - const QString &sGrabber, - const QString &sUserId, - const QString &sFreqTable, - const QString &sLineupId, - const QString &sPassword, - bool bUseEIT, - const QString &sConfigPath, - int nNITId, - uint nBouquetId, - uint nRegionId, - uint nScanFrequency, - uint nLCNOffset ) -{ - int nResult = SourceUtil::CreateSource(sSourceName, sGrabber, sUserId, sFreqTable, - sLineupId, sPassword, bUseEIT, sConfigPath, - nNITId, nBouquetId, nRegionId, nScanFrequency, - nLCNOffset); - - return nResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Channel::RemoveVideoSource( uint nSourceID ) -{ - bool bResult = SourceUtil::DeleteSource( nSourceID ); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LineupList* Channel::GetDDLineupList( const QString &/*sSource*/, - const QString &/*sUserId*/, - const QString &/*sPassword*/ ) -{ - auto *pLineups = new DTC::LineupList(); - return pLineups; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -int Channel::FetchChannelsFromSource( const uint nSourceId, - const uint nCardId, - bool bWaitForFinish ) -{ - if ( nSourceId < 1 || nCardId < 1) - throw( QString("A source ID and card ID are both required.")); - - int nResult = 0; - - QString cardtype = CardUtil::GetRawInputType(nCardId); - - if (!CardUtil::IsUnscanable(cardtype) && - !CardUtil::IsEncoder(cardtype)) - { - throw( QString("This device is incompatible with channel fetching.") ); - } - - SourceUtil::UpdateChannelsFromListings(nSourceId, cardtype, bWaitForFinish); - - if (bWaitForFinish) - nResult = SourceUtil::GetChannelCount(nSourceId); - - return nResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoMultiplexList* Channel::GetVideoMultiplexList( uint nSourceID, - uint nStartIndex, - uint nCount ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to list " - "Video Sources.")); - - query.prepare("SELECT mplexid, sourceid, transportid, networkid, " - "frequency, inversion, symbolrate, fec, polarity, " - "modulation, bandwidth, lp_code_rate, transmission_mode, " - "guard_interval, visible, constellation, hierarchy, hp_code_rate, " - "mod_sys, rolloff, sistandard, serviceversion, updatetimestamp, " - "default_authority FROM dtv_multiplex WHERE sourceid = :SOURCEID " - "ORDER BY mplexid" ); - query.bindValue(":SOURCEID", nSourceID); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetVideoMultiplexList()", query); - - throw( QString( "Database Error executing query." )); - } - - uint muxCount = (uint)query.size(); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pVideoMultiplexes = new DTC::VideoMultiplexList(); - - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, muxCount ) : 0; - nCount = (nCount > 0) ? std::min( nCount, muxCount ) : muxCount; - int nEndIndex = std::min((nStartIndex + nCount), muxCount ); - - for( int n = nStartIndex; n < nEndIndex; n++) - { - if (query.seek(n)) - { - DTC::VideoMultiplex *pVideoMultiplex = pVideoMultiplexes->AddNewVideoMultiplex(); - - pVideoMultiplex->setMplexId( query.value(0).toInt() ); - pVideoMultiplex->setSourceId( query.value(1).toInt() ); - pVideoMultiplex->setTransportId( query.value(2).toInt() ); - pVideoMultiplex->setNetworkId( query.value(3).toInt() ); - pVideoMultiplex->setFrequency( query.value(4).toLongLong() ); - pVideoMultiplex->setInversion( query.value(5).toString() ); - pVideoMultiplex->setSymbolRate( query.value(6).toLongLong() ); - pVideoMultiplex->setFEC( query.value(7).toString() ); - pVideoMultiplex->setPolarity( query.value(8).toString() ); - pVideoMultiplex->setModulation( query.value(9).toString() ); - pVideoMultiplex->setBandwidth( query.value(10).toString() ); - pVideoMultiplex->setLPCodeRate( query.value(11).toString() ); - pVideoMultiplex->setTransmissionMode( query.value(12).toString() ); - pVideoMultiplex->setGuardInterval( query.value(13).toString() ); - pVideoMultiplex->setVisible( query.value(14).toBool() ); - pVideoMultiplex->setConstellation( query.value(15).toString() ); - pVideoMultiplex->setHierarchy( query.value(16).toString() ); - pVideoMultiplex->setHPCodeRate( query.value(17).toString() ); - pVideoMultiplex->setModulationSystem( query.value(18).toString() ); - pVideoMultiplex->setRollOff( query.value(19).toString() ); - pVideoMultiplex->setSIStandard( query.value(20).toString() ); - pVideoMultiplex->setServiceVersion( query.value(21).toInt() ); - pVideoMultiplex->setUpdateTimeStamp( - MythDate::as_utc(query.value(22).toDateTime())); - pVideoMultiplex->setDefaultAuthority( query.value(23).toString() ); - } - } - - int curPage = 0; - int totalPages = 0; - if (nCount == 0) - totalPages = 1; - else - totalPages = (int)std::ceil((float)muxCount / nCount); - - if (totalPages == 1) - curPage = 1; - else - { - curPage = (int)std::ceil((float)nStartIndex / nCount) + 1; - } - - pVideoMultiplexes->setStartIndex ( nStartIndex ); - pVideoMultiplexes->setCount ( nCount ); - pVideoMultiplexes->setCurrentPage ( curPage ); - pVideoMultiplexes->setTotalPages ( totalPages ); - pVideoMultiplexes->setTotalAvailable( muxCount ); - pVideoMultiplexes->setAsOf ( MythDate::current() ); - pVideoMultiplexes->setVersion ( MYTH_BINARY_VERSION ); - pVideoMultiplexes->setProtoVer ( MYTH_PROTO_VERSION ); - - return pVideoMultiplexes; -} - -DTC::VideoMultiplex* Channel::GetVideoMultiplex( uint nMplexID ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to list " - "Video Multiplex.")); - - query.prepare("SELECT sourceid, transportid, networkid, " - "frequency, inversion, symbolrate, fec, polarity, " - "modulation, bandwidth, lp_code_rate, transmission_mode, " - "guard_interval, visible, constellation, hierarchy, hp_code_rate, " - "mod_sys, rolloff, sistandard, serviceversion, updatetimestamp, " - "default_authority FROM dtv_multiplex WHERE mplexid = :MPLEXID " - "ORDER BY mplexid" ); - query.bindValue(":MPLEXID", nMplexID); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetVideoMultiplex()", query); - - throw( QString( "Database Error executing query." )); - } - - auto *pVideoMultiplex = new DTC::VideoMultiplex(); - - if (query.next()) - { - pVideoMultiplex->setMplexId( nMplexID ); - pVideoMultiplex->setSourceId( query.value(0).toInt() ); - pVideoMultiplex->setTransportId( query.value(1).toInt() ); - pVideoMultiplex->setNetworkId( query.value(2).toInt() ); - pVideoMultiplex->setFrequency( query.value(3).toLongLong() ); - pVideoMultiplex->setInversion( query.value(4).toString() ); - pVideoMultiplex->setSymbolRate( query.value(5).toLongLong() ); - pVideoMultiplex->setFEC( query.value(6).toString() ); - pVideoMultiplex->setPolarity( query.value(7).toString() ); - pVideoMultiplex->setModulation( query.value(8).toString() ); - pVideoMultiplex->setBandwidth( query.value(9).toString() ); - pVideoMultiplex->setLPCodeRate( query.value(10).toString() ); - pVideoMultiplex->setTransmissionMode( query.value(11).toString() ); - pVideoMultiplex->setGuardInterval( query.value(12).toString() ); - pVideoMultiplex->setVisible( query.value(13).toBool() ); - pVideoMultiplex->setConstellation( query.value(14).toString() ); - pVideoMultiplex->setHierarchy( query.value(15).toString() ); - pVideoMultiplex->setHPCodeRate( query.value(16).toString() ); - pVideoMultiplex->setModulationSystem( query.value(17).toString() ); - pVideoMultiplex->setRollOff( query.value(18).toString() ); - pVideoMultiplex->setSIStandard( query.value(19).toString() ); - pVideoMultiplex->setServiceVersion( query.value(20).toInt() ); - pVideoMultiplex->setUpdateTimeStamp( - MythDate::as_utc(query.value(21).toDateTime())); - pVideoMultiplex->setDefaultAuthority( query.value(22).toString() ); - } - - return pVideoMultiplex; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Channel::GetXMLTVIdList( uint SourceID ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to get source name.")); - - query.prepare("SELECT name FROM videosource WHERE sourceid = :SOURCEID "); - query.bindValue(":SOURCEID", SourceID); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetXMLTVIdList()", query); - - throw( QString( "Database Error executing query." )); - } - - QStringList idList; - - if (query.next()) - { - QString sourceName = query.value(0).toString(); - - QString xmltvFile = GetConfDir() + '/' + sourceName + ".xmltv"; - - if (QFile::exists(xmltvFile)) - { - QFile file(xmltvFile); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - return idList; - - while (!file.atEnd()) - { - QByteArray line = file.readLine(); - - if (line.startsWith("channel=")) - { - QString id = line.mid(8, -1).trimmed(); - idList.append(id); - } - } - - idList.sort(); - } - } - else - { - throw(QString("SourceID (%1) not found").arg(SourceID)); - } - - return idList; -} diff --git a/mythtv/programs/mythbackend/services/channel.h b/mythtv/programs/mythbackend/services/channel.h deleted file mode 100644 index e091652d31d..00000000000 --- a/mythtv/programs/mythbackend/services/channel.h +++ /dev/null @@ -1,372 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: channel.h -// Created : Apr. 8, 2011 -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CHANNEL_H -#define CHANNEL_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -#include "libmythservicecontracts/services/channelServices.h" - -class Channel : public ChannelServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Channel( QObject */*parent*/ = nullptr ) {} - - public: - - /* Channel Methods */ - - DTC::ChannelInfoList* GetChannelInfoList ( uint SourceID, - uint ChannelGroupID, - uint StartIndex, - uint Count, - bool OnlyVisible, - bool Details, - bool OrderByName, - bool GroupByCallsign, - bool OnlyTunable ) override; // ChannelServices - - DTC::ChannelInfo* GetChannelInfo ( uint ChanID ) override; // ChannelServices - - bool UpdateDBChannel ( uint MplexID, - uint SourceID, - uint ChannelID, - const QString &CallSign, - const QString &ChannelName, - const QString &ChannelNumber, - uint ServiceID, - uint ATSCMajorChannel, - uint ATSCMinorChannel, - bool UseEIT, - bool Visible, - const QString &ExtendedVisible, - const QString &FrequencyID, - const QString &Icon, - const QString &Format, - const QString &XMLTVID, - const QString &DefaultAuthority, - uint ServiceType ) override; // ChannelServices - - bool AddDBChannel ( uint MplexID, - uint SourceID, - uint ChannelID, - const QString &CallSign, - const QString &ChannelName, - const QString &ChannelNumber, - uint ServiceID, - uint ATSCMajorChannel, - uint ATSCMinorChannel, - bool UseEIT, - bool Visible, - const QString &ExtendedVisible, - const QString &FrequencyID, - const QString &Icon, - const QString &Format, - const QString &XMLTVID, - const QString &DefaultAuthority, - uint ServiceType ) override; // ChannelServices - - bool RemoveDBChannel ( uint ChannelID ) override; // ChannelServices - - /* Video Source Methods */ - - DTC::VideoSourceList* GetVideoSourceList ( void ) override; // ChannelServices - - DTC::VideoSource* GetVideoSource ( uint SourceID ) override; // ChannelServices - - bool UpdateVideoSource ( uint SourceID, - const QString &SourceName, - const QString &Grabber, - const QString &UserId, - const QString &FreqTable, - const QString &LineupId, - const QString &Password, - bool UseEIT, - const QString &ConfigPath, - int NITId, - uint BouquetId, - uint RegionId, - uint ScanFrequency, - uint LCNOffset ) override; // ChannelServices - - int AddVideoSource ( const QString &SourceName, - const QString &Grabber, - const QString &UserId, - const QString &FreqTable, - const QString &LineupId, - const QString &Password, - bool UseEIT, - const QString &ConfigPath, - int NITId, - uint BouquetId, - uint RegionId, - uint ScanFrequency, - uint LCNOffset ) override; // ChannelServices - - bool RemoveVideoSource ( uint SourceID ) override; // ChannelServices - - DTC::LineupList* GetDDLineupList ( const QString &/*Source*/, - const QString &/*UserId*/, - const QString &/*Password*/ ) override; // ChannelServices - - int FetchChannelsFromSource( uint SourceId, - uint CardId, - bool WaitForFinish ) override; // ChannelServices - - /* Multiplex Methods */ - - DTC::VideoMultiplexList* GetVideoMultiplexList ( uint SourceID, - uint StartIndex, - uint Count ) override; // ChannelServices - - DTC::VideoMultiplex* GetVideoMultiplex ( uint MplexID ) override; // ChannelServices - - QStringList GetXMLTVIdList ( uint SourceID ) override; // ChannelServices - -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableChannel : public QObject -{ - Q_OBJECT - - private: - - Channel m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableChannel( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QObject* GetChannelInfoList ( int SourceID = 0, - int ChannelGroupID = 0, - int StartIndex = 0, - int Count = 0, - bool OnlyVisible = false, - bool Details = false, - bool OrderByName = false, - bool GroupByCallsign = false, - bool OnlyTunable = false - ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetChannelInfoList( SourceID, ChannelGroupID, StartIndex, Count, OnlyVisible, Details, OrderByName, GroupByCallsign, OnlyTunable ); - ) - } - - QObject* GetChannelInfo ( int ChanID ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetChannelInfo( ChanID ); - ) - } - - bool UpdateDBChannel ( uint MplexID, - uint SourceID, - uint ChannelID, - const QString &CallSign, - const QString &ChannelName, - const QString &ChannelNumber, - uint ServiceID, - uint ATSCMajorChannel, - uint ATSCMinorChannel, - bool UseEIT, - bool Visible, - const QString &ExtendedVisible, - const QString &FrequencyID, - const QString &Icon, - const QString &Format, - const QString &XMLTVID, - const QString &DefaultAuthority, - uint ServiceType ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.UpdateDBChannel(MplexID, SourceID, ChannelID, - CallSign, ChannelName, ChannelNumber, - ServiceID, ATSCMajorChannel, ATSCMinorChannel, - UseEIT, Visible, ExtendedVisible, FrequencyID, Icon, Format, - XMLTVID, DefaultAuthority, ServiceType); - ) - } - - bool AddDBChannel ( uint MplexID, - uint SourceID, - uint ChannelID, - const QString &CallSign, - const QString &ChannelName, - const QString &ChannelNumber, - uint ServiceID, - uint ATSCMajorChannel, - uint ATSCMinorChannel, - bool UseEIT, - bool Visible, - const QString &ExtendedVisible, - const QString &FrequencyID, - const QString &Icon, - const QString &Format, - const QString &XMLTVID, - const QString &DefaultAuthority, - uint ServiceType ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.AddDBChannel(MplexID, SourceID, ChannelID, - CallSign, ChannelName, ChannelNumber, - ServiceID, ATSCMajorChannel, ATSCMinorChannel, - UseEIT, Visible, ExtendedVisible, FrequencyID, Icon, Format, - XMLTVID, DefaultAuthority, ServiceType); - ) - } - - bool RemoveDBChannel ( uint ChannelID ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveDBChannel(ChannelID); - ) - } - - QObject* GetVideoSourceList ( void ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetVideoSourceList(); - ) - } - - QObject* GetVideoSource ( uint SourceID ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetVideoSource( SourceID ); - ) - } - - bool UpdateVideoSource ( uint SourceID, - const QString &SourceName, - const QString &Grabber, - const QString &UserId, - const QString &FreqTable, - const QString &LineupId, - const QString &Password, - bool UseEIT, - const QString &ConfigPath, - int NITId, - uint BouquetId, - uint RegionId, - uint ScanFrequency, - uint LCNOffset ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.UpdateVideoSource( SourceID, SourceName, Grabber, - UserId, FreqTable, LineupId, Password, - UseEIT, ConfigPath, NITId, BouquetId, RegionId, - ScanFrequency, LCNOffset ); - ) - } - - bool AddVideoSource ( const QString &SourceName, - const QString &Grabber, - const QString &UserId, - const QString &FreqTable, - const QString &LineupId, - const QString &Password, - bool UseEIT, - const QString &ConfigPath, - int NITId, - uint BouquetId, - uint RegionId, - uint ScanFrequency, - uint LCNOffset ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.AddVideoSource( SourceName, Grabber, UserId, - FreqTable, LineupId, Password, - UseEIT, ConfigPath, NITId, BouquetId, RegionId, - ScanFrequency, LCNOffset ); - ) - } - - bool RemoveVideoSource ( uint SourceID ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveVideoSource( SourceID ); - ) - } - - QObject* GetVideoMultiplexList ( int SourceID, - int StartIndex, - int Count ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetVideoMultiplexList( SourceID, StartIndex, Count ); - ) - } - - QObject* GetVideoMultiplex ( int MplexID ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetVideoMultiplex( MplexID ); - ) - } - - QStringList GetXMLTVIdList ( int SourceID ) - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetXMLTVIdList(SourceID); - ) - } -}; - - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableChannel, QObject*); -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/channelicon.cpp b/mythtv/programs/mythbackend/services/channelicon.cpp deleted file mode 100644 index 50de4ea57b1..00000000000 --- a/mythtv/programs/mythbackend/services/channelicon.cpp +++ /dev/null @@ -1,132 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: channelicon.cpp -// Created : Jun. 22, 2014 -// -// Copyright (c) 2014 The MythTV Developers -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// Qt -#include - -// MythTV -#include "libmythbase/compat.h" -#include "libmythbase/mythdownloadmanager.h" - -// MythBackend -#include "channelicon.h" -#include "serviceUtil.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ChannelIconList* ChannelIcon::LookupChannelIcon ( const QString &Query, - const QString &FieldName ) -{ - DTC::ChannelIconList *pChannelIcons = new DTC::ChannelIconList(); - LOG(VB_GENERAL, LOG_ERR, - QString("ChannelIcon::LookupChannelIcon - Unexpected FieldName '%1'").arg(FieldName)); - // check the FieldName is valid - if (FieldName != "callsign" || FieldName != "xmltv") - { - //throw( QString("FieldName appears invalid.")); - return pChannelIcons; - } - - // query http://services.mythtv.org/channel-icon/lookup - QByteArray data; - QString lookupUrl = QString("http://services.mythtv.org/channel-icon/lookup?%1=%2").arg(FieldName).arg(Query); - if (!GetMythDownloadManager()->download(lookupUrl, &data)) - { - //throw( QString("Download from services.mythtv.org failed.")); - return pChannelIcons; - } - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - QString response = QString(data.constData()); - QStringList lines = response.split('\n'); - - for (int x = 0; x < lines.count(); x++) - { - QString line = lines.at(x); - QStringList fields = line.split(','); - - if (fields.size() >= 4) - { - QString id = fields.at(2); - QString name = fields.at(3); - QString url = fields.at(1); - - DTC::ChannelIcon *pChannelIcon = pChannelIcons->AddNewChannelIcon(); - pChannelIcon->setChannelIconId(id.toUInt()); - pChannelIcon->setIconName(name); - pChannelIcon->setURL(url); - } - } - - return pChannelIcons; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - - -DTC::ChannelIconList* ChannelIcon::SearchChannelIcon ( const QString &Query ) -{ - DTC::ChannelIconList *pChannelIcons = new DTC::ChannelIconList(); - - // query http://services.mythtv.org/channel-icon/search - QByteArray data; - QString searchUrl = QString("http://services.mythtv.org/channel-icon/search?s=%1").arg(Query); - if (!GetMythDownloadManager()->download(searchUrl, &data)) - return pChannelIcons; - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - QString response = QString(data.constData()); - QStringList lines = response.split('\n'); - - for (int x = 0; x < lines.count(); x++) - { - QString line = lines.at(x); - QStringList fields = line.split(','); - - if (fields.size() >= 3) - { - QString id = fields.at(0); - QString name = fields.at(1); - QString url = fields.at(2); - - DTC::ChannelIcon *pChannelIcon = pChannelIcons->AddNewChannelIcon(); - pChannelIcon->setChannelIconId(id.toUInt()); - pChannelIcon->setIconName(name); - pChannelIcon->setURL(url); - } - } - - return pChannelIcons; -} diff --git a/mythtv/programs/mythbackend/services/channelicon.h b/mythtv/programs/mythbackend/services/channelicon.h deleted file mode 100644 index fe073d20420..00000000000 --- a/mythtv/programs/mythbackend/services/channelicon.h +++ /dev/null @@ -1,101 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: channelicon.h -// Created : Jun. 22, 2014 -// -// Copyright (c) 2014 The MythTV Team -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CHANNELICON_H -#define CHANNELICON_H - -#include "mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -#include "services/channelIconServices.h" - -class ChannelIcon : public ChannelIconServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit ChannelIcon( QObject *parent = nullptr ) {} - - public: - - /* ChannelIcon Methods */ - - DTC::ChannelIconList* LookupChannelIcon ( const QString &Query, - const QString &FieldName ); - - DTC::ChannelIconList* SearchChannelIcon ( const QString &Query ); - -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableChannelIcon : public QObject -{ - Q_OBJECT - - private: - - ChannelIcon m_obj; - - public: - - Q_INVOKABLE explicit ScriptableChannelIcon( QObject *parent = nullptr ) : QObject( parent ) {} - - public slots: - - QObject* LookupChannelIcon ( const QString &Query, - const QString &FieldName ) - { - return m_obj.LookupChannelIcon( Query, FieldName ); - } - - QObject* SearchChannelIcon ( const QString &Query ) - { - return m_obj.SearchChannelIcon( Query ); - } -}; - - -Q_SCRIPT_DECLARE_QMETAOBJECT( ScriptableChannelIcon, QObject*); -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/content.cpp b/mythtv/programs/mythbackend/services/content.cpp deleted file mode 100644 index 18ce65ca095..00000000000 --- a/mythtv/programs/mythbackend/services/content.cpp +++ /dev/null @@ -1,1143 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: content.cpp -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// C++ -#include - -// Qt -#include -#include -#include - -// MythTV -#include "libmythbase/compat.h" -#include "libmythbase/mythcorecontext.h" -#include "libmythbase/mythdate.h" -#include "libmythbase/mythdownloadmanager.h" -#include "libmythbase/mythmiscutil.h" -#include "libmythbase/programinfo.h" -#include "libmythbase/remotefile.h" -#include "libmythbase/storagegroup.h" -#include "libmythmetadata/musicmetadata.h" -#include "libmythmetadata/videometadatalistmanager.h" -#include "libmythprotoserver/requesthandler/fileserverutil.h" -#include "libmythtv/HLS/httplivestream.h" -#include "libmythtv/metadataimagehelper.h" -#include "libmythtv/previewgenerator.h" -#include "libmythupnp/httprequest.h" - -// MythBackend -#include "content.h" -#include "serviceUtil.h" - -// Qt6 has made the QFileInfo::QFileInfo(QString) constructor -// explicit, which means that it is no longer possible to use an -// initializer list to construct a QFileInfo. Disable that clang-tidy -// check for this file so it can still be run on the rest of the file -// in the project. -// -// NOLINTBEGIN(modernize-return-braced-init-list) - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetFile( const QString &sStorageGroup, - const QString &sFileName ) -{ - QString sGroup = sStorageGroup; - - if (sGroup.isEmpty()) - { - LOG(VB_UPNP, LOG_WARNING, - "GetFile - StorageGroup missing... using 'Default'"); - sGroup = "Default"; - } - - if (sFileName.isEmpty()) - { - QString sMsg ( "GetFile - FileName missing." ); - - //LOG(VB_UPNP, LOG_ERR, sMsg); - - throw QString(sMsg); - } - - // ------------------------------------------------------------------ - // Search for the filename - // ------------------------------------------------------------------ - - StorageGroup storage( sGroup ); - QString sFullFileName = storage.FindFile( sFileName ); - - if (sFullFileName.isEmpty()) - { - LOG(VB_UPNP, LOG_ERR, - QString("GetFile - Unable to find %1.").arg(sFileName)); - - return {}; - } - - // ---------------------------------------------------------------------- - // check to see if the file (still) exists - // ---------------------------------------------------------------------- - - if (QFile::exists( sFullFileName )) - { - return QFileInfo( sFullFileName ); - } - - LOG(VB_UPNP, LOG_ERR, - QString("GetFile - File Does not exist %1.").arg(sFullFileName)); - - return {}; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetImageFile( const QString &sStorageGroup, - const QString &sFileName, - int nWidth, - int nHeight) -{ - QString sGroup = sStorageGroup; - - if (sGroup.isEmpty()) - { - LOG(VB_UPNP, LOG_WARNING, - "GetImageFile - StorageGroup missing... using 'Default'"); - sGroup = "Default"; - } - - if (sFileName.isEmpty()) - { - QString sMsg ( "GetImageFile - FileName missing." ); - - //LOG(VB_UPNP, LOG_WARNING, sMsg); - - throw QString(sMsg); - } - - // ------------------------------------------------------------------ - // Search for the filename - // ------------------------------------------------------------------ - - StorageGroup storage( sGroup ); - QString sFullFileName = storage.FindFile( sFileName ); - - if (sFullFileName.isEmpty()) - { - LOG(VB_UPNP, LOG_WARNING, - QString("GetImageFile - Unable to find %1.").arg(sFileName)); - - return {}; - } - - // ---------------------------------------------------------------------- - // check to see if the file (still) exists - // ---------------------------------------------------------------------- - - if (!QFile::exists( sFullFileName )) - { - LOG(VB_UPNP, LOG_WARNING, - QString("GetImageFile - File Does not exist %1.").arg(sFullFileName)); - return {}; - } - - // ---------------------------------------------------------------------- - // If no scaling is required return the file info - // ---------------------------------------------------------------------- - if ((nWidth == 0) && (nHeight == 0)) - return QFileInfo( sFullFileName ); - - // ---------------------------------------------------------------------- - // Create a filename for the scaled copy - // ---------------------------------------------------------------------- - QString sNewFileName = QString( "%1.%2x%3.jpg" ) - .arg( sFullFileName ) - .arg( nWidth ) - .arg( nHeight ); - - // ---------------------------------------------------------------------- - // check to see if image is already created. - // ---------------------------------------------------------------------- - - if (QFile::exists( sNewFileName )) - return QFileInfo( sNewFileName ); - - // ---------------------------------------------------------------------- - // Must generate Generate Image and save. - // ---------------------------------------------------------------------- - - auto *pImage = new QImage( sFullFileName ); - - if (!pImage || pImage->isNull()) - return {}; - - float fAspect = (float)(pImage->width()) / pImage->height(); - - if ( nWidth == 0 ) - nWidth = (int)rint(nHeight * fAspect); - - if ( nHeight == 0 ) - nHeight = (int)rint(nWidth / fAspect); - - QImage img = pImage->scaled( nWidth, nHeight, Qt::KeepAspectRatio, - Qt::SmoothTransformation); - - QByteArray fname = sNewFileName.toLatin1(); - img.save( fname.constData(), "JPG", 60 ); - - delete pImage; - - return QFileInfo( sNewFileName ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Content::GetDirList( const QString &sStorageGroup ) -{ - - if (sStorageGroup.isEmpty()) - { - QString sMsg( "GetDirList - StorageGroup missing."); - LOG(VB_UPNP, LOG_ERR, sMsg); - - throw QString(sMsg); - } - - StorageGroup sgroup(sStorageGroup); - - return sgroup.GetDirList("", true); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Content::GetFileList( const QString &sStorageGroup ) -{ - - if (sStorageGroup.isEmpty()) - { - QString sMsg( "GetFileList - StorageGroup missing."); - LOG(VB_UPNP, LOG_ERR, sMsg); - - throw QString(sMsg); - } - - StorageGroup sgroup(sStorageGroup); - - return sgroup.GetFileList("", true); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetRecordingArtwork ( const QString &sType, - const QString &sInetref, - int nSeason, - int nWidth, - int nHeight) -{ - ArtworkMap map = GetArtwork(sInetref, nSeason); - - if (map.isEmpty()) - return {}; - - VideoArtworkType type = kArtworkCoverart; - QString sgroup; - - if (sType.toLower() == "coverart") - { - sgroup = "Coverart"; - type = kArtworkCoverart; - } - else if (sType.toLower() == "fanart") - { - sgroup = "Fanart"; - type = kArtworkFanart; - } - else if (sType.toLower() == "banner") - { - sgroup = "Banners"; - type = kArtworkBanner; - } - - if (!map.contains(type)) - return {}; - - QUrl url(map.value(type).url); - QString sFileName = url.path(); - - if (sFileName.isEmpty()) - return {}; - - return GetImageFile( sgroup, sFileName, nWidth, nHeight); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ArtworkInfoList* Content::GetRecordingArtworkList( int RecordedId, - int chanid, - const QDateTime &recstarttsRaw) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - // TODO Should use RecordingInfo - ProgramInfo pginfo; - if (RecordedId > 0) - pginfo = ProgramInfo(RecordedId); - else - pginfo = ProgramInfo(chanid, recstarttsRaw.toUTC()); - - return GetProgramArtworkList(pginfo.GetInetRef(), pginfo.GetSeason()); -} - -DTC::ArtworkInfoList* Content::GetProgramArtworkList( const QString &sInetref, - int nSeason ) -{ - auto *pArtwork = new DTC::ArtworkInfoList(); - - FillArtworkInfoList (pArtwork, sInetref, nSeason); - - return pArtwork; -} -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -// NOTE: If you rename this, you must also update upnpcdsvideo.cpp -QFileInfo Content::GetVideoArtwork( const QString &sType, - int nId, int nWidth, int nHeight ) -{ - LOG(VB_UPNP, LOG_INFO, QString("GetVideoArtwork ID = %1").arg(nId)); - - QString sgroup = "Coverart"; - QString column = "coverfile"; - - if (sType.toLower() == "coverart") - { - sgroup = "Coverart"; - column = "coverfile"; - } - else if (sType.toLower() == "fanart") - { - sgroup = "Fanart"; - column = "fanart"; - } - else if (sType.toLower() == "banner") - { - sgroup = "Banners"; - column = "banner"; - } - else if (sType.toLower() == "screenshot") - { - sgroup = "Screenshots"; - column = "screenshot"; - } - - // ---------------------------------------------------------------------- - // Read Video artwork file path from database - // ---------------------------------------------------------------------- - - MSqlQuery query(MSqlQuery::InitCon()); - - QString querystr = QString("SELECT %1 FROM videometadata WHERE " - "intid = :ITEMID").arg(column); - - query.prepare(querystr); - query.bindValue(":ITEMID", nId); - - if (!query.exec()) - MythDB::DBError("GetVideoArtwork ", query); - - if (!query.next()) - return {}; - - QString sFileName = query.value(0).toString(); - - if (sFileName.isEmpty()) - return {}; - - return GetImageFile( sgroup, sFileName, nWidth, nHeight ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetAlbumArt( int nTrackId, int nWidth, int nHeight ) -{ - // ---------------------------------------------------------------------- - // Read AlbumArt file path from database - // ---------------------------------------------------------------------- - - MusicMetadata *metadata = MusicMetadata::createFromID(nTrackId); - - if (!metadata) - return {}; - - QString sFullFileName = metadata->getAlbumArtFile(); - LOG(VB_GENERAL, LOG_DEBUG, QString("GetAlbumArt: %1").arg(sFullFileName)); - - delete metadata; - - if (!RemoteFile::Exists(sFullFileName)) - return {}; - - QString sNewFileName = QString( "/tmp/%1.%2x%3.jpg" ) - .arg( QFileInfo(sFullFileName).fileName() ) - .arg( nWidth ) - .arg( nHeight ); - - // ---------------------------------------------------------------------- - // check to see if albumart image is already created. - // ---------------------------------------------------------------------- - - if (QFile::exists( sNewFileName )) - return QFileInfo( sNewFileName ); - - // ---------------------------------------------------------------------- - // Must generate Albumart Image, Generate Image and save. - // ---------------------------------------------------------------------- - - - QImage img; - if (sFullFileName.startsWith("myth://")) - { - RemoteFile rf(sFullFileName, false, false, 0s); - QByteArray data; - rf.SaveAs(data); - - img.loadFromData(data); - } - else - { - img.load(sFullFileName); - } - - if (img.isNull()) - return {}; - - // We don't need to scale if no height and width were specified - // but still need to save as jpg if it's in another format - if ((nWidth == 0) && (nHeight == 0)) - { - if (!sFullFileName.startsWith("myth://")) - { - QFileInfo fi(sFullFileName); - if (fi.suffix().toLower() == "jpg") - return fi; - } - } - else if (nWidth > img.width() && nHeight > img.height()) - { - // Requested dimensions are larger than the source image, so instead of - // scaling up which will produce horrible results return the fullsize - // image and the user can scale further if they want instead - // NOTE: If this behaviour is changed, for example making it optional, - // then upnp code will need changing to compensate - } - else - { - float fAspect = (float)(img.width()) / img.height(); - - if ( nWidth == 0 || nWidth > img.width() ) - nWidth = (int)rint(nHeight * fAspect); - - if ( nHeight == 0 || nHeight > img.height() ) - nHeight = (int)rint(nWidth / fAspect); - - img = img.scaled( nWidth, nHeight, Qt::KeepAspectRatio, - Qt::SmoothTransformation); - } - - QString fname = sNewFileName.toLatin1().constData(); - // Use JPG not PNG for compatibility with the most uPnP devices and - // faster loading (smaller file to send over network) - if (!img.save( fname, "JPG" )) - return {}; - - return QFileInfo( sNewFileName ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetPreviewImage( int nRecordedId, - int nChanId, - const QDateTime &recstarttsRaw, - int nWidth, - int nHeight, - int nSecsIn, - const QString &sFormat ) -{ - if ((nRecordedId <= 0) && - (nChanId <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - if (!sFormat.isEmpty() - && !QImageWriter::supportedImageFormats().contains(sFormat.toLower().toLocal8Bit())) - { - throw QString("GetPreviewImage: Specified 'Format' is not supported."); - } - - // ---------------------------------------------------------------------- - // Read Recording From Database - // ---------------------------------------------------------------------- - - // TODO Should use RecordingInfo - ProgramInfo pginfo; - if (nRecordedId > 0) - pginfo = ProgramInfo(nRecordedId); - else - pginfo = ProgramInfo(nChanId, recstarttsRaw.toUTC()); - - if (!pginfo.GetChanID()) - { - LOG(VB_GENERAL, LOG_ERR, - QString("GetPreviewImage: No recording for '%1'") - .arg(nRecordedId)); - return {}; - } - - if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower() - && ! gCoreContext->GetBoolSetting("MasterBackendOverride", false)) - { - QString sMsg = - QString("GetPreviewImage: Wrong Host '%1' request from '%2'") - .arg( gCoreContext->GetHostName(), - pginfo.GetHostname() ); - - LOG(VB_UPNP, LOG_ERR, sMsg); - - throw HttpRedirectException( pginfo.GetHostname() ); - } - - QString sImageFormat = sFormat; - if (sImageFormat.isEmpty()) - sImageFormat = "PNG"; - - QString sFileName = GetPlaybackURL(&pginfo); - - // ---------------------------------------------------------------------- - // check to see if default preview image is already created. - // ---------------------------------------------------------------------- - - QString sPreviewFileName; - - auto nSecs = std::chrono::seconds(nSecsIn); - if (nSecs <= 0s) - { - nSecs = -1s; - sPreviewFileName = QString("%1.png").arg(sFileName); - } - else - { - sPreviewFileName = QString("%1.%2.png").arg(sFileName).arg(nSecsIn); - } - - if (!QFile::exists( sPreviewFileName )) - { - // ------------------------------------------------------------------ - // Must generate Preview Image, Generate Image and save. - // ------------------------------------------------------------------ - if (!pginfo.IsLocal() && sFileName.startsWith("/")) - pginfo.SetPathname(sFileName); - - if (!pginfo.IsLocal()) - return {}; - - auto *previewgen = new PreviewGenerator( &pginfo, QString(), - PreviewGenerator::kLocal); - previewgen->SetPreviewTimeAsSeconds( nSecs ); - previewgen->SetOutputFilename ( sPreviewFileName ); - - bool ok = previewgen->Run(); - - previewgen->deleteLater(); - - if (!ok) - return {}; - } - - bool bDefaultPixmap = (nWidth == 0) && (nHeight == 0); - - QString sNewFileName; - - if (bDefaultPixmap) - sNewFileName = sPreviewFileName; - else - { - sNewFileName = QString( "%1.%2.%3x%4.%5" ) - .arg( sFileName ) - .arg( nSecsIn ) - .arg( nWidth == 0 ? -1 : nWidth ) - .arg( nHeight == 0 ? -1 : nHeight ) - .arg( sImageFormat.toLower() ); - - // ---------------------------------------------------------------------- - // check to see if scaled preview image is already created and isn't - // out of date - // ---------------------------------------------------------------------- - if (QFile::exists( sNewFileName )) - { - if (QFileInfo(sPreviewFileName).lastModified() <= - QFileInfo(sNewFileName).lastModified()) - return QFileInfo( sNewFileName ); - } - - QImage image = QImage(sPreviewFileName); - - if (image.isNull()) - return {}; - - // We can just re-scale the default (full-size version) to avoid - // a preview generator run - if ( nWidth <= 0 ) - image = image.scaledToHeight(nHeight, Qt::SmoothTransformation); - else if ( nHeight <= 0 ) - image = image.scaledToWidth(nWidth, Qt::SmoothTransformation); - else - image = image.scaled(nWidth, nHeight, Qt::IgnoreAspectRatio, - Qt::SmoothTransformation); - - image.save(sNewFileName, sImageFormat.toUpper().toLocal8Bit()); - - // Let anybody update it - bool ret = makeFileAccessible(sNewFileName.toLocal8Bit().constData()); - if (!ret) - { - LOG(VB_GENERAL, LOG_ERR, "Unable to change permissions on " - "preview image. Backends and frontends " - "running under different users will be " - "unable to access it"); - } - } - - if (QFile::exists( sNewFileName )) - return QFileInfo( sNewFileName ); - - auto *previewgen = new PreviewGenerator( &pginfo, QString(), - PreviewGenerator::kLocal); - previewgen->SetPreviewTimeAsSeconds( nSecs ); - previewgen->SetOutputFilename ( sNewFileName ); - previewgen->SetOutputSize (QSize(nWidth,nHeight)); - - bool ok = previewgen->Run(); - - previewgen->deleteLater(); - - if (!ok) - return {}; - - return QFileInfo( sNewFileName ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetRecording( int nRecordedId, - int nChanId, - const QDateTime &recstarttsRaw ) -{ - if ((nRecordedId <= 0) && - (nChanId <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - // ------------------------------------------------------------------ - // Read Recording From Database - // ------------------------------------------------------------------ - - // TODO Should use RecordingInfo - ProgramInfo pginfo; - if (nRecordedId > 0) - pginfo = ProgramInfo(nRecordedId); - else - pginfo = ProgramInfo(nChanId, recstarttsRaw.toUTC()); - - if (!pginfo.GetChanID()) - { - LOG(VB_UPNP, LOG_ERR, QString("GetRecording - for '%1' failed") - .arg(nRecordedId)); - - return {}; - } - - if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower() - && ! gCoreContext->GetBoolSetting("MasterBackendOverride", false)) - { - // We only handle requests for local resources - - QString sMsg = - QString("GetRecording: Wrong Host '%1' request from '%2'.") - .arg( gCoreContext->GetHostName(), - pginfo.GetHostname() ); - - LOG(VB_UPNP, LOG_ERR, sMsg); - - throw HttpRedirectException( pginfo.GetHostname() ); - } - - QString sFileName( GetPlaybackURL(&pginfo) ); - - // ---------------------------------------------------------------------- - // check to see if the file exists - // ---------------------------------------------------------------------- - - if (QFile::exists( sFileName )) - return QFileInfo( sFileName ); - - return {}; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetMusic( int nId ) -{ - QString sFileName; - - // ---------------------------------------------------------------------- - // Load Track's FileName - // ---------------------------------------------------------------------- - - MSqlQuery query(MSqlQuery::InitCon()); - - if (query.isConnected()) - { - query.prepare("SELECT CONCAT_WS('/', music_directories.path, " - "music_songs.filename) AS filename FROM music_songs " - "LEFT JOIN music_directories ON " - "music_songs.directory_id=" - "music_directories.directory_id " - "WHERE music_songs.song_id = :KEY"); - - query.bindValue(":KEY", nId ); - - if (!query.exec()) - { - MythDB::DBError("GetMusic()", query); - return {}; - } - - if (query.next()) - { - sFileName = query.value(0).toString(); - } - } - - if (sFileName.isEmpty()) - return {}; - - return GetFile( "Music", sFileName ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Content::GetVideo( int nId ) -{ - QString sFileName; - - // ---------------------------------------------------------------------- - // Load Track's FileName - // ---------------------------------------------------------------------- - - MSqlQuery query(MSqlQuery::InitCon()); - - if (query.isConnected()) - { - query.prepare("SELECT filename FROM videometadata WHERE intid = :KEY" ); - query.bindValue(":KEY", nId ); - - if (!query.exec()) - { - MythDB::DBError("GetVideo()", query); - return {}; - } - - if (query.next()) - sFileName = query.value(0).toString(); - } - - if (sFileName.isEmpty()) - return {}; - - if (!QFile::exists( sFileName )) - return GetFile( "Videos", sFileName ); - - return QFileInfo( sFileName ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Content::GetHash( const QString &sStorageGroup, - const QString &sFileName ) -{ - if ((sFileName.isEmpty()) || - (sFileName.contains("/../")) || - (sFileName.startsWith("../"))) - { - LOG(VB_GENERAL, LOG_ERR, - QString("ERROR checking for file, filename '%1' " - "fails sanity checks").arg(sFileName)); - return {}; - } - - QString storageGroup = "Default"; - - if (!sStorageGroup.isEmpty()) - storageGroup = sStorageGroup; - - StorageGroup sgroup(storageGroup, gCoreContext->GetHostName()); - - QString fullname = sgroup.FindFile(sFileName); - QString hash = FileHash(fullname); - - if (hash == "NULL") - return {}; - - return hash; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Content::DownloadFile( const QString &sURL, const QString &sStorageGroup ) -{ - QFileInfo finfo(sURL); - QString filename = finfo.fileName(); - StorageGroup sgroup(sStorageGroup, gCoreContext->GetHostName(), false); - QString outDir = sgroup.FindNextDirMostFree(); - QString outFile; - - if (outDir.isEmpty()) - { - LOG(VB_GENERAL, LOG_ERR, - QString("Unable to determine directory " - "to write to in %1 write command").arg(sURL)); - return false; - } - - if ((filename.contains("/../")) || - (filename.startsWith("../"))) - { - LOG(VB_GENERAL, LOG_ERR, - QString("ERROR: %1 write filename '%2' does not " - "pass sanity checks.").arg(sURL, filename)); - return false; - } - - outFile = outDir + "/" + filename; - - return GetMythDownloadManager()->download(sURL, outFile); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LiveStreamInfo *Content::AddLiveStream( const QString &sStorageGroup, - const QString &sFileName, - const QString &sHostName, - int nMaxSegments, - int nWidth, - int nHeight, - int nBitrate, - int nAudioBitrate, - int nSampleRate ) -{ - QString sGroup = sStorageGroup; - - if (sGroup.isEmpty()) - { - LOG(VB_UPNP, LOG_WARNING, - "AddLiveStream - StorageGroup missing... using 'Default'"); - sGroup = "Default"; - } - - if (sFileName.isEmpty()) - { - QString sMsg ( "AddLiveStream - FileName missing." ); - - LOG(VB_UPNP, LOG_ERR, sMsg); - - throw QString(sMsg); - } - - // ------------------------------------------------------------------ - // Search for the filename - // ------------------------------------------------------------------ - - QString sFullFileName; - if (sHostName.isEmpty() || sHostName == gCoreContext->GetHostName()) - { - StorageGroup storage( sGroup ); - sFullFileName = storage.FindFile( sFileName ); - - if (sFullFileName.isEmpty()) - { - LOG(VB_UPNP, LOG_ERR, - QString("AddLiveStream - Unable to find %1.").arg(sFileName)); - - return nullptr; - } - } - else - { - sFullFileName = - MythCoreContext::GenMythURL(sHostName, 0, sFileName, sStorageGroup); - } - - auto *hls = new HTTPLiveStream(sFullFileName, nWidth, nHeight, nBitrate, - nAudioBitrate, nMaxSegments, 0, 0, nSampleRate); - - if (!hls) - { - LOG(VB_UPNP, LOG_ERR, - "AddLiveStream - Unable to create HTTPLiveStream."); - return nullptr; - } - - DTC::LiveStreamInfo *lsInfo = hls->StartStream(); - - delete hls; - - return lsInfo; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Content::RemoveLiveStream( int nId ) -{ - return HTTPLiveStream::RemoveStream(nId); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LiveStreamInfo *Content::StopLiveStream( int nId ) -{ - return HTTPLiveStream::StopStream(nId); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LiveStreamInfo *Content::GetLiveStream( int nId ) -{ - auto *hls = new HTTPLiveStream(nId); - - if (!hls) - { - LOG( VB_UPNP, LOG_ERR, - QString("GetLiveStream - for stream id %1 failed").arg( nId )); - return nullptr; - } - - DTC::LiveStreamInfo *hlsInfo = hls->GetLiveStreamInfo(); - if (!hlsInfo) - { - LOG( VB_UPNP, LOG_ERR, - QString("HLS::GetLiveStreamInfo - for stream id %1 failed") - .arg( nId )); - return nullptr; - } - - delete hls; - return hlsInfo; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LiveStreamInfoList *Content::GetLiveStreamList( const QString &FileName ) -{ - return HTTPLiveStream::GetLiveStreamInfoList(FileName); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LiveStreamInfo *Content::AddRecordingLiveStream( - int nRecordedId, - int nChanId, - const QDateTime &recstarttsRaw, - int nMaxSegments, - int nWidth, - int nHeight, - int nBitrate, - int nAudioBitrate, - int nSampleRate ) -{ - if ((nRecordedId <= 0) && - (nChanId <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - // ------------------------------------------------------------------ - // Read Recording From Database - // ------------------------------------------------------------------ - - // TODO Should use RecordingInfo - ProgramInfo pginfo; - if (nRecordedId > 0) - pginfo = ProgramInfo(nRecordedId); - else - pginfo = ProgramInfo(nChanId, recstarttsRaw.toUTC()); - - if (!pginfo.GetChanID()) - { - LOG(VB_UPNP, LOG_ERR, - QString("AddRecordingLiveStream - for %1, %2 failed") - .arg(QString::number(nRecordedId))); - return nullptr; - } - - bool masterBackendOverride = gCoreContext->GetBoolSetting("MasterBackendOverride", false); - - if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower() - && ! masterBackendOverride) - { - // We only handle requests for local resources - - QString sMsg = - QString("GetRecording: Wrong Host '%1' request from '%2'.") - .arg( gCoreContext->GetHostName(), - pginfo.GetHostname() ); - - LOG(VB_UPNP, LOG_ERR, sMsg); - - throw HttpRedirectException( pginfo.GetHostname() ); - } - - QString sFileName( GetPlaybackURL(&pginfo) ); - - // ---------------------------------------------------------------------- - // check to see if the file exists - // ---------------------------------------------------------------------- - - if (!QFile::exists( sFileName )) - { - LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed") - .arg( nChanId ) - .arg( recstarttsRaw.toUTC().toString() )); - return nullptr; - } - - QFileInfo fInfo( sFileName ); - - QString hostName; - if (masterBackendOverride) - hostName = gCoreContext->GetHostName(); - else - hostName = pginfo.GetHostname(); - - return AddLiveStream( pginfo.GetStorageGroup(), fInfo.fileName(), - hostName, nMaxSegments, nWidth, - nHeight, nBitrate, nAudioBitrate, nSampleRate ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LiveStreamInfo *Content::AddVideoLiveStream( int nId, - int nMaxSegments, - int nWidth, - int nHeight, - int nBitrate, - int nAudioBitrate, - int nSampleRate ) -{ - if (nId < 0) - throw QString( "Id is invalid" ); - - VideoMetadataListManager::VideoMetadataPtr metadata = - VideoMetadataListManager::loadOneFromDatabase(nId); - - if (!metadata) - { - LOG( VB_UPNP, LOG_ERR, QString("AddVideoLiveStream - no metadata for %1") - .arg( nId )); - return nullptr; - } - - if ( metadata->GetHost().toLower() != gCoreContext->GetHostName().toLower()) - { - // We only handle requests for local resources - - QString sMsg = - QString("AddVideoLiveStream: Wrong Host '%1' request from '%2'.") - .arg( gCoreContext->GetHostName(), - metadata->GetHost() ); - - LOG(VB_UPNP, LOG_ERR, sMsg); - - throw HttpRedirectException( metadata->GetHost() ); - } - - StorageGroup sg("Videos", metadata->GetHost()); - QString sFileName = sg.FindFile(metadata->GetFilename()); - - // ---------------------------------------------------------------------- - // check to see if the file exists - // ---------------------------------------------------------------------- - - if (!QFile::exists( sFileName )) - { - LOG( VB_UPNP, LOG_ERR, QString("AddVideoLiveStream - file does not exist.")); - return nullptr; - } - - return AddLiveStream( "Videos", metadata->GetFilename(), - metadata->GetHost(), nMaxSegments, nWidth, - nHeight, nBitrate, nAudioBitrate, nSampleRate ); -} - -// NOLINTEND(modernize-return-braced-init-list) diff --git a/mythtv/programs/mythbackend/services/content.h b/mythtv/programs/mythbackend/services/content.h deleted file mode 100644 index 2a1441e8a2a..00000000000 --- a/mythtv/programs/mythbackend/services/content.h +++ /dev/null @@ -1,271 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: content.h -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef CONTENT_H -#define CONTENT_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -#include "libmythservicecontracts/services/contentServices.h" - -class Content : public ContentServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Content( QObject */*parent*/ = nullptr ) {} - - public: - - QFileInfo GetFile ( const QString &StorageGroup, - const QString &FileName ) override; // ContentServices - - QFileInfo GetImageFile ( const QString &StorageGroup, - const QString &FileName, - int Width, int Height ) override; // ContentServices - - QStringList GetFileList ( const QString &StorageGroup ) override; // ContentServices - - QStringList GetDirList ( const QString &StorageGroup ) override; // ContentServices - - QFileInfo GetRecordingArtwork ( const QString &Type, - const QString &Inetref, - int Season, int Width, - int Height) override; // ContentServices - - DTC::ArtworkInfoList* - GetRecordingArtworkList( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw ) override; // ContentServices - - DTC::ArtworkInfoList* - GetProgramArtworkList( const QString &Inetref, - int Season ) override; // ContentServices - - QFileInfo GetVideoArtwork ( const QString &Type, - int Id, int Width, int Height ) override; // ContentServices - - QFileInfo GetAlbumArt ( int Id, int Width, int Height ) override; // ContentServices - - QFileInfo GetPreviewImage ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - int Width, - int Height, - int SecsIn, - const QString &Format) override; // ContentServices - - QFileInfo GetRecording ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw ) override; // ContentServices - - QFileInfo GetMusic ( int Id ) override; // ContentServices - QFileInfo GetVideo ( int Id ) override; // ContentServices - - QString GetHash ( const QString &StorageGroup, - const QString &FileName ) override; // ContentServices - - bool DownloadFile ( const QString &URL, - const QString &StorageGroup ) override; // ContentServices - - // HTTP Live Streaming - DTC::LiveStreamInfo *AddLiveStream ( const QString &StorageGroup, - const QString &FileName, - const QString &HostName, - int MaxSegments, - int Width, - int Height, - int Bitrate, - int AudioBitrate, - int SampleRate ) override; // ContentServices - - DTC::LiveStreamInfo *AddRecordingLiveStream ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - int MaxSegments, - int Width, - int Height, - int Bitrate, - int AudioBitrate, - int SampleRate ) override; // ContentServices - - DTC::LiveStreamInfo *AddVideoLiveStream ( int Id, - int MaxSegments, - int Width, - int Height, - int Bitrate, - int AudioBitrate, - int SampleRate ) override; // ContentServices - - DTC::LiveStreamInfo *GetLiveStream ( int Id ) override; // ContentServices - DTC::LiveStreamInfoList *GetLiveStreamList ( const QString &FileName ) override; // ContentServices - - DTC::LiveStreamInfo *StopLiveStream ( int Id ) override; // ContentServices - bool RemoveLiveStream ( int Id ) override; // ContentServices -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableContent : public QObject -{ - Q_OBJECT - - private: - - Content m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableContent( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QObject* GetRecordingArtworkList( int RecordedId ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetRecordingArtworkList( RecordedId, 0, QDateTime() ); - ) - } - - QObject* GetProgramArtworkList( const QString &Inetref, - int Season ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetProgramArtworkList( Inetref, Season ); - ) - } - - QString GetHash ( const QString &StorageGroup, - const QString &FileName ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.GetHash( StorageGroup, FileName ); - ) - } - - // HTTP Live Streaming - QObject* AddLiveStream ( const QString &StorageGroup, - const QString &FileName, - const QString &HostName, - int MaxSegments, - int Width, - int Height, - int Bitrate, - int AudioBitrate, - int SampleRate ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.AddLiveStream(StorageGroup, FileName, HostName, - MaxSegments, Width, Height, Bitrate, - AudioBitrate, SampleRate); - ) - } - - QObject* AddRecordingLiveStream (int RecordedId, - int MaxSegments, - int Width, - int Height, - int Bitrate, - int AudioBitrate, - int SampleRate ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.AddRecordingLiveStream(RecordedId, 0, QDateTime(), - MaxSegments, - Width, Height, Bitrate, - AudioBitrate, SampleRate); - ) - } - - QObject* AddVideoLiveStream( int Id, - int MaxSegments, - int Width, - int Height, - int Bitrate, - int AudioBitrate, - int SampleRate ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.AddVideoLiveStream(Id, MaxSegments, Width, Height, - Bitrate, AudioBitrate, SampleRate); - ) - } - - QObject* GetLiveStream( int Id ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetLiveStream( Id ); - ) - } - - QObject* GetLiveStreamList( const QString &FileName ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetLiveStreamList( FileName ); - ) - } - - QObject* StopLiveStream( int Id ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.StopLiveStream(Id); - ) - } - - bool RemoveLiveStream( int Id ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveLiveStream(Id); - ) - } -}; - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableContent, QObject*); -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/dvr.cpp b/mythtv/programs/mythbackend/services/dvr.cpp deleted file mode 100644 index ba238a534da..00000000000 --- a/mythtv/programs/mythbackend/services/dvr.cpp +++ /dev/null @@ -1,2104 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: dvr.cpp -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// Qt -#include -#include - -// MythTV -#include "libmythbase/compat.h" -#include "libmythbase/mythcorecontext.h" -#include "libmythbase/mythdate.h" -#include "libmythbase/mythevent.h" -#include "libmythbase/mythscheduler.h" -#include "libmythbase/mythversion.h" -#include "libmythbase/programinfo.h" -#include "libmythbase/programtypes.h" -#include "libmythbase/recordingtypes.h" -#include "libmythbase/remoteutil.h" -#include "libmythbase/storagegroup.h" -#include "libmythtv/cardutil.h" -#include "libmythtv/channelutil.h" -#include "libmythtv/inputinfo.h" -#include "libmythtv/jobqueue.h" -#include "libmythtv/playgroup.h" -#include "libmythtv/programdata.h" -#include "libmythtv/recordinginfo.h" -#include "libmythtv/recordingprofile.h" -#include "libmythtv/tv_rec.h" - -// MythBackend -#include "autoexpire.h" -#include "backendcontext.h" -#include "dvr.h" -#include "encoderlink.h" -#include "scheduler.h" -#include "serviceUtil.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ProgramList* Dvr::GetRecordedList( bool bDescending, - int nStartIndex, - int nCount, - const QString &sTitleRegEx, - const QString &sRecGroup, - const QString &sStorageGroup, - const QString &sCategory, - const QString &sSort, - bool bIgnoreLiveTV, - bool bIgnoreDeleted - ) -{ - QMap< QString, ProgramInfo* > recMap; - - if (gCoreContext->GetScheduler()) - recMap = gCoreContext->GetScheduler()->GetRecording(); - - QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap(); - QMap< QString, bool > isJobRunning= ProgramInfo::QueryJobsRunning(JOB_COMMFLAG); - - ProgramList progList; - - int desc = 1; - if (bDescending) - desc = -1; - - if (bIgnoreLiveTV && (sRecGroup == "LiveTV")) - { - bIgnoreLiveTV = false; - LOG(VB_GENERAL, LOG_ERR, QString("Setting Ignore%1=false because RecGroup=%1") - .arg(sRecGroup)); - } - - if (bIgnoreDeleted && (sRecGroup == "Deleted")) - { - bIgnoreDeleted = false; - LOG(VB_GENERAL, LOG_ERR, QString("Setting Ignore%1=false because RecGroup=%1") - .arg(sRecGroup)); - } - - LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, desc, - sSort, bIgnoreLiveTV, bIgnoreDeleted ); - - QMap< QString, ProgramInfo* >::iterator mit = recMap.begin(); - - for (; mit != recMap.end(); mit = recMap.erase(mit)) - delete *mit; - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pPrograms = new DTC::ProgramList(); - int nAvailable = 0; - - int nMax = (nCount > 0) ? nCount : progList.size(); - - nAvailable = 0; - nCount = 0; - - QRegularExpression rTitleRegEx - { sTitleRegEx, QRegularExpression::CaseInsensitiveOption }; - - for (auto *pInfo : progList) - { - if (pInfo->IsDeletePending() || - (!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) || - (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) || - (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()) || - (!sCategory.isEmpty() && sCategory != pInfo->GetCategory())) - continue; - - if ((nAvailable < nStartIndex) || - (nCount >= nMax)) - { - ++nAvailable; - continue; - } - - ++nAvailable; - ++nCount; - - DTC::Program *pProgram = pPrograms->AddNewProgram(); - - FillProgramInfo( pProgram, pInfo, true ); - } - - // ---------------------------------------------------------------------- - - pPrograms->setStartIndex ( nStartIndex ); - pPrograms->setCount ( nCount ); - pPrograms->setTotalAvailable( nAvailable ); - pPrograms->setAsOf ( MythDate::current() ); - pPrograms->setVersion ( MYTH_BINARY_VERSION ); - pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); - - return pPrograms; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ProgramList* Dvr::GetOldRecordedList( bool bDescending, - int nStartIndex, - int nCount, - const QDateTime &sStartTime, - const QDateTime &sEndTime, - const QString &sTitle, - const QString &sSeriesId, - int nRecordId, - const QString &sSort) -{ - if (!sStartTime.isNull() && !sStartTime.isValid()) - throw QString("StartTime is invalid"); - - if (!sEndTime.isNull() && !sEndTime.isValid()) - throw QString("EndTime is invalid"); - - const QDateTime& dtStartTime = sStartTime; - const QDateTime& dtEndTime = sEndTime; - - if (!sEndTime.isNull() && dtEndTime < dtStartTime) - throw QString("EndTime is before StartTime"); - - // ---------------------------------------------------------------------- - // Build SQL statement for Program Listing - // ---------------------------------------------------------------------- - - ProgramList progList; - MSqlBindings bindings; - QString sSQL; - - if (!dtStartTime.isNull()) - { - sSQL += " AND endtime >= :StartDate "; - bindings[":StartDate"] = dtStartTime; - } - - if (!dtEndTime.isNull()) - { - sSQL += " AND starttime <= :EndDate "; - bindings[":EndDate"] = dtEndTime; - } - - QStringList clause; - - if (nRecordId > 0) - { - clause << "recordid = :RecordId"; - bindings[":RecordId"] = nRecordId; - } - - if (!sTitle.isEmpty()) - { - clause << "title = :Title"; - bindings[":Title"] = sTitle; - } - - if (!sSeriesId.isEmpty()) - { - clause << "seriesid = :SeriesId"; - bindings[":SeriesId"] = sSeriesId; - } - - if (!clause.isEmpty()) - { - sSQL += QString(" AND (%1) ").arg(clause.join(" OR ")); - } - - if (sSort == "starttime") - sSQL += "ORDER BY starttime "; // NOLINT(bugprone-branch-clone) - else if (sSort == "title") - sSQL += "ORDER BY title "; - else - sSQL += "ORDER BY starttime "; - - if (bDescending) - sSQL += "DESC "; - else - sSQL += "ASC "; - - uint nTotalAvailable = (nStartIndex == 0) ? 1 : 0; - LoadFromOldRecorded( progList, sSQL, bindings, - (uint)nStartIndex, (uint)nCount, nTotalAvailable ); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pPrograms = new DTC::ProgramList(); - - nCount = (int)progList.size(); - int nEndIndex = (int)progList.size(); - - for( int n = 0; n < nEndIndex; n++) - { - ProgramInfo *pInfo = progList[ n ]; - - DTC::Program *pProgram = pPrograms->AddNewProgram(); - - FillProgramInfo( pProgram, pInfo, true ); - } - - // ---------------------------------------------------------------------- - - pPrograms->setStartIndex ( nStartIndex ); - pPrograms->setCount ( nCount ); - pPrograms->setTotalAvailable( nTotalAvailable ); - pPrograms->setAsOf ( MythDate::current() ); - pPrograms->setVersion ( MYTH_BINARY_VERSION ); - pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); - - return pPrograms; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::Program* Dvr::GetRecorded(int RecordedId, - int chanid, const QDateTime &recstarttsRaw) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - // TODO Should use RecordingInfo - ProgramInfo pi; - if (RecordedId > 0) - pi = ProgramInfo(RecordedId); - else - pi = ProgramInfo(chanid, recstarttsRaw.toUTC()); - - auto *pProgram = new DTC::Program(); - FillProgramInfo( pProgram, &pi, true ); - - return pProgram; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::AddRecordedCredits(int RecordedId, const QJsonObject &jsonObj) -{ - // Verify the corresponding recording exists - RecordingInfo ri(RecordedId); - if (!ri.HasPathname()) - throw QString("AddRecordedCredits: recordedid %1 does " - "not exist.").arg(RecordedId); - - DBCredits* credits = jsonCastToCredits(jsonObj); - if (credits == nullptr) - throw QString("AddRecordedCredits: Failed to parse cast from json."); - - MSqlQuery query(MSqlQuery::InitCon()); - for (auto & person : *credits) - { - if (!person.InsertDB(query, ri.GetChanID(), - ri.GetScheduledStartTime(), true)) - throw QString("AddRecordedCredits: Failed to add credit " - "%1 to DB").arg(person.toString()); - } - - delete credits; - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -int Dvr::AddRecordedProgram(const QJsonObject &jsonObj) -{ - QJsonObject root = jsonObj; - QJsonObject program = root["Program"].toObject(); - QJsonObject channel = program["Channel"].toObject(); - QJsonObject recording = program["Recording"].toObject(); - QJsonObject cast = program["Cast"].toObject(); - - auto *pi = new ProgInfo(); - int chanid = channel.value("ChanId").toString("0").toUInt(); - QString hostname = program["HostName"].toString(""); - - if (ChannelUtil::GetChanNum(chanid).isEmpty()) - throw QString("AddRecordedProgram: chanid %1 does " - "not exist.").arg(chanid); - - pi->m_title = program.value("Title").toString(""); - pi->m_subtitle = program.value("SubTitle").toString(""); - pi->m_description = program.value("Description").toString(""); - pi->m_category = program.value("Category").toString(""); - pi->m_starttime = QDateTime::fromString(program.value("StartTime") - .toString(""), Qt::ISODate); - pi->m_endtime = QDateTime::fromString(program.value("EndTime") - .toString(""), Qt::ISODate); - pi->m_originalairdate = QDate::fromString(program.value("Airdate").toString(), - Qt::ISODate); - pi->m_airdate = pi->m_originalairdate.year(); - pi->m_partnumber = program.value("PartNumber").toString("0").toUInt(); - pi->m_parttotal = program.value("PartTotal").toString("0").toUInt(); - pi->m_syndicatedepisodenumber = ""; - pi->m_subtitleType = ProgramInfo::SubtitleTypesFromNames - (program.value("SubPropNames").toString("")); - pi->m_audioProps = ProgramInfo::AudioPropertiesFromNames - (program.value("AudioPropNames").toString("")); - pi->m_videoProps = ProgramInfo::VideoPropertiesFromNames - (program.value("VideoPropNames").toString("")); - pi->m_stars = program.value("Stars").toString("0.0").toFloat(); - pi->m_categoryType = string_to_myth_category_type(program.value("CatType").toString("")); - pi->m_seriesId = program.value("SeriesId").toString(""); - pi->m_programId = program.value("ProgramId").toString(""); - pi->m_inetref = program.value("Inetref").toString(""); - pi->m_previouslyshown = false; - pi->m_listingsource = 0; -// pi->m_ratings = -// pi->m_genres = - pi->m_season = program.value("Season").toString("0").toUInt(); - pi->m_episode = program.value("Episode").toString("0").toUInt(); - pi->m_totalepisodes = program.value("TotalEpisodes").toString("0").toUInt(); - - pi->m_channel = channel.value("ChannelName").toString(""); - - pi->m_startts = recording.value("StartTs").toString(""); - pi->m_endts = recording.value("EndTs").toString(""); - QDateTime recstartts = QDateTime::fromString(pi->m_startts, Qt::ISODate); - QDateTime recendts = QDateTime::fromString(pi->m_endts, Qt::ISODate); - - pi->m_title_pronounce = ""; - pi->m_credits = jsonCastToCredits(cast); - pi->m_showtype = ""; - pi->m_colorcode = ""; - pi->m_clumpidx = ""; - pi->m_clumpmax = ""; - - // pi->m_ratings = - - /* Create a recordedprogram DB entry. */ - MSqlQuery query(MSqlQuery::InitCon()); - if (!pi->InsertDB(query, chanid, true)) - { - throw QString("AddRecordedProgram: " - "Failed to add recordedprogram entry."); - } - - /* Create recorded DB entry */ - RecordingInfo ri(pi->m_title, pi->m_title, - pi->m_subtitle, pi->m_subtitle, - pi->m_description, - pi->m_season, pi->m_episode, - pi->m_totalepisodes, - pi->m_syndicatedepisodenumber, - pi->m_category, - chanid, - channel.value("ChanNum").toString("0"), - channel.value("CallSign").toString(""), - pi->m_channel, - recording.value("RecGroup").toString(""), - recording.value("PlayGroup").toString(""), - hostname, - recording.value("StorageGroup").toString(""), - pi->m_airdate, - pi->m_partnumber, - pi->m_parttotal, - pi->m_seriesId, - pi->m_programId, - pi->m_inetref, - pi->m_categoryType, - recording.value("Priority").toString("0").toInt(), - pi->m_starttime, - pi->m_endtime, - recstartts, - recendts, - pi->m_stars, - pi->m_originalairdate, - program.value("Repeat").toString("false").toLower() == "true", - static_cast(recording.value("Status").toString("-3").toInt()), - false, // reactivate - recording.value("RecordedId").toString("0").toInt(), - 0, // parentid - static_cast(recording.value("RecType").toString("0").toInt()), - static_cast(recording.value("DupInType").toString("0").toInt()), - static_cast(recording.value("DupMethod").toString("0").toInt()), - channel.value("SourceId").toString("0").toUInt(), - channel.value("InputId").toString("0").toUInt(), - 0, // findid - channel.value("CommFree").toString("false").toLower() == "true", - pi->m_subtitleType, - pi->m_videoProps, - pi->m_audioProps, - false, // future - 0, // schedorder - 0, // mplexid - 0, // sgroupid, - recording.value("EncoderName").toString("")); - - ri.ProgramFlagsFromNames(program.value("ProgramFlagNames").toString("")); - - QString filename = program.value("FileName").toString(""); - QString ext(""); - int idx = filename.lastIndexOf('.'); - if (idx > 0) - ext = filename.right(filename.size() - idx - 1); - // Inserts this RecordingInfo into the database as an existing recording - if (!ri.InsertRecording(ext, true)) - throw QString("Failed to create RecordingInfo database entry. " - "Non unique starttime?"); - - ri.InsertFile(); - - ri.SaveAutoExpire(ri.IsAutoExpirable() ? - kNormalAutoExpire : kDisableAutoExpire); - ri.SavePreserve(ri.IsPreserved()); - ri.SaveCommFlagged(ri.IsCommercialFlagged() ? - COMM_FLAG_DONE : COMM_FLAG_NOT_FLAGGED); - ri.SaveWatched(ri.IsWatched()); - // TODO: Cutlist - - ri.SetRecordingStatus(RecStatus::Recorded); - ri.SendUpdateEvent(); - - return ri.GetRecordingID(); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::RemoveRecorded(int RecordedId, - int chanid, const QDateTime &recstarttsRaw, - bool forceDelete, bool allowRerecord) -{ - return DeleteRecording(RecordedId, chanid, recstarttsRaw, forceDelete, - allowRerecord); -} - - -bool Dvr::DeleteRecording(int RecordedId, - int chanid, const QDateTime &recstarttsRaw, - bool forceDelete, bool allowRerecord) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - // TODO Should use RecordingInfo - ProgramInfo pi; - if (RecordedId > 0) - pi = ProgramInfo(RecordedId); - else - pi = ProgramInfo(chanid, recstarttsRaw.toUTC()); - - if (pi.GetChanID() && pi.HasPathname()) - { - QString cmd = QString("DELETE_RECORDING %1 %2 %3 %4") - .arg(QString::number(pi.GetChanID()), - pi.GetRecordingStartTime(MythDate::ISODate), - forceDelete ? "FORCE" : "NO_FORCE", - allowRerecord ? "FORGET" : "NO_FORGET"); - MythEvent me(cmd); - - gCoreContext->dispatch(me); - return true; - } - - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::UnDeleteRecording(int RecordedId, - int chanid, const QDateTime &recstarttsRaw) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - RecordingInfo ri; - if (RecordedId > 0) - ri = RecordingInfo(RecordedId); - else - ri = RecordingInfo(chanid, recstarttsRaw.toUTC()); - - if (ri.GetChanID() && ri.HasPathname()) - { - QString cmd = QString("UNDELETE_RECORDING %1 %2") - .arg(ri.GetChanID()) - .arg(ri.GetRecordingStartTime(MythDate::ISODate)); - MythEvent me(cmd); - - gCoreContext->dispatch(me); - return true; - } - - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::StopRecording(int RecordedId) -{ - if (RecordedId <= 0) - throw QString("RecordedId param is invalid."); - - RecordingInfo ri = RecordingInfo(RecordedId); - - if (ri.GetChanID()) - { - QString cmd = QString("STOP_RECORDING %1 %2") - .arg(ri.GetChanID()) - .arg(ri.GetRecordingStartTime(MythDate::ISODate)); - MythEvent me(cmd); - - gCoreContext->dispatch(me); - return true; - } - throw QString("RecordedId %1 not found").arg(RecordedId); - - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::ReactivateRecording(int RecordedId, - int chanid, const QDateTime &recstarttsRaw) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - RecordingInfo ri; - if (RecordedId > 0) - ri = RecordingInfo(RecordedId); - else - ri = RecordingInfo(chanid, recstarttsRaw.toUTC()); - - if (ri.GetChanID() && ri.HasPathname()) - { - ri.ReactivateRecording(); - return true; - } - - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::RescheduleRecordings(void) -{ - ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(), - "RescheduleRecordings"); - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::AllowReRecord ( int RecordedId ) -{ - if (RecordedId <= 0) - throw QString("RecordedId param is invalid."); - - RecordingInfo ri = RecordingInfo(RecordedId); - - if (!ri.GetChanID()) - throw QString("RecordedId %1 not found").arg(RecordedId); - - ri.ForgetHistory(); - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::UpdateRecordedWatchedStatus ( int RecordedId, - int chanid, - const QDateTime &recstarttsRaw, - bool watched) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - // TODO Should use RecordingInfo - ProgramInfo pi; - if (RecordedId > 0) - pi = ProgramInfo(RecordedId); - else - pi = ProgramInfo(chanid, recstarttsRaw.toUTC()); - - if (pi.GetChanID() && pi.HasPathname()) - { - pi.SaveWatched(watched); - return true; - } - - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -long Dvr::GetSavedBookmark( int RecordedId, - int chanid, - const QDateTime &recstarttsRaw, - const QString &offsettype ) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - RecordingInfo ri; - if (RecordedId > 0) - ri = RecordingInfo(RecordedId); - else - ri = RecordingInfo(chanid, recstarttsRaw.toUTC()); - uint64_t offset = 0; - bool isend=true; - uint64_t position = ri.QueryBookmark(); - // if no bookmark return 0 - if (position == 0) - return 0; - if (offsettype.toLower() == "position"){ - // if bookmark cannot be converted to a keyframe we will - // just return the actual frame saved as the bookmark - if (ri.QueryKeyFramePosition(&offset, position, isend)) - return offset; - } - if (offsettype.toLower() == "duration"){ - if (ri.QueryKeyFrameDuration(&offset, position, isend)) - return offset; - // If bookmark cannot be converted to a duration return -1 - return -1; - } - return position; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::SetSavedBookmark( int RecordedId, - int chanid, - const QDateTime &recstarttsRaw, - const QString &offsettype, - long Offset ) -{ - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - if (Offset < 0) - throw QString("Offset must be >= 0."); - - RecordingInfo ri; - if (RecordedId > 0) - ri = RecordingInfo(RecordedId); - else - ri = RecordingInfo(chanid, recstarttsRaw.toUTC()); - uint64_t position = 0; - bool isend=true; - if (offsettype.toLower() == "position"){ - if (!ri.QueryPositionKeyFrame(&position, Offset, isend)) - return false; - } - else if (offsettype.toLower() == "duration"){ - if (!ri.QueryDurationKeyFrame(&position, Offset, isend)) - return false; - } - else - { - position = Offset; - } - ri.SaveBookmark(position); - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::CutList* Dvr::GetRecordedCutList ( int RecordedId, - int chanid, - const QDateTime &recstarttsRaw, - const QString &offsettype ) -{ - int marktype = 0; - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - RecordingInfo ri; - if (RecordedId > 0) - ri = RecordingInfo(RecordedId); - else - ri = RecordingInfo(chanid, recstarttsRaw.toUTC()); - - auto* pCutList = new DTC::CutList(); - if (offsettype.toLower() == "position") - marktype = 1; - else if (offsettype.toLower() == "duration") - marktype = 2; - else - marktype = 0; - - FillCutList(pCutList, &ri, marktype); - - return pCutList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::CutList* Dvr::GetRecordedCommBreak ( int RecordedId, - int chanid, - const QDateTime &recstarttsRaw, - const QString &offsettype ) -{ - int marktype = 0; - if ((RecordedId <= 0) && - (chanid <= 0 || !recstarttsRaw.isValid())) - throw QString("Recorded ID or Channel ID and StartTime appears invalid."); - - RecordingInfo ri; - if (RecordedId > 0) - ri = RecordingInfo(RecordedId); - else - ri = RecordingInfo(chanid, recstarttsRaw.toUTC()); - - auto* pCutList = new DTC::CutList(); - if (offsettype.toLower() == "position") - marktype = 1; - else if (offsettype.toLower() == "duration") - marktype = 2; - else - marktype = 0; - - FillCommBreak(pCutList, &ri, marktype); - - return pCutList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::CutList* Dvr::GetRecordedSeek ( int RecordedId, - const QString &offsettype ) -{ - MarkTypes marktype = MARK_UNSET; - if (RecordedId <= 0) - throw QString("Recorded ID appears invalid."); - - RecordingInfo ri; - ri = RecordingInfo(RecordedId); - - auto* pCutList = new DTC::CutList(); - if (offsettype.toLower() == "bytes") - marktype = MARK_GOP_BYFRAME; - else if (offsettype.toLower() == "duration") - marktype = MARK_DURATION_MS; - else - { - delete pCutList; - throw QString("Type must be 'BYTES' or 'DURATION'."); - } - - FillSeek(pCutList, &ri, marktype); - - return pCutList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::MarkupList* Dvr::GetRecordedMarkup ( int RecordedId ) -{ - RecordingInfo ri; - ri = RecordingInfo(RecordedId); - - if (!ri.HasPathname()) - throw QString("Invalid RecordedId %1").arg(RecordedId); - - QVector mapMark; - QVector mapSeek; - - ri.QueryMarkup(mapMark, mapSeek); - - auto* pMarkupList = new DTC::MarkupList(); - for (const auto& entry : std::as_const(mapMark)) - { - DTC::Markup *pMarkup = pMarkupList->AddNewMarkup(); - QString typestr = toString(static_cast(entry.type)); - pMarkup->setType(typestr); - pMarkup->setFrame(entry.frame); - if (entry.isDataNull) - pMarkup->setData("NULL"); - else - pMarkup->setData(QString::number(entry.data)); - } - for (const auto& entry : std::as_const(mapSeek)) - { - DTC::Markup *pSeek = pMarkupList->AddNewSeek(); - QString typestr = toString(static_cast(entry.type)); - pSeek->setType(typestr); - pSeek->setFrame(entry.frame); - if (entry.isDataNull) - pSeek->setData("NULL"); - else - pSeek->setData(QString::number(entry.data)); - } - - - return pMarkupList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Dvr::SetRecordedMarkup (int RecordedId, const QJsonObject &jsonObj) -{ - RecordingInfo ri; - ri = RecordingInfo(RecordedId); - - if (!ri.HasPathname()) - throw QString("Invalid RecordedId %1").arg(RecordedId); - - QVector mapMark; - QVector mapSeek; - - QJsonObject markuplist = jsonObj["MarkupList"].toObject(); - - QJsonArray marks = markuplist["Mark"].toArray(); - for (const auto & m : std::as_const(marks)) - { - QJsonObject markup = m.toObject(); - ProgramInfo::MarkupEntry entry; - - QString typestr = markup.value("Type").toString(""); - entry.type = markTypeFromString(typestr); - entry.frame = markup.value("Frame").toString("-1").toLongLong(); - QString data = markup.value("Data").toString("NULL"); - entry.isDataNull = (data == "NULL"); - if (!entry.isDataNull) - entry.data = data.toLongLong(); - - mapMark.append(entry); - } - - QJsonArray seeks = markuplist["Seek"].toArray(); - for (const auto & m : std::as_const(seeks)) - { - QJsonObject markup = m.toObject(); - ProgramInfo::MarkupEntry entry; - - QString typestr = markup.value("Type").toString(""); - entry.type = markTypeFromString(typestr); - entry.frame = markup.value("Frame").toString("-1").toLongLong(); - QString data = markup.value("Data").toString("NULL"); - entry.isDataNull = (data == "NULL"); - if (!entry.isDataNull) - entry.data = data.toLongLong(); - - mapSeek.append(entry); - } - - ri.SaveMarkup(mapMark, mapSeek); - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ProgramList* Dvr::GetExpiringList( int nStartIndex, - int nCount ) -{ - pginfolist_t infoList; - - if (gExpirer) - gExpirer->GetAllExpiring( infoList ); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pPrograms = new DTC::ProgramList(); - - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)infoList.size() ) : 0; - nCount = (nCount > 0) ? std::min( nCount, (int)infoList.size() ) : infoList.size(); - int nEndIndex = std::min((nStartIndex + nCount), (int)infoList.size() ); - - for( int n = nStartIndex; n < nEndIndex; n++) - { - ProgramInfo *pInfo = infoList[ n ]; - - if (pInfo != nullptr) - { - DTC::Program *pProgram = pPrograms->AddNewProgram(); - - FillProgramInfo( pProgram, pInfo, true ); - - delete pInfo; - } - } - - // ---------------------------------------------------------------------- - - pPrograms->setStartIndex ( nStartIndex ); - pPrograms->setCount ( nCount ); - pPrograms->setTotalAvailable( infoList.size() ); - pPrograms->setAsOf ( MythDate::current() ); - pPrograms->setVersion ( MYTH_BINARY_VERSION ); - pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); - - return pPrograms; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::EncoderList* Dvr::GetEncoderList() -{ - auto* pList = new DTC::EncoderList(); - - QReadLocker tvlocker(&TVRec::s_inputsLock); - QList inputInfoList = CardUtil::GetAllInputInfo(true); - for (auto * elink : std::as_const(gTVList)) - { - if (elink != nullptr) - { - DTC::Encoder *pEncoder = pList->AddNewEncoder(); - - pEncoder->setId ( elink->GetInputID() ); - pEncoder->setState ( elink->GetState() ); - pEncoder->setLocal ( elink->IsLocal() ); - pEncoder->setConnected ( elink->IsConnected() ); - pEncoder->setSleepStatus ( elink->GetSleepStatus() ); - // pEncoder->setLowOnFreeSpace( elink->isLowOnFreeSpace()); - - if (pEncoder->Local()) - pEncoder->setHostName( gCoreContext->GetHostName() ); - else - pEncoder->setHostName( elink->GetHostName() ); - - for (const auto & inputInfo : std::as_const(inputInfoList)) - { - if (inputInfo.m_inputId == static_cast(elink->GetInputID())) - { - DTC::Input *input = pEncoder->AddNewInput(); - FillInputInfo(input, inputInfo); - } - } - - switch ( pEncoder->State() ) - { - case kState_WatchingLiveTV: - case kState_RecordingOnly: - case kState_WatchingRecording: - { - ProgramInfo *pInfo = elink->GetRecording(); - - if (pInfo) - { - DTC::Program *pProgram = pEncoder->Recording(); - - FillProgramInfo( pProgram, pInfo, true, true ); - - delete pInfo; - } - - break; - } - - default: - break; - } - } - } - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::InputList* Dvr::GetInputList() -{ - auto *pList = new DTC::InputList(); - - QList inputInfoList = CardUtil::GetAllInputInfo(false); - for (const auto & inputInfo : std::as_const(inputInfoList)) - { - DTC::Input *input = pList->AddNewInput(); - FillInputInfo(input, inputInfo); - } - - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Dvr::GetRecGroupList() -{ - MSqlQuery query(MSqlQuery::InitCon()); - query.prepare("SELECT recgroup FROM recgroups WHERE recgroup <> 'Deleted' " - "ORDER BY recgroup"); - - QStringList result; - if (!query.exec()) - { - MythDB::DBError("GetRecGroupList", query); - return result; - } - - while (query.next()) - result << query.value(0).toString(); - - return result; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Dvr::GetProgramCategories( bool OnlyRecorded ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (OnlyRecorded) - query.prepare("SELECT DISTINCT category FROM recorded ORDER BY category"); - else - query.prepare("SELECT DISTINCT category FROM program ORDER BY category"); - - QStringList result; - if (!query.exec()) - { - MythDB::DBError("GetProgramCategories", query); - return result; - } - - while (query.next()) - result << query.value(0).toString(); - - return result; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Dvr::GetRecStorageGroupList() -{ - return StorageGroup::getRecordingsGroups(); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Dvr::GetPlayGroupList() -{ - return PlayGroup::GetNames(); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::RecRuleFilterList* Dvr::GetRecRuleFilterList() -{ - auto* filterList = new DTC::RecRuleFilterList(); - - MSqlQuery query(MSqlQuery::InitCon()); - - query.prepare("SELECT filterid, description, newruledefault " - "FROM recordfilter ORDER BY filterid"); - - if (query.exec()) - { - while (query.next()) - { - DTC::RecRuleFilter* ruleFilter = filterList->AddNewRecRuleFilter(); - ruleFilter->setId(query.value(0).toInt()); - ruleFilter->setDescription(QObject::tr(query.value(1).toString() - .toUtf8().constData())); - } - } - - return filterList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Dvr::GetTitleList(const QString& RecGroup) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - QString querystr = "SELECT DISTINCT title FROM recorded " - "WHERE deletepending = 0"; - - if (!RecGroup.isEmpty()) - querystr += " AND recgroup = :RECGROUP"; - else - querystr += " AND recgroup != 'Deleted'"; - - querystr += " ORDER BY title"; - - query.prepare(querystr); - - if (!RecGroup.isEmpty()) - query.bindValue(":RECGROUP", RecGroup); - - QStringList result; - if (!query.exec()) - { - MythDB::DBError("GetTitleList recorded", query); - return result; - } - - while (query.next()) - result << query.value(0).toString(); - - return result; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::TitleInfoList* Dvr::GetTitleInfoList() -{ - MSqlQuery query(MSqlQuery::InitCon()); - - QString querystr = QString( - "SELECT title, inetref, count(title) as count " - " FROM recorded AS r " - " JOIN recgroups AS g ON r.recgroupid = g.recgroupid " - " WHERE g.recgroup NOT IN ('Deleted', 'LiveTV') " - " AND r.deletepending = 0 " - " GROUP BY title, inetref " - " ORDER BY title"); - - query.prepare(querystr); - - auto *pTitleInfos = new DTC::TitleInfoList(); - if (!query.exec()) - { - MythDB::DBError("GetTitleList recorded", query); - return pTitleInfos; - } - - while (query.next()) - { - DTC::TitleInfo *pTitleInfo = pTitleInfos->AddNewTitleInfo(); - - pTitleInfo->setTitle(query.value(0).toString()); - pTitleInfo->setInetref(query.value(1).toString()); - pTitleInfo->setCount(query.value(2).toInt()); - } - - return pTitleInfos; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ProgramList* Dvr::GetUpcomingList( int nStartIndex, - int nCount, - bool bShowAll, - int nRecordId, - int nRecStatus ) -{ - RecordingList recordingList; // Auto-delete deque - RecList tmpList; // Standard deque, objects must be deleted - - if (nRecordId <= 0) - nRecordId = -1; - - // NOTE: Fetching this information directly from the schedule is - // significantly faster than using ProgramInfo::LoadFromScheduler() - auto *scheduler = dynamic_cast(gCoreContext->GetScheduler()); - if (scheduler) - scheduler->GetAllPending(tmpList, nRecordId); - - // Sort the upcoming into only those which will record - // NOLINTNEXTLINE(modernize-loop-convert) - for (auto it = tmpList.begin(); it < tmpList.end(); ++it) - { - if ((nRecStatus != 0) && - ((*it)->GetRecordingStatus() != nRecStatus)) - { - delete *it; - *it = nullptr; - continue; - } - - if (!bShowAll && ((((*it)->GetRecordingStatus() >= RecStatus::Pending) && - ((*it)->GetRecordingStatus() <= RecStatus::WillRecord)) || - ((*it)->GetRecordingStatus() == RecStatus::Recorded) || - ((*it)->GetRecordingStatus() == RecStatus::Conflict)) && - ((*it)->GetRecordingEndTime() > MythDate::current())) - { // NOLINT(bugprone-branch-clone) - recordingList.push_back(new RecordingInfo(**it)); - } - else if (bShowAll && - ((*it)->GetRecordingEndTime() > MythDate::current())) - { - recordingList.push_back(new RecordingInfo(**it)); - } - - delete *it; - *it = nullptr; - } - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pPrograms = new DTC::ProgramList(); - - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)recordingList.size() ) : 0; - nCount = (nCount > 0) ? std::min( nCount, (int)recordingList.size() ) : recordingList.size(); - int nEndIndex = std::min((nStartIndex + nCount), (int)recordingList.size() ); - - for( int n = nStartIndex; n < nEndIndex; n++) - { - ProgramInfo *pInfo = recordingList[ n ]; - - DTC::Program *pProgram = pPrograms->AddNewProgram(); - - FillProgramInfo( pProgram, pInfo, true ); - } - - // ---------------------------------------------------------------------- - - pPrograms->setStartIndex ( nStartIndex ); - pPrograms->setCount ( nCount ); - pPrograms->setTotalAvailable( recordingList.size() ); - pPrograms->setAsOf ( MythDate::current() ); - pPrograms->setVersion ( MYTH_BINARY_VERSION ); - pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); - - return pPrograms; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ProgramList* Dvr::GetConflictList( int nStartIndex, - int nCount, - int nRecordId ) -{ - RecordingList recordingList; // Auto-delete deque - RecList tmpList; // Standard deque, objects must be deleted - - if (nRecordId <= 0) - nRecordId = -1; - - // NOTE: Fetching this information directly from the schedule is - // significantly faster than using ProgramInfo::LoadFromScheduler() - auto *scheduler = dynamic_cast(gCoreContext->GetScheduler()); - if (scheduler) - scheduler->GetAllPending(tmpList, nRecordId); - - // Sort the upcoming into only those which are conflicts - // NOLINTNEXTLINE(modernize-loop-convert) - for (auto it = tmpList.begin(); it < tmpList.end(); ++it) - { - if (((*it)->GetRecordingStatus() == RecStatus::Conflict) && - ((*it)->GetRecordingStartTime() >= MythDate::current())) - { - recordingList.push_back(new RecordingInfo(**it)); - } - delete *it; - *it = nullptr; - } - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pPrograms = new DTC::ProgramList(); - - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)recordingList.size() ) : 0; - nCount = (nCount > 0) ? std::min( nCount, (int)recordingList.size() ) : recordingList.size(); - int nEndIndex = std::min((nStartIndex + nCount), (int)recordingList.size() ); - - for( int n = nStartIndex; n < nEndIndex; n++) - { - ProgramInfo *pInfo = recordingList[ n ]; - - DTC::Program *pProgram = pPrograms->AddNewProgram(); - - FillProgramInfo( pProgram, pInfo, true ); - } - - // ---------------------------------------------------------------------- - - pPrograms->setStartIndex ( nStartIndex ); - pPrograms->setCount ( nCount ); - pPrograms->setTotalAvailable( recordingList.size() ); - pPrograms->setAsOf ( MythDate::current() ); - pPrograms->setVersion ( MYTH_BINARY_VERSION ); - pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); - - return pPrograms; -} - -uint Dvr::AddRecordSchedule ( - const QString& sTitle, - const QString& sSubtitle, - const QString& sDescription, - const QString& sCategory, - const QDateTime& recstarttsRaw, - const QDateTime& recendtsRaw, - const QString& sSeriesId, - const QString& sProgramId, - int nChanId, - const QString& sStation, - int nFindDay, - QTime tFindTime, - int nParentId, - bool bInactive, - uint nSeason, - uint nEpisode, - const QString& sInetref, - QString sType, - QString sSearchType, - int nRecPriority, - uint nPreferredInput, - int nStartOffset, - int nEndOffset, - const QDateTime& lastrectsRaw, - QString sDupMethod, - QString sDupIn, - bool bNewEpisOnly, - uint nFilter, - QString sRecProfile, - QString sRecGroup, - QString sStorageGroup, - QString sPlayGroup, - bool bAutoExpire, - int nMaxEpisodes, - bool bMaxNewest, - bool bAutoCommflag, - bool bAutoTranscode, - bool bAutoMetaLookup, - bool bAutoUserJob1, - bool bAutoUserJob2, - bool bAutoUserJob3, - bool bAutoUserJob4, - int nTranscoder) -{ - QDateTime recstartts = recstarttsRaw.toUTC(); - QDateTime recendts = recendtsRaw.toUTC(); - QDateTime lastrects = lastrectsRaw.toUTC(); - RecordingRule rule; - rule.LoadTemplate("Default"); - - if (sType.isEmpty()) - sType = "single"; - - if (sSearchType.isEmpty()) - sSearchType = "none"; - - if (sDupMethod.isEmpty()) - sDupMethod = "subtitleanddescription"; - - if (sDupIn.isEmpty()) - sDupIn = "all"; - - rule.m_title = sTitle; - rule.m_subtitle = sSubtitle; - rule.m_description = sDescription; - - rule.m_startdate = recstartts.date(); - rule.m_starttime = recstartts.time(); - rule.m_enddate = recendts.date(); - rule.m_endtime = recendts.time(); - - rule.m_type = recTypeFromString(sType); - rule.m_searchType = searchTypeFromString(sSearchType); - if (rule.m_searchType == kManualSearch) - rule.m_dupMethod = kDupCheckNone; - else - rule.m_dupMethod = dupMethodFromString(sDupMethod); - rule.m_dupIn = dupInFromStringAndBool(sDupIn, bNewEpisOnly); - - if (sRecProfile.isEmpty()) - sRecProfile = "Default"; - - if (sRecGroup.isEmpty()) - sRecGroup = "Default"; - - if (sStorageGroup.isEmpty()) - sStorageGroup = "Default"; - - if (sPlayGroup.isEmpty()) - sPlayGroup = "Default"; - - rule.m_category = sCategory; - rule.m_seriesid = sSeriesId; - rule.m_programid = sProgramId; - - rule.m_channelid = nChanId; - rule.m_station = sStation; - - rule.m_findday = nFindDay; - rule.m_findtime = tFindTime; - - rule.m_recProfile = sRecProfile; - rule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup); - if (rule.m_recGroupID == 0) - { - rule.m_recGroupID = CreateRecordingGroup(sRecGroup); - if (rule.m_recGroupID <= 0) - rule.m_recGroupID = RecordingInfo::kDefaultRecGroup; - } - rule.m_storageGroup = sStorageGroup; - rule.m_playGroup = sPlayGroup; - - rule.m_parentRecID = nParentId; - rule.m_isInactive = bInactive; - - rule.m_season = nSeason; - rule.m_episode = nEpisode; - rule.m_inetref = sInetref; - - rule.m_recPriority = nRecPriority; - rule.m_prefInput = nPreferredInput; - rule.m_startOffset = nStartOffset; - rule.m_endOffset = nEndOffset; - rule.m_filter = nFilter; - - rule.m_autoExpire = bAutoExpire; - rule.m_maxEpisodes = nMaxEpisodes; - rule.m_maxNewest = bMaxNewest; - - rule.m_autoCommFlag = bAutoCommflag; - rule.m_autoTranscode = bAutoTranscode; - rule.m_autoMetadataLookup = bAutoMetaLookup; - - rule.m_autoUserJob1 = bAutoUserJob1; - rule.m_autoUserJob2 = bAutoUserJob2; - rule.m_autoUserJob3 = bAutoUserJob3; - rule.m_autoUserJob4 = bAutoUserJob4; - - rule.m_transcoder = nTranscoder; - - rule.m_lastRecorded = lastrects; - - QString msg; - if (!rule.IsValid(msg)) - throw QString(msg); - - rule.Save(); - - uint recid = rule.m_recordID; - - return recid; -} - -bool Dvr::UpdateRecordSchedule ( uint nRecordId, - const QString& sTitle, - const QString& sSubtitle, - const QString& sDescription, - const QString& sCategory, - const QDateTime& dStartTimeRaw, - const QDateTime& dEndTimeRaw, - const QString& sSeriesId, - const QString& sProgramId, - int nChanId, - const QString& sStation, - int nFindDay, - QTime tFindTime, - bool bInactive, - uint nSeason, - uint nEpisode, - const QString& sInetref, - QString sType, - QString sSearchType, - int nRecPriority, - uint nPreferredInput, - int nStartOffset, - int nEndOffset, - QString sDupMethod, - QString sDupIn, - bool bNewEpisOnly, - uint nFilter, - QString sRecProfile, - QString sRecGroup, - QString sStorageGroup, - QString sPlayGroup, - bool bAutoExpire, - int nMaxEpisodes, - bool bMaxNewest, - bool bAutoCommflag, - bool bAutoTranscode, - bool bAutoMetaLookup, - bool bAutoUserJob1, - bool bAutoUserJob2, - bool bAutoUserJob3, - bool bAutoUserJob4, - int nTranscoder) -{ - if (nRecordId == 0 ) - throw QString("Record ID is invalid."); - - RecordingRule pRule; - pRule.m_recordID = nRecordId; - pRule.Load(); - - if (!pRule.IsLoaded()) - throw QString("Record ID does not exist."); - - QDateTime recstartts = dStartTimeRaw.toUTC(); - QDateTime recendts = dEndTimeRaw.toUTC(); - - pRule.m_isInactive = bInactive; - if (sType.isEmpty()) - sType = "single"; - - if (sSearchType.isEmpty()) - sSearchType = "none"; - - if (sDupMethod.isEmpty()) - sDupMethod = "subtitleanddescription"; - - if (sDupIn.isEmpty()) - sDupIn = "all"; - - pRule.m_type = recTypeFromString(sType); - pRule.m_searchType = searchTypeFromString(sSearchType); - if (pRule.m_searchType == kManualSearch) - pRule.m_dupMethod = kDupCheckNone; - else - pRule.m_dupMethod = dupMethodFromString(sDupMethod); - pRule.m_dupIn = dupInFromStringAndBool(sDupIn, bNewEpisOnly); - - if (sRecProfile.isEmpty()) - sRecProfile = "Default"; - - if (sRecGroup.isEmpty()) - sRecGroup = "Default"; - - if (sStorageGroup.isEmpty()) - sStorageGroup = "Default"; - - if (sPlayGroup.isEmpty()) - sPlayGroup = "Default"; - - if (!sTitle.isEmpty()) - pRule.m_title = sTitle; - - if (!sSubtitle.isEmpty()) - pRule.m_subtitle = sSubtitle; - - if(!sDescription.isEmpty()) - pRule.m_description = sDescription; - - if (!sCategory.isEmpty()) - pRule.m_category = sCategory; - - if (!sSeriesId.isEmpty()) - pRule.m_seriesid = sSeriesId; - - if (!sProgramId.isEmpty()) - pRule.m_programid = sProgramId; - - if (nChanId) - pRule.m_channelid = nChanId; - if (!sStation.isEmpty()) - pRule.m_station = sStation; - - pRule.m_startdate = recstartts.date(); - pRule.m_starttime = recstartts.time(); - pRule.m_enddate = recendts.date(); - pRule.m_endtime = recendts.time(); - - pRule.m_findday = nFindDay; - pRule.m_findtime = tFindTime; - - pRule.m_recProfile = sRecProfile; - pRule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup); - if (pRule.m_recGroupID == 0) - { - pRule.m_recGroupID = CreateRecordingGroup(sRecGroup); - if (pRule.m_recGroupID <= 0) - pRule.m_recGroupID = RecordingInfo::kDefaultRecGroup; - } - pRule.m_storageGroup = sStorageGroup; - pRule.m_playGroup = sPlayGroup; - - pRule.m_isInactive = bInactive; - - pRule.m_season = nSeason; - pRule.m_episode = nEpisode; - pRule.m_inetref = sInetref; - - pRule.m_recPriority = nRecPriority; - pRule.m_prefInput = nPreferredInput; - pRule.m_startOffset = nStartOffset; - pRule.m_endOffset = nEndOffset; - pRule.m_filter = nFilter; - - pRule.m_autoExpire = bAutoExpire; - pRule.m_maxEpisodes = nMaxEpisodes; - pRule.m_maxNewest = bMaxNewest; - - pRule.m_autoCommFlag = bAutoCommflag; - pRule.m_autoTranscode = bAutoTranscode; - pRule.m_autoMetadataLookup = bAutoMetaLookup; - - pRule.m_autoUserJob1 = bAutoUserJob1; - pRule.m_autoUserJob2 = bAutoUserJob2; - pRule.m_autoUserJob3 = bAutoUserJob3; - pRule.m_autoUserJob4 = bAutoUserJob4; - - pRule.m_transcoder = nTranscoder; - - QString msg; - if (!pRule.IsValid(msg)) - throw QString(msg); - - bool bResult = pRule.Save(); - - return bResult; -} - -bool Dvr::RemoveRecordSchedule ( uint nRecordId ) -{ - bool bResult = false; - - if (nRecordId == 0 ) - throw QString("Record ID does not exist."); - - RecordingRule pRule; - pRule.m_recordID = nRecordId; - - bResult = pRule.Delete(); - - return bResult; -} - -bool Dvr::AddDontRecordSchedule(int nChanId, const QDateTime &dStartTime, - bool bNeverRecord) -{ - bool bResult = true; - - if (nChanId <= 0 || !dStartTime.isValid()) - throw QString("Program does not exist."); - - ProgramInfo *pi = LoadProgramFromProgram(nChanId, dStartTime.toUTC()); - - if (!pi) - throw QString("Program does not exist."); - - // Why RecordingInfo instead of ProgramInfo? Good question ... - RecordingInfo recInfo = RecordingInfo(*pi); - - delete pi; - - if (bNeverRecord) - { - recInfo.ApplyNeverRecord(); - } - else - { - recInfo.ApplyRecordStateChange(kDontRecord); - } - - return bResult; -} - -DTC::RecRuleList* Dvr::GetRecordScheduleList( int nStartIndex, - int nCount, - const QString &Sort, - bool Descending ) -{ - Scheduler::SchedSortColumn sortingColumn = Scheduler::kSortTitle; - if (Sort.toLower() == "lastrecorded") - sortingColumn = Scheduler::kSortLastRecorded; - else if (Sort.toLower() == "nextrecording") - sortingColumn = Scheduler::kSortNextRecording; - else if (Sort.toLower() == "title") - sortingColumn = Scheduler::kSortTitle; // NOLINT(bugprone-branch-clone) - else if (Sort.toLower() == "priority") - sortingColumn = Scheduler::kSortPriority; - else if (Sort.toLower() == "type") - sortingColumn = Scheduler::kSortType; - else - sortingColumn = Scheduler::kSortTitle; - - RecList recList; - Scheduler::GetAllScheduled(recList, sortingColumn, !Descending); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pRecRules = new DTC::RecRuleList(); - - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)recList.size() ) : 0; - nCount = (nCount > 0) ? std::min( nCount, (int)recList.size() ) : recList.size(); - int nEndIndex = std::min((nStartIndex + nCount), (int)recList.size() ); - - for( int n = nStartIndex; n < nEndIndex; n++) - { - RecordingInfo *info = recList[n]; - - if (info != nullptr) - { - DTC::RecRule *pRecRule = pRecRules->AddNewRecRule(); - - FillRecRuleInfo( pRecRule, info->GetRecordingRule() ); - } - } - - // ---------------------------------------------------------------------- - - pRecRules->setStartIndex ( nStartIndex ); - pRecRules->setCount ( nCount ); - pRecRules->setTotalAvailable( recList.size() ); - pRecRules->setAsOf ( MythDate::current() ); - pRecRules->setVersion ( MYTH_BINARY_VERSION ); - pRecRules->setProtoVer ( MYTH_PROTO_VERSION ); - - while (!recList.empty()) - { - delete recList.back(); - recList.pop_back(); - } - - return pRecRules; -} - -DTC::RecRule* Dvr::GetRecordSchedule( uint nRecordId, - const QString& sTemplate, - int nRecordedId, - int nChanId, - const QDateTime& dStartTimeRaw, - bool bMakeOverride ) -{ - RecordingRule rule; - QDateTime dStartTime = dStartTimeRaw.toUTC(); - - if (nRecordId > 0) - { - rule.m_recordID = nRecordId; - if (!rule.Load()) - throw QString("Record ID does not exist."); - } - else if (!sTemplate.isEmpty()) - { - if (!rule.LoadTemplate(sTemplate)) - throw QString("Template does not exist."); - } - else if (nRecordedId > 0) // Loads from the Recorded/Recorded Program Table - { - // Despite the use of ProgramInfo, this only applies to Recordings. - ProgramInfo recInfo(nRecordedId); - if (!rule.LoadByProgram(&recInfo)) - throw QString("Recording does not exist"); - } - else if (nChanId > 0 && dStartTime.isValid()) // Loads from Program Table, should NOT be used with recordings - { - // Despite the use of RecordingInfo, this only applies to programs in the - // present or future, not to recordings? Confused yet? - RecordingInfo::LoadStatus status = RecordingInfo::kNoProgram; - RecordingInfo info(nChanId, dStartTime, false, 0h, &status); - if (status != RecordingInfo::kFoundProgram) - throw QString("Program does not exist."); - RecordingRule *pRule = info.GetRecordingRule(); - if (bMakeOverride && rule.m_type != kSingleRecord && - rule.m_type != kOverrideRecord && rule.m_type != kDontRecord) - pRule->MakeOverride(); - rule = *pRule; - } - else - { - throw QString("Invalid request."); - } - - auto *pRecRule = new DTC::RecRule(); - FillRecRuleInfo( pRecRule, &rule ); - - return pRecRule; -} - -bool Dvr::EnableRecordSchedule ( uint nRecordId ) -{ - bool bResult = false; - - if (nRecordId == 0 ) - throw QString("Record ID appears invalid."); - - RecordingRule pRule; - pRule.m_recordID = nRecordId; - pRule.Load(); - - if (pRule.IsLoaded()) - { - pRule.m_isInactive = false; - bResult = pRule.Save(); - } - - return bResult; -} - -bool Dvr::DisableRecordSchedule( uint nRecordId ) -{ - bool bResult = false; - - if (nRecordId == 0 ) - throw QString("Record ID appears invalid."); - - RecordingRule pRule; - pRule.m_recordID = nRecordId; - pRule.Load(); - - if (pRule.IsLoaded()) - { - pRule.m_isInactive = true; - bResult = pRule.Save(); - } - - return bResult; -} - -int Dvr::RecordedIdForKey(int chanid, const QDateTime &recstarttsRaw) -{ - int recordedid = 0; - - if (!RecordingInfo::QueryRecordedIdForKey(recordedid, chanid, - recstarttsRaw)) - return -1; - - return recordedid; -} - -int Dvr::RecordedIdForPathname(const QString & pathname) -{ - uint recordedid = 0; - - if (!ProgramInfo::QueryRecordedIdFromPathname(pathname, recordedid)) - return -1; - - return recordedid; -} - -QString Dvr::RecStatusToString(int RecStatus) -{ - auto type = static_cast(RecStatus); - return RecStatus::toString(type); -} - -QString Dvr::RecStatusToDescription(int RecStatus, int recType, - const QDateTime &StartTime) -{ - //if (!StartTime.isValid()) - // throw QString("StartTime appears invalid."); - auto recstatusType = static_cast(RecStatus); - auto recordingType = static_cast(recType); - return RecStatus::toDescription(recstatusType, recordingType, StartTime); -} - -QString Dvr::RecTypeToString(const QString& recType) -{ - bool ok = false; - auto enumType = static_cast(recType.toInt(&ok, 10)); - if (ok) - return toString(enumType); - // RecordingType type = static_cast(recType); - return toString(recTypeFromString(recType)); -} - -QString Dvr::RecTypeToDescription(const QString& recType) -{ - bool ok = false; - auto enumType = static_cast(recType.toInt(&ok, 10)); - if (ok) - return toDescription(enumType); - // RecordingType type = static_cast(recType); - return toDescription(recTypeFromString(recType)); -} - -QString Dvr::DupInToString(const QString& DupIn) -{ - // RecordingDupInType type= static_cast(DupIn); - // return toString(type); - return toString(dupInFromString(DupIn)); -} - -QString Dvr::DupInToDescription(const QString& DupIn) -{ - // RecordingDupInType type= static_cast(DupIn); - //return toDescription(type); - return toDescription(dupInFromString(DupIn)); -} - -QString Dvr::DupMethodToString(const QString& DupMethod) -{ - // RecordingDupMethodType method = static_cast(DupMethod); - return toString(dupMethodFromString(DupMethod)); -} - -QString Dvr::DupMethodToDescription(const QString& DupMethod) -{ - // RecordingDupMethodType method = static_cast(DupMethod); - return toDescription(dupMethodFromString(DupMethod)); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -int Dvr::ManageJobQueue( const QString &sAction, - const QString &sJobName, - int nJobId, - int nRecordedId, - QDateTime jobstarttsRaw, - QString sRemoteHost, - QString sJobArgs ) -{ - int nReturn = -1; - - if (!m_parsedParams.contains("jobname") && - !m_parsedParams.contains("recordedid") ) - { - LOG(VB_GENERAL, LOG_ERR, "JobName and RecordedId are required."); - return nReturn; - } - - if (sRemoteHost.isEmpty()) - sRemoteHost = gCoreContext->GetHostName(); - - int jobType = JobQueue::GetJobTypeFromName(sJobName); - - if (jobType == JOB_NONE) - return nReturn; - - RecordingInfo ri = RecordingInfo(nRecordedId); - - if (!ri.GetChanID()) - return nReturn; - - if ( sAction == "Remove") - { - if (!m_parsedParams.contains("jobid") || nJobId < 0) - { - LOG(VB_GENERAL, LOG_ERR, "For Remove, a valid JobId is required."); - return nReturn; - } - - if (!JobQueue::SafeDeleteJob(nJobId, jobType, ri.GetChanID(), - ri.GetRecordingStartTime())) - return nReturn; - - return nJobId; - } - - if ( sAction != "Add") - { - LOG(VB_GENERAL, LOG_ERR, QString("Illegal Action name '%1'. Use: Add, " - "or Remove").arg(sAction)); - return nReturn; - } - - if (((jobType & JOB_USERJOB) != 0) && - gCoreContext->GetSetting(sJobName, "").isEmpty()) - { - LOG(VB_GENERAL, LOG_ERR, QString("%1 hasn't been defined.") - .arg(sJobName)); - return nReturn; - } - - if (!gCoreContext->GetBoolSettingOnHost(QString("JobAllow%1").arg(sJobName), - sRemoteHost, false)) - { - LOG(VB_GENERAL, LOG_ERR, QString("%1 hasn't been allowed on host %2.") - .arg(sJobName, sRemoteHost)); - return nReturn; - } - - if (!jobstarttsRaw.isValid()) - jobstarttsRaw = QDateTime::currentDateTime(); - - if (!JobQueue::InJobRunWindow(jobstarttsRaw)) - return nReturn; - - if (sJobArgs.isNull()) - sJobArgs = ""; - - bool bReturn = JobQueue::QueueJob(jobType, - ri.GetChanID(), - ri.GetRecordingStartTime(), - sJobArgs, - QString("Dvr/ManageJobQueue"), // comment col. - sRemoteHost, - JOB_NO_FLAGS, - JOB_QUEUED, - jobstarttsRaw.toUTC()); - - if (!bReturn) - { - LOG(VB_GENERAL, LOG_ERR, QString("%1 job wasn't queued because of a " - "database error or because it was " - "already running/stopping etc.") - .arg(sJobName)); - - return nReturn; - } - - return JobQueue::GetJobID(jobType, ri.GetChanID(), - ri.GetRecordingStartTime()); -} diff --git a/mythtv/programs/mythbackend/services/dvr.h b/mythtv/programs/mythbackend/services/dvr.h deleted file mode 100644 index d7337162a20..00000000000 --- a/mythtv/programs/mythbackend/services/dvr.h +++ /dev/null @@ -1,707 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: dvr.h -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef DVR_H -#define DVR_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -#include "libmythservicecontracts/services/dvrServices.h" - -class Dvr : public DvrServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Dvr( QObject */*parent*/ = nullptr ) {} - - public: - - DTC::ProgramList* GetExpiringList ( int StartIndex, - int Count ) override; // DvrServices - - DTC::ProgramList* GetRecordedList ( bool Descending, - int StartIndex, - int Count, - const QString &TitleRegEx, - const QString &RecGroup, - const QString &StorageGroup, - const QString &Category, - const QString &Sort, - bool IgnoreLiveTV, - bool IgnoreDeleted) override; // DvrServices - - DTC::ProgramList* GetOldRecordedList ( bool Descending, - int StartIndex, - int Count, - const QDateTime &StartTime, - const QDateTime &EndTime, - const QString &Title, - const QString &SeriesId, - int RecordId, - const QString &Sort) override; // DvrServices - - DTC::Program* GetRecorded ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw ) override; // DvrServices - - bool AddRecordedCredits ( int RecordedId, - const QJsonObject & json) override; - - int AddRecordedProgram ( const QJsonObject & json) override; - - bool RemoveRecorded ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - bool ForceDelete, - bool AllowRerecord ) override; // DvrServices - - bool DeleteRecording ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - bool ForceDelete, - bool AllowRerecord ) override; // DvrServices - - bool UnDeleteRecording ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw ) override; // DvrServices - - bool StopRecording ( int RecordedId ) override; // DvrServices - - bool ReactivateRecording ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw ) override; // DvrServices - - bool RescheduleRecordings( void ) override; // DvrServices - - bool AllowReRecord ( int RecordedId ) override; - - bool UpdateRecordedWatchedStatus ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - bool Watched) override; // DvrServices - - long GetSavedBookmark ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - const QString &OffsetType ) override; // DvrServices - - bool SetSavedBookmark ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - const QString &OffsetType, - long Offset - ) override; // DvrServices - - DTC::CutList* GetRecordedCutList ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - const QString &OffsetType ) override; // DvrServices - - DTC::CutList* GetRecordedCommBreak ( int RecordedId, - int ChanId, - const QDateTime &recstarttsRaw, - const QString &OffsetType ) override; // DvrServices - - DTC::CutList* GetRecordedSeek ( int RecordedId, - const QString &OffsetType ) override; // DvrServices - - DTC::MarkupList* GetRecordedMarkup ( int RecordedId ) override; // DvrServices - - bool SetRecordedMarkup ( int RecordedId, - const QJsonObject & json ) override; // DvrServices - - DTC::ProgramList* GetConflictList ( int StartIndex, - int Count, - int RecordId ) override; // DvrServices - - DTC::ProgramList* GetUpcomingList ( int StartIndex, - int Count, - bool ShowAll, - int RecordId, - int RecStatus ) override; // DvrServices - - DTC::EncoderList* GetEncoderList ( ) override; // DvrServices - - DTC::InputList* GetInputList ( ) override; // DvrServices - - QStringList GetRecGroupList ( ) override; // DvrServices - - QStringList GetProgramCategories ( bool OnlyRecorded ) override; // DvrServices - - QStringList GetRecStorageGroupList ( ) override; // DvrServices - - QStringList GetPlayGroupList ( ) override; // DvrServices - - DTC::RecRuleFilterList* GetRecRuleFilterList ( ) override; // DvrServices - - QStringList GetTitleList ( const QString &RecGroup ) override; // DvrServices - - DTC::TitleInfoList* GetTitleInfoList ( ) override; // DvrServices - - // Recording Rules - - uint AddRecordSchedule ( const QString& Title, - const QString& Subtitle, - const QString& Description, - const QString& Category, - const QDateTime& recstarttsRaw, - const QDateTime& recendtsRaw, - const QString& SeriesId, - const QString& ProgramId, - int ChanId, - const QString& Station, - int FindDay, - QTime FindTime, - int ParentId, - bool Inactive, - uint Season, - uint Episode, - const QString& Inetref, - QString Type, - QString SearchType, - int RecPriority, - uint PreferredInput, - int StartOffset, - int EndOffset, - const QDateTime& lastrectsRaw, - QString DupMethod, - QString DupIn, - bool NewEpisOnly, - uint Filter, - QString RecProfile, - QString RecGroup, - QString StorageGroup, - QString PlayGroup, - bool AutoExpire, - int MaxEpisodes, - bool MaxNewest, - bool AutoCommflag, - bool AutoTranscode, - bool AutoMetaLookup, - bool AutoUserJob1, - bool AutoUserJob2, - bool AutoUserJob3, - bool AutoUserJob4, - int Transcoder) override; // DvrServices - - bool UpdateRecordSchedule ( uint RecordId, - const QString& Title, - const QString& Subtitle, - const QString& Description, - const QString& Category, - const QDateTime& dStartTimeRaw, - const QDateTime& dEndTimeRaw, - const QString& SeriesId, - const QString& ProgramId, - int ChanId, - const QString& Station, - int FindDay, - QTime FindTime, - bool Inactive, - uint Season, - uint Episode, - const QString& Inetref, - QString Type, - QString SearchType, - int RecPriority, - uint PreferredInput, - int StartOffset, - int EndOffset, - QString DupMethod, - QString DupIn, - bool NewEpisOnly, - uint Filter, - QString RecProfile, - QString RecGroup, - QString StorageGroup, - QString PlayGroup, - bool AutoExpire, - int MaxEpisodes, - bool MaxNewest, - bool AutoCommflag, - bool AutoTranscode, - bool AutoMetaLookup, - bool AutoUserJob1, - bool AutoUserJob2, - bool AutoUserJob3, - bool AutoUserJob4, - int Transcoder) override; // DvrServices - - bool RemoveRecordSchedule ( uint RecordId ) override; // DvrServices - - bool AddDontRecordSchedule( int ChanId, - const QDateTime &StartTime, - bool NeverRecord ) override; // DvrServices - - DTC::RecRuleList* GetRecordScheduleList( int StartIndex, - int Count, - const QString &Sort, - bool Descending ) override; // DvrServices - - DTC::RecRule* GetRecordSchedule ( uint RecordId, - const QString& Template, - int nRecordedId, - int ChanId, - const QDateTime& dStartTimeRaw, - bool MakeOverride ) override; // DvrServices - - bool EnableRecordSchedule ( uint RecordId ) override; // DvrServices - - bool DisableRecordSchedule( uint RecordId ) override; // DvrServices - - int RecordedIdForKey( int ChanId, - const QDateTime &recstarttsRaw ) override; // DvrServices - - int RecordedIdForPathname( const QString &pathname ) override; // DvrServices - - QString RecStatusToString ( int RecStatus ) override; // DvrServices - - QString RecStatusToDescription ( int RecStatus, - int RecType, - const QDateTime &StartTime ) override; // DvrServices - - QString RecTypeToString ( const QString& RecType ) override; // DvrServices - - QString RecTypeToDescription ( const QString& RecType ) override; // DvrServices - - QString DupMethodToString ( const QString& DupMethod ) override; // DvrServices - - QString DupMethodToDescription ( const QString& DupMethod ) override; // DvrServices - - QString DupInToString ( const QString& DupIn ) override; // DvrServices - - QString DupInToDescription ( const QString& DupIn ) override; // DvrServices - - int ManageJobQueue ( const QString &Action, - const QString &JobName, - int JobId, - int RecordedId, - QDateTime jobstarttsRaw, - QString RemoteHost, - QString JobArgs ) override; // DvrServices - -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - - -#include -#if CONFIG_QTSCRIPT -class ScriptableDvr : public QObject -{ - Q_OBJECT - - private: - - Dvr m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableDvr( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QObject* GetExpiringList ( int StartIndex, - int Count ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetExpiringList( StartIndex, Count ); - ) - } - - QObject* GetRecordedList ( bool Descending, - int StartIndex, - int Count, - const QString &TitleRegEx, - const QString &RecGroup, - const QString &StorageGroup, - const QString &Category, - const QString &Sort, - bool IgnoreLiveTV, - bool IgnoreDeleted - ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetRecordedList( Descending, StartIndex, Count, - TitleRegEx, RecGroup, - StorageGroup, Category, Sort, - IgnoreLiveTV, IgnoreDeleted); - ) - } - - QObject* GetOldRecordedList ( bool Descending, - int StartIndex, - int Count, - const QDateTime &StartTime, - const QDateTime &EndTime, - const QString &Title, - const QString &SeriesId, - int RecordId, - const QString &Sort) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetOldRecordedList( Descending, StartIndex, Count, - StartTime, EndTime, Title, - SeriesId, RecordId, Sort); - ) - } - - QObject* GetRecorded ( int RecordedId ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetRecorded( RecordedId, 0, QDateTime() ); - ) - } - - bool RemoveRecorded ( int RecordedId, - bool ForceDelete, - bool AllowRerecord ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveRecorded( RecordedId, 0, QDateTime(), - ForceDelete, AllowRerecord ); - ) - } - - bool DeleteRecording ( int RecordedId, - bool ForceDelete, - bool AllowRerecord ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.DeleteRecording(RecordedId, 0, QDateTime(), - ForceDelete, AllowRerecord); - ) - } - - bool UnDeleteRecording ( int RecordedId ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.UnDeleteRecording(RecordedId, 0, QDateTime()); - ) - } - - QObject* GetConflictList ( int StartIndex, - int Count, - int RecordId ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetConflictList( StartIndex, Count, RecordId ); - ) - } - - QObject* GetUpcomingList ( int StartIndex, - int Count, - bool ShowAll, - int RecordId, - int RecStatus ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetUpcomingList( StartIndex, Count, ShowAll, - RecordId, RecStatus ); - ) - } - - QObject* GetEncoderList() - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetEncoderList(); - ) - } - - QObject* GetInputList() - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetInputList(); - ) - } - - QStringList GetRecGroupList() - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetRecGroupList(); - ) - } - - QStringList GetRecStorageGroupList() - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetRecStorageGroupList(); - ) - } - - QStringList GetPlayGroupList() - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetPlayGroupList(); - ) - } - - QObject* GetRecRuleFilterList() - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetRecRuleFilterList(); - ) - } - - QStringList GetTitleList( const QString &RecGroup ) - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetTitleList( RecGroup ); - ) - } - - QObject* GetTitleInfoList() - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetTitleInfoList(); - ) - } - - uint AddRecordSchedule ( DTC::RecRule *rule ) - { - SCRIPT_CATCH_EXCEPTION( 0, - return m_obj.AddRecordSchedule( - rule->Title(), rule->SubTitle(), - rule->Description(), rule->Category(), - rule->StartTime(), rule->EndTime(), - rule->SeriesId(), rule->ProgramId(), - rule->ChanId(), rule->CallSign(), - rule->FindDay(), rule->FindTime(), - rule->ParentId(), rule->Inactive(), - rule->Season(), rule->Episode(), - rule->Inetref(), rule->Type(), - rule->SearchType(), rule->RecPriority(), - rule->PreferredInput(), rule->StartOffset(), - rule->EndOffset(), rule->LastRecorded(), - rule->DupMethod(), - rule->DupIn(), rule->NewEpisOnly(), - rule->Filter(), - rule->RecProfile(), rule->RecGroup(), - rule->StorageGroup(), rule->PlayGroup(), - rule->AutoExpire(), rule->MaxEpisodes(), - rule->MaxNewest(), rule->AutoCommflag(), - rule->AutoTranscode(), rule->AutoMetaLookup(), - rule->AutoUserJob1(), rule->AutoUserJob2(), - rule->AutoUserJob3(), rule->AutoUserJob4(), - rule->Transcoder()); - ) - } - - bool UpdateRecordSchedule ( DTC::RecRule *rule ) - { - SCRIPT_CATCH_EXCEPTION( false, - - if (rule->Id() <= 0) - throw QString("Record ID cannot be <= zero"); - - return m_obj.UpdateRecordSchedule( - static_cast(rule->Id()), - rule->Title(), rule->SubTitle(), - rule->Description(), rule->Category(), - rule->StartTime(), rule->EndTime(), - rule->SeriesId(), rule->ProgramId(), - rule->ChanId(), rule->CallSign(), - rule->FindDay(), rule->FindTime(), - rule->Inactive(), - rule->Season(), rule->Episode(), - rule->Inetref(), rule->Type(), - rule->SearchType(), rule->RecPriority(), - rule->PreferredInput(), rule->StartOffset(), - rule->EndOffset(), rule->DupMethod(), - rule->DupIn(), rule->NewEpisOnly(), - rule->Filter(), - rule->RecProfile(), rule->RecGroup(), - rule->StorageGroup(), rule->PlayGroup(), - rule->AutoExpire(), rule->MaxEpisodes(), - rule->MaxNewest(), rule->AutoCommflag(), - rule->AutoTranscode(), rule->AutoMetaLookup(), - rule->AutoUserJob1(), rule->AutoUserJob2(), - rule->AutoUserJob3(), rule->AutoUserJob4(), - rule->Transcoder()); - ) - } - - bool RemoveRecordSchedule ( uint RecordId ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveRecordSchedule(RecordId); - ) - } - - bool AddDontRecordSchedule( int ChanId, - const QDateTime &StartTime, - bool NeverRecord ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.AddDontRecordSchedule(ChanId, StartTime, NeverRecord); - ) - } - - QObject* GetRecordScheduleList( int StartIndex, - int Count, - const QString &Sort, - bool Descending ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetRecordScheduleList(StartIndex, Count, Sort, Descending); - ) - } - - QObject* GetRecordSchedule ( uint RecordId, - const QString &Template, - int RecordedId, - int ChanId, - const QDateTime &StartTime, - bool MakeOverride ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetRecordSchedule( RecordId, Template, RecordedId, - ChanId, StartTime, MakeOverride); - ) - } - - bool EnableRecordSchedule ( uint RecordId ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.EnableRecordSchedule(RecordId); - ) - } - - bool DisableRecordSchedule( uint RecordId ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.DisableRecordSchedule(RecordId); - ) - } - - QString RecStatusToString( int RecStatus ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.RecStatusToString(RecStatus); - ) - } - - QString RecStatusToDescription( int RecStatus, - int RecType, - const QDateTime &StartTime ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.RecStatusToDescription(RecStatus, - RecType, - StartTime ); - ) - } - - QString RecTypeToString( const QString &RecType ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.RecTypeToString( RecType ); - ) - } - - QString RecTypeToDescription( const QString &RecType ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.RecTypeToDescription( RecType ); - ) - } - - QString DupMethodToString( const QString &DupMethod ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.DupMethodToString( DupMethod ); - ) - } - - QString DupMethodToDescription( const QString &DupMethod ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.DupMethodToDescription( DupMethod ); - ) - } - - QString DupInToString( const QString &DupIn ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.DupInToString( DupIn ); - ) - } - - QString DupInToDescription( const QString &DupIn ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.DupInToDescription( DupIn ); - ) - } - - int ManageJobQueue( const QString &Action, - const QString &JobName, - int JobId, - int RecordedId, - QDateTime JobStartTime, - QString RemoteHost, - QString JobArgs ) - - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.ManageJobQueue( Action, - JobName, - JobId, - RecordedId, - std::move(JobStartTime), - std::move(RemoteHost), - std::move(JobArgs) ); - ) - } - -}; - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableDvr, QObject*) -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/guide.cpp b/mythtv/programs/mythbackend/services/guide.cpp deleted file mode 100644 index fa3e20ad7bb..00000000000 --- a/mythtv/programs/mythbackend/services/guide.cpp +++ /dev/null @@ -1,616 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: guide.cpp -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// C++ -#include -#include - -// MythTV -#include "libmythbase/compat.h" -#include "libmythbase/mythcorecontext.h" -#include "libmythbase/mythlogging.h" -#include "libmythbase/mythversion.h" -#include "libmythbase/storagegroup.h" -#include "libmythtv/channelgroup.h" -#include "libmythtv/channelutil.h" - -// MythBackend -#include "autoexpire.h" -#include "scheduler.h" -#include "guide.h" - -// Qt6 has made the QFileInfo::QFileInfo(QString) constructor -// explicit, which means that it is no longer possible to use an -// initializer list to construct a QFileInfo. Disable that clang-tidy -// check for this file so it can still be run on the rest of the file -// in the project. -// -// NOLINTBEGIN(modernize-return-braced-init-list) - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ProgramGuide *Guide::GetProgramGuide( const QDateTime &rawStartTime, - const QDateTime &rawEndTime, - bool bDetails, - int nChannelGroupId, - int nStartIndex, - int nCount, - bool bWithInvisible) -{ - if (!rawStartTime.isValid()) - throw QString( "StartTime is invalid" ); - - if (!rawEndTime.isValid()) - throw QString( "EndTime is invalid" ); - - QDateTime dtStartTime = rawStartTime.toUTC(); - QDateTime dtEndTime = rawEndTime.toUTC(); - - if (dtEndTime < dtStartTime) - throw QString( "EndTime is before StartTime"); - - nStartIndex = std::max(nStartIndex, 0); - - if (nCount <= 0) - nCount = 20000; - - // ---------------------------------------------------------------------- - // Load the channel list - // ---------------------------------------------------------------------- - - uint nTotalAvailable = 0; - ChannelInfoList chanList = ChannelUtil::LoadChannels(nStartIndex, nCount, - nTotalAvailable, - !bWithInvisible, - ChannelUtil::kChanOrderByChanNum, - ChannelUtil::kChanGroupByCallsignAndChannum, - 0, - nChannelGroupId); - - // ---------------------------------------------------------------------- - // Build SQL statement for Program Listing - // ---------------------------------------------------------------------- - - ProgramList schedList; - MSqlBindings bindings; - - QString sWhere = "program.chanid = :CHANID " - "AND program.endtime >= :STARTDATE " - "AND program.starttime < :ENDDATE " - "AND program.starttime >= :STARTDATELIMIT " - "AND program.manualid = 0"; // Omit 'manual' recordings scheds - -#if 0 - QString sGroupBy = "program.starttime, channel.channum," - "channel.callsign, program.title"; -#endif - - QString sOrderBy = "program.starttime"; - - bindings[":STARTDATE" ] = dtStartTime; - bindings[":STARTDATELIMIT"] = dtStartTime.addDays(-1); - bindings[":ENDDATE" ] = dtEndTime; - - // ---------------------------------------------------------------------- - // Get all Pending Scheduled Programs - // ---------------------------------------------------------------------- - - // NOTE: Fetching this information directly from the schedule is - // significantly faster than using ProgramInfo::LoadFromScheduler() - auto *scheduler = dynamic_cast(gCoreContext->GetScheduler()); - if (scheduler) - scheduler->GetAllPending(schedList); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pGuide = new DTC::ProgramGuide(); - - ChannelInfoList::iterator chan_it; - for (chan_it = chanList.begin(); chan_it != chanList.end(); ++chan_it) - { - // Create ChannelInfo Object - DTC::ChannelInfo *pChannel = pGuide->AddNewChannel(); - FillChannelInfo( pChannel, (*chan_it), bDetails ); - - // Load the list of programmes for this channel - ProgramList progList; - bindings[":CHANID"] = (*chan_it).m_chanId; - LoadFromProgram( progList, sWhere, sOrderBy, sOrderBy, bindings, - schedList ); - - // Create Program objects and add them to the channel object - ProgramList::iterator progIt; - for( progIt = progList.begin(); progIt != progList.end(); ++progIt) - { - DTC::Program *pProgram = pChannel->AddNewProgram(); - FillProgramInfo( pProgram, *progIt, false, bDetails, false ); // No cast info - } - } - - // ---------------------------------------------------------------------- - - pGuide->setStartTime ( dtStartTime ); - pGuide->setEndTime ( dtEndTime ); - pGuide->setDetails ( bDetails ); - - pGuide->setStartIndex ( nStartIndex ); - pGuide->setCount ( chanList.size() ); - pGuide->setTotalAvailable( nTotalAvailable ); - pGuide->setAsOf ( MythDate::current() ); - - pGuide->setVersion ( MYTH_BINARY_VERSION ); - pGuide->setProtoVer ( MYTH_PROTO_VERSION ); - - return pGuide; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ProgramList* Guide::GetProgramList(int nStartIndex, - int nCount, - const QDateTime& rawStartTime, - const QDateTime& rawEndTime, - int nChanId, - const QString& sTitleFilter, - const QString& sCategoryFilter, - const QString& sPersonFilter, - const QString& sKeywordFilter, - bool bOnlyNew, - bool bDetails, - const QString &sSort, - bool bDescending, - bool bWithInvisible) -{ - if (!rawStartTime.isNull() && !rawStartTime.isValid()) - throw QString( "StartTime is invalid" ); - - if (!rawEndTime.isNull() && !rawEndTime.isValid()) - throw QString( "EndTime is invalid" ); - - QDateTime dtStartTime = rawStartTime; - const QDateTime& dtEndTime = rawEndTime; - - if (!rawEndTime.isNull() && dtEndTime < dtStartTime) - throw QString( "EndTime is before StartTime"); - - MSqlQuery query(MSqlQuery::InitCon()); - - - // ---------------------------------------------------------------------- - // Build SQL statement for Program Listing - // ---------------------------------------------------------------------- - - ProgramList progList; - ProgramList schedList; - MSqlBindings bindings; - - QString sSQL; - - if (!sPersonFilter.isEmpty()) - { - sSQL = ", people, credits " // LEFT JOIN - "WHERE people.name LIKE :PersonFilter " - "AND credits.person = people.person " - "AND program.chanid = credits.chanid " - "AND program.starttime = credits.starttime AND "; - bindings[":PersonFilter"] = QString("%%1%").arg(sPersonFilter); - } - else - { - sSQL = "WHERE "; - } - - if (bOnlyNew) - { - sSQL = "LEFT JOIN oldprogram ON oldprogram.oldtitle = program.title " - + sSQL - + "oldprogram.oldtitle IS NULL AND "; - } - - sSQL += "deleted IS NULL AND "; - - if (!bWithInvisible) - sSQL += "visible > 0 AND "; - - sSQL += "program.manualid = 0 "; // Exclude programmes created purely for 'manual' recording schedules - - nChanId = std::max(nChanId, 0); - - if (nChanId > 0) - { - sSQL += "AND program.chanid = :ChanId "; - bindings[":ChanId"] = nChanId; - } - - if (dtStartTime.isNull()) - dtStartTime = QDateTime::currentDateTimeUtc(); - - sSQL += " AND program.endtime >= :StartDate "; - bindings[":StartDate"] = dtStartTime; - - if (!dtEndTime.isNull()) - { - sSQL += "AND program.starttime <= :EndDate "; - bindings[":EndDate"] = dtEndTime; - } - - if (!sTitleFilter.isEmpty()) - { - sSQL += "AND program.title LIKE :Title "; - bindings[":Title"] = QString("%%1%").arg(sTitleFilter); - } - - if (!sCategoryFilter.isEmpty()) - { - sSQL += "AND program.category LIKE :Category "; - bindings[":Category"] = sCategoryFilter; - } - - if (!sKeywordFilter.isEmpty()) - { - sSQL += "AND (program.title LIKE :Keyword1 " - "OR program.subtitle LIKE :Keyword2 " - "OR program.description LIKE :Keyword3) "; - - QString filter = QString("%%1%").arg(sKeywordFilter); - bindings[":Keyword1"] = filter; - bindings[":Keyword2"] = filter; - bindings[":Keyword3"] = filter; - } - - if (sSort == "starttime") - sSQL += "ORDER BY program.starttime "; // NOLINT(bugprone-branch-clone) - else if (sSort == "title") - sSQL += "ORDER BY program.title "; - else if (sSort == "channel") - sSQL += "ORDER BY channel.channum "; - else if (sSort == "duration") - sSQL += "ORDER BY (program.endtime - program.starttime) "; - else - sSQL += "ORDER BY program.starttime "; - - if (bDescending) - sSQL += "DESC "; - else - sSQL += "ASC "; - - // ---------------------------------------------------------------------- - // Get all Pending Scheduled Programs - // ---------------------------------------------------------------------- - - // NOTE: Fetching this information directly from the schedule is - // significantly faster than using ProgramInfo::LoadFromScheduler() - auto *scheduler = dynamic_cast(gCoreContext->GetScheduler()); - if (scheduler) - scheduler->GetAllPending(schedList); - - // ---------------------------------------------------------------------- - - uint nTotalAvailable = 0; - LoadFromProgram( progList, sSQL, bindings, schedList, - (uint)nStartIndex, (uint)nCount, nTotalAvailable); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pPrograms = new DTC::ProgramList(); - - nCount = (int)progList.size(); - int nEndIndex = (int)progList.size(); - - for( int n = 0; n < nEndIndex; n++) - { - ProgramInfo *pInfo = progList[ n ]; - - DTC::Program *pProgram = pPrograms->AddNewProgram(); - - FillProgramInfo( pProgram, pInfo, true, bDetails, false ); // No cast info, loading this takes far too long - } - - // ---------------------------------------------------------------------- - - pPrograms->setStartIndex ( nStartIndex ); - pPrograms->setCount ( nCount ); - pPrograms->setTotalAvailable( nTotalAvailable ); - pPrograms->setAsOf ( MythDate::current() ); - pPrograms->setVersion ( MYTH_BINARY_VERSION ); - pPrograms->setProtoVer ( MYTH_PROTO_VERSION ); - - return pPrograms; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::Program* Guide::GetProgramDetails( int nChanId, - const QDateTime &rawStartTime ) - -{ - if (!(nChanId > 0)) - throw QString( "Channel ID is invalid" ); - if (!rawStartTime.isValid()) - throw QString( "StartTime is invalid" ); - - QDateTime dtStartTime = rawStartTime.toUTC(); - - // ---------------------------------------------------------------------- - // -=>TODO: Add support for getting Recorded Program Info - // ---------------------------------------------------------------------- - - // Build Response - - auto *pProgram = new DTC::Program(); - ProgramInfo *pInfo = LoadProgramFromProgram(nChanId, dtStartTime); - - FillProgramInfo( pProgram, pInfo, true, true, true ); - - delete pInfo; - - return pProgram; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QFileInfo Guide::GetChannelIcon( int nChanId, - int nWidth /* = 0 */, - int nHeight /* = 0 */ ) -{ - // Get Icon file path - - QString sFileName = ChannelUtil::GetIcon( nChanId ); - - if (sFileName.isEmpty()) - { - LOG(VB_UPNP, LOG_ERR, - QString("GetImageFile - ChanId %1 doesn't exist or isn't visible") - .arg(nChanId)); - return {}; - } - - // ------------------------------------------------------------------ - // Search for the filename - // ------------------------------------------------------------------ - - StorageGroup storage( "ChannelIcons" ); - const QString sFullFileName = storage.FindFile( sFileName ); - - if (sFullFileName.isEmpty()) - { - LOG(VB_UPNP, LOG_ERR, - QString("GetImageFile - Unable to find %1.").arg(sFileName)); - - return {}; - } - - // ---------------------------------------------------------------------- - // check to see if the file (still) exists - // ---------------------------------------------------------------------- - - if ((nWidth == 0) && (nHeight == 0)) - { - if (QFile::exists( sFullFileName )) - { - return QFileInfo( sFullFileName ); - } - - LOG(VB_UPNP, LOG_ERR, - QString("GetImageFile - File Does not exist %1.").arg(sFullFileName)); - - return {}; - } - // ------------------------------------------------------------------- - - QString sNewFileName = QString( "%1.%2x%3.png" ) - .arg( sFullFileName ) - .arg( nWidth ) - .arg( nHeight ); - - // ---------------------------------------------------------------------- - // check to see if image is already created. - // ---------------------------------------------------------------------- - - if (QFile::exists( sNewFileName )) - return QFileInfo( sNewFileName ); - - // ---------------------------------------------------------------------- - // We need to create it... - // ---------------------------------------------------------------------- - - QString sChannelsDirectory = QFileInfo( sNewFileName ).absolutePath(); - - if (!QFileInfo( sChannelsDirectory ).isWritable()) - { - LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - no write access to: %1") - .arg( sChannelsDirectory )); - return {}; - } - - auto *pImage = new QImage( sFullFileName ); - - if (!pImage) - { - LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - can't create image: %1") - .arg( sFullFileName )); - return {}; - } - - float fAspect = (float)(pImage->width()) / pImage->height(); - if (fAspect == 0) - { - LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - zero aspect")); - delete pImage; - return {}; - } - - if ( nWidth == 0 ) - nWidth = (int)std::rint(nHeight * fAspect); - - if ( nHeight == 0 ) - nHeight = (int)std::rint(nWidth / fAspect); - - QImage img = pImage->scaled( nWidth, nHeight, Qt::IgnoreAspectRatio, - Qt::SmoothTransformation); - - if (img.isNull()) - { - LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - unable to scale. " - "See if %1 is really an image.").arg( sFullFileName )); - delete pImage; - return {}; - } - - if (!img.save( sNewFileName, "PNG" )) - { - LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - failed, %1") - .arg( sNewFileName )); - delete pImage; - return {}; - } - - delete pImage; - - return QFileInfo( sNewFileName ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ChannelGroupList* Guide::GetChannelGroupList( bool bIncludeEmpty ) -{ - ChannelGroupList list = ChannelGroup::GetChannelGroups(bIncludeEmpty); - auto *pGroupList = new DTC::ChannelGroupList(); - - ChannelGroupList::iterator it; - for (it = list.begin(); it < list.end(); ++it) - { - DTC::ChannelGroup *pGroup = pGroupList->AddNewChannelGroup(); - FillChannelGroup(pGroup, (*it)); - } - - return pGroupList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Guide::GetCategoryList( ) //int nStartIndex, int nCount) -{ - QStringList catList; - MSqlQuery query(MSqlQuery::InitCon()); - - query.prepare("SELECT DISTINCT category FROM program WHERE category != '' " - "ORDER BY category"); - - if (!query.exec()) - return catList; - - while (query.next()) - { - catList << query.value(0).toString(); - } - - return catList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Guide::GetStoredSearches( const QString& sType ) -{ - QStringList keywordList; - MSqlQuery query(MSqlQuery::InitCon()); - - RecSearchType iType = searchTypeFromString(sType); - - if (iType == kNoSearch) - { - //throw QString( "Invalid Type" ); - return keywordList; - } - - query.prepare("SELECT DISTINCT phrase FROM keyword " - "WHERE searchtype = :TYPE " - "ORDER BY phrase"); - query.bindValue(":TYPE", static_cast(iType)); - - if (!query.exec()) - return keywordList; - - while (query.next()) - { - keywordList << query.value(0).toString(); - } - - return keywordList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Guide::AddToChannelGroup ( int nChannelGroupId, - int nChanId ) -{ - bool bResult = false; - - if (!(nChanId > 0)) - throw QString( "Channel ID is invalid" ); - - bResult = ChannelGroup::AddChannel(nChanId, nChannelGroupId); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Guide::RemoveFromChannelGroup ( int nChannelGroupId, - int nChanId ) -{ - bool bResult = false; - - if (!(nChanId > 0)) - throw QString( "Channel ID is invalid" ); - - bResult = ChannelGroup::DeleteChannel(nChanId, nChannelGroupId); - - return bResult; -} - -// NOLINTEND(modernize-return-braced-init-list) diff --git a/mythtv/programs/mythbackend/services/guide.h b/mythtv/programs/mythbackend/services/guide.h deleted file mode 100644 index cb6dcf66f6b..00000000000 --- a/mythtv/programs/mythbackend/services/guide.h +++ /dev/null @@ -1,226 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: guide.h -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef GUIDE_H -#define GUIDE_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -// MythTV -#include "libmythbase/programinfo.h" -#include "libmythservicecontracts/datacontracts/channelGroupList.h" -#include "libmythservicecontracts/datacontracts/programAndChannel.h" -#include "libmythservicecontracts/datacontracts/programList.h" -#include "libmythservicecontracts/services/guideServices.h" - -// MythBackend -#include "serviceUtil.h" - -class Guide : public GuideServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Guide( QObject */*parent*/ = nullptr ) {} - - public: - - - DTC::ProgramGuide* GetProgramGuide ( const QDateTime &StartTime , - const QDateTime &EndTime , - bool Details, - int ChannelGroupId, - int StartIndex, - int Count, - bool WithInvisible) override; // GuideServices - - DTC::ProgramList* GetProgramList ( int StartIndex, - int Count, - const QDateTime &StartTime , - const QDateTime &EndTime , - int ChanId, - const QString &TitleFilter, - const QString &CategoryFilter, - const QString &PersonFilter, - const QString &KeywordFilter, - bool OnlyNew, - bool Details, - const QString &Sort, - bool Descending, - bool WithInvisible) override; // GuideServices - - DTC::Program* GetProgramDetails ( int ChanId, - const QDateTime &StartTime ) override; // GuideServices - - QFileInfo GetChannelIcon ( int ChanId, - int Width , - int Height ) override; // GuideServices - - DTC::ChannelGroupList* GetChannelGroupList ( bool IncludeEmpty ) override; // GuideServices - - QStringList GetCategoryList ( ) override; // GuideServices - - QStringList GetStoredSearches( const QString &Type ) override; // GuideServices - - bool AddToChannelGroup ( int ChannelGroupId, - int ChanId ) override; // GuideServices - - bool RemoveFromChannelGroup ( int ChannelGroupId, - int ChanId ) override; // GuideServices -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableGuide : public QObject -{ - Q_OBJECT - - private: - - Guide m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableGuide( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QObject* GetProgramGuide( const QDateTime &StartTime , - const QDateTime &EndTime , - bool Details, - int ChannelGroupId, - int StartIndex, - int Count, - bool WithInvisible) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetProgramGuide( StartTime, EndTime, Details, - ChannelGroupId, StartIndex, Count, - WithInvisible ); - ) - } - - QObject* GetProgramList(int StartIndex, - int Count, - const QDateTime &StartTime, - const QDateTime &EndTime, - int ChanId, - const QString &TitleFilter, - const QString &CategoryFilter, - const QString &PersonFilter, - const QString &KeywordFilter, - bool OnlyNew, - bool Details, - const QString &Sort, - bool Descending, - bool WithInvisible) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetProgramList( StartIndex, Count, - StartTime, EndTime, ChanId, - TitleFilter, CategoryFilter, - PersonFilter, KeywordFilter, - OnlyNew, Details, - Sort, Descending, WithInvisible ); - ) - } - - QObject* GetProgramDetails( int ChanId, const QDateTime &StartTime ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetProgramDetails( ChanId, StartTime ); - ) - } - - //QFileInfo GetChannelIcon( int ChanId, int Width, int Height ) - //{ - // return m_obj.GetChannelIcon( ChanId, Width, Height ); - //} - - QObject* GetChannelGroupList( bool IncludeEmpty = false ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetChannelGroupList( IncludeEmpty ); - ) - } - - QStringList GetCategoryList( ) - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetCategoryList(); - ) - } - - QStringList GetStoredSearches( const QString& Type ) - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetStoredSearches( Type ); - ) - } - - bool AddToChannelGroup( int ChannelGroupId, - int ChanId ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.AddToChannelGroup( ChannelGroupId, ChanId ); - ) - } - - bool RemoveFromChannelGroup( int ChannelGroupId, - int ChanId ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveFromChannelGroup( ChannelGroupId, ChanId ); - ) - } -}; - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableGuide, QObject*); -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/image.cpp b/mythtv/programs/mythbackend/services/image.cpp deleted file mode 100644 index a4dd53bde43..00000000000 --- a/mythtv/programs/mythbackend/services/image.cpp +++ /dev/null @@ -1,225 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: image.cpp -// Created : Jul. 27, 2012 -// -// Copyright (c) 2012 Robert Siebert -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -//#include "libmythbase/mythcorecontext.h" - -#include "image.h" - -#define LOC QString("ImageService: ") - -/** - * \brief Returns the value of the specified exif tag from the image - file. If the filename or exif tag do not - exist or the tag has no contents, an empty value is returned. - * \param id The database id of the file - * \param tag The exif tag - * \return QString The exif tag value if successful, otherwise empty - */ -QString Image::GetImageInfo( int /*id*/, const QString &/*tag*/ ) -{ -// ImageManagerBe *mgr = ImageManagerBe::getInstance(); - -// // Find image in DB -// ImageList images; -// if (mgr->GetFiles(images, QString::number(id)) != 1) -// { -// qDeleteAll(images); -// LOG(VB_FILE, LOG_NOTICE, LOC + QString("Image %1 not found").arg(id)); -// return QString(); -// } - -// // Read all metadata tags -// ImageAdapterBase::TagMap tags; -// tags.insert(tag, qMakePair(QString(), QString())); - -// ImageItem *im = images[0]; -// bool found = mgr->HandleGetMetadata(id, tags); -// delete im; - -// if (found) -// return tags[tag].first; - -// LOG(VB_FILE, LOG_DEBUG, LOC + QString("Tag %1 not found for %2").arg(tag).arg(id)); - return {}; -} - - - -/** - * \brief Returns all values from all available exif tags - * \param id The database id of the file - * \return DTC::ImageMetadataInfoList The list with all exif values - */ -DTC::ImageMetadataInfoList* Image::GetImageInfoList(int id) -{ - // This holds the xml data structure from - // the returned stringlist with the exif data - auto *imInfoList = new DTC::ImageMetadataInfoList(); - - // Read all metadata tags -// ImageManagerBe *mgr = ImageManagerBe::getInstance(); - QStringList tags; // = mgr->HandleGetMetadata(QString::number(id)); - - if (tags.size() < 2 || tags[0] != "OK") - { - LOG(VB_FILE, LOG_NOTICE, LOC + - QString("Image %1 - %2").arg(id).arg(tags.join(","))); - return imInfoList; - } - tags.removeFirst(); - - // Set the general information of the image - imInfoList->setCount(tags.size()); -// imInfoList->setFile(im->m_filePath); -// imInfoList->setPath(im->m_path); -// imInfoList->setSize(im->m_size); -// imInfoList->setExtension(im->m_extension); - - // Each string contains a NameLabelValue. - QString seperator = tags.takeFirst(); - int index = 0; - for (const QString & token : std::as_const(tags)) - { - QStringList parts = token.split(seperator); - if (parts.size() != 3) - { - LOG(VB_GENERAL, LOG_ERR, LOC + - QString("Bad Metadata received: '%1' (%2)").arg(token, seperator)); - continue; - } - DTC::ImageMetadataInfo *imInfo = imInfoList->AddNewImageMetadataInfo(); - - imInfo->setNumber(index++); - imInfo->setTag(parts[0]); - imInfo->setLabel(parts[1]); - imInfo->setValue(parts[2]); - -#if defined(DUMP_METADATA_TAGS) && DUMP_METADATA_TAGS - LOG(VB_FILE, LOG_DEBUG, LOC + - QString("Metadata %1 : %2 : '%3'").arg(parts[0], parts[1], parts[2])); -#endif - } - return imInfoList; -} - - - -/*! - \brief Deletes an image file or dir subtree from filesystem and database - \param id Image - \return bool True if deleted, false otherwise -*/ -bool Image::RemoveImage( int id ) -{ - QStringList result = ImageManagerBe::getInstance()-> - HandleDelete(QString::number(id)); - return result[0] == "OK"; -} - - -/** - * \brief Renames the file to the new name. - * \param id The database id of the file - * \param newName The new name of the file (only the name, no path) - * \return bool True if renaming was successful, otherwise false - */ -bool Image::RenameImage( int id, const QString &newName) -{ - QStringList result = ImageManagerBe::getInstance()-> - HandleRename(QString::number(id), newName); - return result[0] == "OK"; -} - - -/** - * \brief Starts the synchronization of the images with the database - * \return bool True if the sync has started, otherwise false - */ -bool Image::StartSync( void ) -{ - QStringList result = ImageManagerBe::getInstance()->HandleScanRequest("START"); - return result.size() >= 2 && !result[1].isEmpty(); -} - - - -/** - * \brief Stops the image synchronization if its running - * \return bool True if the sync has stopped, otherwise false - */ -bool Image::StopSync( void ) -{ - QStringList result = ImageManagerBe::getInstance()->HandleScanRequest("STOP"); - return result.size() >= 2 && !result[1].isEmpty(); -} - - - -/** - * \brief Returns a list with information if the synchronization is - currently running, the already synchronized images and - the total amount of images that shall be synchronized. - * \return DTC::ImageSyncInfo The status information - */ -DTC::ImageSyncInfo* Image::GetSyncStatus( void ) -{ - // Default to No Scan - bool running = false; - int current = 0; - int total = 0; - - // Expects OK, scanner id, current#, total# - QStringList result = ImageManagerBe::getInstance()->HandleScanRequest("QUERY"); - if (result.size() == 4 && result[0] == "OK") - { - current = result[2].toInt(); - total = result[3].toInt(); - running = (current != total); - } - - LOG(VB_GENERAL, LOG_DEBUG, - QString("Image: Sync status is running: %1, current: %2, total: %3") - .arg(running).arg(current).arg(total)); - - auto *syncInfo = new DTC::ImageSyncInfo(); - syncInfo->setRunning(running); - syncInfo->setCurrent(current); - syncInfo->setTotal(total); - - return syncInfo; -} - -/*! - \brief Request creation of a thumbnail - \param id Image - \return bool True if image is valid -*/ -bool Image::CreateThumbnail(int id) -{ - QStringList mesg("0"); - mesg << QString::number(id); - ImageManagerBe::getInstance()->HandleCreateThumbnails(mesg); - return true; -} diff --git a/mythtv/programs/mythbackend/services/image.h b/mythtv/programs/mythbackend/services/image.h deleted file mode 100644 index d9f068fd97b..00000000000 --- a/mythtv/programs/mythbackend/services/image.h +++ /dev/null @@ -1,155 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: image.h -// Created : Jul. 27, 2012 -// -// Copyright (c) 2012 Robert Siebert -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or at your option any later version of the LGPL. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef IMAGE_H -#define IMAGE_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif -#include "libmythmetadata/imagemanager.h" -#include "libmythservicecontracts/services/imageServices.h" - - -class Image : public ImageServices -{ - Q_OBJECT - -public: - Q_INVOKABLE explicit Image( QObject */*parent*/ = nullptr ) {} - -public: - QString GetImageInfo ( int id, - const QString &tag ) override; // ImageServices - - DTC::ImageMetadataInfoList* GetImageInfoList ( int id ) override; // ImageServices - - bool RemoveImage ( int id ) override; // ImageServices - bool RenameImage ( int id, - const QString &newName ) override; // ImageServices - - bool StartSync ( void ) override; // ImageServices - bool StopSync ( void ) override; // ImageServices - DTC::ImageSyncInfo* GetSyncStatus ( void ) override; // ImageServices - - bool CreateThumbnail (int id) override; // ImageServices - -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableImage : public QObject -{ - Q_OBJECT - - private: - - Image m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableImage( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QString GetImageInfo( int Id, - const QString &Tag ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.GetImageInfo( Id, Tag ); - ) - } - - QObject* GetImageInfoList( int Id ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetImageInfoList( Id ); - ) - } - - bool RemoveImage( int Id ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveImage( Id ); - ) - } - - bool RenameImage( int Id, - const QString &NewName ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RenameImage( Id, NewName ); - ) - } - - bool StartSync( void ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.StartSync(); - ) - } - - bool StopSync( void ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.StopSync(); - ) - } - - QObject* GetSyncStatus( void ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetSyncStatus(); - ) - } - - bool CreateThumbnail ( int Id ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.CreateThumbnail( Id ); - ) - } -}; - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableImage, QObject*) -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/music.cpp b/mythtv/programs/mythbackend/services/music.cpp deleted file mode 100644 index e8eecf7c666..00000000000 --- a/mythtv/programs/mythbackend/services/music.cpp +++ /dev/null @@ -1,118 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: music.cpp -// Created : July 20, 2017 -// -// Copyright (c) 2017 Paul Harrison -// -// Licensed under the GPL v2 or later, see LICENSE for details -// -////////////////////////////////////////////////////////////////////////////// - -// C++ -#include -#include - -// MythTV -#include "libmythbase/mythversion.h" -#include "libmythmetadata/musicmetadata.h" - -// MythBackend -#include "music.h" -#include "serviceUtil.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::MusicMetadataInfoList* Music::GetTrackList(int nStartIndex, - int nCount) -{ - auto *all_music = new AllMusic(); - - while (!all_music->doneLoading()) - { - qApp->processEvents(); - usleep(50000); - } - - MetadataPtrList *musicList = all_music->getAllMetadata(); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pMusicMetadataInfos = new DTC::MusicMetadataInfoList(); - - int musicListCount = musicList->count(); - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, musicListCount ) : 0; - nCount = (nCount > 0) ? std::min( nCount, musicListCount ) : musicListCount; - int nEndIndex = std::min((nStartIndex + nCount), musicListCount ); - - for( int n = nStartIndex; n < nEndIndex; n++ ) - { - DTC::MusicMetadataInfo *pMusicMetadataInfo = pMusicMetadataInfos->AddNewMusicMetadataInfo(); - - MusicMetadata *metadata = musicList->at(n); - - if (metadata) - FillMusicMetadataInfo ( pMusicMetadataInfo, metadata, true ); - } - - int curPage = 0; - int totalPages = 0; - if (nCount == 0) - totalPages = 1; - else - totalPages = (int)std::ceil((float)musicList->count() / nCount); - - if (totalPages == 1) - curPage = 1; - else - { - curPage = (int)std::ceil((float)nStartIndex / nCount) + 1; - } - - pMusicMetadataInfos->setStartIndex ( nStartIndex ); - pMusicMetadataInfos->setCount ( nCount ); - pMusicMetadataInfos->setCurrentPage ( curPage ); - pMusicMetadataInfos->setTotalPages ( totalPages ); - pMusicMetadataInfos->setTotalAvailable( musicList->count() ); - pMusicMetadataInfos->setAsOf ( MythDate::current() ); - pMusicMetadataInfos->setVersion ( MYTH_BINARY_VERSION ); - pMusicMetadataInfos->setProtoVer ( MYTH_PROTO_VERSION ); - - delete all_music; - - return pMusicMetadataInfos; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::MusicMetadataInfo* Music::GetTrack(int Id) -{ - auto *all_music = new AllMusic(); - - while (!all_music->doneLoading()) - { - qApp->processEvents(); - usleep(50000); - } - - MusicMetadata *metadata = all_music->getMetadata(Id); - - if (!metadata) - { - delete all_music; - throw(QString("No metadata found for selected ID!.")); - } - - auto *pMusicMetadataInfo = new DTC::MusicMetadataInfo(); - - FillMusicMetadataInfo(pMusicMetadataInfo, metadata, true); - - delete all_music; - - return pMusicMetadataInfo; -} diff --git a/mythtv/programs/mythbackend/services/music.h b/mythtv/programs/mythbackend/services/music.h deleted file mode 100644 index dc681c1e7e8..00000000000 --- a/mythtv/programs/mythbackend/services/music.h +++ /dev/null @@ -1,94 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: music.h -// Created : July 20, 2017 -// -// Copyright (c) 2017 Paul Harrison -// -// Licensed under the GPL v2 or later, see LICENSE for details -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef MUSIC_H -#define MUSIC_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif -#include "libmythservicecontracts/services/musicServices.h" - -class Music : public MusicServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Music( QObject */*parent*/ = nullptr ) {} - - public: - - /* Music Metadata Methods */ - - DTC::MusicMetadataInfoList* GetTrackList ( int StartIndex, - int Count ) override; // MusicServices - - DTC::MusicMetadataInfo* GetTrack ( int Id ) override; // MusicServices - - -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableMusic : public QObject -{ - Q_OBJECT - - private: - - Music m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableMusic( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QObject* GetTrackList( int StartIndex, - int Count ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetTrackList(StartIndex, Count ); - ) - } - - QObject* GetTrack( int Id ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetTrack( Id ); - ) - } -}; - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableMusic, QObject*); -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/myth.cpp b/mythtv/programs/mythbackend/services/myth.cpp deleted file mode 100644 index 21a5667f9a9..00000000000 --- a/mythtv/programs/mythbackend/services/myth.cpp +++ /dev/null @@ -1,1160 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: myth.cpp -// Created : Jan. 19, 2010 -// -// Copyright (c) 2010 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// Qt -#include -#include -#include -#include -#include - -// MythTV -#include "libmythbase/dbutil.h" -#include "libmythbase/hardwareprofile.h" -#include "libmythbase/mythcorecontext.h" -#include "libmythbase/mythcoreutil.h" -#include "libmythbase/mythdate.h" -#include "libmythbase/mythdbcon.h" -#include "libmythbase/mythlogging.h" -#include "libmythbase/mythtimezone.h" -#include "libmythbase/mythversion.h" -#include "libmythbase/storagegroup.h" -#include "libmythbase/version.h" - -// MythBackend -#include "backendcontext.h" -#include "myth.h" -#include "scheduler.h" -#include "serviceUtil.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::ConnectionInfo* Myth::GetConnectionInfo( const QString &sPin ) -{ - QString sSecurityPin = gCoreContext->GetSetting( "SecurityPin", ""); - - if ( sSecurityPin.isEmpty() ) - throw( QString( "No Security Pin assigned. Run mythtv-setup to set one." )); - //SB: UPnPResult_HumanInterventionRequired, - - if ((sSecurityPin != "0000" ) && ( sPin != sSecurityPin )) - throw( QString( "Not Authorized" )); - //SB: UPnPResult_ActionNotAuthorized ); - - DatabaseParams params = GetMythDB()->GetDatabaseParams(); - - // ---------------------------------------------------------------------- - // Check for DBHostName of "localhost" and change to public name or IP - // ---------------------------------------------------------------------- - - QString sServerIP = gCoreContext->GetBackendServerIP(); - //QString sPeerIP = pRequest->GetPeerAddress(); - - if ((params.m_dbHostName.compare("localhost",Qt::CaseInsensitive)==0 - || params.m_dbHostName == "127.0.0.1" - || params.m_dbHostName == "::1") - && !sServerIP.isEmpty()) // && - //(sServerIP != sPeerIP )) - { - params.m_dbHostName = sServerIP; - } - - // If dbHostName is an IPV6 address with scope, - // remove the scope. Unescaped % signs are an - // xml violation - QString dbHostName(params.m_dbHostName); - QHostAddress addr; - if (addr.setAddress(dbHostName)) - { - addr.setScopeId(QString()); - dbHostName = addr.toString(); - } - // ---------------------------------------------------------------------- - // Create and populate a ConnectionInfo object - // ---------------------------------------------------------------------- - - auto *pInfo = new DTC::ConnectionInfo(); - DTC::DatabaseInfo *pDatabase = pInfo->Database(); - DTC::WOLInfo *pWOL = pInfo->WOL(); - DTC::VersionInfo *pVersion = pInfo->Version(); - - pDatabase->setHost ( dbHostName ); - pDatabase->setPing ( params.m_dbHostPing ); - pDatabase->setPort ( params.m_dbPort ); - pDatabase->setUserName ( params.m_dbUserName ); - pDatabase->setPassword ( params.m_dbPassword ); - pDatabase->setName ( params.m_dbName ); - pDatabase->setType ( params.m_dbType ); - pDatabase->setLocalEnabled ( params.m_localEnabled ); - pDatabase->setLocalHostName( params.m_localHostName ); - - pWOL->setEnabled ( params.m_wolEnabled ); - pWOL->setReconnect ( params.m_wolReconnect.count() ); - pWOL->setRetry ( params.m_wolRetry ); - pWOL->setCommand ( params.m_wolCommand ); - - pVersion->setVersion ( MYTH_SOURCE_VERSION ); - pVersion->setBranch ( MYTH_SOURCE_PATH ); - pVersion->setProtocol ( MYTH_PROTO_VERSION ); - pVersion->setBinary ( MYTH_BINARY_VERSION ); - pVersion->setSchema ( MYTH_DATABASE_VERSION ); - - // ---------------------------------------------------------------------- - // Return the pointer... caller is responsible to delete it!!! - // ---------------------------------------------------------------------- - - return pInfo; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::GetHostName( ) -{ - if (!gCoreContext) - throw( QString( "No MythCoreContext in GetHostName." )); - - return gCoreContext->GetHostName(); -} -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Myth::GetHosts( ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString( "Database not open while trying to load list of hosts" )); - - query.prepare( - "SELECT DISTINCTROW hostname " - "FROM settings " - "WHERE (not isNull( hostname ))"); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetHosts()", query); - - throw( QString( "Database Error executing query." )); - } - - // ---------------------------------------------------------------------- - // return the results of the query - // ---------------------------------------------------------------------- - - QStringList oList; - - while (query.next()) - oList.append( query.value(0).toString() ); - - return oList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QStringList Myth::GetKeys() -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to load settings")); - - query.prepare("SELECT DISTINCTROW value FROM settings;" ); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetKeys()", query); - - throw( QString( "Database Error executing query." )); - } - - // ---------------------------------------------------------------------- - // return the results of the query - // ---------------------------------------------------------------------- - - QStringList oResults; - - //pResults->setObjectName( "KeyList" ); - - while (query.next()) - oResults.append( query.value(0).toString() ); - - return oResults; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::StorageGroupDirList *Myth::GetStorageGroupDirs( const QString &sGroupName, - const QString &sHostName ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to list " - "Storage Group Dirs")); - - if (!sGroupName.isEmpty() && !sHostName.isEmpty()) - { - query.prepare("SELECT id, groupname, hostname, dirname " - "FROM storagegroup " - "WHERE groupname = :GROUP AND hostname = :HOST " - "ORDER BY groupname, hostname, dirname" ); - query.bindValue(":HOST", sHostName); - query.bindValue(":GROUP", sGroupName); - } - else if (!sHostName.isEmpty()) - { - query.prepare("SELECT id, groupname, hostname, dirname " - "FROM storagegroup " - "WHERE hostname = :HOST " - "ORDER BY groupname, hostname, dirname" ); - query.bindValue(":HOST", sHostName); - } - else if (!sGroupName.isEmpty()) - { - query.prepare("SELECT id, groupname, hostname, dirname " - "FROM storagegroup " - "WHERE groupname = :GROUP " - "ORDER BY groupname, hostname, dirname" ); - query.bindValue(":GROUP", sGroupName); - } - else - { - query.prepare("SELECT id, groupname, hostname, dirname " - "FROM storagegroup " - "ORDER BY groupname, hostname, dirname" ); - } - - if (!query.exec()) - { - MythDB::DBError("MythAPI::GetStorageGroupDirs()", query); - - throw( QString( "Database Error executing query." )); - } - - // ---------------------------------------------------------------------- - // return the results of the query plus R/W and size information - // ---------------------------------------------------------------------- - - auto* pList = new DTC::StorageGroupDirList(); - - while (query.next()) - { - DTC::StorageGroupDir *pStorageGroupDir = pList->AddNewStorageGroupDir(); - QFileInfo fi(query.value(3).toString()); - int64_t free = 0; - int64_t total = 0; - int64_t used = 0; - - free = getDiskSpace(query.value(3).toString(), total, used); - - pStorageGroupDir->setId ( query.value(0).toInt() ); - pStorageGroupDir->setGroupName ( query.value(1).toString() ); - pStorageGroupDir->setHostName ( query.value(2).toString() ); - pStorageGroupDir->setDirName ( query.value(3).toString() ); - pStorageGroupDir->setDirRead ( fi.isReadable() ); - pStorageGroupDir->setDirWrite ( fi.isWritable() ); - pStorageGroupDir->setKiBFree ( free ); - } - - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::AddStorageGroupDir( const QString &sGroupName, - const QString &sDirName, - const QString &sHostName ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to add Storage Group " - "dir")); - - if (sGroupName.isEmpty()) - throw ( QString( "Storage Group Required" )); - - if (sDirName.isEmpty()) - throw ( QString( "Directory Name Required" )); - - if (sHostName.isEmpty()) - throw ( QString( "HostName Required" )); - - query.prepare("SELECT COUNT(*) " - "FROM storagegroup " - "WHERE groupname = :GROUPNAME " - "AND dirname = :DIRNAME " - "AND hostname = :HOSTNAME;"); - query.bindValue(":GROUPNAME", sGroupName ); - query.bindValue(":DIRNAME" , sDirName ); - query.bindValue(":HOSTNAME" , sHostName ); - if (!query.exec()) - { - MythDB::DBError("MythAPI::AddStorageGroupDir()", query); - - throw( QString( "Database Error executing query." )); - } - - if (query.next()) - { - if (query.value(0).toInt() > 0) - return false; - } - - query.prepare("INSERT storagegroup " - "( groupname, dirname, hostname ) " - "VALUES " - "( :GROUPNAME, :DIRNAME, :HOSTNAME );"); - query.bindValue(":GROUPNAME", sGroupName ); - query.bindValue(":DIRNAME" , sDirName ); - query.bindValue(":HOSTNAME" , sHostName ); - - if (!query.exec()) - { - MythDB::DBError("MythAPI::AddStorageGroupDir()", query); - - throw( QString( "Database Error executing query." )); - } - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::RemoveStorageGroupDir( const QString &sGroupName, - const QString &sDirName, - const QString &sHostName ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - throw( QString("Database not open while trying to remove Storage " - "Group dir")); - - if (sGroupName.isEmpty()) - throw ( QString( "Storage Group Required" )); - - if (sDirName.isEmpty()) - throw ( QString( "Directory Name Required" )); - - if (sHostName.isEmpty()) - throw ( QString( "HostName Required" )); - - query.prepare("DELETE " - "FROM storagegroup " - "WHERE groupname = :GROUPNAME " - "AND dirname = :DIRNAME " - "AND hostname = :HOSTNAME;"); - query.bindValue(":GROUPNAME", sGroupName ); - query.bindValue(":DIRNAME" , sDirName ); - query.bindValue(":HOSTNAME" , sHostName ); - if (!query.exec()) - { - MythDB::DBError("MythAPI::AddStorageGroupDir()", query); - - throw( QString( "Database Error executing query." )); - } - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::TimeZoneInfo *Myth::GetTimeZone( ) -{ - auto *pResults = new DTC::TimeZoneInfo(); - - pResults->setTimeZoneID( MythTZ::getTimeZoneID() ); - pResults->setUTCOffset( MythTZ::calc_utc_offset() ); - pResults->setCurrentDateTime( MythDate::current(true) ); - - return pResults; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::GetFormatDate(const QDateTime &Date, bool ShortDate) -{ - uint dateFormat = MythDate::kDateFull | MythDate::kSimplify | MythDate::kAutoYear; - if (ShortDate) - dateFormat = MythDate::kDateShort | MythDate::kSimplify | MythDate::kAutoYear; - - return MythDate::toString(Date, dateFormat); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::GetFormatDateTime(const QDateTime &DateTime, bool ShortDate) -{ - uint dateFormat = MythDate::kDateTimeFull | MythDate::kSimplify | MythDate::kAutoYear; - if (ShortDate) - dateFormat = MythDate::kDateTimeShort | MythDate::kSimplify | MythDate::kAutoYear; - - return MythDate::toString(DateTime, dateFormat); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::GetFormatTime(const QDateTime &Time) -{ - return MythDate::toString(Time, MythDate::kTime); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QDateTime Myth::ParseISODateString(const QString& DateTimeString) -{ - QDateTime dateTime = QDateTime::fromString(DateTimeString, Qt::ISODate); - - if (!dateTime.isValid()) - throw QString( "Unable to parse DateTimeString" ); - - return dateTime; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::LogMessageList *Myth::GetLogs( const QString &HostName, - const QString &Application, - int PID, - int TID, - const QString &Thread, - const QString &Filename, - int Line, - const QString &Function, - const QDateTime &FromTime, - const QDateTime &ToTime, - const QString &Level, - const QString &MsgContains ) -{ - auto *pList = new DTC::LogMessageList(); - - MSqlQuery query(MSqlQuery::InitCon()); - - // Get host name list - QString sql = "SELECT DISTINCT host FROM logging ORDER BY host ASC"; - if (!query.exec(sql)) - { - MythDB::DBError("Retrieving log host names", query); - delete pList; - throw( QString( "Database Error executing query." )); - } - while (query.next()) - { - DTC::LabelValue *pLabelValue = pList->AddNewHostName(); - QString availableHostName = query.value(0).toString(); - pLabelValue->setValue ( availableHostName ); - pLabelValue->setActive ( availableHostName == HostName ); - pLabelValue->setSelected( availableHostName == HostName ); - } - // Get application list - sql = "SELECT DISTINCT application FROM logging ORDER BY application ASC"; - if (!query.exec(sql)) - { - MythDB::DBError("Retrieving log applications", query); - delete pList; - throw( QString( "Database Error executing query." )); - } - while (query.next()) - { - DTC::LabelValue *pLabelValue = pList->AddNewApplication(); - QString availableApplication = query.value(0).toString(); - pLabelValue->setValue ( availableApplication ); - pLabelValue->setActive ( availableApplication == Application ); - pLabelValue->setSelected( availableApplication == Application ); - } - - if (!HostName.isEmpty() && !Application.isEmpty()) - { - // Get log messages - sql = "SELECT host, application, pid, tid, thread, filename, " - " line, `function`, msgtime, level, message " - " FROM logging " - " WHERE host = COALESCE(:HOSTNAME, host) " - " AND application = COALESCE(:APPLICATION, application) " - " AND pid = COALESCE(:PID, pid) " - " AND tid = COALESCE(:TID, tid) " - " AND thread = COALESCE(:THREAD, thread) " - " AND filename = COALESCE(:FILENAME, filename) " - " AND line = COALESCE(:LINE, line) " - " AND `function` = COALESCE(:FUNCTION, `function`) " - " AND msgtime >= COALESCE(:FROMTIME, msgtime) " - " AND msgtime <= COALESCE(:TOTIME, msgtime) " - " AND level <= COALESCE(:LEVEL, level) " - ; - if (!MsgContains.isEmpty()) - { - sql.append(" AND message LIKE :MSGCONTAINS "); - } - sql.append(" ORDER BY msgtime ASC;"); - -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - QVariant ullNull = QVariant(QVariant::ULongLong); -#else - QVariant ullNull = QVariant(QMetaType(QMetaType::ULongLong)); -#endif - query.prepare(sql); - - query.bindValue(":HOSTNAME", (HostName.isEmpty()) ? QString() : HostName); - query.bindValue(":APPLICATION", (Application.isEmpty()) ? QString() : - Application); - query.bindValue(":PID", ( PID == 0 ) ? ullNull : (qint64)PID); - query.bindValue(":TID", ( TID == 0 ) ? ullNull : (qint64)TID); - query.bindValue(":THREAD", (Thread.isEmpty()) ? QString() : Thread); - query.bindValue(":FILENAME", (Filename.isEmpty()) ? QString() : Filename); - query.bindValue(":LINE", ( Line == 0 ) ? ullNull : (qint64)Line); - query.bindValue(":FUNCTION", (Function.isEmpty()) ? QString() : Function); - query.bindValue(":FROMTIME", (FromTime.isValid()) ? FromTime : QDateTime()); - query.bindValue(":TOTIME", (ToTime.isValid()) ? ToTime : QDateTime()); - query.bindValue(":LEVEL", (Level.isEmpty()) ? ullNull : - (qint64)logLevelGet(Level)); - - if (!MsgContains.isEmpty()) - { - query.bindValue(":MSGCONTAINS", "%" + MsgContains + "%" ); - } - - if (!query.exec()) - { - MythDB::DBError("Retrieving log messages", query); - delete pList; - throw( QString( "Database Error executing query." )); - } - - while (query.next()) - { - DTC::LogMessage *pLogMessage = pList->AddNewLogMessage(); - - pLogMessage->setHostName( query.value(0).toString() ); - pLogMessage->setApplication( query.value(1).toString() ); - pLogMessage->setPID( query.value(2).toInt() ); - pLogMessage->setTID( query.value(3).toInt() ); - pLogMessage->setThread( query.value(4).toString() ); - pLogMessage->setFilename( query.value(5).toString() ); - pLogMessage->setLine( query.value(6).toInt() ); - pLogMessage->setFunction( query.value(7).toString() ); - pLogMessage->setTime(MythDate::as_utc(query.value(8).toDateTime())); - pLogMessage->setLevel( logLevelGetName( - (LogLevel_t)query.value(9).toInt()) ); - pLogMessage->setMessage( query.value(10).toString() ); - } - } - - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::FrontendList *Myth::GetFrontends( bool OnLine ) -{ - auto *pList = new DTC::FrontendList(); - QMap frontends; - if (OnLine) - frontends = gBackendContext->GetConnectedFrontends(); - else - frontends = gBackendContext->GetFrontends(); - - for (auto * fe : std::as_const(frontends)) - { - DTC::Frontend *pFrontend = pList->AddNewFrontend(); - pFrontend->setName(fe->m_name); - pFrontend->setIP(fe->m_ip.toString()); - int port = gCoreContext->GetNumSettingOnHost("FrontendStatusPort", - fe->m_name, 6547); - pFrontend->setPort(port); - pFrontend->setOnLine(fe->m_connectionCount > 0); - } - - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::GetSetting( const QString &sHostName, - const QString &sKey, - const QString &sDefault ) -{ - if (sKey.isEmpty()) - throw( QString("Missing or empty Key (settings.value)") ); - - if (sHostName == "_GLOBAL_") - { - MSqlQuery query(MSqlQuery::InitCon()); - - query.prepare("SELECT data FROM settings " - "WHERE value = :VALUE " - "AND (hostname IS NULL)" ); - - query.bindValue(":VALUE", sKey ); - - if (!query.exec()) - { - MythDB::DBError("API Myth/GetSetting ", query); - throw( QString( "Database Error executing query." )); - } - - return query.next() ? query.value(0).toString() : sDefault; - } - - QString hostname = sHostName; - - if (sHostName.isEmpty()) - hostname = gCoreContext->GetHostName(); - - return gCoreContext->GetSettingOnHost(sKey, hostname, sDefault); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::SettingList *Myth::GetSettingList(const QString &sHostName) -{ - - MSqlQuery query(MSqlQuery::InitCon()); - - if (!query.isConnected()) - { - throw( QString("Database not open while trying to load settings for host: %1") - .arg( sHostName )); - } - - auto *pList = new DTC::SettingList(); - - //pList->setObjectName( "Settings" ); - pList->setHostName ( sHostName ); - - // ------------------------------------------------------------------ - // Looking to return all Setting for supplied hostname - // ------------------------------------------------------------------ - - if (sHostName.isEmpty()) - { - query.prepare("SELECT value, data FROM settings " - "WHERE (hostname IS NULL)" ); - } - else - { - query.prepare("SELECT value, data FROM settings " - "WHERE (hostname = :HOSTNAME)" ); - - query.bindValue(":HOSTNAME", sHostName ); - } - - if (!query.exec()) - { - // clean up unused object we created. - - delete pList; - - MythDB::DBError("MythAPI::GetSetting() w/o key ", query); - throw( QString( "Database Error executing query." )); - } - - while (query.next()) - pList->Settings().insert( query.value(0).toString(), query.value(1) ); - - return pList; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::PutSetting( const QString &sHostName, - const QString &sKey, - const QString &sValue ) -{ - if (!sKey.isEmpty()) - { - return gCoreContext->SaveSettingOnHost( sKey, sValue, sHostName ); - } - - throw ( QString( "Key Required" )); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::ChangePassword( const QString &sUserName, - const QString &sOldPassword, - const QString &sNewPassword ) -{ - LOG(VB_GENERAL, LOG_NOTICE, "ChangePassword is deprecated, use " - "ManageDigestUser."); - - return ( ManageDigestUser("ChangePassword", sUserName, sOldPassword, - sNewPassword, "") ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::TestDBSettings( const QString &sHostName, - const QString &sUserName, - const QString &sPassword, - const QString &sDBName, - int dbPort) -{ - bool bResult = false; - - QString db("mythconverg"); - int port = 3306; - - if (!sDBName.isEmpty()) - db = sDBName; - - if (dbPort != 0) - port = dbPort; - - bResult = TestDatabase(sHostName, sUserName, sPassword, db, port); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::SendMessage( const QString &sMessage, - const QString &sAddress, - int udpPort, - int Timeout) -{ - bool bResult = false; - - if (sMessage.isEmpty()) - return bResult; - - if (Timeout < 0 || Timeout > 999) - Timeout = 0; - - QString xmlMessage = - "\n" - " " + sMessage + "\n" - " " + QString::number(Timeout) + "\n" - ""; - - QHostAddress address = QHostAddress::Broadcast; - unsigned short port = 6948; - - if (!sAddress.isEmpty()) - address.setAddress(sAddress); - - if (udpPort != 0) - port = udpPort; - - auto *sock = new QUdpSocket(); - QByteArray utf8 = xmlMessage.toUtf8(); - int size = utf8.length(); - - if (sock->writeDatagram(utf8.constData(), size, address, port) < 0) - { - LOG(VB_GENERAL, LOG_ERR, - QString("Failed to send UDP/XML packet (Message: %1 " - "Address: %2 Port: %3") - .arg(sMessage, sAddress, QString::number(port))); - } - else - { - LOG(VB_GENERAL, LOG_DEBUG, - QString("UDP/XML packet sent! (Message: %1 Address: %2 Port: %3") - .arg(sMessage, - address.toString().toLocal8Bit(), - QString::number(port))); - bResult = true; - } - - sock->deleteLater(); - - return bResult; -} - -bool Myth::SendNotification( bool bError, - const QString &Type, - const QString &sMessage, - const QString &sOrigin, - const QString &sDescription, - const QString &sImage, - const QString &sExtra, - const QString &sProgressText, - float fProgress, - int Duration, - bool bFullscreen, - uint Visibility, - uint Priority, - const QString &sAddress, - int udpPort ) -{ - bool bResult = false; - - if (sMessage.isEmpty()) - return bResult; - - if (Duration < 0 || Duration > 999) - Duration = -1; - - QString xmlMessage = - "\n" - " " + sMessage + "\n" - " " + (sOrigin.isNull() ? tr("MythServices") : sOrigin) + "\n" - " " + sDescription + "\n" - " " + QString::number(Duration) + "\n" - " " + sImage + "\n" - " " + sExtra + "\n" - " " + sProgressText + "\n" - " " + QString::number(fProgress) + "\n" - " " + (bFullscreen ? "true" : "false") + "\n" - " " + QString::number(Visibility) + "\n" - " " + QString::number(Priority) + "\n" - " " + (bError ? "error" : Type) + "\n" - ""; - - QHostAddress address = QHostAddress::Broadcast; - unsigned short port = 6948; - - if (!sAddress.isEmpty()) - address.setAddress(sAddress); - - if (udpPort != 0) - port = udpPort; - - auto *sock = new QUdpSocket(); - QByteArray utf8 = xmlMessage.toUtf8(); - int size = utf8.length(); - - if (sock->writeDatagram(utf8.constData(), size, address, port) < 0) - { - LOG(VB_GENERAL, LOG_ERR, - QString("Failed to send UDP/XML packet (Notification: %1 " - "Address: %2 Port: %3") - .arg(sMessage, sAddress, QString::number(port))); - } - else - { - LOG(VB_GENERAL, LOG_DEBUG, - QString("UDP/XML packet sent! (Notification: %1 Address: %2 Port: %3") - .arg(sMessage, - address.toString().toLocal8Bit(), QString::number(port))); - bResult = true; - } - - sock->deleteLater(); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::BackupDatabase(void) -{ - bool bResult = false; - - DBUtil dbutil; - MythDBBackupStatus status = kDB_Backup_Unknown; - QString filename; - - LOG(VB_GENERAL, LOG_NOTICE, "Performing API invoked DB Backup."); - - status = DBUtil::BackupDB(filename); - - if (status == kDB_Backup_Completed) - { - LOG(VB_GENERAL, LOG_NOTICE, "Database backup succeeded."); - bResult = true; - } - else - { - LOG(VB_GENERAL, LOG_ERR, "Database backup failed."); - } - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::CheckDatabase( bool repair ) -{ - LOG(VB_GENERAL, LOG_NOTICE, "Performing API invoked DB Check."); - - bool bResult = DBUtil::CheckTables(repair); - - if (bResult) - LOG(VB_GENERAL, LOG_NOTICE, "Database check complete."); - else - LOG(VB_GENERAL, LOG_ERR, "Database check failed."); - - return bResult; -} - -bool Myth::DelayShutdown( void ) -{ - auto *scheduler = dynamic_cast(gCoreContext->GetScheduler()); - if (scheduler == nullptr) - return false; - scheduler->DelayShutdown(); - LOG(VB_GENERAL, LOG_NOTICE, "Shutdown delayed 5 minutes for external application."); - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::ProfileSubmit() -{ - HardwareProfile profile; - LOG(VB_GENERAL, LOG_NOTICE, "Profile Submission..."); - profile.GenerateUUIDs(); - bool bResult = profile.SubmitProfile(); - if (bResult) - LOG(VB_GENERAL, LOG_NOTICE, "Profile Submitted."); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::ProfileDelete() -{ - HardwareProfile profile; - LOG(VB_GENERAL, LOG_NOTICE, "Profile Deletion..."); - profile.GenerateUUIDs(); - bool bResult = profile.DeleteProfile(); - if (bResult) - LOG(VB_GENERAL, LOG_NOTICE, "Profile Deleted."); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::ProfileURL() -{ - QString sProfileURL; - - HardwareProfile profile; - profile.GenerateUUIDs(); - sProfileURL = profile.GetProfileURL(); - LOG(VB_GENERAL, LOG_NOTICE, QString("ProfileURL: %1").arg(sProfileURL)); - - return sProfileURL; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::ProfileUpdated() -{ - QString sProfileUpdate; - - HardwareProfile profile; - profile.GenerateUUIDs(); - QDateTime tUpdated; - tUpdated = profile.GetLastUpdate(); - sProfileUpdate = tUpdated.toString( - gCoreContext->GetSetting( "DateFormat", "MM.dd.yyyy")); - - return sProfileUpdate; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -QString Myth::ProfileText() -{ - QString sProfileText; - - HardwareProfile profile; - sProfileText = HardwareProfile::GetHardwareProfile(); - - return sProfileText; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::BackendInfo* Myth::GetBackendInfo( void ) -{ - - // ---------------------------------------------------------------------- - // Create and populate a Configuration object - // ---------------------------------------------------------------------- - - auto *pInfo = new DTC::BackendInfo(); - DTC::BuildInfo *pBuild = pInfo->Build(); - DTC::EnvInfo *pEnv = pInfo->Env(); - DTC::LogInfo *pLog = pInfo->Log(); - - pBuild->setVersion ( MYTH_SOURCE_VERSION ); - pBuild->setLibX264 ( CONFIG_LIBX264 ); - pBuild->setLibDNS_SD ( CONFIG_LIBDNS_SD ); - pEnv->setLANG ( qEnvironmentVariable("LANG") ); - pEnv->setLCALL ( qEnvironmentVariable("LC_ALL") ); - pEnv->setLCCTYPE ( qEnvironmentVariable("LC_CTYPE") ); - pEnv->setHOME ( qEnvironmentVariable("HOME") ); - pEnv->setMYTHCONFDIR ( qEnvironmentVariable("MYTHCONFDIR") ); - pLog->setLogArgs ( logPropagateArgs ); - - // ---------------------------------------------------------------------- - // Return the pointer... caller is responsible to delete it!!! - // ---------------------------------------------------------------------- - - return pInfo; - -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::ManageDigestUser( const QString &sAction, - const QString &sUserName, - const QString &sPassword, - const QString &sNewPassword, - const QString &sAdminPassword ) -{ - - DigestUserActions sessionAction = DIGEST_USER_ADD; - - if (sAction == "Add") - sessionAction = DIGEST_USER_ADD; - else if (sAction == "Remove") - sessionAction = DIGEST_USER_REMOVE; - else if (sAction == "ChangePassword") - sessionAction = DIGEST_USER_CHANGE_PW; - else - { - LOG(VB_GENERAL, LOG_ERR, QString("Action must be Add, Remove or " - "ChangePassword, not '%1'") - .arg(sAction)); - return false; - } - - return MythSessionManager::ManageDigestUser(sessionAction, sUserName, - sPassword, sNewPassword, - sAdminPassword); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Myth::ManageUrlProtection( const QString &sServices, - const QString &sAdminPassword ) -{ - if (!MythSessionManager::IsValidUser("admin")) - { - LOG(VB_GENERAL, LOG_ERR, QString("Backend has no '%1' user!") - .arg("admin")); - return false; - } - - if (MythSessionManager::CreateDigest("admin", sAdminPassword) != - MythSessionManager::GetPasswordDigest("admin")) - { - LOG(VB_GENERAL, LOG_ERR, QString("Incorrect password for user: %1") - .arg("admin")); - return false; - } - - QStringList serviceList = sServices.split(","); - - serviceList.removeDuplicates(); - - QStringList protectedURLs; - - if (serviceList.size() == 1 && serviceList.first() == "All") - { - for (const QString& service : KnownServices) - protectedURLs << '/' + service; - } - else if (serviceList.size() == 1 && serviceList.first() == "None") - { - protectedURLs << "Unprotected"; - } - else - { - for (const QString& service : std::as_const(serviceList)) - { - if (KnownServices.contains(service)) - protectedURLs << '/' + service; - else - LOG(VB_GENERAL, LOG_ERR, QString("Invalid service name: '%1'") - .arg(service)); - } - } - - if (protectedURLs.isEmpty()) - { - LOG(VB_GENERAL, LOG_ERR, "No valid Services were found"); - return false; - } - - return gCoreContext->SaveSettingOnHost("HTTP/Protected/Urls", - protectedURLs.join(';'), ""); -} diff --git a/mythtv/programs/mythbackend/services/myth.h b/mythtv/programs/mythbackend/services/myth.h deleted file mode 100644 index d51798d4902..00000000000 --- a/mythtv/programs/mythbackend/services/myth.h +++ /dev/null @@ -1,447 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: myth.h -// Created : Jan. 19, 2010 -// -// Copyright (c) 2010 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef MYTH_H -#define MYTH_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -#include "libmythservicecontracts/datacontracts/frontend.h" -#include "libmythservicecontracts/services/mythServices.h" - -class Myth : public MythServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Myth( QObject *parent = nullptr ) : MythServices( parent ) {} - - public: - - DTC::ConnectionInfo* GetConnectionInfo ( const QString &Pin ) override; // MythServices - - QString GetHostName ( ) override; // MythServices - QStringList GetHosts ( ) override; // MythServices - QStringList GetKeys ( ) override; // MythServices - - DTC::StorageGroupDirList* GetStorageGroupDirs ( const QString &GroupName, - const QString &HostName ) override; // MythServices - - bool AddStorageGroupDir ( const QString &GroupName, - const QString &DirName, - const QString &HostName ) override; // MythServices - - bool RemoveStorageGroupDir( const QString &GroupName, - const QString &DirName, - const QString &HostName ) override; // MythServices - - DTC::TimeZoneInfo* GetTimeZone ( ) override; // MythServices - - QString GetFormatDate ( const QDateTime &Date, - bool ShortDate ) override; // MythServices - QString GetFormatDateTime ( const QDateTime &DateTime, - bool ShortDate ) override; // MythServices - QString GetFormatTime ( const QDateTime &Time ) override; // MythServices - QDateTime ParseISODateString ( const QString &DateTime ) override; // MythServices - - DTC::LogMessageList* GetLogs ( const QString &HostName, - const QString &Application, - int PID, - int TID, - const QString &Thread, - const QString &Filename, - int Line, - const QString &Function, - const QDateTime &FromTime, - const QDateTime &ToTime, - const QString &Level, - const QString &MsgContains - ) override; // MythServices - - - DTC::FrontendList* GetFrontends ( bool OnLine ) override; // MythServices - - QString GetSetting ( const QString &HostName, - const QString &Key, - const QString &Default ) override; // MythServices - - DTC::SettingList* GetSettingList ( const QString &HostName ) override; // MythServices - - bool PutSetting ( const QString &HostName, - const QString &Key, - const QString &Value ) override; // MythServices - - bool ChangePassword ( const QString &UserName, - const QString &OldPassword, - const QString &NewPassword ) override; // MythServices - - bool TestDBSettings ( const QString &HostName, - const QString &UserName, - const QString &Password, - const QString &DBName, - int dbPort) override; // MythServices - - bool SendMessage ( const QString &Message, - const QString &Address, - int udpPort, - int Timeout) override; // MythServices - - bool SendNotification ( bool Error, - const QString &Type, - const QString &Message, - const QString &Origin, - const QString &Description, - const QString &Image, - const QString &Extra, - const QString &ProgressText, - float Progress, - int Duration, - bool Fullscreen, - uint Visibility, - uint Priority, - const QString &Address, - int udpPort ) override; // MythServices - - bool BackupDatabase ( void ) override; // MythServices - - bool CheckDatabase ( bool Repair ) override; // MythServices - - bool DelayShutdown ( void ) override; // MythServices - - bool ProfileSubmit ( void ) override; // MythServices - - bool ProfileDelete ( void ) override; // MythServices - - QString ProfileURL ( void ) override; // MythServices - - QString ProfileUpdated ( void ) override; // MythServices - - QString ProfileText ( void ) override; // MythServices - - DTC::BackendInfo* GetBackendInfo ( void ) override; // MythServices - - bool ManageDigestUser ( const QString &Action, - const QString &UserName, - const QString &Password, - const QString &NewPassword, - const QString &AdminPassword ) override; // MythServices - - bool ManageUrlProtection ( const QString &Services, - const QString &AdminPassword ) override; // MythServices -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableMyth : public QObject -{ - Q_OBJECT - - private: - - Myth m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableMyth( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QObject* GetConnectionInfo ( const QString &Pin ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetConnectionInfo( Pin ); - ) - } - - QString GetHostName() - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.GetHostName(); - ) - } - - QStringList GetHosts() - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetHosts(); - ) - } - - QStringList GetKeys() - { - SCRIPT_CATCH_EXCEPTION( QStringList(), - return m_obj.GetKeys(); - ) - } - - QObject* GetStorageGroupDirs ( const QString &GroupName, - const QString &HostName ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetStorageGroupDirs( GroupName, HostName ); - ) - } - - bool AddStorageGroupDir ( const QString &GroupName, - const QString &DirName, - const QString &HostName ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.AddStorageGroupDir( GroupName, DirName, HostName ); - ) - } - - bool RemoveStorageGroupDir ( const QString &GroupName, - const QString &DirName, - const QString &HostName ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveStorageGroupDir( GroupName, DirName, HostName ); - ) - } - - QObject* GetTimeZone() - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetTimeZone( ); - ) - } - - QString GetFormatDate( const QDateTime& Date, - bool ShortDate = false ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.GetFormatDate( Date, ShortDate ); - ) - } - - QString GetFormatDateTime( const QDateTime& DateTime, - bool ShortDate = false ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.GetFormatDateTime( DateTime, ShortDate ); - ) - } - - QString GetFormatTime( const QDateTime& Time ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.GetFormatTime( Time ); - ) - } - - QDateTime ParseISODateString( const QString &DateTime ) - { - SCRIPT_CATCH_EXCEPTION( QDateTime(), - return m_obj.ParseISODateString(DateTime); - ) - } - - QObject* GetLogs( const QString &HostName, - const QString &Application, - int PID, - int TID, - const QString &Thread, - const QString &Filename, - int Line, - const QString &Function, - const QDateTime &FromTime, - const QDateTime &ToTime, - const QString &Level, - const QString &MsgContains ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetLogs( HostName, Application, PID, TID, Thread, - Filename, Line, Function, FromTime, ToTime, - Level, MsgContains ); - ) - } - - QObject* GetFrontends( bool OnLine ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetFrontends( OnLine ); - ) - } - - QString GetSetting ( const QString &HostName, - const QString &Key, - const QString &Default ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.GetSetting( HostName, Key, Default ); - ) - } - - QObject* GetSettingList ( const QString &HostName ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetSettingList( HostName ); - ) - } - - bool PutSetting( const QString &HostName, - const QString &Key, - const QString &Value ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.PutSetting( HostName, Key, Value ); - ) - } - - bool TestDBSettings( const QString &HostName, - const QString &UserName, - const QString &Password, - const QString &DBName, - int dbPort) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.TestDBSettings( HostName, UserName, Password, - DBName, dbPort ); - ) - } - - bool SendMessage( const QString &Message, - const QString &Address, - int udpPort, - int Timeout) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.SendMessage( Message, Address, udpPort, Timeout ); - ) - } - - bool BackupDatabase( void ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.BackupDatabase(); - ) - } - - bool CheckDatabase( bool Repair ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.CheckDatabase( Repair ); - ) - } - - bool DelayShutdown( void ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.DelayShutdown(); - ) - } - - bool ProfileSubmit( void ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.ProfileSubmit(); - ) - } - - bool ProfileDelete( void ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.ProfileDelete(); - ) - } - - QString ProfileURL( void ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.ProfileURL(); - ) - } - - QString ProfileUpdated( void ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.ProfileUpdated(); - ) - } - - QString ProfileText( void ) - { - SCRIPT_CATCH_EXCEPTION( QString(), - return m_obj.ProfileText(); - ) - } - - QObject* GetBackendInfo( void ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetBackendInfo(); - ) - } - bool ManageDigestUser( const QString &Action, - const QString &UserName, - const QString &Password, - const QString &NewPassword, - const QString &AdminPassword ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.ManageDigestUser( Action, - UserName, - Password, - NewPassword, - AdminPassword ); - ) - } - bool ManageUrlProtection( const QString &Services, - const QString &AdminPassword ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.ManageUrlProtection( Services, AdminPassword ); - ) - } -}; - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableMyth, QObject*); -#endif - -#endif diff --git a/mythtv/programs/mythbackend/services/serviceUtil.cpp b/mythtv/programs/mythbackend/services/serviceUtil.cpp deleted file mode 100644 index eb4ffaf4274..00000000000 --- a/mythtv/programs/mythbackend/services/serviceUtil.cpp +++ /dev/null @@ -1,790 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: serviceUtil.cpp -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// Qt -#include -#include -#include - -// MythTV -#include "libmythbase/programinfo.h" -#include "libmythbase/recordingtypes.h" -#include "libmythmetadata/videoutils.h" -#include "libmythservicecontracts/datacontracts/cutList.h" -#include "libmythtv/cardutil.h" -#include "libmythtv/channelinfo.h" -#include "libmythtv/channelutil.h" -#include "libmythtv/metadataimagehelper.h" -#include "libmythtv/recordinginfo.h" - -// MythBackend -#include "serviceUtil.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillProgramInfo( DTC::Program *pProgram, - ProgramInfo *pInfo, - bool bIncChannel /* = true */, - bool bDetails /* = true */, - bool bIncCast /* = true */) -{ - if ((pProgram == nullptr) || (pInfo == nullptr)) - return; - - pProgram->setStartTime ( pInfo->GetScheduledStartTime()); - pProgram->setEndTime ( pInfo->GetScheduledEndTime ()); - pProgram->setTitle ( pInfo->GetTitle() ); - pProgram->setSubTitle ( pInfo->GetSubtitle() ); - pProgram->setCategory ( pInfo->GetCategory() ); - pProgram->setCatType ( pInfo->GetCategoryTypeString()); - pProgram->setRepeat ( pInfo->IsRepeat() ); - pProgram->setVideoProps( pInfo->GetVideoProperties() ); - pProgram->setVideoPropNames( pInfo->GetVideoPropertyNames() ); - pProgram->setAudioProps( pInfo->GetAudioProperties() ); - pProgram->setAudioPropNames( pInfo->GetAudioPropertyNames() ); - pProgram->setSubProps ( pInfo->GetSubtitleType() ); - pProgram->setSubPropNames( pInfo->GetSubtitleTypeNames() ); - - pProgram->setSerializeDetails( bDetails ); - - if (bDetails) - { - pProgram->setSeriesId ( pInfo->GetSeriesID() ); - pProgram->setProgramId ( pInfo->GetProgramID() ); - pProgram->setStars ( pInfo->GetStars() ); - pProgram->setLastModified( pInfo->GetLastModifiedTime() ); - pProgram->setProgramFlags( pInfo->GetProgramFlags() ); - pProgram->setProgramFlagNames( pInfo->GetProgramFlagNames() ); - - // ---- - // DEPRECATED - See RecordingInfo instead - pProgram->setFileName ( pInfo->GetPathname() ); - pProgram->setFileSize ( pInfo->GetFilesize() ); - pProgram->setHostName ( pInfo->GetHostname() ); - // ---- - - if (pInfo->GetOriginalAirDate().isValid()) - pProgram->setAirdate( pInfo->GetOriginalAirDate() ); - else if (pInfo->GetYearOfInitialRelease() > 0) - { - QDate year; - year.setDate(pInfo->GetYearOfInitialRelease(), 1, 1); - pProgram->setAirdate( year ); - } - - pProgram->setDescription( pInfo->GetDescription() ); - pProgram->setInetref ( pInfo->GetInetRef() ); - pProgram->setSeason ( pInfo->GetSeason() ); - pProgram->setEpisode ( pInfo->GetEpisode() ); - pProgram->setTotalEpisodes( pInfo->GetEpisodeTotal() ); - } - - pProgram->setSerializeCast(bIncCast); - if (bIncCast) - { - FillCastMemberList( pProgram->Cast(), pInfo ); - } - - pProgram->setSerializeChannel( bIncChannel ); - - if ( bIncChannel ) - { - // Build Channel Child Element - if (!FillChannelInfo( pProgram->Channel(), pInfo->GetChanID(), bDetails )) - { - // The channel associated with a given recording may no longer exist - // however the ChanID is one half of the unique identifier for the - // recording and therefore MUST be included in the return data - pProgram->Channel()->setChanId(pInfo->GetChanID()); - } - } - - // Build Recording Child Element - - if ( pInfo->GetRecordingStatus() != RecStatus::Unknown ) - { - pProgram->setSerializeRecording( true ); - - DTC::RecordingInfo *pRecording = pProgram->Recording(); - - const RecordingInfo pRecInfo(*pInfo); - - pRecording->setRecordedId ( pRecInfo.GetRecordingID() ); - pRecording->setStatus ( pRecInfo.GetRecordingStatus() ); - pRecording->setPriority( pRecInfo.GetRecordingPriority() ); - pRecording->setStartTs ( pRecInfo.GetRecordingStartTime() ); - pRecording->setEndTs ( pRecInfo.GetRecordingEndTime() ); - - pRecording->setSerializeDetails( bDetails ); - - if (bDetails) - { - pRecording->setFileName ( pRecInfo.GetPathname() ); - pRecording->setFileSize ( pRecInfo.GetFilesize() ); - pRecording->setHostName ( pRecInfo.GetHostname() ); - pRecording->setLastModified( pRecInfo.GetLastModifiedTime() ); - - pRecording->setRecordId ( pRecInfo.GetRecordingRuleID() ); - pRecording->setRecGroup ( pRecInfo.GetRecordingGroup() ); - pRecording->setPlayGroup ( pRecInfo.GetPlaybackGroup() ); - pRecording->setStorageGroup( pRecInfo.GetStorageGroup() ); - pRecording->setRecType ( pRecInfo.GetRecordingRuleType() ); - pRecording->setDupInType ( pRecInfo.GetDuplicateCheckSource() ); - pRecording->setDupMethod ( pRecInfo.GetDuplicateCheckMethod() ); - pRecording->setEncoderId ( pRecInfo.GetInputID() ); - pRecording->setEncoderName ( pRecInfo.GetInputName() ); - pRecording->setProfile ( pRecInfo.GetProgramRecordingProfile() ); - } - } - - if (!pInfo->GetInetRef().isEmpty() ) - { - pProgram->setSerializeArtwork( true ); - - FillArtworkInfoList( pProgram->Artwork(), pInfo->GetInetRef(), - pInfo->GetSeason()); - } -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool FillChannelInfo( DTC::ChannelInfo *pChannel, - uint nChanID, - bool bDetails /* = true */ ) -{ - ChannelInfo channel; - if (channel.Load(nChanID)) - { - return FillChannelInfo(pChannel, channel, bDetails); - } - - return false; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool FillChannelInfo( DTC::ChannelInfo *pChannel, - const ChannelInfo &channelInfo, - bool bDetails /* = true */ ) -{ - - // TODO update DTC::ChannelInfo to match functionality of ChannelInfo, - // ultimately replacing it's progenitor? - pChannel->setChanId(channelInfo.m_chanId); - pChannel->setChanNum(channelInfo.m_chanNum); - pChannel->setCallSign(channelInfo.m_callSign); - if (!channelInfo.m_icon.isEmpty()) - { - QString sIconURL = QString( "/Guide/GetChannelIcon?ChanId=%3") - .arg( channelInfo.m_chanId ); - pChannel->setIconURL( sIconURL ); - } - pChannel->setChannelName(channelInfo.m_name); - pChannel->setVisible(channelInfo.m_visible > kChannelNotVisible); - #ifndef _WIN32 // Needs fixing for Windows - pChannel->setExtendedVisible(toRawString(channelInfo.m_visible)); - #endif - - pChannel->setSerializeDetails( bDetails ); - - if (bDetails) - { - pChannel->setMplexId(channelInfo.m_mplexId); - pChannel->setServiceId(channelInfo.m_serviceId); - pChannel->setATSCMajorChan(channelInfo.m_atscMajorChan); - pChannel->setATSCMinorChan(channelInfo.m_atscMinorChan); - pChannel->setFormat(channelInfo.m_tvFormat); - pChannel->setFineTune(channelInfo.m_fineTune); - pChannel->setFrequencyId(channelInfo.m_freqId); - pChannel->setChanFilters(channelInfo.m_videoFilters); - pChannel->setSourceId(channelInfo.m_sourceId); - pChannel->setCommFree(channelInfo.m_commMethod == -2); - pChannel->setUseEIT(channelInfo.m_useOnAirGuide); - pChannel->setXMLTVID(channelInfo.m_xmltvId); - pChannel->setDefaultAuth(channelInfo.m_defaultAuthority); - pChannel->setServiceType(channelInfo.m_serviceType); - - QList groupIds = channelInfo.GetGroupIds(); - QString sGroupIds; - for (int x = 0; x < groupIds.size(); x++) - { - if (x > 0) - sGroupIds += ","; - - sGroupIds += QString::number(groupIds.at(x)); - } - pChannel->setChannelGroups(sGroupIds); - - QList inputIds = channelInfo.GetInputIds(); - QString sInputIds; - for (int x = 0; x < inputIds.size(); x++) - { - if (x > 0) - sInputIds += ","; - - sInputIds += QString::number(inputIds.at(x)); - } - pChannel->setInputs(sInputIds); - } - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillChannelGroup(DTC::ChannelGroup* pGroup, const ChannelGroupItem& pGroupItem) -{ - if (!pGroup) - return; - - pGroup->setGroupId(pGroupItem.m_grpId); - pGroup->setName(pGroupItem.m_name); - pGroup->setPassword(""); // Not currently supported -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillRecRuleInfo( DTC::RecRule *pRecRule, - RecordingRule *pRule ) -{ - if ((pRecRule == nullptr) || (pRule == nullptr)) - return; - - pRecRule->setId ( pRule->m_recordID ); - pRecRule->setParentId ( pRule->m_parentRecID ); - pRecRule->setInactive ( pRule->m_isInactive ); - pRecRule->setTitle ( pRule->m_title ); - pRecRule->setSubTitle ( pRule->m_subtitle ); - pRecRule->setDescription ( pRule->m_description ); - pRecRule->setSeason ( pRule->m_season ); - pRecRule->setEpisode ( pRule->m_episode ); - pRecRule->setCategory ( pRule->m_category ); - pRecRule->setStartTime ( QDateTime(pRule->m_startdate, - pRule->m_starttime, Qt::UTC)); - pRecRule->setEndTime ( QDateTime(pRule->m_enddate, - pRule->m_endtime, Qt::UTC)); - pRecRule->setSeriesId ( pRule->m_seriesid ); - pRecRule->setProgramId ( pRule->m_programid ); - pRecRule->setInetref ( pRule->m_inetref ); - pRecRule->setChanId ( pRule->m_channelid ); - pRecRule->setCallSign ( pRule->m_station ); - pRecRule->setFindDay ( pRule->m_findday ); - pRecRule->setFindTime ( pRule->m_findtime ); - pRecRule->setType ( toRawString(pRule->m_type) ); - pRecRule->setSearchType ( toRawString(pRule->m_searchType)); - pRecRule->setRecPriority ( pRule->m_recPriority ); - pRecRule->setPreferredInput ( pRule->m_prefInput ); - pRecRule->setStartOffset ( pRule->m_startOffset ); - pRecRule->setEndOffset ( pRule->m_endOffset ); - pRecRule->setDupMethod ( toRawString(pRule->m_dupMethod) ); - pRecRule->setDupIn ( toRawString(pRule->m_dupIn) ); - pRecRule->setNewEpisOnly ( newEpifromDupIn(pRule->m_dupIn) ); - pRecRule->setFilter ( pRule->m_filter ); - pRecRule->setRecProfile ( pRule->m_recProfile ); - pRecRule->setRecGroup ( RecordingInfo::GetRecgroupString(pRule->m_recGroupID) ); - pRecRule->setStorageGroup ( pRule->m_storageGroup ); - pRecRule->setPlayGroup ( pRule->m_playGroup ); - pRecRule->setAutoExpire ( pRule->m_autoExpire ); - pRecRule->setMaxEpisodes ( pRule->m_maxEpisodes ); - pRecRule->setMaxNewest ( pRule->m_maxNewest ); - pRecRule->setAutoCommflag ( pRule->m_autoCommFlag ); - pRecRule->setAutoTranscode ( pRule->m_autoTranscode ); - pRecRule->setAutoMetaLookup ( pRule->m_autoMetadataLookup ); - pRecRule->setAutoUserJob1 ( pRule->m_autoUserJob1 ); - pRecRule->setAutoUserJob2 ( pRule->m_autoUserJob2 ); - pRecRule->setAutoUserJob3 ( pRule->m_autoUserJob3 ); - pRecRule->setAutoUserJob4 ( pRule->m_autoUserJob4 ); - pRecRule->setTranscoder ( pRule->m_transcoder ); - pRecRule->setNextRecording ( pRule->m_nextRecording ); - pRecRule->setLastRecorded ( pRule->m_lastRecorded ); - pRecRule->setLastDeleted ( pRule->m_lastDeleted ); - pRecRule->setAverageDelay ( pRule->m_averageDelay ); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillArtworkInfoList( DTC::ArtworkInfoList *pArtworkInfoList, - const QString &sInetref, - uint nSeason ) -{ - ArtworkMap map = GetArtwork(sInetref, nSeason); - for (auto i = map.cbegin(); i != map.cend(); ++i) - { - DTC::ArtworkInfo *pArtInfo = pArtworkInfoList->AddNewArtworkInfo(); - pArtInfo->setFileName(i.value().url); - switch (i.key()) - { - case kArtworkFanart: - pArtInfo->setStorageGroup("Fanart"); - pArtInfo->setType("fanart"); - pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1" - "&FileName=%2") - .arg("Fanart", - QString(QUrl::toPercentEncoding( - QUrl(i.value().url).path())))); - break; - case kArtworkBanner: - pArtInfo->setStorageGroup("Banners"); - pArtInfo->setType("banner"); - pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1" - "&FileName=%2") - .arg("Banners", - QString(QUrl::toPercentEncoding( - QUrl(i.value().url).path())))); - break; - case kArtworkCoverart: - default: - pArtInfo->setStorageGroup("Coverart"); - pArtInfo->setType("coverart"); - pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1" - "&FileName=%2") - .arg("Coverart", - QString(QUrl::toPercentEncoding( - QUrl(i.value().url).path())))); - break; - } - } -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillGenreList(DTC::GenreList* pGenreList, int videoID) -{ - if (!pGenreList) - return; - - MSqlQuery query(MSqlQuery::InitCon()); - query.prepare("SELECT genre from videogenre " - "LEFT JOIN videometadatagenre ON videometadatagenre.idgenre = videogenre.intid " - "WHERE idvideo = :ID " - "ORDER BY genre;"); - query.bindValue(":ID", videoID); - - if (query.exec() && query.size() > 0) - { - while (query.next()) - { - DTC::Genre *pGenre = pGenreList->AddNewGenre(); - QString genre = query.value(0).toString(); - pGenre->setName(genre); - } - } -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillVideoMetadataInfo ( - DTC::VideoMetadataInfo *pVideoMetadataInfo, - const VideoMetadataListManager::VideoMetadataPtr& pMetadata, - bool bDetails) -{ - pVideoMetadataInfo->setId(pMetadata->GetID()); - pVideoMetadataInfo->setTitle(pMetadata->GetTitle()); - pVideoMetadataInfo->setSubTitle(pMetadata->GetSubtitle()); - pVideoMetadataInfo->setTagline(pMetadata->GetTagline()); - pVideoMetadataInfo->setDirector(pMetadata->GetDirector()); - pVideoMetadataInfo->setStudio(pMetadata->GetStudio()); - pVideoMetadataInfo->setDescription(pMetadata->GetPlot()); - pVideoMetadataInfo->setCertification(pMetadata->GetRating()); - pVideoMetadataInfo->setInetref(pMetadata->GetInetRef()); - pVideoMetadataInfo->setCollectionref(pMetadata->GetCollectionRef()); - pVideoMetadataInfo->setHomePage(pMetadata->GetHomepage()); - pVideoMetadataInfo->setReleaseDate( - QDateTime(pMetadata->GetReleaseDate(), - QTime(0,0),Qt::LocalTime).toUTC()); - pVideoMetadataInfo->setAddDate( - QDateTime(pMetadata->GetInsertdate(), - QTime(0,0),Qt::LocalTime).toUTC()); - pVideoMetadataInfo->setUserRating(pMetadata->GetUserRating()); - pVideoMetadataInfo->setChildID(pMetadata->GetChildID()); - pVideoMetadataInfo->setLength(pMetadata->GetLength().count()); - pVideoMetadataInfo->setPlayCount(pMetadata->GetPlayCount()); - pVideoMetadataInfo->setSeason(pMetadata->GetSeason()); - pVideoMetadataInfo->setEpisode(pMetadata->GetEpisode()); - pVideoMetadataInfo->setParentalLevel(pMetadata->GetShowLevel()); - pVideoMetadataInfo->setVisible(pMetadata->GetBrowse()); - pVideoMetadataInfo->setWatched(pMetadata->GetWatched()); - pVideoMetadataInfo->setProcessed(pMetadata->GetProcessed()); - pVideoMetadataInfo->setContentType(ContentTypeToString( - pMetadata->GetContentType())); - pVideoMetadataInfo->setFileName(pMetadata->GetFilename()); - pVideoMetadataInfo->setHash(pMetadata->GetHash()); - pVideoMetadataInfo->setHostName(pMetadata->GetHost()); - pVideoMetadataInfo->setCoverart(pMetadata->GetCoverFile()); - pVideoMetadataInfo->setFanart(pMetadata->GetFanart()); - pVideoMetadataInfo->setBanner(pMetadata->GetBanner()); - pVideoMetadataInfo->setScreenshot(pMetadata->GetScreenshot()); - pVideoMetadataInfo->setTrailer(pMetadata->GetTrailer()); - pVideoMetadataInfo->setSerializeArtwork( true ); - - if (bDetails) - { - if (!pMetadata->GetFanart().isEmpty()) - { - DTC::ArtworkInfo *pArtInfo = - pVideoMetadataInfo->Artwork()->AddNewArtworkInfo(); - pArtInfo->setStorageGroup("Fanart"); - pArtInfo->setType("fanart"); - pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1" - "&FileName=%2") - .arg("Fanart", - QString( - QUrl::toPercentEncoding(pMetadata->GetFanart())))); - } - if (!pMetadata->GetCoverFile().isEmpty()) - { - DTC::ArtworkInfo *pArtInfo = - pVideoMetadataInfo->Artwork()->AddNewArtworkInfo(); - pArtInfo->setStorageGroup("Coverart"); - pArtInfo->setType("coverart"); - pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1" - "&FileName=%2") - .arg("Coverart", - QString( - QUrl::toPercentEncoding(pMetadata->GetCoverFile())))); - } - if (!pMetadata->GetBanner().isEmpty()) - { - DTC::ArtworkInfo *pArtInfo = - pVideoMetadataInfo->Artwork()->AddNewArtworkInfo(); - pArtInfo->setStorageGroup("Banners"); - pArtInfo->setType("banner"); - pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1" - "&FileName=%2") - .arg("Banners", - QString( - QUrl::toPercentEncoding(pMetadata->GetBanner())))); - } - if (!pMetadata->GetScreenshot().isEmpty()) - { - DTC::ArtworkInfo *pArtInfo = - pVideoMetadataInfo->Artwork()->AddNewArtworkInfo(); - pArtInfo->setStorageGroup("Screenshots"); - pArtInfo->setType("screenshot"); - pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1" - "&FileName=%2") - .arg("Screenshots", - QString( - QUrl::toPercentEncoding(pMetadata->GetScreenshot())))); - } - } - - FillGenreList(pVideoMetadataInfo->Genres(), pVideoMetadataInfo->Id()); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillMusicMetadataInfo (DTC::MusicMetadataInfo *pVideoMetadataInfo, - MusicMetadata *pMetadata, bool bDetails) -{ - pVideoMetadataInfo->setId(pMetadata->ID()); - pVideoMetadataInfo->setArtist(pMetadata->Artist()); - pVideoMetadataInfo->setCompilationArtist(pMetadata->CompilationArtist()); - pVideoMetadataInfo->setAlbum(pMetadata->Album()); - pVideoMetadataInfo->setTitle(pMetadata->Title()); - pVideoMetadataInfo->setTrackNo(pMetadata->Track()); - pVideoMetadataInfo->setGenre(pMetadata->Genre()); - pVideoMetadataInfo->setYear(pMetadata->Year()); - pVideoMetadataInfo->setPlayCount(pMetadata->PlayCount()); - pVideoMetadataInfo->setLength(pMetadata->Length().count()); - pVideoMetadataInfo->setRating(pMetadata->Rating()); - pVideoMetadataInfo->setFileName(pMetadata->Filename()); - pVideoMetadataInfo->setHostName(pMetadata->Hostname()); - pVideoMetadataInfo->setLastPlayed(pMetadata->LastPlay()); - pVideoMetadataInfo->setCompilation(pMetadata->Compilation()); - - if (bDetails) - { - //TODO add coverart here - } -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillInputInfo(DTC::Input* input, const InputInfo& inputInfo) -{ - input->setId(inputInfo.m_inputId); - input->setInputName(inputInfo.m_name); - input->setCardId(inputInfo.m_inputId); - input->setSourceId(inputInfo.m_sourceId); - input->setDisplayName(inputInfo.m_displayName); - input->setLiveTVOrder(inputInfo.m_liveTvOrder); - input->setScheduleOrder(inputInfo.m_scheduleOrder); - input->setRecPriority(inputInfo.m_recPriority); - input->setQuickTune(inputInfo.m_quickTune); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillCastMemberList(DTC::CastMemberList* pCastMemberList, - ProgramInfo* pInfo) -{ - if (!pCastMemberList || !pInfo) - return; - - MSqlQuery query(MSqlQuery::InitCon()); - - QString table; - if (pInfo->GetFilesize() > 0) // FIXME: This shouldn't be the way to determine what is or isn't a recording! - table = "recordedcredits"; - else - table = "credits"; - - query.prepare(QString("SELECT role, people.name, roles.name FROM %1" - " AS credits" - " LEFT JOIN people ON" - " credits.person = people.person" - " LEFT JOIN roles ON" - " credits.roleid = roles.roleid" - " WHERE credits.chanid = :CHANID" - " AND credits.starttime = :STARTTIME" - " ORDER BY role, priority;").arg(table)); - - query.bindValue(":CHANID", pInfo->GetChanID()); - query.bindValue(":STARTTIME", pInfo->GetScheduledStartTime()); - - if (query.exec() && query.size() > 0) - { - QMap translations; - translations["ACTOR"] = QObject::tr("Actors"); - translations["DIRECTOR"] = QObject::tr("Director"); - translations["PRODUCER"] = QObject::tr("Producer"); - translations["EXECUTIVE_PRODUCER"] = QObject::tr("Executive Producer"); - translations["WRITER"] = QObject::tr("Writer"); - translations["GUEST_STAR"] = QObject::tr("Guest Star"); - translations["HOST"] = QObject::tr("Host"); - translations["ADAPTER"] = QObject::tr("Adapter"); - translations["PRESENTER"] = QObject::tr("Presenter"); - translations["COMMENTATOR"] = QObject::tr("Commentator"); - translations["GUEST"] = QObject::tr("Guest"); - - while (query.next()) - { - DTC::CastMember *pCastMember = pCastMemberList->AddNewCastMember(); - - QString role = query.value(0).toString(); - pCastMember->setRole(role); - pCastMember->setTranslatedRole(translations.value(role.toUpper())); - /* The people.name column uses utf8_bin collation. - * Qt-MySQL drivers use QVariant::ByteArray for string-type - * MySQL fields marked with the BINARY attribute (those using a - * *_bin collation) and QVariant::String for all others. - * Since QVariant::toString() uses QString::fromAscii() - * (through QVariant::convert()) when the QVariant's type is - * QVariant::ByteArray, we have to use QString::fromUtf8() - * explicitly to prevent corrupting characters. - * The following code should be changed to use the simpler - * toString() approach, as above, if we do a DB update to - * coalesce the people.name values that differ only in case and - * change the collation to utf8_general_ci, to match the - * majority of other columns, or we'll have the same problem in - * reverse. - */ - pCastMember->setName(QString::fromUtf8(query.value(1) - .toByteArray().constData())); - pCastMember->setCharacterName(QString::fromUtf8(query.value(2) - .toByteArray().constData())); - } - } - - //pCastMemberList->setCount(query.size()); - //pCastMemberList->setTotalAvailable(query.size()); -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillCutList(DTC::CutList* pCutList, RecordingInfo* rInfo, int marktype) -{ - frm_dir_map_t markMap; - frm_dir_map_t::const_iterator it; - - if (rInfo && rInfo->GetChanID()) - { - rInfo->QueryCutList(markMap); - - for (it = markMap.cbegin(); it != markMap.cend(); ++it) - { - bool isend = (*it) == MARK_CUT_END || (*it) == MARK_COMM_END; - if (marktype == 0) - { - DTC::Cutting *pCutting = pCutList->AddNewCutting(); - pCutting->setMark(*it); - pCutting->setOffset(it.key()); - } - else if (marktype == 1) - { - uint64_t offset = 0; - if (rInfo->QueryKeyFramePosition(&offset, it.key(), isend)) - { - DTC::Cutting *pCutting = pCutList->AddNewCutting(); - pCutting->setMark(*it); - pCutting->setOffset(offset); - } - } - else if (marktype == 2) - { - uint64_t offset = 0; - if (rInfo->QueryKeyFrameDuration(&offset, it.key(), isend)) - { - DTC::Cutting *pCutting = pCutList->AddNewCutting(); - pCutting->setMark(*it); - pCutting->setOffset(offset); - } - } - } - } -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillCommBreak(DTC::CutList* pCutList, RecordingInfo* rInfo, int marktype) -{ - frm_dir_map_t markMap; - frm_dir_map_t::const_iterator it; - - if (rInfo && rInfo->GetChanID()) - { - rInfo->QueryCommBreakList(markMap); - - for (it = markMap.cbegin(); it != markMap.cend(); ++it) - { - bool isend = (*it) == MARK_CUT_END || (*it) == MARK_COMM_END; - if (marktype == 0) - { - DTC::Cutting *pCutting = pCutList->AddNewCutting(); - pCutting->setMark(*it); - pCutting->setOffset(it.key()); - } - else if (marktype == 1) - { - uint64_t offset = 0; - if (rInfo->QueryKeyFramePosition(&offset, it.key(), isend)) - { - DTC::Cutting *pCutting = pCutList->AddNewCutting(); - pCutting->setMark(*it); - pCutting->setOffset(offset); - } - } - else if (marktype == 2) - { - uint64_t offset = 0; - if (rInfo->QueryKeyFrameDuration(&offset, it.key(), isend)) - { - DTC::Cutting *pCutting = pCutList->AddNewCutting(); - pCutting->setMark(*it); - pCutting->setOffset(offset); - } - } - } - } -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -void FillSeek(DTC::CutList* pCutList, RecordingInfo* rInfo, MarkTypes marktype) -{ - frm_pos_map_t markMap; - frm_pos_map_t::const_iterator it; - - if (rInfo && rInfo->GetChanID()) - { - rInfo->QueryPositionMap(markMap, marktype); - - for (it = markMap.cbegin(); it != markMap.cend(); ++it) - { - DTC::Cutting *pCutting = pCutList->AddNewCutting(); - pCutting->setMark(it.key()); - pCutting->setOffset(it.value()); - } - } -} - -int CreateRecordingGroup(const QString& groupName) -{ - int groupID = -1; - MSqlQuery query(MSqlQuery::InitCon()); - - query.prepare("INSERT INTO recgroups SET recgroup = :NAME, " - "displayname = :DISPLAYNAME"); - query.bindValue(":NAME", groupName); - query.bindValue(":DISPLAYNAME", groupName); - - if (query.exec()) - groupID = query.lastInsertId().toInt(); - - if (groupID <= 0) - LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). " - "Does it already exist?").arg(groupName)); - - return groupID; -} - -DBCredits * jsonCastToCredits(const QJsonObject &cast) -{ - int priority = 1; - auto* credits = new DBCredits; - - QJsonArray members = cast["CastMembers"].toArray(); - for (const auto & m : std::as_const(members)) - { - QJsonObject actor = m.toObject(); - QString name = actor.value("Name").toString(""); - QString character = actor.value("CharacterName").toString(""); - QString role = actor.value("Role").toString(""); - - credits->emplace_back(role, name, priority, character); - ++priority; - } - - return credits; -} diff --git a/mythtv/programs/mythbackend/services/serviceUtil.h b/mythtv/programs/mythbackend/services/serviceUtil.h deleted file mode 100644 index 48528fe2e72..00000000000 --- a/mythtv/programs/mythbackend/services/serviceUtil.h +++ /dev/null @@ -1,111 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: serviceUtil.h -// Created : Mar. 7, 2011 -// -// Copyright (c) 2011 David Blain -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef SERVICEUTIL_H -#define SERVICEUTIL_H - -// MythTV -#include "libmythbase/programinfo.h" -#include "libmythmetadata/musicmetadata.h" -#include "libmythmetadata/videometadatalistmanager.h" -#include "libmythservicecontracts/datacontracts/artworkInfoList.h" -#include "libmythservicecontracts/datacontracts/castMemberList.h" -#include "libmythservicecontracts/datacontracts/channelGroup.h" -#include "libmythservicecontracts/datacontracts/cutList.h" -#include "libmythservicecontracts/datacontracts/genreList.h" -#include "libmythservicecontracts/datacontracts/input.h" -#include "libmythservicecontracts/datacontracts/musicMetadataInfo.h" -#include "libmythservicecontracts/datacontracts/programAndChannel.h" -#include "libmythservicecontracts/datacontracts/recRule.h" -#include "libmythservicecontracts/datacontracts/videoMetadataInfo.h" -#include "libmythtv/channelgroup.h" -#include "libmythtv/channelinfo.h" -#include "libmythtv/inputinfo.h" -#include "libmythtv/programdata.h" -#include "libmythtv/recordinginfo.h" -#include "libmythtv/recordingrule.h" - -template -static inline void -ADD_SQL(QString& settings_var, MSqlBindings& bindvar, - const QString& col, const QString& api_param, const T& val) -{ - settings_var += QString("%1=:%2, ").arg(col, api_param); - bindvar[QString(":").append(api_param)] = val; -} - -const QStringList KnownServices = { "Capture", "Channel", "Content", \ - "Dvr", "Guide", "Music", \ - "Myth", "Video" }; - -void FillProgramInfo( DTC::Program *pProgram, - ProgramInfo *pInfo, - bool bIncChannel = true, - bool bDetails = true, - bool bIncCast = true); - -bool FillChannelInfo( DTC::ChannelInfo *pChannel, - uint nChanID, - bool bDetails = true ); - -bool FillChannelInfo( DTC::ChannelInfo *pChannel, - const ChannelInfo &channelInfo, - bool bDetails = true ); - -void FillChannelGroup( DTC::ChannelGroup *pGroup, const ChannelGroupItem& pGroupItem); - -void FillRecRuleInfo( DTC::RecRule *pRecRule, - RecordingRule *pRule ); - -void FillArtworkInfoList( DTC::ArtworkInfoList *pArtworkInfoList, - const QString &sInetref, - uint nSeason ); - -void FillGenreList( DTC::GenreList *pGenreList, int videoID); - -void FillVideoMetadataInfo ( - DTC::VideoMetadataInfo *pVideoMetadataInfo, - const VideoMetadataListManager::VideoMetadataPtr& pMetadata, - bool bDetails); - -void FillMusicMetadataInfo (DTC::MusicMetadataInfo *pVideoMetadataInfo, - MusicMetadata *pMetadata, bool bDetails); - -void FillInputInfo( DTC::Input *input, const InputInfo& inputInfo); - -void FillCastMemberList( DTC::CastMemberList *pCastMemberList, - ProgramInfo *pInfo); - -void FillCutList( DTC::CutList* pCutList, RecordingInfo* rInfo, int marktype); - -void FillCommBreak( DTC::CutList* pCutList, RecordingInfo* rInfo, int marktype); - -void FillSeek(DTC::CutList* pCutList, RecordingInfo* rInfo, MarkTypes marktype); - -int CreateRecordingGroup(const QString& groupName); - -DBCredits * jsonCastToCredits(const QJsonObject &cast); - -#endif // SERVICEUTIL_H diff --git a/mythtv/programs/mythbackend/services/video.cpp b/mythtv/programs/mythbackend/services/video.cpp deleted file mode 100644 index 038d975c38a..00000000000 --- a/mythtv/programs/mythbackend/services/video.cpp +++ /dev/null @@ -1,923 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: video.cpp -// Created : Apr. 21, 2011 -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -// C++ -#include - -// Qt -#include -#include -#include - -// MythTV -#include "libmythbase/compat.h" -#include "libmythbase/mythcorecontext.h" -#include "libmythbase/mythdate.h" -#include "libmythbase/mythmiscutil.h" -#include "libmythbase/mythversion.h" -#include "libmythbase/remotefile.h" -#include "libmythbase/storagegroup.h" -#include "libmythmetadata/bluraymetadata.h" -#include "libmythmetadata/globals.h" -#include "libmythmetadata/metadatafactory.h" -#include "libmythmetadata/videometadata.h" -#include "libmythtv/mythavutil.h" - -// MythBackend -#include "serviceUtil.h" -#include "video.h" - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoMetadataInfoList* Video::GetVideoList( const QString &Folder, - const QString &Sort, - bool bDescending, - int nStartIndex, - int nCount ) -{ - QString fields = "title,director,studio,plot,rating,year,releasedate," - "userrating,length,playcount,filename,hash,showlevel," - "coverfile,inetref,collectionref,homepage,childid,browse,watched," - "playcommand,category,intid,trailer,screenshot,banner,fanart," - "subtitle,tagline,season,episode,host,insertdate,processed,contenttype"; - - QStringList sortFields = fields.split(','); - - VideoMetadataListManager::metadata_list videolist; - - QString sql = ""; - if (!Folder.isEmpty()) - sql.append(" WHERE filename LIKE '" + Folder + "%'"); - - sql.append(" ORDER BY "); - QString sort = Sort.toLower(); - if (sort == "added") - sql.append("insertdate"); - else if (sort == "released") - sql.append("releasedate"); - else if (sortFields.contains(sort)) - sql.append(sort); - else - sql.append("intid"); - - if (bDescending) - sql += " DESC"; - VideoMetadataListManager::loadAllFromDatabase(videolist, sql); - - std::vector videos(videolist.begin(), videolist.end()); - - // ---------------------------------------------------------------------- - // Build Response - // ---------------------------------------------------------------------- - - auto *pVideoMetadataInfos = new DTC::VideoMetadataInfoList(); - - nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)videos.size() ) : 0; - nCount = (nCount > 0) ? std::min( nCount, (int)videos.size() ) : videos.size(); - int nEndIndex = std::min((nStartIndex + nCount), (int)videos.size() ); - - for( int n = nStartIndex; n < nEndIndex; n++ ) - { - DTC::VideoMetadataInfo *pVideoMetadataInfo = pVideoMetadataInfos->AddNewVideoMetadataInfo(); - - const VideoMetadataListManager::VideoMetadataPtr& metadata = videos[n]; - - if (metadata) - FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true ); - } - - int curPage = 0; - int totalPages = 0; - if (nCount == 0) - totalPages = 1; - else - totalPages = (int)ceil((float)videos.size() / nCount); - - if (totalPages == 1) - curPage = 1; - else - { - curPage = (int)ceil((float)nStartIndex / nCount) + 1; - } - - pVideoMetadataInfos->setStartIndex ( nStartIndex ); - pVideoMetadataInfos->setCount ( nCount ); - pVideoMetadataInfos->setCurrentPage ( curPage ); - pVideoMetadataInfos->setTotalPages ( totalPages ); - pVideoMetadataInfos->setTotalAvailable( videos.size() ); - pVideoMetadataInfos->setAsOf ( MythDate::current() ); - pVideoMetadataInfos->setVersion ( MYTH_BINARY_VERSION ); - pVideoMetadataInfos->setProtoVer ( MYTH_PROTO_VERSION ); - - return pVideoMetadataInfos; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoMetadataInfo* Video::GetVideo( int Id ) -{ - VideoMetadataListManager::VideoMetadataPtr metadata = - VideoMetadataListManager::loadOneFromDatabase(Id); - - if ( !metadata ) - throw( QString( "No metadata found for selected ID!." )); - - auto *pVideoMetadataInfo = new DTC::VideoMetadataInfo(); - - FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true ); - - return pVideoMetadataInfo; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoMetadataInfo* Video::GetVideoByFileName( const QString &FileName ) -{ - VideoMetadataListManager::metadata_list videolist; - VideoMetadataListManager::loadAllFromDatabase(videolist); - QScopedPointer mlm(new VideoMetadataListManager()); - mlm->setList(videolist); - VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byFilename(FileName); - - if ( !metadata ) - throw( QString( "No metadata found for selected filename!." )); - - auto *pVideoMetadataInfo = new DTC::VideoMetadataInfo(); - - FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true ); - - return pVideoMetadataInfo; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoLookupList* Video::LookupVideo( const QString &Title, - const QString &Subtitle, - const QString &Inetref, - int Season, - int Episode, - const QString &GrabberType, - bool AllowGeneric ) -{ - auto *pVideoLookups = new DTC::VideoLookupList(); - - MetadataLookupList list; - - auto *factory = new MetadataFactory(nullptr); - - if (factory) - { - list = factory->SynchronousLookup(Title, Subtitle, - Inetref, Season, Episode, - GrabberType, AllowGeneric); - } - - if ( list.empty() ) - return pVideoLookups; - - //MetadataLookupList is a reference counted list. - //it will delete all its content at its end of life - for(const auto & lookup : std::as_const(list)) - { - DTC::VideoLookup *pVideoLookup = pVideoLookups->AddNewVideoLookup(); - - if (lookup) - { - pVideoLookup->setTitle(lookup->GetTitle()); - pVideoLookup->setSubTitle(lookup->GetSubtitle()); - pVideoLookup->setSeason(lookup->GetSeason()); - pVideoLookup->setEpisode(lookup->GetEpisode()); - pVideoLookup->setYear(lookup->GetYear()); - pVideoLookup->setTagline(lookup->GetTagline()); - pVideoLookup->setDescription(lookup->GetDescription()); - pVideoLookup->setCertification(lookup->GetCertification()); - pVideoLookup->setInetref(lookup->GetInetref()); - pVideoLookup->setCollectionref(lookup->GetCollectionref()); - pVideoLookup->setHomePage(lookup->GetHomepage()); - pVideoLookup->setReleaseDate( - QDateTime(lookup->GetReleaseDate(), - QTime(0,0),Qt::LocalTime).toUTC()); - pVideoLookup->setUserRating(lookup->GetUserRating()); - pVideoLookup->setLength(lookup->GetRuntime().count()); - pVideoLookup->setLanguage(lookup->GetLanguage()); - pVideoLookup->setCountries(lookup->GetCountries()); - pVideoLookup->setPopularity(lookup->GetPopularity()); - pVideoLookup->setBudget(lookup->GetBudget()); - pVideoLookup->setRevenue(lookup->GetRevenue()); - pVideoLookup->setIMDB(lookup->GetIMDB()); - pVideoLookup->setTMSRef(lookup->GetTMSref()); - - ArtworkList coverartlist = lookup->GetArtwork(kArtworkCoverart); - ArtworkList::iterator c; - for (c = coverartlist.begin(); c != coverartlist.end(); ++c) - { - DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork(); - art->setType("coverart"); - art->setUrl((*c).url); - art->setThumbnail((*c).thumbnail); - art->setWidth((*c).width); - art->setHeight((*c).height); - } - ArtworkList fanartlist = lookup->GetArtwork(kArtworkFanart); - ArtworkList::iterator f; - for (f = fanartlist.begin(); f != fanartlist.end(); ++f) - { - DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork(); - art->setType("fanart"); - art->setUrl((*f).url); - art->setThumbnail((*f).thumbnail); - art->setWidth((*f).width); - art->setHeight((*f).height); - } - ArtworkList bannerlist = lookup->GetArtwork(kArtworkBanner); - ArtworkList::iterator b; - for (b = bannerlist.begin(); b != bannerlist.end(); ++b) - { - DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork(); - art->setType("banner"); - art->setUrl((*b).url); - art->setThumbnail((*b).thumbnail); - art->setWidth((*b).width); - art->setHeight((*b).height); - } - ArtworkList screenshotlist = lookup->GetArtwork(kArtworkScreenshot); - ArtworkList::iterator s; - for (s = screenshotlist.begin(); s != screenshotlist.end(); ++s) - { - DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork(); - art->setType("screenshot"); - art->setUrl((*s).url); - art->setThumbnail((*s).thumbnail); - art->setWidth((*s).width); - art->setHeight((*s).height); - } - } - } - - pVideoLookups->setCount ( list.count() ); - pVideoLookups->setAsOf ( MythDate::current() ); - pVideoLookups->setVersion ( MYTH_BINARY_VERSION ); - pVideoLookups->setProtoVer ( MYTH_PROTO_VERSION ); - - delete factory; - - return pVideoLookups; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Video::RemoveVideoFromDB( int Id ) -{ - bool bResult = false; - - VideoMetadataListManager::metadata_list videolist; - VideoMetadataListManager::loadAllFromDatabase(videolist); - QScopedPointer mlm(new VideoMetadataListManager()); - mlm->setList(videolist); - VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(Id); - - if (metadata) - bResult = metadata->DeleteFromDatabase(); - - return bResult; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Video::AddVideo( const QString &sFileName, - const QString &sHostName ) -{ - if ( sHostName.isEmpty() ) - throw( QString( "Host not provided! Local storage is deprecated and " - "is not supported by the API." )); - - if ( sFileName.isEmpty() || - (sFileName.contains("/../")) || - (sFileName.startsWith("../")) ) - { - throw( QString( "Filename not provided, or fails sanity checks!" )); - } - - StorageGroup sgroup("Videos", sHostName); - - QString fullname = sgroup.FindFile(sFileName); - - if ( !QFile::exists(fullname) ) - throw( QString( "Provided filename does not exist!" )); - - QString hash = FileHash(fullname); - - if (hash == "NULL") - { - LOG(VB_GENERAL, LOG_ERR, "Video Hash Failed. Unless this is a DVD or " - "Blu-ray, something has probably gone wrong."); - hash = ""; - } - - VideoMetadata newFile(sFileName, QString(), hash, - VIDEO_TRAILER_DEFAULT, - VIDEO_COVERFILE_DEFAULT, - VIDEO_SCREENSHOT_DEFAULT, - VIDEO_BANNER_DEFAULT, - VIDEO_FANART_DEFAULT, - QString(), QString(), QString(), QString(), - QString(), VIDEO_YEAR_DEFAULT, - QDate::fromString("0000-00-00","YYYY-MM-DD"), - VIDEO_INETREF_DEFAULT, 0, QString(), - VIDEO_DIRECTOR_DEFAULT, QString(), VIDEO_PLOT_DEFAULT, - 0.0, VIDEO_RATING_DEFAULT, 0, 0, - 0, 0, - MythDate::current().date(), 0, - ParentalLevel::plLowest); - - newFile.SetHost(sHostName); - newFile.SaveToDatabase(); - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Video::UpdateVideoWatchedStatus ( int nId, - bool bWatched ) -{ - VideoMetadataListManager::metadata_list videolist; - VideoMetadataListManager::loadAllFromDatabase(videolist); - QScopedPointer mlm(new VideoMetadataListManager()); - mlm->setList(videolist); - VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId); - - if ( !metadata ) - return false; - - metadata->SetWatched(bWatched); - metadata->UpdateDatabase(); - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -DTC::BlurayInfo* Video::GetBluray( const QString &sPath ) -{ - QString path = sPath; - - if (sPath.isEmpty()) - path = gCoreContext->GetSetting( "BluRayMountpoint", "/media/cdrom"); - - LOG(VB_GENERAL, LOG_NOTICE, - QString("Parsing Blu-ray at path: %1 ").arg(path)); - - auto *bdmeta = new BlurayMetadata(path); - - if ( !bdmeta ) - throw( QString( "Unable to open Blu-ray Metadata Parser!" )); - - if ( !bdmeta->OpenDisc() ) - throw( QString( "Unable to open Blu-ray Disc/Path!" )); - - if ( !bdmeta->ParseDisc() ) - throw( QString( "Unable to parse metadata from Blu-ray Disc/Path!" )); - - auto *pBlurayInfo = new DTC::BlurayInfo(); - - pBlurayInfo->setPath(path); - pBlurayInfo->setTitle(bdmeta->GetTitle()); - pBlurayInfo->setAltTitle(bdmeta->GetAlternateTitle()); - pBlurayInfo->setDiscLang(bdmeta->GetDiscLanguage()); - pBlurayInfo->setDiscNum(bdmeta->GetCurrentDiscNumber()); - pBlurayInfo->setTotalDiscNum(bdmeta->GetTotalDiscNumber()); - pBlurayInfo->setTitleCount(bdmeta->GetTitleCount()); - pBlurayInfo->setThumbCount(bdmeta->GetThumbnailCount()); - pBlurayInfo->setTopMenuSupported(bdmeta->GetTopMenuSupported()); - pBlurayInfo->setFirstPlaySupported(bdmeta->GetFirstPlaySupported()); - pBlurayInfo->setNumHDMVTitles(bdmeta->GetNumHDMVTitles()); - pBlurayInfo->setNumBDJTitles(bdmeta->GetNumBDJTitles()); - pBlurayInfo->setNumUnsupportedTitles(bdmeta->GetNumUnsupportedTitles()); - pBlurayInfo->setAACSDetected(bdmeta->GetAACSDetected()); - pBlurayInfo->setLibAACSDetected(bdmeta->GetLibAACSDetected()); - pBlurayInfo->setAACSHandled(bdmeta->GetAACSHandled()); - pBlurayInfo->setBDPlusDetected(bdmeta->GetBDPlusDetected()); - pBlurayInfo->setLibBDPlusDetected(bdmeta->GetLibBDPlusDetected()); - pBlurayInfo->setBDPlusHandled(bdmeta->GetBDPlusHandled()); - - QStringList thumbs = bdmeta->GetThumbnails(); - if (!thumbs.empty()) - pBlurayInfo->setThumbPath(thumbs.at(0)); - - delete bdmeta; - - return pBlurayInfo; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// - -bool Video::UpdateVideoMetadata ( int nId, - const QString &sTitle, - const QString &sSubTitle, - const QString &sTagLine, - const QString &sDirector, - const QString &sStudio, - const QString &sPlot, - const QString &sRating, - const QString &sInetref, - int nCollectionRef, - const QString &sHomePage, - int nYear, - const QDate &sReleasedate, - float fUserRating, - int nLength, - int nPlayCount, - int nSeason, - int nEpisode, - int nShowLevel, - const QString &sFileName, - const QString &sHash, - const QString &sCoverFile, - int nChildID, - bool bBrowse, - bool bWatched, - bool bProcessed, - const QString &sPlayCommand, - int nCategory, - const QString &sTrailer, - const QString &sHost, - const QString &sScreenshot, - const QString &sBanner, - const QString &sFanart, - const QDate &sInsertDate, - const QString &sContentType, - const QString &sGenres, - const QString &sCast, - const QString &sCountries) -{ - bool update_required = false; - VideoMetadataListManager::metadata_list videolist; - VideoMetadataListManager::loadAllFromDatabase(videolist); - QScopedPointer mlm(new VideoMetadataListManager()); - mlm->setList(videolist); - VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId); - - if (!metadata) - { - LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Id=%1 not found") - .arg(nId)); - return false; - } - - if (m_parsedParams.contains("title")) - { - metadata->SetTitle(sTitle); - update_required = true; - } - - if (m_parsedParams.contains("subtitle")) - { - metadata->SetSubtitle(sSubTitle); - update_required = true; - } - - if (m_parsedParams.contains("tagline")) - { - metadata->SetTagline(sTagLine); - update_required = true; - } - - if (m_parsedParams.contains("director")) - { - metadata->SetDirector(sDirector); - update_required = true; - } - - if (m_parsedParams.contains("studio")) - { - metadata->SetStudio(sStudio); - update_required = true; - } - - if (m_parsedParams.contains("plot")) - { - metadata->SetPlot(sPlot); - update_required = true; - } - - if (m_parsedParams.contains("userrating")) - { - metadata->SetUserRating(fUserRating); - update_required = true; - } - - if (m_parsedParams.contains("inetref")) - { - metadata->SetInetRef(sInetref); - update_required = true; - } - - if (m_parsedParams.contains("collectionref")) - { - metadata->SetCollectionRef(nCollectionRef); - update_required = true; - } - - if (m_parsedParams.contains("homepage")) - { - metadata->SetHomepage(sHomePage); - update_required = true; - } - - if (m_parsedParams.contains("year")) - { - metadata->SetYear(nYear); - update_required = true; - } - - if (m_parsedParams.contains("releasedate")) - { - metadata->SetReleaseDate(sReleasedate); - update_required = true; - } - - if (m_parsedParams.contains("rating")) - { - metadata->SetRating(sRating); - update_required = true; - } - - if (m_parsedParams.contains("length")) - { - metadata->SetLength(std::chrono::minutes(nLength)); - update_required = true; - } - - if (m_parsedParams.contains("playcount")) - { - metadata->SetPlayCount(nPlayCount); - update_required = true; - } - - if (m_parsedParams.contains("season")) - { - metadata->SetSeason(nSeason); - update_required = true; - } - - if (m_parsedParams.contains("episode")) - { - metadata->SetEpisode(nEpisode); - update_required = true; - } - - if (m_parsedParams.contains("showlevel")) - { - metadata->SetShowLevel(ParentalLevel::Level(nShowLevel)); - update_required = true; - } - - if (m_parsedParams.contains("filename")) - { - metadata->SetFilename(sFileName); - update_required = true; - } - - if (m_parsedParams.contains("hash")) - { - metadata->SetHash(sHash); - update_required = true; - } - - if (m_parsedParams.contains("coverfile")) - { - metadata->SetCoverFile(sCoverFile); - update_required = true; - } - - if (m_parsedParams.contains("childid")) - { - metadata->SetChildID(nChildID); - update_required = true; - } - - if (m_parsedParams.contains("browse")) - { - metadata->SetBrowse(bBrowse); - update_required = true; - } - - if (m_parsedParams.contains("watched")) - { - metadata->SetWatched(bWatched); - update_required = true; - } - - if (m_parsedParams.contains("processed")) - { - metadata->SetProcessed(bProcessed); - update_required = true; - } - - if (m_parsedParams.contains("playcommand")) - { - metadata->SetPlayCommand(sPlayCommand); - update_required = true; - } - - if (m_parsedParams.contains("category")) - { - metadata->SetCategoryID(nCategory); - update_required = true; - } - - if (m_parsedParams.contains("trailer")) - { - metadata->SetTrailer(sTrailer); - update_required = true; - } - - if (m_parsedParams.contains("host")) - { - metadata->SetHost(sHost); - update_required = true; - } - - if (m_parsedParams.contains("screenshot")) - { - metadata->SetScreenshot(sScreenshot); - update_required = true; - } - - if (m_parsedParams.contains("banner")) - { - metadata->SetBanner(sBanner); - update_required = true; - } - - if (m_parsedParams.contains("fanart")) - { - metadata->SetFanart(sFanart); - update_required = true; - } - - if (m_parsedParams.contains("insertdate")) - { - metadata->SetInsertdate(sInsertDate); - update_required = true; - } - - if (m_parsedParams.contains("contenttype")) - { - // valid values for ContentType are 'MOVIE','TELEVISION','ADULT','MUSICVIDEO','HOMEVIDEO' - VideoContentType contentType = kContentUnknown; - if (sContentType == "MOVIE") - contentType = kContentMovie; - - if (sContentType == "TELEVISION") - contentType = kContentTelevision; - - if (sContentType == "ADULT") - contentType = kContentAdult; - - if (sContentType == "MUSICVIDEO") - contentType = kContentMusicVideo; - - if (sContentType == "HOMEVIDEO") - contentType = kContentHomeMovie; - - if (contentType != kContentUnknown) - { - metadata->SetContentType(contentType); - update_required = true; - } - else - { - LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Ignoring unknown ContentType: %1").arg(sContentType)); - } - } - - if (m_parsedParams.contains("genres")) - { - VideoMetadata::genre_list genres; - QStringList genresList = sGenres.split(',', Qt::SkipEmptyParts); - std::transform(genresList.cbegin(), genresList.cend(), std::back_inserter(genres), - [](const QString& name) - {return VideoMetadata::genre_list::value_type(-1, name.simplified());} ); - - metadata->SetGenres(genres); - update_required = true; - } - - if (m_parsedParams.contains("cast")) - { - VideoMetadata::cast_list cast; - QStringList castList = sCast.split(',', Qt::SkipEmptyParts); - std::transform(castList.cbegin(), castList.cend(), std::back_inserter(cast), - [](const QString& name) - {return VideoMetadata::cast_list::value_type(-1, name.simplified());} ); - - metadata->SetCast(cast); - update_required = true; - } - - if (m_parsedParams.contains("countries")) - { - VideoMetadata::country_list countries; - QStringList countryList = sCountries.split(',', Qt::SkipEmptyParts); - std::transform(countryList.cbegin(), countryList.cend(), std::back_inserter(countries), - [](const QString& name) - {return VideoMetadata::country_list::value_type(-1, name.simplified());} ); - - metadata->SetCountries(countries); - update_required = true; - } - - if (update_required) - metadata->UpdateDatabase(); - - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// Jun 3, 2020 -// Service to get stream info for all streams in a media file. -// This gets some basic info. If anything more is needed it can be added, -// depending on whether it is available from ffmpeg avformat apis. -// See the MythStreamInfoList class for the code that uses avformat to -// extract the information. -///////////////////////////////////////////////////////////////////////////// - -DTC::VideoStreamInfoList* Video::GetStreamInfo - ( const QString &storageGroup, - const QString &FileName ) -{ - - // Search for the filename - - StorageGroup storage( storageGroup ); - QString sFullFileName = storage.FindFile( FileName ); - MythStreamInfoList infos(sFullFileName); - - // The constructor of this class reads the file and gets the needed - // information. - auto *pVideoStreamInfos = new DTC::VideoStreamInfoList(); - - pVideoStreamInfos->setCount ( infos.m_streamInfoList.size() ); - pVideoStreamInfos->setAsOf ( MythDate::current() ); - pVideoStreamInfos->setVersion ( MYTH_BINARY_VERSION ); - pVideoStreamInfos->setProtoVer ( MYTH_PROTO_VERSION ); - pVideoStreamInfos->setErrorCode ( infos.m_errorCode ); - pVideoStreamInfos->setErrorMsg ( infos.m_errorMsg ); - - for (const auto & info : std::as_const(infos.m_streamInfoList)) - { - DTC::VideoStreamInfo *pVideoStreamInfo = pVideoStreamInfos->AddNewVideoStreamInfo(); - pVideoStreamInfo->setCodecType ( QString(QChar(info.m_codecType)) ); - pVideoStreamInfo->setCodecName ( info.m_codecName ); - pVideoStreamInfo->setWidth ( info.m_width ); - pVideoStreamInfo->setHeight ( info.m_height ); - pVideoStreamInfo->setAspectRatio ( info.m_SampleAspectRatio ); - pVideoStreamInfo->setFieldOrder ( info.m_fieldOrder ); - pVideoStreamInfo->setFrameRate ( info.m_frameRate ); - pVideoStreamInfo->setAvgFrameRate ( info.m_avgFrameRate ); - pVideoStreamInfo->setChannels ( info.m_channels ); - pVideoStreamInfo->setDuration ( info.m_duration ); - - } - return pVideoStreamInfos; -} - -///////////////////////////////////////////////////////////////////////////// -// Get bookmark of a video as a frame number. -///////////////////////////////////////////////////////////////////////////// - -long Video::GetSavedBookmark( int Id ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - query.prepare("SELECT filename " - "FROM videometadata " - "WHERE intid = :ID "); - query.bindValue(":ID", Id); - - if (!query.exec()) - { - MythDB::DBError("Video::GetSavedBookmark", query); - return 0; - } - - QString fileName; - - if (query.next()) - fileName = query.value(0).toString(); - else - { - LOG(VB_GENERAL, LOG_ERR, QString("Video/GetSavedBookmark Video id %1 Not found.").arg(Id)); - return -1; - } - - ProgramInfo pi(fileName, - nullptr, // _plot, - nullptr, // _title, - nullptr, // const QString &_sortTitle, - nullptr, // const QString &_subtitle, - nullptr, // const QString &_sortSubtitle, - nullptr, // const QString &_director, - 0, // int _season, - 0, // int _episode, - nullptr, // const QString &_inetref, - 0min, // uint _length_in_minutes, - 0, // uint _year, - nullptr); //const QString &_programid); - - long ret = pi.QueryBookmark(); - return ret; -} - -///////////////////////////////////////////////////////////////////////////// -// Set bookmark of a video as a frame number. -///////////////////////////////////////////////////////////////////////////// - -bool Video::SetSavedBookmark( int Id, long Offset ) -{ - MSqlQuery query(MSqlQuery::InitCon()); - - query.prepare("SELECT filename " - "FROM videometadata " - "WHERE intid = :ID "); - query.bindValue(":ID", Id); - - if (!query.exec()) - { - MythDB::DBError("Video::SetSavedBookmark", query); - return false; - } - - QString fileName; - - if (query.next()) - fileName = query.value(0).toString(); - else - { - LOG(VB_GENERAL, LOG_ERR, QString("Video/SetSavedBookmark Video id %1 Not found.").arg(Id)); - return false; - } - - ProgramInfo pi(fileName, - nullptr, // _plot, - nullptr, // _title, - nullptr, // const QString &_sortTitle, - nullptr, // const QString &_subtitle, - nullptr, // const QString &_sortSubtitle, - nullptr, // const QString &_director, - 0, // int _season, - 0, // int _episode, - nullptr, // const QString &_inetref, - 0min, // uint _length_in_minutes, - 0, // uint _year, - nullptr); //const QString &_programid); - - pi.SaveBookmark(Offset); - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// -///////////////////////////////////////////////////////////////////////////// diff --git a/mythtv/programs/mythbackend/services/video.h b/mythtv/programs/mythbackend/services/video.h deleted file mode 100644 index 778448ca807..00000000000 --- a/mythtv/programs/mythbackend/services/video.h +++ /dev/null @@ -1,305 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// Program Name: video.h -// Created : Apr. 21, 2011 -// -// Copyright (c) 2011 Robert McNamara -// -// 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 2 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, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef VIDEO_H -#define VIDEO_H - -#include "libmythbase/mythconfig.h" -#if CONFIG_QTSCRIPT -#include -#endif - -#include "libmythmetadata/videometadatalistmanager.h" -#include "libmythservicecontracts/services/videoServices.h" - -class Video : public VideoServices -{ - Q_OBJECT - - public: - - Q_INVOKABLE explicit Video( QObject */*parent*/ = nullptr ) {} - - public: - - /* Video Metadata Methods */ - - DTC::VideoMetadataInfoList* GetVideoList ( const QString &Folder, - const QString &Sort, - bool Descending, - int StartIndex, - int Count ) override; // VideoServices - - DTC::VideoMetadataInfo* GetVideo ( int Id ) override; // VideoServices - - DTC::VideoMetadataInfo* GetVideoByFileName ( const QString &FileName ) override; // VideoServices - - DTC::VideoLookupList* LookupVideo ( const QString &Title, - const QString &Subtitle, - const QString &Inetref, - int Season, - int Episode, - const QString &GrabberType, - bool AllowGeneric ) override; // VideoServices - - bool RemoveVideoFromDB ( int Id ) override; // VideoServices - - bool AddVideo ( const QString &FileName, - const QString &HostName ) override; // VideoServices - - bool UpdateVideoWatchedStatus ( int Id, - bool Watched ) override; // VideoServices - - bool UpdateVideoMetadata ( int Id, - const QString &Title, - const QString &SubTitle, - const QString &TagLine, - const QString &Director, - const QString &Studio, - const QString &Plot, - const QString &Rating, - const QString &Inetref, - int CollectionRef, - const QString &HomePage, - int Year, - const QDate &ReleaseDate, - float UserRating, - int Length, - int PlayCount, - int Season, - int Episode, - int ShowLevel, - const QString &FileName, - const QString &Hash, - const QString &CoverFile, - int ChildID, - bool Browse, - bool Watched, - bool Processed, - const QString &PlayCommand, - int Category, - const QString &Trailer, - const QString &Host, - const QString &Screenshot, - const QString &Banner, - const QString &Fanart, - const QDate &InsertDate, - const QString &ContentType, - const QString &Genres, - const QString &Cast, - const QString &Countries - ) override; // VideoServices - - long GetSavedBookmark ( int Id ) override; - - bool SetSavedBookmark ( int Id, - long Offset ) override; - - /* Bluray Methods */ - - DTC::BlurayInfo* GetBluray ( const QString &Path ) override; // VideoServices - - DTC::VideoStreamInfoList* GetStreamInfo ( const QString &StorageGroup, - const QString &FileName ) override; // VideoServices -}; - -// -------------------------------------------------------------------------- -// The following class wrapper is due to a limitation in Qt Script Engine. It -// requires all methods that return pointers to user classes that are derived from -// QObject actually return QObject* (not the user class *). If the user class pointer -// is returned, the script engine treats it as a QVariant and doesn't create a -// javascript prototype wrapper for it. -// -// This class allows us to keep the rich return types in the main API class while -// offering the script engine a class it can work with. -// -// Only API Classes that return custom classes needs to implement these wrappers. -// -// We should continue to look for a cleaning solution to this problem. -// -------------------------------------------------------------------------- - -#if CONFIG_QTSCRIPT -class ScriptableVideo : public QObject -{ - Q_OBJECT - - private: - - Video m_obj; - QScriptEngine *m_pEngine; - - public: - - Q_INVOKABLE explicit ScriptableVideo( QScriptEngine *pEngine, QObject *parent = nullptr ) - : QObject( parent ), m_pEngine(pEngine) - { - } - - public slots: - - QObject* GetVideoList( const QString &Folder, - const QString &Sort, - bool Descending, - int StartIndex, - int Count ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetVideoList( Folder, Sort, Descending, - StartIndex, Count ); - ) - } - - QObject* GetVideo( int Id ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetVideo( Id ); - ) - } - - QObject* GetVideoByFileName( const QString &FileName ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.GetVideoByFileName( FileName ); - ) - } - - QObject* LookupVideo( const QString &Title, - const QString &Subtitle, - const QString &Inetref, - int Season, - int Episode, - const QString &GrabberType, - bool AllowGeneric ) - { - SCRIPT_CATCH_EXCEPTION( nullptr, - return m_obj.LookupVideo( Title, Subtitle, Inetref, - Season, Episode, GrabberType, - AllowGeneric ); - ) - } - - bool RemoveVideoFromDB( int Id ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.RemoveVideoFromDB( Id ); - ) - } - - bool AddVideo( const QString &FileName, - const QString &HostName ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.AddVideo( FileName, HostName ); - ) - } - - bool UpdateVideoMetadata( int Id, - const QString &Title, - const QString &SubTitle, - const QString &TagLine, - const QString &Director, - const QString &Studio, - const QString &Plot, - const QString &Rating, - const QString &Inetref, - int CollectionRef, - const QString &HomePage, - int Year, - const QDate ReleaseDate, - float UserRating, - int Length, - int PlayCount, - int Season, - int Episode, - int ShowLevel, - const QString &FileName, - const QString &Hash, - const QString &CoverFile, - int ChildID, - bool Browse, - bool Watched, - bool Processed, - const QString &PlayCommand, - int Category, - const QString &Trailer, - const QString &Host, - const QString &Screenshot, - const QString &Banner, - const QString &Fanart, - const QDate InsertDate, - const QString &ContentType, - const QString &Genres, - const QString &Cast, - const QString &Countries - ) - { - SCRIPT_CATCH_EXCEPTION( false, - return m_obj.UpdateVideoMetadata( Id, - Title, - SubTitle, - TagLine, - Director, - Studio, - Plot, - Rating, - Inetref, - CollectionRef, - HomePage, - Year, - ReleaseDate, - UserRating, - Length, - PlayCount, - Season, - Episode, - ShowLevel, - FileName, - Hash, - CoverFile, - ChildID, - Browse, - Watched, - Processed, - PlayCommand, - Category, - Trailer, - Host, - Screenshot, - Banner, - Fanart, - InsertDate, - ContentType, - Genres, - Cast, - Countries); - ) - } -}; - -// NOLINTNEXTLINE(modernize-use-auto) -Q_SCRIPT_DECLARE_QMETAOBJECT_MYTHTV( ScriptableVideo, QObject*); -#endif - -#endif