Skip to content

Commit

Permalink
New and changed services to support Channel Icon Download
Browse files Browse the repository at this point in the history
- Channel/CopyIconToBackend: New Service to copy an icon from the internet
- Guide/GetChannelIcon: Add ability to retieve an icon by file name.
- Channel/UpdateDBChannel: Add ability to update icon.
- Myth/Proxy: New Service to proxy internet requests.
- Myth/GetDirListing: Add ability to get a file listing.
- Channel/GetChannelInfo and related functions: Add icon file name to returned data.
  • Loading branch information
bennettpeter committed Apr 22, 2024
1 parent d7fd1cc commit db8bc84
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 14 deletions.
95 changes: 90 additions & 5 deletions mythtv/programs/mythbackend/servicesv2/v2channel.cpp
Expand Up @@ -29,6 +29,7 @@

// Qt
#include <QList>
#include <QTemporaryFile>

// MythTV
#include "libmythbase/http/mythhttpmetaservice.h"
Expand All @@ -38,6 +39,8 @@
#include "libmythbase/mythversion.h"
#include "libmythbase/mythcorecontext.h"
#include "libmythbase/programtypes.h"
#include "libmythbase/mythdirs.h"
#include "libmythbase/mythdownloadmanager.h"
#include "libmythtv/channelutil.h"
#include "libmythtv/channelscan/scanwizardconfig.h"
#include "libmythtv/channelscan/channelscanner_web.h"
Expand Down Expand Up @@ -702,15 +705,20 @@ V2VideoMultiplexList* V2Channel::GetVideoMultiplexList( uint nSourceID,
if (!query.isConnected())
throw( QString("Database not open while trying to list "
"Video Sources."));

query.prepare("SELECT mplexid, sourceid, transportid, networkid, "
QString where;
if (nSourceID > 0)
where = "WHERE sourceid = :SOURCEID";
QString sql = QString("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);
"default_authority FROM dtv_multiplex %1 "
"ORDER BY mplexid").arg(where);

query.prepare(sql);
if (nSourceID > 0)
query.bindValue(":SOURCEID", nSourceID);

if (!query.exec())
{
Expand Down Expand Up @@ -1167,3 +1175,80 @@ bool V2Channel::SaveRestoreData ( uint SourceId )
RestoreData::freeInstance();
return result;
}


bool V2Channel::CopyIconToBackend(const QString& Url, const QString& ChanId)
{
QString filename = Url.section('/', -1);

QString dirpath = GetConfDir();
QDir configDir(dirpath);
if (!configDir.exists() && !configDir.mkdir(dirpath))
{
LOG(VB_GENERAL, LOG_ERR, QString("Could not create %1").arg(dirpath));
}

QString channelDir = QString("%1/%2").arg(configDir.absolutePath(),
"/channels");
QDir strChannelDir(channelDir);
if (!strChannelDir.exists() && !strChannelDir.mkdir(channelDir))
{
LOG(VB_GENERAL, LOG_ERR,
QString("Could not create %1").arg(channelDir));
}
channelDir += "/";

QString filePath = channelDir + filename;

// If we get to this point we've already checked whether the icon already
// exist locally, we want to download anyway to fix a broken image or
// get the latest version of the icon

QTemporaryFile tmpFile(filePath);
if (!tmpFile.open())
{
LOG(VB_GENERAL, LOG_INFO, "Icon Download: Couldn't create temporary file");
return false;
}

bool fRet = GetMythDownloadManager()->download(Url, tmpFile.fileName());

if (!fRet)
{
LOG(VB_GENERAL, LOG_INFO,
QString("Download for icon %1 failed").arg(filename));
return false;
}

QImage icon(tmpFile.fileName());
if (icon.isNull())
{
LOG(VB_GENERAL, LOG_INFO,
QString("Downloaded icon for %1 isn't a valid image").arg(filename));
return false;
}

// Remove any existing icon
QFile file(filePath);
file.remove();

// Rename temporary file & prevent it being cleaned up
tmpFile.rename(filePath);
tmpFile.setAutoRemove(false);

MSqlQuery query(MSqlQuery::InitCon());
QString qstr = "UPDATE channel SET icon = :ICON "
"WHERE chanid = :CHANID";

query.prepare(qstr);
query.bindValue(":ICON", filename);
query.bindValue(":CHANID", ChanId);

if (!query.exec())
{
MythDB::DBError("Error inserting channel icon", query);
return false;
}

return fRet;
}
3 changes: 3 additions & 0 deletions mythtv/programs/mythbackend/servicesv2/v2channel.h
Expand Up @@ -58,6 +58,7 @@ class V2Channel : public MythHTTPService
Q_CLASSINFO("StopScan", "methods=POST;name=bool")
Q_CLASSINFO("SendScanDialogResponse", "methods=POST;name=bool")
Q_CLASSINFO("SaveRestoreData", "methods=POST;name=bool")
Q_CLASSINFO("CopyIconToBackend", "methods=POST")

public:
V2Channel();
Expand Down Expand Up @@ -240,6 +241,8 @@ class V2Channel : public MythHTTPService

static bool SaveRestoreData ( uint SourceId);

static bool CopyIconToBackend ( const QString& Url,
const QString& ChanId);
private:
Q_DISABLE_COPY(V2Channel)

Expand Down
10 changes: 8 additions & 2 deletions mythtv/programs/mythbackend/servicesv2/v2guide.cpp
Expand Up @@ -413,11 +413,17 @@ V2Program* V2Guide::GetProgramDetails( int nChanId,

QFileInfo V2Guide::GetChannelIcon( int nChanId,
int nWidth /* = 0 */,
int nHeight /* = 0 */ )
int nHeight /* = 0 */,
const QString &FileName )
{

QString sFileName;
// Get Icon file path

QString sFileName = ChannelUtil::GetIcon( nChanId );
if (FileName.isEmpty())
sFileName = ChannelUtil::GetIcon( nChanId );
else
sFileName = FileName;

if (sFileName.isEmpty())
{
Expand Down
3 changes: 2 additions & 1 deletion mythtv/programs/mythbackend/servicesv2/v2guide.h
Expand Up @@ -85,7 +85,8 @@ class V2Guide : public MythHTTPService

static QFileInfo GetChannelIcon ( int ChanId,
int Width ,
int Height );
int Height,
const QString &FileName );

static V2ChannelGroupList* GetChannelGroupList ( bool IncludeEmpty );

Expand Down
33 changes: 31 additions & 2 deletions mythtv/programs/mythbackend/servicesv2/v2myth.cpp
Expand Up @@ -4,6 +4,7 @@
#include <QCryptographicHash>
#include <QHostAddress>
#include <QUdpSocket>
#include <QNetworkRequest>

// MythTV
#include "libmythbase/dbutil.h"
Expand All @@ -18,6 +19,7 @@
#include "libmythbase/mythversion.h"
#include "libmythbase/storagegroup.h"
#include "libmythbase/version.h"
#include "libmythbase/mythdownloadmanager.h"
#include "libmythtv/tv_rec.h"

// MythBackend
Expand Down Expand Up @@ -263,10 +265,15 @@ QStringList V2Myth::GetKeys()
// DirListing gets a list of subdirectories
/////////////////////////////////////////////////////////////////////////////

QStringList V2Myth::GetDirListing ( const QString &DirName)
QStringList V2Myth::GetDirListing ( const QString &DirName, bool Files)
{
QDir directory(DirName);
return directory.entryList(QDir::AllDirs|QDir::NoDotAndDotDot, QDir::Name);
QDir::Filters filts = QDir::AllDirs|QDir::NoDotAndDotDot;
if (Files)
filts = QDir::Files;
else
filts = QDir::AllDirs|QDir::NoDotAndDotDot;
return directory.entryList(filts, QDir::Name);
}


Expand Down Expand Up @@ -1283,3 +1290,25 @@ bool V2Myth::Shutdown ( int Retcode, bool Restart )
QCoreApplication::exit(Retcode);
return true;
}

QString V2Myth::Proxy ( const QString &urlString)
{
QUrl url(urlString);

QByteArray data;

auto *req = new QNetworkRequest(url);
req->setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
// req->setHeader(QNetworkRequest::ContentLengthHeader, data.size());

LOG(VB_CHANNEL, LOG_DEBUG, QString("ImportIconsWizard: posting to: %1")
.arg(url.toString()));

if (GetMythDownloadManager()->post(req, &data))
{
LOG(VB_CHANNEL, LOG_DEBUG, QString("ImportIconsWizard: result: %1").arg(QString(data)));
return {data};
}

return {};
}
7 changes: 5 additions & 2 deletions mythtv/programs/mythbackend/servicesv2/v2myth.h
Expand Up @@ -48,7 +48,7 @@ class V2Myth : public MythHTTPService
Q_CLASSINFO( "SetConnectionInfo", "methods=POST" )
Q_CLASSINFO("ManageScheduler", "methods=POST")
Q_CLASSINFO("Shutdown", "methods=POST")

Q_CLASSINFO("Proxy", "methods=GET,POST")

public:
V2Myth();
Expand All @@ -72,7 +72,8 @@ class V2Myth : public MythHTTPService

static QStringList GetKeys ( );

static QStringList GetDirListing ( const QString &DirName );
static QStringList GetDirListing ( const QString &DirName,
bool Files );

static V2StorageGroupDirList* GetStorageGroupDirs ( const QString &GroupName,
const QString &HostName );
Expand Down Expand Up @@ -184,6 +185,8 @@ class V2Myth : public MythHTTPService

static bool Shutdown ( int Retcode, bool Restart);

static QString Proxy ( const QString &Url);

private:
Q_DISABLE_COPY(V2Myth)

Expand Down
19 changes: 17 additions & 2 deletions mythtv/programs/mythbackend/servicesv2/v2programAndChannel.h
Expand Up @@ -38,6 +38,7 @@ class V2ChannelInfo : public QObject
SERVICE_PROPERTY2( QString , ChanNum )
SERVICE_PROPERTY2( QString , CallSign )
SERVICE_PROPERTY2( QString , IconURL )
SERVICE_PROPERTY2( QString , Icon )
SERVICE_PROPERTY2( QString , ChannelName )
SERVICE_PROPERTY2( uint , MplexId )
SERVICE_PROPERTY2( uint , ServiceId )
Expand Down Expand Up @@ -66,8 +67,21 @@ class V2ChannelInfo : public QObject
public:

Q_INVOKABLE V2ChannelInfo(QObject *parent = nullptr)
: QObject ( parent ),
m_Visible ( true )
: QObject ( parent ),
m_Visible ( true ),
m_MplexId (0),
m_ServiceId (0),
m_ATSCMajorChan (0),
m_ATSCMinorChan (0),
m_FineTune (0),
m_SourceId (0),
m_InputId (0),
m_CommFree (false),
m_UseEIT (false),
m_ServiceType (0),
m_RecPriority (0),
m_TimeOffset (0),
m_CommMethod (0)
{
}

Expand All @@ -77,6 +91,7 @@ class V2ChannelInfo : public QObject
m_ChanNum = src->m_ChanNum ;
m_CallSign = src->m_CallSign ;
m_IconURL = src->m_IconURL ;
m_Icon = src->m_Icon ;
m_ChannelName = src->m_ChannelName ;
m_ChanFilters = src->m_ChanFilters ;
m_SourceId = src->m_SourceId ;
Expand Down
1 change: 1 addition & 0 deletions mythtv/programs/mythbackend/servicesv2/v2serviceUtil.cpp
Expand Up @@ -192,6 +192,7 @@ bool V2FillChannelInfo( V2ChannelInfo *pChannel,
QString sIconURL = QString( "/Guide/GetChannelIcon?ChanId=%3")
.arg( channelInfo.m_chanId );
pChannel->setIconURL( sIconURL );
pChannel->setIcon( channelInfo.m_icon );
}
pChannel->setChannelName(channelInfo.m_name);
pChannel->setVisible(channelInfo.m_visible > kChannelNotVisible);
Expand Down

0 comments on commit db8bc84

Please sign in to comment.