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"
39
40// MythBackend
41#include "autoexpire.h"
42#include "scheduler.h"
43#include "v2artworkInfoList.h"
44#include "v2castMemberList.h"
45#include "v2guide.h"
46
47// Qt6 has made the QFileInfo::QFileInfo(QString) constructor
48// explicit, which means that it is no longer possible to use an
49// initializer list to construct a QFileInfo. Disable that clang-tidy
50// check for this file so it can still be run on the rest of the file
51// in the project.
52//
53// NOLINTBEGIN(modernize-return-braced-init-list)
54
55extern AutoExpire *expirer;
56extern Scheduler *sched;
57
59//
61
62// This will be initialised in a thread safe manner on first use
64 (GUIDE_HANDLE, V2Guide::staticMetaObject, &V2Guide::RegisterCustomTypes))
65
67{
68 qRegisterMetaType< QFileInfo >();
69 qRegisterMetaType<V2ProgramGuide*>("V2ProgramGuide");
70 qRegisterMetaType<V2ProgramList*>("V2ProgramList");
71 qRegisterMetaType<V2Program*>("V2Program");
72 qRegisterMetaType<V2ChannelGroupList*>("V2ChannelGroupList");
73 qRegisterMetaType<V2ChannelGroup*>("V2ChannelGroup");
74 qRegisterMetaType<V2ChannelInfo*>("V2ChannelInfo");
75 qRegisterMetaType<V2RecordingInfo*>("V2RecordingInfo");
76 qRegisterMetaType<V2ArtworkInfoList*>("V2ArtworkInfoList");
77 qRegisterMetaType<V2ArtworkInfo*>("V2ArtworkInfo");
78 qRegisterMetaType<V2CastMemberList*>("V2CastMemberList");
79 qRegisterMetaType<V2CastMember*>("V2CastMember");
80}
81
83{
84}
85
86V2ProgramGuide *V2Guide::GetProgramGuide( const QDateTime &rawStartTime,
87 const QDateTime &rawEndTime,
88 bool bDetails,
89 int nChannelGroupId,
90 int nStartIndex,
91 int nCount,
92 bool bWithInvisible)
93{
94 if (!rawStartTime.isValid())
95 throw QString( "StartTime is invalid" );
96
97 if (!rawEndTime.isValid())
98 throw QString( "EndTime is invalid" );
99
100 QDateTime dtStartTime = rawStartTime.toUTC();
101 QDateTime dtEndTime = rawEndTime.toUTC();
102
103 if (dtEndTime < dtStartTime)
104 throw QString( "EndTime is before StartTime");
105
106 nStartIndex = std::max(nStartIndex, 0);
107
108 if (nCount <= 0)
109 nCount = 20000;
110
111 // ----------------------------------------------------------------------
112 // Load the channel list
113 // ----------------------------------------------------------------------
114
115 uint nTotalAvailable = 0;
116 ChannelInfoList chanList = ChannelUtil::LoadChannels(nStartIndex, nCount,
117 nTotalAvailable,
118 !bWithInvisible,
121 0,
122 nChannelGroupId);
123
124 // ----------------------------------------------------------------------
125 // Build SQL statement for Program Listing
126 // ----------------------------------------------------------------------
127
128 ProgramList schedList;
129 MSqlBindings bindings;
130
131 QString sWhere = "program.chanid = :CHANID "
132 "AND program.endtime >= :STARTDATE "
133 "AND program.starttime < :ENDDATE "
134 "AND program.starttime >= :STARTDATELIMIT "
135 "AND program.manualid = 0"; // Omit 'manual' recordings scheds
136
137#if 0
138 QString sGroupBy = "program.starttime, channel.channum,"
139 "channel.callsign, program.title";
140#endif
141
142 QString sOrderBy = "program.starttime";
143
144 bindings[":STARTDATE" ] = dtStartTime;
145 bindings[":STARTDATELIMIT"] = dtStartTime.addDays(-1);
146 bindings[":ENDDATE" ] = dtEndTime;
147
148 // ----------------------------------------------------------------------
149 // Get all Pending Scheduled Programs
150 // ----------------------------------------------------------------------
151
152 // NOTE: Fetching this information directly from the schedule is
153 // significantly faster than using ProgramInfo::LoadFromScheduler()
154 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
155 if (scheduler)
156 scheduler->GetAllPending(schedList);
157
158 // ----------------------------------------------------------------------
159 // Build Response
160 // ----------------------------------------------------------------------
161
162 auto *pGuide = new V2ProgramGuide();
163
164 ChannelInfoList::iterator chan_it;
165 for (chan_it = chanList.begin(); chan_it != chanList.end(); ++chan_it)
166 {
167 // Create ChannelInfo Object
168 V2ChannelInfo *pChannel = pGuide->AddNewChannel();
169 V2FillChannelInfo( pChannel, (*chan_it), bDetails );
170
171 // Load the list of programmes for this channel
172 ProgramList progList;
173 bindings[":CHANID"] = (*chan_it).m_chanId;
174 LoadFromProgram( progList, sWhere, sOrderBy, sOrderBy, bindings,
175 schedList );
176
177 // Create Program objects and add them to the channel object
179 for( progIt = progList.begin(); progIt != progList.end(); ++progIt)
180 {
181 V2Program *pProgram = pChannel->AddNewProgram();
182 V2FillProgramInfo( pProgram, *progIt, false, bDetails, false ); // No cast info
183 }
184 }
185
186 // ----------------------------------------------------------------------
187
188 pGuide->setStartTime ( dtStartTime );
189 pGuide->setEndTime ( dtEndTime );
190 pGuide->setDetails ( bDetails );
191
192 pGuide->setStartIndex ( nStartIndex );
193 pGuide->setCount ( chanList.size() );
194 pGuide->setTotalAvailable( nTotalAvailable );
195 pGuide->setAsOf ( MythDate::current() );
196
197 pGuide->setVersion ( MYTH_BINARY_VERSION );
198 pGuide->setProtoVer ( MYTH_PROTO_VERSION );
199
200 return pGuide;
201}
202
204//
206
208 int nCount,
209 const QDateTime& rawStartTime,
210 const QDateTime& rawEndTime,
211 int nChanId,
212 const QString& sTitleFilter,
213 const QString& sCategoryFilter,
214 const QString& sPersonFilter,
215 const QString& sKeywordFilter,
216 bool bOnlyNew,
217 bool bDetails,
218 const QString &sSort,
219 bool bDescending,
220 bool bWithInvisible,
221 const QString& sCatType,
222 const QString& sGroupBy)
223{
224 if (!rawStartTime.isNull() && !rawStartTime.isValid())
225 throw QString( "StartTime is invalid" );
226
227 if (!rawEndTime.isNull() && !rawEndTime.isValid())
228 throw QString( "EndTime is invalid" );
229
230 QDateTime dtStartTime = rawStartTime;
231 const QDateTime& dtEndTime = rawEndTime;
232
233 if (!rawEndTime.isNull() && dtEndTime < dtStartTime)
234 throw QString( "EndTime is before StartTime");
235
237 if (!sGroupBy.isEmpty())
238 {
239 // Handle ProgGroupBy enum name
240 auto meta = QMetaEnum::fromType<ProgGroupBy::Type>();
241 bool ok = false;
242 nGroupBy = ProgGroupBy::Type(meta.keyToValue(sGroupBy.toLocal8Bit(), &ok));
243 if (!ok)
244 throw QString( "GroupBy is invalid" );
245 }
246
248
249
250 // ----------------------------------------------------------------------
251 // Build SQL statement for Program Listing
252 // ----------------------------------------------------------------------
253
254 ProgramList progList;
255 ProgramList schedList;
256 MSqlBindings bindings;
257
258 QString sSQL;
259
260 if (!sPersonFilter.isEmpty())
261 {
262 sSQL = ", people, credits " // LEFT JOIN
263 "WHERE people.name LIKE :PersonFilter "
264 "AND credits.person = people.person "
265 "AND program.chanid = credits.chanid "
266 "AND program.starttime = credits.starttime AND ";
267 bindings[":PersonFilter"] = QString("%%1%").arg(sPersonFilter);
268 }
269 else
270 {
271 sSQL = "WHERE ";
272 }
273
274 if (bOnlyNew)
275 {
276 sSQL = "LEFT JOIN oldprogram ON oldprogram.oldtitle = program.title "
277 + sSQL
278 + "oldprogram.oldtitle IS NULL AND ";
279 }
280
281 sSQL += "deleted IS NULL AND ";
282
283 if (!bWithInvisible)
284 sSQL += "visible > 0 AND ";
285
286 sSQL += "program.manualid = 0 "; // Exclude programmes created purely for 'manual' recording schedules
287
288 nChanId = std::max(nChanId, 0);
289
290 if (nChanId > 0)
291 {
292 sSQL += "AND program.chanid = :ChanId ";
293 bindings[":ChanId"] = nChanId;
294 }
295
296 if (dtStartTime.isNull())
297 dtStartTime = QDateTime::currentDateTimeUtc();
298
299 sSQL += " AND program.endtime >= :StartDate ";
300 bindings[":StartDate"] = dtStartTime;
301
302 if (!dtEndTime.isNull())
303 {
304 sSQL += "AND program.starttime <= :EndDate ";
305 bindings[":EndDate"] = dtEndTime;
306 }
307
308 if (!sTitleFilter.isEmpty())
309 {
310 sSQL += "AND program.title LIKE :Title ";
311 bindings[":Title"] = QString("%%1%").arg(sTitleFilter);
312 }
313
314 if (!sCategoryFilter.isEmpty())
315 {
316 sSQL += "AND program.category LIKE :Category ";
317 bindings[":Category"] = sCategoryFilter;
318 }
319
320 if (!sCatType.isEmpty())
321 {
322 sSQL += "AND program.category_type LIKE :CatType ";
323 bindings[":CatType"] = sCatType;
324 }
325
326 if (!sKeywordFilter.isEmpty())
327 {
328 sSQL += "AND (program.title LIKE :Keyword1 "
329 "OR program.subtitle LIKE :Keyword2 "
330 "OR program.description LIKE :Keyword3) ";
331
332 QString filter = QString("%%1%").arg(sKeywordFilter);
333 bindings[":Keyword1"] = filter;
334 bindings[":Keyword2"] = filter;
335 bindings[":Keyword3"] = filter;
336 }
337
338 if (sSort == "starttime")
339 sSQL += "ORDER BY program.starttime "; // NOLINT(bugprone-branch-clone)
340 else if (sSort == "title")
341 sSQL += "ORDER BY program.title ";
342 else if (sSort == "channel")
343 sSQL += "ORDER BY channel.channum ";
344 else if (sSort == "duration")
345 sSQL += "ORDER BY (program.endtime - program.starttime) ";
346 else
347 sSQL += "ORDER BY program.starttime, channel.channum + 0 ";
348
349 if (bDescending)
350 sSQL += "DESC ";
351 else
352 sSQL += "ASC ";
353
354 // ----------------------------------------------------------------------
355 // Get all Pending Scheduled Programs
356 // ----------------------------------------------------------------------
357
358 // NOTE: Fetching this information directly from the schedule is
359 // significantly faster than using ProgramInfo::LoadFromScheduler()
360 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
361 if (scheduler)
362 scheduler->GetAllPending(schedList);
363
364 // ----------------------------------------------------------------------
365
366 uint nTotalAvailable = 0;
367 LoadFromProgram( progList, sSQL, bindings, schedList,
368 (uint)nStartIndex, (uint)nCount, nTotalAvailable,
369 nGroupBy);
370
371 // ----------------------------------------------------------------------
372 // Build Response
373 // ----------------------------------------------------------------------
374
375 auto *pPrograms = new V2ProgramList();
376
377 nCount = (int)progList.size();
378 int nEndIndex = (int)progList.size();
379
380 for( int n = 0; n < nEndIndex; n++)
381 {
382 ProgramInfo *pInfo = progList[ n ];
383
384 if (bOnlyNew)
385 {
386 // Eliminate duplicate titles
387 bool duplicate = false;
388 for (int back = n-1 ; back >= 0 ; back--) {
389 auto *prior = progList[back];
390 if (prior != nullptr) {
391 if (pInfo -> GetTitle() == prior -> GetTitle()) {
392 duplicate = true;
393 break;
394 }
395 }
396 }
397 if (duplicate)
398 continue;
399 }
400
401 V2Program *pProgram = pPrograms->AddNewProgram();
402
403 V2FillProgramInfo( pProgram, pInfo, true, bDetails, false ); // No cast info, loading this takes far too long
404 }
405
406 // ----------------------------------------------------------------------
407
408 pPrograms->setStartIndex ( nStartIndex );
409 pPrograms->setCount ( nCount );
410 pPrograms->setTotalAvailable( nTotalAvailable );
411 pPrograms->setAsOf ( MythDate::current() );
412 pPrograms->setVersion ( MYTH_BINARY_VERSION );
413 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
414
415 return pPrograms;
416}
417
419//
421
423 const QDateTime &rawStartTime )
424
425{
426 if (!(nChanId > 0))
427 throw QString( "Channel ID is invalid" );
428 if (!rawStartTime.isValid())
429 throw QString( "StartTime is invalid" );
430
431 QDateTime dtStartTime = rawStartTime.toUTC();
432
433 // ----------------------------------------------------------------------
434 // -=>TODO: Add support for getting Recorded Program Info
435 // ----------------------------------------------------------------------
436
437 // Build Response
438
439 auto *pProgram = new V2Program();
440 ProgramInfo *pInfo = LoadProgramFromProgram(nChanId, dtStartTime);
441
442 V2FillProgramInfo( pProgram, pInfo, true, true, true );
443
444 delete pInfo;
445
446 return pProgram;
447}
448
450//
452
453QFileInfo V2Guide::GetChannelIcon( int nChanId,
454 int nWidth /* = 0 */,
455 int nHeight /* = 0 */,
456 const QString &FileName )
457{
458
459 QString sFileName;
460 // Get Icon file path
461
462 if (FileName.isEmpty())
463 sFileName = ChannelUtil::GetIcon( nChanId );
464 else
465 sFileName = FileName;
466
467 if (sFileName.isEmpty())
468 {
469 LOG(VB_UPNP, LOG_ERR,
470 QString("GetImageFile - ChanId %1 doesn't exist or isn't visible")
471 .arg(nChanId));
472 return {};
473 }
474
475 // ------------------------------------------------------------------
476 // Search for the filename
477 // ------------------------------------------------------------------
478
479 StorageGroup storage( "ChannelIcons" );
480 QString sFullFileName = storage.FindFile( sFileName );
481
482 if (sFullFileName.isEmpty())
483 {
484 LOG(VB_UPNP, LOG_ERR,
485 QString("GetImageFile - Unable to find %1.").arg(sFileName));
486
487 return {};
488 }
489
490 // ----------------------------------------------------------------------
491 // check to see if the file (still) exists
492 // ----------------------------------------------------------------------
493
494 if ((nWidth == 0) && (nHeight == 0))
495 {
496 if (QFile::exists( sFullFileName ))
497 {
498 return QFileInfo( sFullFileName );
499 }
500
501 LOG(VB_UPNP, LOG_ERR,
502 QString("GetImageFile - File Does not exist %1.").arg(sFullFileName));
503
504 return {};
505 }
506 // -------------------------------------------------------------------
507
508 QString sNewFileName = QString( "%1.%2x%3.png" )
509 .arg( sFullFileName )
510 .arg( nWidth )
511 .arg( nHeight );
512
513 // ----------------------------------------------------------------------
514 // check to see if image is already created.
515 // ----------------------------------------------------------------------
516
517 if (QFile::exists( sNewFileName ))
518 return QFileInfo( sNewFileName );
519
520 // ----------------------------------------------------------------------
521 // We need to create it...
522 // ----------------------------------------------------------------------
523
524 QString sChannelsDirectory = QFileInfo( sNewFileName ).absolutePath();
525
526 if (!QFileInfo( sChannelsDirectory ).isWritable())
527 {
528 LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - no write access to: %1")
529 .arg( sChannelsDirectory ));
530 return {};
531 }
532
533 auto *pImage = new QImage( sFullFileName );
534
535 if (!pImage)
536 {
537 LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - can't create image: %1")
538 .arg( sFullFileName ));
539 return {};
540 }
541
542 float fAspect = (float)(pImage->width()) / pImage->height();
543 if (fAspect == 0)
544 {
545 LOG(VB_UPNP, LOG_ERR, QString("GetImageFile - zero aspect"));
546 delete pImage;
547 return {};
548 }
549
550 if ( nWidth == 0 )
551 nWidth = (int)std::rint(nHeight * fAspect);
552
553 if ( nHeight == 0 )
554 nHeight = (int)std::rint(nWidth / fAspect);
555
556 QImage img = pImage->scaled( nWidth, nHeight, Qt::IgnoreAspectRatio,
557 Qt::SmoothTransformation);
558
559 if (img.isNull())
560 {
561 LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - unable to scale. "
562 "See if %1 is really an image.").arg( sFullFileName ));
563 delete pImage;
564 return {};
565 }
566
567 if (!img.save( sNewFileName, "PNG" ))
568 {
569 LOG(VB_UPNP, LOG_ERR, QString("SaveImageFile - failed, %1")
570 .arg( sNewFileName ));
571 delete pImage;
572 return {};
573 }
574
575 delete pImage;
576
577 return QFileInfo( sNewFileName );
578}
579
581//
583
585{
587 auto *pGroupList = new V2ChannelGroupList();
588
589 ChannelGroupList::iterator it;
590 for (it = list.begin(); it < list.end(); ++it)
591 {
592 V2ChannelGroup *pGroup = pGroupList->AddNewChannelGroup();
593 V2FillChannelGroup(pGroup, (*it));
594 }
595
596 return pGroupList;
597}
598
600//
602
603QStringList V2Guide::GetCategoryList( ) //int nStartIndex, int nCount)
604{
605 QStringList catList;
607
608 query.prepare("SELECT DISTINCT category FROM program WHERE category != '' "
609 "ORDER BY category");
610
611 if (!query.exec())
612 return catList;
613
614 while (query.next())
615 {
616 catList << query.value(0).toString();
617 }
618
619 return catList;
620}
621
623//
625
626QStringList V2Guide::GetStoredSearches( const QString& sType )
627{
628 QStringList keywordList;
630
631 RecSearchType iType = searchTypeFromString(sType);
632
633 if (iType == kNoSearch)
634 {
635 //throw QString( "Invalid Type" );
636 return keywordList;
637 }
638
639 query.prepare("SELECT DISTINCT phrase FROM keyword "
640 "WHERE searchtype = :TYPE "
641 "ORDER BY phrase");
642 query.bindValue(":TYPE", static_cast<int>(iType));
643
644 if (!query.exec())
645 return keywordList;
646
647 while (query.next())
648 {
649 keywordList << query.value(0).toString();
650 }
651
652 return keywordList;
653}
654
656//
658
659bool V2Guide::AddToChannelGroup ( int nChannelGroupId,
660 int nChanId )
661{
662 bool bResult = false;
663
664 if (!(nChanId > 0))
665 throw QString( "Channel ID is invalid" );
666
667 bResult = ChannelGroup::AddChannel(nChanId, nChannelGroupId);
668
669 return bResult;
670}
671
673//
675
676bool V2Guide::RemoveFromChannelGroup ( int nChannelGroupId,
677 int nChanId )
678{
679 bool bResult = false;
680
681 if (!(nChanId > 0))
682 throw QString( "Channel ID is invalid" );
683
684 bResult = ChannelGroup::DeleteChannel(nChanId, nChannelGroupId);
685
686 return bResult;
687}
688
689int V2Guide::AddChannelGroup ( const QString &Name)
690{
692}
693
694bool V2Guide::RemoveChannelGroup ( const QString &Name )
695{
697}
698
699bool V2Guide::UpdateChannelGroup ( const QString & oldName, const QString & newName)
700{
701 return ChannelGroup::UpdateChannelGroup(oldName, newName);
702}
703
704
705// NOLINTEND(modernize-return-braced-init-list)
std::vector< ChannelGroupItem > ChannelGroupList
Definition: channelgroup.h:31
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:131
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:68
bool GetAllPending(RecList &retList, int recRuleId=0) const
Definition: scheduler.cpp:1746
QString FindFile(const QString &filename)
V2Program * AddNewProgram()
static V2ChannelGroupList * GetChannelGroupList(bool IncludeEmpty)
Definition: v2guide.cpp:584
static QFileInfo GetChannelIcon(int ChanId, int Width, int Height, const QString &FileName)
Definition: v2guide.cpp:453
static bool UpdateChannelGroup(const QString &OldName, const QString &NewName)
Definition: v2guide.cpp:699
static V2ProgramGuide * GetProgramGuide(const QDateTime &StartTime, const QDateTime &EndTime, bool Details, int ChannelGroupId, int StartIndex, int Count, bool WithInvisible)
Definition: v2guide.cpp:86
static bool RemoveChannelGroup(const QString &Name)
Definition: v2guide.cpp:694
V2Guide()
Definition: v2guide.cpp:82
static int AddChannelGroup(const QString &Name)
Definition: v2guide.cpp:689
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:207
static QStringList GetStoredSearches(const QString &Type)
Definition: v2guide.cpp:626
static void RegisterCustomTypes()
static QStringList GetCategoryList()
Definition: v2guide.cpp:603
static bool RemoveFromChannelGroup(int ChannelGroupId, int ChanId)
Definition: v2guide.cpp:676
static bool AddToChannelGroup(int ChannelGroupId, int ChanId)
Definition: v2guide.cpp:659
static V2Program * GetProgramDetails(int ChanId, const QDateTime &StartTime)
Definition: v2guide.cpp:422
unsigned int uint
Definition: freesurround.h:24
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:63
AutoExpire * expirer
#define GUIDE_HANDLE
Definition: v2guide.h:44
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)