176 changes: 15 additions & 161 deletions mythtv/programs/mythbackend/servicesv2/v2dvr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,60 +1011,7 @@ bool V2Dvr::SetRecordedMarkup (int RecordedId, const QJsonObject &jsonObj)
V2EncoderList* V2Dvr::GetEncoderList()
{
auto* pList = new V2EncoderList();

QReadLocker tvlocker(&TVRec::s_inputsLock);
QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo();
for (auto * elink : qAsConst(tvList))
{
if (elink != nullptr)
{
V2Encoder *pEncoder = pList->AddNewEncoder();

pEncoder->setId ( elink->GetInputID() );
pEncoder->setState ( elink->GetState() );
pEncoder->setLocal ( elink->IsLocal() );
pEncoder->setConnected ( elink->IsConnected() );
pEncoder->setSleepStatus ( elink->GetSleepStatus() );

if (pEncoder->GetLocal())
pEncoder->setHostName( gCoreContext->GetHostName() );
else
pEncoder->setHostName( elink->GetHostName() );

for (const auto & inputInfo : qAsConst(inputInfoList))
{
if (inputInfo.m_inputId == static_cast<uint>(elink->GetInputID()))
{
V2Input *input = pEncoder->AddNewInput();
V2FillInputInfo(input, inputInfo);
}
}

switch ( pEncoder->GetState() )
{
case kState_WatchingLiveTV:
case kState_RecordingOnly:
case kState_WatchingRecording:
{
ProgramInfo *pInfo = elink->GetRecording();

if (pInfo)
{
V2Program *pProgram = pEncoder->Recording();

V2FillProgramInfo( pProgram, pInfo, true, true );

delete pInfo;
}

break;
}

default:
break;
}
}
}
FillEncoderList(pList->GetEncoders(), pList);
return pList;
}

Expand Down Expand Up @@ -1259,55 +1206,17 @@ V2ProgramList* V2Dvr::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<Scheduler*>(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 V2ProgramList();

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 ];

V2Program *pProgram = pPrograms->AddNewProgram();

V2FillProgramInfo( pProgram, pInfo, true );
}

// ----------------------------------------------------------------------
int size = FillUpcomingList(pPrograms->GetPrograms(), pPrograms,
nStartIndex,
nCount,
true, // bShowAll,
nRecordId,
RecStatus::Conflict); // nRecStatus );

pPrograms->setStartIndex ( nStartIndex );
pPrograms->setCount ( nCount );
pPrograms->setTotalAvailable( recordingList.size() );
pPrograms->setTotalAvailable( size );
pPrograms->setAsOf ( MythDate::current() );
pPrograms->setVersion ( MYTH_BINARY_VERSION );
pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
Expand All @@ -1321,72 +1230,17 @@ V2ProgramList* V2Dvr::GetUpcomingList( int nStartIndex,
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<Scheduler*>(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 V2ProgramList();

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 ];

V2Program *pProgram = pPrograms->AddNewProgram();

V2FillProgramInfo( pProgram, pInfo, true );
}

// ----------------------------------------------------------------------
int size = FillUpcomingList(pPrograms->GetPrograms(), pPrograms,
nStartIndex,
nCount,
bShowAll,
nRecordId,
nRecStatus );

pPrograms->setStartIndex ( nStartIndex );
pPrograms->setCount ( nCount );
pPrograms->setTotalAvailable( recordingList.size() );
pPrograms->setTotalAvailable( size );
pPrograms->setAsOf ( MythDate::current() );
pPrograms->setVersion ( MYTH_BINARY_VERSION );
pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
Expand Down
4 changes: 3 additions & 1 deletion mythtv/programs/mythbackend/servicesv2/v2encoderList.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ class V2EncoderList : public QObject
{
CopyListContents< V2Encoder >( this, m_Encoders, src->m_Encoders );
}

// This is needed so that common routines can get a non-const m_Encoders
// reference
QVariantList& GetEncoders() {return m_Encoders;}
V2Encoder *AddNewEncoder()
{
// We must make sure the object added to the QVariantList has
Expand Down
3 changes: 3 additions & 0 deletions mythtv/programs/mythbackend/servicesv2/v2frontendList.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class V2FrontendList : public QObject
CopyListContents< V2Frontend >( this, m_Frontends, src->m_Frontends );
}

// This is needed so that common routines can get a non-const m_Encoders
// reference
QVariantList& GetFrontends() {return m_Frontends;}
V2Frontend *AddNewFrontend()
{
// We must make sure the object added to the QVariantList has
Expand Down
18 changes: 2 additions & 16 deletions mythtv/programs/mythbackend/servicesv2/v2myth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,23 +610,9 @@ V2LogMessageList* V2Myth::GetLogs( const QString &HostName,
V2FrontendList* V2Myth::GetFrontends( bool OnLine )
{
auto *pList = new V2FrontendList();
QMap<QString, Frontend*> frontends;
if (OnLine)
frontends = gBackendContext->GetConnectedFrontends();
else
frontends = gBackendContext->GetFrontends();

for (auto * fe : qAsConst(frontends))
{
V2Frontend *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);
}

FillFrontendList(pList->GetFrontends(), pList,
OnLine);
return pList;
}

Expand Down
5 changes: 5 additions & 0 deletions mythtv/programs/mythbackend/servicesv2/v2programList.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ class V2ProgramList : public QObject
CopyListContents< V2Program >( this, m_Programs, src->m_Programs );
}

// This is here so that a routine in serviceutil (FillUpcomingList)
// can fill the QVariantlist of programs. Unfortunately the standard
// call Programs() generated by the macros returns a const QVariantlist.
QVariantList& GetPrograms() {return m_Programs;}

V2Program *AddNewProgram()
{
// We must make sure the object added to the QVariantList has
Expand Down
163 changes: 163 additions & 0 deletions mythtv/programs/mythbackend/servicesv2/v2serviceUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
#include "channelutil.h"
#include "channelinfo.h"
#include "channelgroup.h"
#include "v2encoder.h"
#include "tv_rec.h"
#include "cardutil.h"
#include "encoderlink.h"
#include "mythscheduler.h"
#include "scheduler.h"
#include "v2frontend.h"
#include "backendcontext.h"

extern QMap<int, EncoderLink *> tvList;

void V2FillProgramInfo( V2Program *pProgram,
ProgramInfo *pInfo,
Expand Down Expand Up @@ -664,6 +674,159 @@ void V2FillSeek(V2CutList* pCutList, RecordingInfo* rInfo, MarkTypes marktype)
}
}

void FillEncoderList(QVariantList &list, QObject* parent)
{
QReadLocker tvlocker(&TVRec::s_inputsLock);
QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo();
for (auto * elink : qAsConst(tvList))
{
if (elink != nullptr)
{
// V2Encoder *pEncoder = list->AddNewEncoder();
V2Encoder *pEncoder = new V2Encoder( parent );
list.append( QVariant::fromValue<QObject *>( pEncoder ));

pEncoder->setId ( elink->GetInputID() );
pEncoder->setState ( elink->GetState() );
pEncoder->setLocal ( elink->IsLocal() );
pEncoder->setConnected ( elink->IsConnected() );
pEncoder->setSleepStatus ( elink->GetSleepStatus() );

if (pEncoder->GetLocal())
pEncoder->setHostName( gCoreContext->GetHostName() );
else
pEncoder->setHostName( elink->GetHostName() );

for (const auto & inputInfo : qAsConst(inputInfoList))
{
if (inputInfo.m_inputId == static_cast<uint>(elink->GetInputID()))
{
V2Input *input = pEncoder->AddNewInput();
V2FillInputInfo(input, inputInfo);
}
}

switch ( pEncoder->GetState() )
{
case kState_WatchingLiveTV:
case kState_RecordingOnly:
case kState_WatchingRecording:
{
ProgramInfo *pInfo = elink->GetRecording();

if (pInfo)
{
V2Program *pProgram = pEncoder->Recording();

V2FillProgramInfo( pProgram, pInfo, true, true );

delete pInfo;
}

break;
}

default:
break;
}
}
}
}

// Note - special value -999 for nRecStatus means all values less than 0.
// This is needed by BackendStatus API
int FillUpcomingList(QVariantList &list, QObject* parent,
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<Scheduler*>(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 == -999
&& (*it)->GetRecordingStatus() >= 0)
|| (nRecStatus != 0 && nRecStatus != -999
&& (*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
// ----------------------------------------------------------------------

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 ];
V2Program *pProgram = new V2Program( parent );
list.append( QVariant::fromValue<QObject *>( pProgram ));
V2FillProgramInfo( pProgram, pInfo, true );
}

return recordingList.size();
}

void FillFrontendList(QVariantList &list, QObject* parent, bool OnLine)
{
QMap<QString, Frontend*> frontends;
if (OnLine)
frontends = gBackendContext->GetConnectedFrontends();
else
frontends = gBackendContext->GetFrontends();

for (auto * fe : qAsConst(frontends))
{
V2Frontend *pFrontend = new V2Frontend( parent );
list.append( QVariant::fromValue<QObject *>( pFrontend ));
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);
}
}


int V2CreateRecordingGroup(const QString& groupName)
{
int groupID = -1;
Expand Down
11 changes: 11 additions & 0 deletions mythtv/programs/mythbackend/servicesv2/v2serviceUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,15 @@ void V2FillInputInfo( V2Input *input, const InputInfo& inputInfo);

int V2CreateRecordingGroup(const QString& groupName);

void FillEncoderList(QVariantList& list, QObject* parent);

int FillUpcomingList(QVariantList& list, QObject* parent,
int& nStartIndex,
int& nCount,
bool bShowAll,
int nRecordId,
int nRecStatus );

void FillFrontendList(QVariantList &list, QObject* parent, bool OnLine);

#endif //V2SERVICEUTIL_H
254 changes: 252 additions & 2 deletions mythtv/programs/mythbackend/servicesv2/v2status.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
// MythTV headers
#include "v2status.h"
#include "libmythbase/http/mythhttpmetaservice.h"
#include "v2backendStatus.h"
#include "v2serviceUtil.h"

#include "mythcorecontext.h"
#include "mythversion.h"
Expand Down Expand Up @@ -54,16 +56,31 @@ Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,
void V2Status::RegisterCustomTypes()
{
qRegisterMetaType<Preformat*>("Preformat");
qRegisterMetaType<V2MachineInfo*>("V2MachineInfo");
qRegisterMetaType<V2BackendStatus*>("V2BackendStatus");
qRegisterMetaType<V2Encoder*>("V2Encoder");
qRegisterMetaType<V2Program*>("V2Program");
qRegisterMetaType<V2Frontend*>("V2Frontend");
qRegisterMetaType<V2StorageGroup*>("V2StorageGroup");
qRegisterMetaType<V2Job*>("V2Job");
qRegisterMetaType<V2ChannelInfo*>("V2ChannelInfo");
qRegisterMetaType<V2RecordingInfo*>("V2RecordingInfo");
qRegisterMetaType<V2ArtworkInfoList*>("V2ArtworkInfoList");
qRegisterMetaType<V2ArtworkInfo*>("V2ArtworkInfo");
qRegisterMetaType<V2CastMemberList*>("V2CastMemberList");
qRegisterMetaType<V2CastMember*>("V2CastMember");
qRegisterMetaType<V2Input*>("V2Input");
qRegisterMetaType<V2Backend*>("V2Backend");
}

V2Status::V2Status () : MythHTTPService(s_service)
{
m_pEncoders = &tvList; // extern
m_pSched = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
m_pExpirer = m_pSched->GetExpirer();;
if (m_pSched)
m_pMainServer = m_pSched->GetMainServer();
m_bIsMaster = gCoreContext->IsMasterHost();
m_nPreRollSeconds = gCoreContext->GetNumSetting("RecordPreRoll", 0);
m_pMainServer = m_pSched->GetMainServer();
}

// HTML
Expand Down Expand Up @@ -115,6 +132,239 @@ static QString setting_to_localtime(const char *setting)
return MythDate::toString(origDate, MythDate::kDateTimeFull);
}

static QDateTime setting_to_qdatetime(const char *setting)
{
QString origDateString = gCoreContext->GetSetting(setting);
QDateTime origDate = MythDate::fromString(origDateString);
return origDate;
}

// Standardized version of GetStatus that supports xml, json, etc.
V2BackendStatus* V2Status::GetBackendStatus()
{
auto* pStatus = new V2BackendStatus();
pStatus->setAsOf ( MythDate::current() );
pStatus->setVersion ( MYTH_BINARY_VERSION );
pStatus->setProtoVer ( MYTH_PROTO_VERSION );
// Encoders
FillEncoderList(pStatus->GetEncoders(), pStatus);
// Upcoming recordings
int nStartIndex = 0;
int nCount = 10;
// Scheduled Recordings
FillUpcomingList(pStatus->GetScheduled(), pStatus,
nStartIndex,
nCount,
true, // bShowAll,
-1, // nRecordId,
-999); // nRecStatus )
// Frontends
FillFrontendList(pStatus->GetFrontends(), pStatus,
false); // OnLine)
// Backends
V2Backend *backend;

// Add this host
backend = pStatus->AddNewBackend();
QString thisHost = gCoreContext->GetHostName();
backend->setName(thisHost);
backend->setIP(gCoreContext->GetBackendServerIP());

if (m_pMainServer)
{
backend->setType("Master");
QStringList backends;
m_pMainServer->GetActiveBackends(backends);
for (const QString& hostname : backends)
{
if (hostname != thisHost)
{
PlaybackSock * pSock = m_pMainServer->GetMediaServerByHostname(hostname);
backend = pStatus->AddNewBackend();
backend->setName(hostname);
backend->setType("Slave");
if (pSock)
{
backend->setIP(pSock->getIP());
}
}
}
}
else
{
backend->setType("Slave");
QString masterhost = gCoreContext->GetMasterHostName();
QString masterip = gCoreContext->GetMasterServerIP();
backend = pStatus->AddNewBackend();
backend->setName(masterhost);
backend->setIP(masterip);
backend->setType("Master");
}

// Add Job Queue Entries
QMap<int, JobQueueEntry> jobs;
QMap<int, JobQueueEntry>::Iterator it;

JobQueue::GetJobsInQueue(jobs,
JOB_LIST_NOT_DONE | JOB_LIST_ERROR |
JOB_LIST_RECENT);

for (it = jobs.begin(); it != jobs.end(); ++it)
{
ProgramInfo pginfo((*it).chanid, (*it).recstartts);
if (!pginfo.GetChanID())
continue;

V2Job * pJob = pStatus->AddNewJob();

pJob->setId( (*it).id );
pJob->setChanId((*it).chanid );
pJob->setStartTime( (*it).recstartts);
pJob->setStartTs( (*it).startts );
pJob->setInsertTime((*it).inserttime);
pJob->setType( (*it).type );
pJob->setCmds( (*it).cmds );
pJob->setFlags( (*it).flags );
pJob->setStatus( (*it).status );
pJob->setStatusTime( (*it).statustime);
pJob->setSchedRunTime( (*it).schedruntime);
pJob->setArgs( (*it).args );
if ((*it).hostname.isEmpty())
pJob->setHostName( QObject::tr("master"));
else
pJob->setHostName((*it).hostname);
pJob->setComment((*it).comment);
V2Program *pProgram = pJob->Program();
V2FillProgramInfo( pProgram, &pginfo, true, false, false);
}

// Machine Info
V2MachineInfo *pMachineInfo = pStatus->MachineInfo();
FillDriveSpace(pMachineInfo);
// load average
loadArray rgdAverages = getLoadAvgs();
if (rgdAverages[0] != -1)
{
pMachineInfo->setLoadAvg1(rgdAverages[0]);
pMachineInfo->setLoadAvg2(rgdAverages[1]);
pMachineInfo->setLoadAvg3(rgdAverages[2]);
}

// Guide Data
QDateTime GuideDataThrough;
MSqlQuery query(MSqlQuery::InitCon());
query.prepare("SELECT MAX(endtime) FROM program WHERE manualid = 0;");
if (query.exec() && query.next())
{
GuideDataThrough = MythDate::fromString(query.value(0).toString());
}
pMachineInfo->setGuideStart
(setting_to_qdatetime("mythfilldatabaseLastRunStart"));
pMachineInfo->setGuideEnd(
setting_to_qdatetime("mythfilldatabaseLastRunEnd"));
pMachineInfo->setGuideStatus(
gCoreContext->GetSetting("mythfilldatabaseLastRunStatus"));
if (gCoreContext->GetBoolSetting("MythFillGrabberSuggestsTime", false))
{
pMachineInfo->setGuideNext(
gCoreContext->GetSetting("MythFillSuggestedRunTime"));
}

if (!GuideDataThrough.isNull())
{
QDateTime qdtNow = MythDate::current();
pMachineInfo->setGuideThru(GuideDataThrough);
pMachineInfo->setGuideDays(qdtNow.daysTo(GuideDataThrough));
}

// Add Miscellaneous information
QString info_script = gCoreContext->GetSetting("MiscStatusScript");
if ((!info_script.isEmpty()) && (info_script != "none"))
{
uint flags = kMSRunShell | kMSStdOut;
MythSystemLegacy ms(info_script, flags);
ms.Run(10s);
if (ms.Wait() != GENERIC_EXIT_OK)
{
LOG(VB_GENERAL, LOG_ERR,
QString("Error running miscellaneous "
"status information script: %1").arg(info_script));
}

QByteArray input = ms.ReadAll();
pStatus->setMiscellaneous(QString(input));
}
return pStatus;
}

void V2Status::FillDriveSpace(V2MachineInfo* pMachineInfo)
{
QStringList strlist;
QString hostname;
QString directory;
QString isLocalstr;
QString fsID;

if (m_pMainServer)
m_pMainServer->BackendQueryDiskSpace(strlist, true, m_bIsMaster);

QStringList::const_iterator sit = strlist.cbegin();
while (sit != strlist.cend())
{
hostname = *(sit++);
directory = *(sit++);
isLocalstr = *(sit++);
fsID = *(sit++);
++sit; // ignore dirID
++sit; // ignore blocksize
long long iTotal = (*(sit++)).toLongLong();
long long iUsed = (*(sit++)).toLongLong();;
long long iAvail = iTotal - iUsed;

if (fsID == "-2")
fsID = "total";

V2StorageGroup* group = pMachineInfo->AddNewStorageGroup();
group->setId (fsID);
group->setTotal((int)(iTotal>>10));
group->setUsed((int)(iUsed>>10));
group->setFree((int)(iAvail>>10));
group->setDirectory(directory);

if (fsID == "total")
{
long long iLiveTV = -1;
long long iDeleted = -1;
long long iExpirable = -1;
MSqlQuery query(MSqlQuery::InitCon());
query.prepare("SELECT SUM(filesize) FROM recorded "
" WHERE recgroup = :RECGROUP;");

query.bindValue(":RECGROUP", "LiveTV");
if (query.exec() && query.next())
{
iLiveTV = query.value(0).toLongLong();
}
query.bindValue(":RECGROUP", "Deleted");
if (query.exec() && query.next())
{
iDeleted = query.value(0).toLongLong();
}
query.prepare("SELECT SUM(filesize) FROM recorded "
" WHERE autoexpire = 1 "
" AND recgroup NOT IN ('LiveTV', 'Deleted');");
if (query.exec() && query.next())
{
iExpirable = query.value(0).toLongLong();
}
group->setLiveTV( (int)(iLiveTV>>20) );
group->setDeleted( (int)(iDeleted>>20) );
group->setExpirable ( (int)(iExpirable>>20) );
}
}

}

void V2Status::FillStatusXML( QDomDocument *pDoc )
{
QDateTime qdtNow = MythDate::current();
Expand Down
10 changes: 6 additions & 4 deletions mythtv/programs/mythbackend/servicesv2/v2status.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
#include <QMutex>
#include <QMap>

// #include "httpserver.h"
#include "libmythbase/http/mythhttpservice.h"
#include "http/mythmimedatabase.h"
#include "http/mythhttpdata.h"
#include "preformat.h"

#include "programinfo.h"
#include "v2backendStatus.h"

class Scheduler;
class AutoExpire;
Expand All @@ -38,6 +38,7 @@ class V2Status : public MythHTTPService
Q_CLASSINFO("Version", "1.0")
Q_CLASSINFO("Status", "methods=GET,POST,HEAD")
Q_CLASSINFO("xml", "methods=GET,POST,HEAD")
Q_CLASSINFO("GetBackendStatus", "methods=GET,POST,HEAD")

public:
V2Status();
Expand All @@ -49,13 +50,13 @@ class V2Status : public MythHTTPService
Preformat* GetStatusHTML ( ); // HTML
Preformat* GetStatus (); // XML
Preformat* xml (); // XML
V2BackendStatus* GetBackendStatus(); // Standardized version of GetStatus

private:

Scheduler *m_pSched;
Scheduler *m_pSched {nullptr};
QMap<int, EncoderLink *> *m_pEncoders;
AutoExpire *m_pExpirer;
MainServer *m_pMainServer;
MainServer *m_pMainServer {nullptr};
bool m_bIsMaster;
int m_nPreRollSeconds;
QMutex m_settingLock;
Expand All @@ -82,6 +83,7 @@ class V2Status : public MythHTTPService
static void FillChannelInfo ( QDomElement &channel,
ProgramInfo *pInfo,
bool bDetails = true );
void FillDriveSpace(V2MachineInfo* pMachineInfo);
};

#endif