MythTV master
v2guide.cpp
Go to the documentation of this file.
1
2// Program Name: guide.cpp
3// Created : Mar. 7, 2011
4//
5// Copyright (c) 2011 David Blain <dblain@mythtv.org>
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20//
21// You should have received a copy of the GNU General Public License
22// along with this program. If not, see <http://www.gnu.org/licenses/>.
23//
25
26// C++
27#include <algorithm>
28#include <cmath>
29
30// MythTV
31#include "libmythbase/compat.h"
35#include "libmythbase/mythversion.h"
40
41// MythBackend
42#include "autoexpire.h"
43#include "scheduler.h"
44#include "v2artworkInfoList.h"
45#include "v2castMemberList.h"
46#include "v2guide.h"
47
48// Qt6 has made the QFileInfo::QFileInfo(QString) constructor
49// explicit, which means that it is no longer possible to use an
50// initializer list to construct a QFileInfo. Disable that clang-tidy
51// check for this file so it can still be run on the rest of the file
52// in the project.
53//
54// NOLINTBEGIN(modernize-return-braced-init-list)
55
56extern AutoExpire *expirer;
57extern Scheduler *sched;
58
60//
62
63// This will be initialised in a thread safe manner on first use
65 (GUIDE_HANDLE, V2Guide::staticMetaObject, &V2Guide::RegisterCustomTypes))
66
68{
69 qRegisterMetaType< QFileInfo >();
70 qRegisterMetaType<V2ProgramGuide*>("V2ProgramGuide");
71 qRegisterMetaType<V2ProgramList*>("V2ProgramList");
72 qRegisterMetaType<V2Program*>("V2Program");
73 qRegisterMetaType<V2ChannelGroupList*>("V2ChannelGroupList");
74 qRegisterMetaType<V2ChannelGroup*>("V2ChannelGroup");
75 qRegisterMetaType<V2ChannelInfo*>("V2ChannelInfo");
76 qRegisterMetaType<V2RecordingInfo*>("V2RecordingInfo");
77 qRegisterMetaType<V2ArtworkInfoList*>("V2ArtworkInfoList");
78 qRegisterMetaType<V2ArtworkInfo*>("V2ArtworkInfo");
79 qRegisterMetaType<V2CastMemberList*>("V2CastMemberList");
80 qRegisterMetaType<V2CastMember*>("V2CastMember");
81}
82
84{
85}
86
87V2ProgramGuide *V2Guide::GetProgramGuide( const QDateTime &rawStartTime,
88 const QDateTime &rawEndTime,
89 bool bDetails,
90 int nChannelGroupId,
91 int nStartIndex,
92 int nCount,
93 bool bWithInvisible)
94{
95 if (!rawStartTime.isValid())
96 throw QString( "StartTime is invalid" );
97
98 if (!rawEndTime.isValid())
99 throw QString( "EndTime is invalid" );
100
101 QDateTime dtStartTime = rawStartTime.toUTC();
102 QDateTime dtEndTime = rawEndTime.toUTC();
103
104 if (dtEndTime < dtStartTime)
105 throw QString( "EndTime is before StartTime");
106
107 nStartIndex = std::max(nStartIndex, 0);
108
109 if (nCount <= 0)
110 nCount = 20000;
111
112 // ----------------------------------------------------------------------
113 // Load the channel list
114 // ----------------------------------------------------------------------
115
116 uint nTotalAvailable = 0;
117 ChannelInfoList chanList = ChannelUtil::LoadChannels(nStartIndex, nCount,
118 nTotalAvailable,
119 !bWithInvisible,
122 0,
123 nChannelGroupId);
124
125 // ----------------------------------------------------------------------
126 // Build SQL statement for Program Listing
127 // ----------------------------------------------------------------------
128
129 ProgramList schedList;
130 MSqlBindings bindings;
131
132 QString sWhere = "program.chanid = :CHANID "
133 "AND program.endtime >= :STARTDATE "
134 "AND program.starttime < :ENDDATE "
135 "AND program.starttime >= :STARTDATELIMIT "
136 "AND program.manualid = 0"; // Omit 'manual' recordings scheds
137
138#if 0
139 QString sGroupBy = "program.starttime, channel.channum,"
140 "channel.callsign, program.title";
141#endif
142
143 QString sOrderBy = "program.starttime";
144
145 bindings[":STARTDATE" ] = dtStartTime;
146 bindings[":STARTDATELIMIT"] = dtStartTime.addDays(-1);
147 bindings[":ENDDATE" ] = dtEndTime;
148
149 // ----------------------------------------------------------------------
150 // Get all Pending Scheduled Programs
151 // ----------------------------------------------------------------------
152
153 // NOTE: Fetching this information directly from the schedule is
154 // significantly faster than using ProgramInfo::LoadFromScheduler()
155 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
156 if (scheduler)
157 scheduler->GetAllPending(schedList);
158
159 // ----------------------------------------------------------------------
160 // Build Response
161 // ----------------------------------------------------------------------
162
163 auto *pGuide = new V2ProgramGuide();
164
165 ChannelInfoList::iterator chan_it;
166 for (chan_it = chanList.begin(); chan_it != chanList.end(); ++chan_it)
167 {
168 // Create ChannelInfo Object
169 V2ChannelInfo *pChannel = pGuide->AddNewChannel();
170 V2FillChannelInfo( pChannel, (*chan_it), bDetails );
171
172 // Load the list of programmes for this channel
173 ProgramList progList;
174 bindings[":CHANID"] = (*chan_it).m_chanId;
175 LoadFromProgram( progList, sWhere, sOrderBy, sOrderBy, bindings,
176 schedList );
177
178 // Create Program objects and add them to the channel object
180 for( progIt = progList.begin(); progIt != progList.end(); ++progIt)
181 {
182 V2Program *pProgram = pChannel->AddNewProgram();
183 V2FillProgramInfo( pProgram, *progIt, false, bDetails, false ); // No cast info
184 }
185 }
186
187 // ----------------------------------------------------------------------
188
189 pGuide->setStartTime ( dtStartTime );
190 pGuide->setEndTime ( dtEndTime );
191 pGuide->setDetails ( bDetails );
192
193 pGuide->setStartIndex ( nStartIndex );
194 pGuide->setCount ( chanList.size() );
195 pGuide->setTotalAvailable( nTotalAvailable );
196 pGuide->setAsOf ( MythDate::current() );
197
198 pGuide->setVersion ( MYTH_BINARY_VERSION );
199 pGuide->setProtoVer ( MYTH_PROTO_VERSION );
200
201 return pGuide;
202}
203
205//
207
209 int nCount,
210 const QDateTime& rawStartTime,
211 const QDateTime& rawEndTime,
212 int nChanId,
213 const QString& sTitleFilter,
214 const QString& sCategoryFilter,
215 const QString& sPersonFilter,
216 const QString& sKeywordFilter,
217 bool bOnlyNew,
218 bool bDetails,
219 const QString &sSort,
220 bool bDescending,
221 bool bWithInvisible,
222 const QString& sCatType,
223 const QString& sGroupBy)
224{
225 if (!rawStartTime.isNull() && !rawStartTime.isValid())
226 throw QString( "StartTime is invalid" );
227
228 if (!rawEndTime.isNull() && !rawEndTime.isValid())
229 throw QString( "EndTime is invalid" );
230
231 QDateTime dtStartTime = rawStartTime;
232 const QDateTime& dtEndTime = rawEndTime;
233
234 if (!rawEndTime.isNull() && dtEndTime < dtStartTime)
235 throw QString( "EndTime is before StartTime");
236
238 if (!sGroupBy.isEmpty())
239 {
240 // Handle ProgGroupBy enum name
241 auto meta = QMetaEnum::fromType<ProgGroupBy::Type>();
242 bool ok = false;
243 nGroupBy = ProgGroupBy::Type(meta.keyToValue(sGroupBy.toLocal8Bit(), &ok));
244 if (!ok)
245 throw QString( "GroupBy is invalid" );
246 }
247
249
250
251 // ----------------------------------------------------------------------
252 // Build SQL statement for Program Listing
253 // ----------------------------------------------------------------------
254
255 ProgramList progList;
256 ProgramList schedList;
257 MSqlBindings bindings;
258
259 QString sSQL;
260
261 if (!sPersonFilter.isEmpty())
262 {
263 sSQL = ", people, credits " // LEFT JOIN
264 "WHERE people.name LIKE :PersonFilter "
265 "AND credits.person = people.person "
266 "AND program.chanid = credits.chanid "
267 "AND program.starttime = credits.starttime AND ";
268 bindings[":PersonFilter"] = QString("%%1%").arg(sPersonFilter);
269 }
270 else
271 {
272 sSQL = "WHERE ";
273 }
274
275 if (bOnlyNew)
276 {
277 sSQL = "LEFT JOIN oldprogram ON oldprogram.oldtitle = program.title "
278 + sSQL
279 + "oldprogram.oldtitle IS NULL AND ";
280 }
281
282 sSQL += "deleted IS NULL AND ";
283
284 if (!bWithInvisible)
285 sSQL += "visible > 0 AND ";
286
287 sSQL += "program.manualid = 0 "; // Exclude programmes created purely for 'manual' recording schedules
288
289 nChanId = std::max(nChanId, 0);
290
291 if (nChanId > 0)
292 {
293 sSQL += "AND program.chanid = :ChanId ";
294 bindings[":ChanId"] = nChanId;
295 }
296
297 if (dtStartTime.isNull())
298 dtStartTime = QDateTime::currentDateTimeUtc();
299
300 sSQL += " AND program.endtime >= :StartDate ";
301 bindings[":StartDate"] = dtStartTime;
302
303 if (!dtEndTime.isNull())
304 {
305 sSQL += "AND program.starttime <= :EndDate ";
306 bindings[":EndDate"] = dtEndTime;
307 }
308
309 if (!sTitleFilter.isEmpty())
310 {
311 sSQL += "AND program.title LIKE :Title ";
312 bindings[":Title"] = QString("%%1%").arg(sTitleFilter);
313 }
314
315 if (!sCategoryFilter.isEmpty())
316 {
317 sSQL += "AND program.category LIKE :Category ";
318 bindings[":Category"] = sCategoryFilter;
319 }
320
321 if (!sCatType.isEmpty())
322 {
323 sSQL += "AND program.category_type LIKE :CatType ";
324 bindings[":CatType"] = sCatType;
325 }
326
327 if (!sKeywordFilter.isEmpty())
328 {
329 sSQL += "AND (program.title LIKE :Keyword1 "
330 "OR program.subtitle LIKE :Keyword2 "
331 "OR program.description LIKE :Keyword3) ";
332
333 QString filter = QString("%%1%").arg(sKeywordFilter);
334 bindings[":Keyword1"] = filter;
335 bindings[":Keyword2"] = filter;
336 bindings[":Keyword3"] = filter;
337 }
338
339 if (sSort == "starttime")
340 sSQL += "ORDER BY program.starttime "; // NOLINT(bugprone-branch-clone)
341 else if (sSort == "title")
342 sSQL += "ORDER BY program.title ";
343 else if (sSort == "channel")
344 sSQL += "ORDER BY channel.channum ";
345 else if (sSort == "duration")
346 sSQL += "ORDER BY (program.endtime - program.starttime) ";
347 else
348 sSQL += "ORDER BY program.starttime, channel.channum + 0 ";
349
350 if (bDescending)
351 sSQL += "DESC ";
352 else
353 sSQL += "ASC ";
354
355 // ----------------------------------------------------------------------
356 // Get all Pending Scheduled Programs
357 // ----------------------------------------------------------------------
358
359 // NOTE: Fetching this information directly from the schedule is
360 // significantly faster than using ProgramInfo::LoadFromScheduler()
361 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
362 if (scheduler)
363 scheduler->GetAllPending(schedList);
364
365 // ----------------------------------------------------------------------
366
367 uint nTotalAvailable = 0;
368 LoadFromProgram( progList, sSQL, bindings, schedList,
369 (uint)nStartIndex, (uint)nCount, nTotalAvailable,
370 nGroupBy);
371
372 // ----------------------------------------------------------------------
373 // Build Response
374 // ----------------------------------------------------------------------
375
376 auto *pPrograms = new V2ProgramList();
377
378 nCount = (int)progList.size();
379 int nEndIndex = (int)progList.size();
380
381 for( int n = 0; n < nEndIndex; n++)
382 {
383 ProgramInfo *pInfo = progList[ n ];
384
385 if (bOnlyNew)
386 {
387 // Eliminate duplicate titles
388 bool duplicate = false;
389 for (int back = n-1 ; back >= 0 ; back--) {
390 auto *prior = progList[back];
391 if (prior != nullptr) {
392 if (pInfo -> GetTitle() == prior -> GetTitle()) {
393 duplicate = true;
394 break;
395 }
396 }
397 }
398 if (duplicate)
399 continue;
400 }
401
402 V2Program *pProgram = pPrograms->AddNewProgram();
403
404 V2FillProgramInfo( pProgram, pInfo, true, bDetails, false ); // No cast info, loading this takes far too long
405 }
406
407 // ----------------------------------------------------------------------
408
409 pPrograms->setStartIndex ( nStartIndex );
410 pPrograms->setCount ( nCount );
411 pPrograms->setTotalAvailable( nTotalAvailable );
412 pPrograms->setAsOf ( MythDate::current() );
413 pPrograms->setVersion ( MYTH_BINARY_VERSION );
414 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
415
416 return pPrograms;
417}
418
420//
422
424 const QDateTime &rawStartTime )
425
426{
427 if (!(nChanId > 0))
428 throw QString( "Channel ID is invalid" );
429 if (!rawStartTime.isValid())
430 throw QString( "StartTime is invalid" );
431
432 QDateTime dtStartTime = rawStartTime.toUTC();
433
434 // ----------------------------------------------------------------------
435 // -=>TODO: Add support for getting Recorded Program Info
436 // ----------------------------------------------------------------------
437
438 // Build Response
439
440 auto *pProgram = new V2Program();
441 ProgramInfo *pInfo = LoadProgramFromProgram(nChanId, dtStartTime);
442
443 V2FillProgramInfo( pProgram, pInfo, true, true, true );
444
445 delete pInfo;
446
447 return pProgram;
448}
449
451//
453
454QFileInfo V2Guide::GetChannelIcon( int nChanId,
455 int nWidth /* = 0 */,
456 int nHeight /* = 0 */,
457 const QString &FileName )
458{
459
460 QString sFileName;
461 // Get Icon file path
462
463 if (FileName.isEmpty())
464 sFileName = ChannelUtil::GetIcon( nChanId );
465 else
466 sFileName = FileName;
467
468 if (sFileName.isEmpty())
469 {
470 LOG(VB_UPNP, LOG_ERR,
471 QString("GetImageFile - ChanId %1 doesn't exist or isn't visible")
472 .arg(nChanId));
473 return {};
474 }
475
476 // ------------------------------------------------------------------
477 // Search for the filename
478 // ------------------------------------------------------------------
479
480 StorageGroup storage( "ChannelIcons" );
481 QString sFullFileName = storage.FindFile( sFileName );
482
483 if (sFullFileName.isEmpty())
484 {
485 LOG(VB_UPNP, LOG_ERR,
486 QString("GetImageFile - Unable to find %1.").arg(sFileName));
487
488 return {};
489 }
490
491 // ----------------------------------------------------------------------
492 // check to see if the file (still) exists
493 // ----------------------------------------------------------------------
494
495 if ((nWidth == 0) && (nHeight == 0))
496 {
497 if (QFile::exists( sFullFileName ))
498 {
499 return QFileInfo( sFullFileName );
500 }
501
502 LOG(VB_UPNP, LOG_ERR,
503 QString("GetImageFile - File Does not exist %1.").arg(sFullFileName));
504
505 return {};
506 }
507 // -------------------------------------------------------------------
508
509 QString sNewFileName = QString( "%1.%2x%3.png" )
510 .arg( sFullFileName )
511 .arg( nWidth )
512 .arg( nHeight );
513
514 // ----------------------------------------------------------------------
515 // check to see if image is already created.
516 // ----------------------------------------------------------------------
517
518 if (QFile::exists( sNewFileName ))
519 return QFileInfo( sNewFileName );
520
521 // ----------------------------------------------------------------------
522 // We need to create it...
523 // ----------------------------------------------------------------------
524
525 QString sChannelsDirectory = QFileInfo( sNewFileName ).absolutePath();
526
527 if (!QFileInfo( sChannelsDirectory ).isWritable())
528 {
529 LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - no write access to: %1")
530 .arg( sChannelsDirectory ));
531 return {};
532 }
533
534 auto *pImage = new QImage( sFullFileName );
535
536 if (!pImage)
537 {
538 LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - can't create image: %1")
539 .arg( sFullFileName ));
540 return {};
541 }
542
543 float fAspect = (float)(pImage->width()) / pImage->height();
544 if (fAspect == 0)
545 {
546 LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - zero aspect"));
547 delete pImage;
548 return {};
549 }
550
551 if ( nWidth == 0 )
552 nWidth = (int)std::rint(nHeight * fAspect);
553
554 if ( nHeight == 0 )
555 nHeight = (int)std::rint(nWidth / fAspect);
556
557 QImage img = pImage->scaled( nWidth, nHeight, Qt::IgnoreAspectRatio,
558 Qt::SmoothTransformation);
559
560 if (img.isNull())
561 {
562 LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - unable to scale. "
563 "See if %1 is really an image.").arg( sFullFileName ));
564 delete pImage;
565 return {};
566 }
567
568 if (!img.save( sNewFileName, "PNG" ))
569 {
570 LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - failed, %1")
571 .arg( sNewFileName ));
572 delete pImage;
573 return {};
574 }
575
576 delete pImage;
577
578 return QFileInfo( sNewFileName );
579}
580
582//
584
586{
588 auto *pGroupList = new V2ChannelGroupList();
589
590 ChannelGroupList::iterator it;
591 for (it = list.begin(); it < list.end(); ++it)
592 {
593 V2ChannelGroup *pGroup = pGroupList->AddNewChannelGroup();
594 V2FillChannelGroup(pGroup, (*it));
595 }
596
597 return pGroupList;
598}
599
601//
603
604QStringList V2Guide::GetCategoryList( ) //int nStartIndex, int nCount)
605{
606 QStringList catList;
608
609 query.prepare("SELECT DISTINCT category FROM program WHERE category != '' "
610 "ORDER BY category");
611
612 if (!query.exec())
613 return catList;
614
615 while (query.next())
616 {
617 catList << query.value(0).toString();
618 }
619
620 return catList;
621}
622
624//
626
627QStringList V2Guide::GetStoredSearches( const QString& sType )
628{
629 QStringList keywordList;
631
632 RecSearchType iType = searchTypeFromString(sType);
633
634 if (iType == kNoSearch)
635 {
636 //throw QString( "Invalid Type" );
637 return keywordList;
638 }
639
640 query.prepare("SELECT DISTINCT phrase FROM keyword "
641 "WHERE searchtype = :TYPE "
642 "ORDER BY phrase");
643 query.bindValue(":TYPE", static_cast<int>(iType));
644
645 if (!query.exec())
646 return keywordList;
647
648 while (query.next())
649 {
650 keywordList << query.value(0).toString();
651 }
652
653 return keywordList;
654}
655
657//
659
660bool V2Guide::AddToChannelGroup ( int nChannelGroupId,
661 int nChanId )
662{
663 bool bResult = false;
664
665 if (!(nChanId > 0))
666 throw QString( "Channel ID is invalid" );
667
668 bResult = ChannelGroup::AddChannel(nChanId, nChannelGroupId);
669
670 return bResult;
671}
672
674//
676
677bool V2Guide::RemoveFromChannelGroup ( int nChannelGroupId,
678 int nChanId )
679{
680 bool bResult = false;
681
682 if (!(nChanId > 0))
683 throw QString( "Channel ID is invalid" );
684
685 bResult = ChannelGroup::DeleteChannel(nChanId, nChannelGroupId);
686
687 return bResult;
688}
689
690int V2Guide::AddChannelGroup ( const QString &Name)
691{
693}
694
695bool V2Guide::RemoveChannelGroup ( const QString &Name )
696{
698}
699
700bool V2Guide::UpdateChannelGroup ( const QString & oldName, const QString & newName)
701{
702 return ChannelGroup::UpdateChannelGroup(oldName, newName);
703}
704
705
706// NOLINTEND(modernize-return-braced-init-list)
std::vector< ChannelGroupItem > ChannelGroupList
Definition: channelgroup.h:31
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:130
iterator begin(void)
typename List::iterator iterator
iterator end(void)
size_t size(void) const
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:60
static bool RemoveChannelGroup(const QString &groupName)
static bool AddChannel(uint chanid, int changrpid)
static ChannelGroupList GetChannelGroups(bool includeEmpty=true)
static bool DeleteChannel(uint chanid, int changrpid)
static int AddChannelGroup(const QString &groupName)
static bool UpdateChannelGroup(const QString &oldName, const QString &newName)
static QString GetIcon(uint chanid)
@ kChanGroupByCallsignAndChannum
Definition: channelutil.h:216
static ChannelInfoList LoadChannels(uint startIndex, uint count, uint &totalAvailable, bool ignoreHidden=true, OrderBy orderBy=kChanOrderByChanNum, GroupBy groupBy=kChanGroupByChanid, uint sourceID=0, uint channelGroupID=0, bool liveTVOnly=false, const QString &callsign="", const QString &channum="", bool ignoreUntunable=true)
Load channels from database into a list of ChannelInfo objects.
@ kChanOrderByChanNum
Definition: channelutil.h:208
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
QVariant value(int i) const
Definition: mythdbcon.h:204
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
MythScheduler * GetScheduler(void)
Holds information on recordings and videos.
Definition: programinfo.h:70
bool GetAllPending(RecList &retList, int recRuleId=0) const
Definition: scheduler.cpp:1745
QString FindFile(const QString &filename)
V2Program * AddNewProgram()
static V2ChannelGroupList * GetChannelGroupList(bool IncludeEmpty)
Definition: v2guide.cpp:585
static QFileInfo GetChannelIcon(int ChanId, int Width, int Height, const QString &FileName)
Definition: v2guide.cpp:454
static bool UpdateChannelGroup(const QString &OldName, const QString &NewName)
Definition: v2guide.cpp:700
static V2ProgramGuide * GetProgramGuide(const QDateTime &StartTime, const QDateTime &EndTime, bool Details, int ChannelGroupId, int StartIndex, int Count, bool WithInvisible)
Definition: v2guide.cpp:87
static bool RemoveChannelGroup(const QString &Name)
Definition: v2guide.cpp:695
V2Guide()
Definition: v2guide.cpp:83
static int AddChannelGroup(const QString &Name)
Definition: v2guide.cpp:690
static V2ProgramList * 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, const QString &CatType, const QString &GroupBy)
Definition: v2guide.cpp:208
static QStringList GetStoredSearches(const QString &Type)
Definition: v2guide.cpp:627
static void RegisterCustomTypes()
static QStringList GetCategoryList()
Definition: v2guide.cpp:604
static bool RemoveFromChannelGroup(int ChannelGroupId, int ChanId)
Definition: v2guide.cpp:677
static bool AddToChannelGroup(int ChannelGroupId, int ChanId)
Definition: v2guide.cpp:660
static V2Program * GetProgramDetails(int ChanId, const QDateTime &StartTime)
Definition: v2guide.cpp:423
unsigned int uint
Definition: compat.h:68
static guint32 * back
Definition: goom_core.cpp:25
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:100
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
bool exists(str path)
Definition: xbmcvfs.py:51
ProgramInfo * LoadProgramFromProgram(const uint chanid, const QDateTime &starttime)
bool LoadFromProgram(ProgramList &destination, const QString &where, const QString &groupBy, const QString &orderBy, const MSqlBindings &bindings, const ProgramList &schedList)
RecSearchType searchTypeFromString(const QString &type)
RecSearchType
@ kNoSearch
Scheduler * sched
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(GUIDE_HANDLE, V2Guide::staticMetaObject, &V2Guide::RegisterCustomTypes)) void V2Guide
Definition: v2guide.cpp:64
AutoExpire * expirer
#define GUIDE_HANDLE
Definition: v2guide.h:43
void V2FillChannelGroup(V2ChannelGroup *pGroup, const ChannelGroupItem &pGroupItem)
void V2FillProgramInfo(V2Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast, bool bIncArtwork, bool bIncRecording)
bool V2FillChannelInfo(V2ChannelInfo *pChannel, uint nChanID, bool bDetails)