MythTV master
v2serviceUtil.cpp
Go to the documentation of this file.
1#include <QtGlobal>
2#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
3#include <QtSystemDetection>
4#endif
5
6// Standard UNIX C headers
7#include <algorithm>
8#include <unistd.h>
9#include <fcntl.h>
10#if defined(Q_OS_BSD4) || defined(Q_OS_WINDOWS)
11#include <sys/types.h>
12#else
13#include <sys/sysmacros.h>
14#endif
15#include <sys/stat.h>
16
17// Qt
18#include <QDir>
19#include <QFileInfoList>
20#include <QJsonArray>
21#include <QJsonObject>
22
23// MythTV
24#include "libmythbase/mythconfig.h"
25#include "libmythbase/compat.h"
29// #include "libmythbase/mythsorthelper.h"
31#include "libmythtv/cardutil.h"
40#include "libmythtv/tv_rec.h"
41
42// MythBackend
43#include "backendcontext.h"
44#include "encoderlink.h"
45#include "scheduler.h"
46#include "v2encoder.h"
47#include "v2frontend.h"
48#include "v2serviceUtil.h"
49
51 ProgramInfo *pInfo,
52 bool bIncChannel /* = true */,
53 bool bDetails /* = true */,
54 bool bIncCast /* = true */,
55 bool bIncArtwork /* = true */,
56 bool bIncRecording /* = true */)
57{
58 if ((pProgram == nullptr) || (pInfo == nullptr))
59 return;
60
61 pProgram->setStartTime ( pInfo->GetScheduledStartTime());
62 pProgram->setEndTime ( pInfo->GetScheduledEndTime ());
63 pProgram->setTitle ( pInfo->GetTitle() );
64 pProgram->setSubTitle ( pInfo->GetSubtitle() );
65 pProgram->setCategory ( pInfo->GetCategory() );
66 pProgram->setCatType ( pInfo->GetCategoryTypeString());
67 pProgram->setRepeat ( pInfo->IsRepeat() );
68 pProgram->setVideoProps( pInfo->GetVideoProperties() );
69 pProgram->setVideoPropNames( pInfo->GetVideoPropertyNames() );
70 pProgram->setAudioProps( pInfo->GetAudioProperties() );
71 pProgram->setAudioPropNames( pInfo->GetAudioPropertyNames() );
72 pProgram->setSubProps ( pInfo->GetSubtitleType() );
73 pProgram->setSubPropNames( pInfo->GetSubtitleTypeNames() );
74
75 if (bDetails)
76 {
77 pProgram->setSeriesId ( pInfo->GetSeriesID() );
78 pProgram->setProgramId ( pInfo->GetProgramID() );
79 pProgram->setStars ( pInfo->GetStars() );
80 pProgram->setLastModified( pInfo->GetLastModifiedTime() );
81 pProgram->setProgramFlags( pInfo->GetProgramFlags() );
82 pProgram->setProgramFlagNames( pInfo->GetProgramFlagNames() );
83
84 // ----
85 // DEPRECATED - See RecordingInfo instead
86 pProgram->setFileName ( pInfo->GetPathname() );
87 pProgram->setFileSize ( pInfo->GetFilesize() );
88 pProgram->setHostName ( pInfo->GetHostname() );
89 // ----
90
91 if (pInfo->GetOriginalAirDate().isValid())
92 pProgram->setAirdate( pInfo->GetOriginalAirDate() );
93 pProgram->setReleaseYear( pInfo->GetYearOfInitialRelease());
94 pProgram->setDescription( pInfo->GetDescription() );
95 pProgram->setInetref ( pInfo->GetInetRef() );
96 pProgram->setSeason ( pInfo->GetSeason() );
97 pProgram->setEpisode ( pInfo->GetEpisode() );
98 pProgram->setTotalEpisodes( pInfo->GetEpisodeTotal() );
99 }
100
101 if (bIncCast)
102 V2FillCastMemberList( pProgram->Cast(), pInfo );
103 else
104 pProgram->enableCast(false);
105
106 if (bIncChannel)
107 {
108 // Build Channel Child Element
109 if (!V2FillChannelInfo( pProgram->Channel(), pInfo->GetChanID(), bDetails ))
110 {
111 // The channel associated with a given recording may no longer exist
112 // however the ChanID is one half of the unique identifier for the
113 // recording and therefore MUST be included in the return data
114 pProgram->Channel()->setChanId(pInfo->GetChanID());
115 }
116 }
117 else
118 {
119 pProgram->enableChannel(false);
120 }
121
122 // Build Recording Child Element
123
124 if ( bIncRecording && pInfo->GetRecordingStatus() != RecStatus::Unknown )
125 {
126 V2RecordingInfo *pRecording = pProgram->Recording();
127
128 const RecordingInfo pRecInfo(*pInfo);
129
130 pRecording->setRecordedId ( pRecInfo.GetRecordingID() );
131 pRecording->setStatus ( pRecInfo.GetRecordingStatus() );
132 pRecording->setStatusName ( RecStatus::toString( pRecInfo.GetRecordingStatus() ) );
133 pRecording->setRecTypeStatus ( pRecInfo.GetRecTypeStatus(true) );
134 pRecording->setPriority( pRecInfo.GetRecordingPriority() );
135 pRecording->setStartTs ( pRecInfo.GetRecordingStartTime() );
136 pRecording->setEndTs ( pRecInfo.GetRecordingEndTime() );
137
138 if (bDetails)
139 {
140 pRecording->setFileName ( pRecInfo.GetPathname() );
141 pRecording->setFileSize ( pRecInfo.GetFilesize() );
142 pRecording->setHostName ( pRecInfo.GetHostname() );
143 pRecording->setLastModified( pRecInfo.GetLastModifiedTime() );
144
145 pRecording->setRecordId ( pRecInfo.GetRecordingRuleID() );
146 pRecording->setRecGroup ( pRecInfo.GetRecordingGroup() );
147 pRecording->setPlayGroup ( pRecInfo.GetPlaybackGroup() );
148 pRecording->setStorageGroup( pRecInfo.GetStorageGroup() );
149 pRecording->setRecType ( pRecInfo.GetRecordingRuleType() );
150 pRecording->setDupInType ( pRecInfo.GetDuplicateCheckSource() );
151 pRecording->setDupMethod ( pRecInfo.GetDuplicateCheckMethod() );
152 pRecording->setEncoderId ( pRecInfo.GetInputID() );
153 pRecording->setEncoderName ( pRecInfo.GetInputName() );
154 pRecording->setProfile ( pRecInfo.GetProgramRecordingProfile() );
155 }
156 }
157 else
158 {
159 pProgram->enableRecording(false);
160 }
161
162 if ( bIncArtwork && !pInfo->GetInetRef().isEmpty() )
163 V2FillArtworkInfoList( pProgram->Artwork(), pInfo->GetInetRef(), pInfo->GetSeason());
164 else
165 pProgram->enableArtwork(false);
166}
167
169//
171
173 uint nChanID,
174 bool bDetails /* = true */ )
175{
176 ChannelInfo channel;
177 if (channel.Load(nChanID))
178 {
179 return V2FillChannelInfo(pChannel, channel, bDetails);
180 }
181
182 return false;
183}
184
186//
188
190 const ChannelInfo &channelInfo,
191 bool bDetails /* = true */ )
192{
193
194 // TODO update V2ChannelInfo to match functionality of ChannelInfo,
195 // ultimately replacing it's progenitor?
196 pChannel->setChanId(channelInfo.m_chanId);
197 pChannel->setChanNum(channelInfo.m_chanNum);
198 pChannel->setCallSign(channelInfo.m_callSign);
199 if (!channelInfo.m_icon.isEmpty())
200 {
201 QString sIconURL = QString( "/Guide/GetChannelIcon?FileName=%1")
202 .arg( channelInfo.m_icon );
203 pChannel->setIconURL( sIconURL );
204 pChannel->setIcon( channelInfo.m_icon );
205 }
206 pChannel->setChannelName(channelInfo.m_name);
207 pChannel->setVisible(channelInfo.m_visible > kChannelNotVisible);
208 pChannel->setExtendedVisible(toRawString(channelInfo.m_visible));
209
210 if (bDetails)
211 {
212 pChannel->setMplexId(channelInfo.m_mplexId);
213 pChannel->setServiceId(channelInfo.m_serviceId);
214 pChannel->setATSCMajorChan(channelInfo.m_atscMajorChan);
215 pChannel->setATSCMinorChan(channelInfo.m_atscMinorChan);
216 pChannel->setFormat(channelInfo.m_tvFormat);
217 pChannel->setFineTune(channelInfo.m_fineTune);
218 pChannel->setFrequencyId(channelInfo.m_freqId);
219 pChannel->setChanFilters(channelInfo.m_videoFilters);
220 pChannel->setSourceId(channelInfo.m_sourceId);
221 pChannel->setCommFree(channelInfo.m_commMethod == -2);
222 pChannel->setUseEIT(channelInfo.m_useOnAirGuide);
223 pChannel->setXMLTVID(channelInfo.m_xmltvId);
224 pChannel->setDefaultAuth(channelInfo.m_defaultAuthority);
225 pChannel->setServiceType(channelInfo.m_serviceType);
226 pChannel->setRecPriority(channelInfo.m_recPriority);
227 pChannel->setTimeOffset(channelInfo.m_tmOffset);
228 pChannel->setCommMethod(channelInfo.m_commMethod);
229
230 QList<uint> groupIds = channelInfo.GetGroupIds();
231 QString sGroupIds;
232 for (int x = 0; x < groupIds.size(); x++)
233 {
234 if (x > 0)
235 sGroupIds += ",";
236
237 sGroupIds += QString::number(groupIds.at(x));
238 }
239 pChannel->setChannelGroups(sGroupIds);
240
241 QList<uint> inputIds = channelInfo.GetInputIds();
242 QString sInputIds;
243 for (int x = 0; x < inputIds.size(); x++)
244 {
245 if (x > 0)
246 sInputIds += ",";
247
248 sInputIds += QString::number(inputIds.at(x));
249 }
250 pChannel->setInputs(sInputIds);
251 }
252
253 return true;
254}
255
256void V2FillChannelGroup(V2ChannelGroup* pGroup, const ChannelGroupItem& pGroupItem)
257{
258 if (!pGroup)
259 return;
260
261 pGroup->setGroupId(pGroupItem.m_grpId);
262 pGroup->setName(pGroupItem.m_name);
263 pGroup->setPassword(""); // Not currently supported
264}
265
267//
269
271 RecordingRule *pRule )
272{
273 if ((pRecRule == nullptr) || (pRule == nullptr))
274 return;
275
276 pRecRule->setId ( pRule->m_recordID );
277 pRecRule->setParentId ( pRule->m_parentRecID );
278 pRecRule->setInactive ( pRule->m_isInactive );
279 pRecRule->setTitle ( pRule->m_title );
280 pRecRule->setSubTitle ( pRule->m_subtitle );
281 pRecRule->setDescription ( pRule->m_description );
282 pRecRule->setSeason ( pRule->m_season );
283 pRecRule->setEpisode ( pRule->m_episode );
284 pRecRule->setCategory ( pRule->m_category );
285#if QT_VERSION < QT_VERSION_CHECK(6,5,0)
286 pRecRule->setStartTime ( QDateTime(pRule->m_startdate,
287 pRule->m_starttime, Qt::UTC));
288 pRecRule->setEndTime ( QDateTime(pRule->m_enddate,
289 pRule->m_endtime, Qt::UTC));
290#else
291 static const QTimeZone utc(QTimeZone::UTC);
292 pRecRule->setStartTime ( QDateTime(pRule->m_startdate,
293 pRule->m_starttime, utc));
294 pRecRule->setEndTime ( QDateTime(pRule->m_enddate,
295 pRule->m_endtime, utc));
296#endif
297 pRecRule->setSeriesId ( pRule->m_seriesid );
298 pRecRule->setProgramId ( pRule->m_programid );
299 pRecRule->setInetref ( pRule->m_inetref );
300 pRecRule->setChanId ( pRule->m_channelid );
301 pRecRule->setCallSign ( pRule->m_station );
302 pRecRule->setFindDay ( pRule->m_findday );
303 pRecRule->setFindTime ( pRule->m_findtime );
304 pRecRule->setType ( toRawString(pRule->m_type) );
305 pRecRule->setSearchType ( toRawString(pRule->m_searchType));
306 pRecRule->setRecPriority ( pRule->m_recPriority );
307 pRecRule->setPreferredInput ( pRule->m_prefInput );
308 pRecRule->setStartOffset ( pRule->m_startOffset );
309 pRecRule->setEndOffset ( pRule->m_endOffset );
310 pRecRule->setDupMethod ( toRawString(pRule->m_dupMethod) );
311 pRecRule->setDupIn ( toRawString(pRule->m_dupIn) );
312 pRecRule->setNewEpisOnly ( newEpifromDupIn(pRule->m_dupIn) );
313 pRecRule->setFilter ( pRule->m_filter );
314 pRecRule->setRecProfile ( pRule->m_recProfile );
315 pRecRule->setRecGroup ( RecordingInfo::GetRecgroupString(pRule->m_recGroupID) );
316 pRecRule->setStorageGroup ( pRule->m_storageGroup );
317 pRecRule->setPlayGroup ( pRule->m_playGroup );
318 pRecRule->setAutoExpire ( pRule->m_autoExpire );
319 pRecRule->setMaxEpisodes ( pRule->m_maxEpisodes );
320 pRecRule->setMaxNewest ( pRule->m_maxNewest );
321 pRecRule->setAutoCommflag ( pRule->m_autoCommFlag );
322 pRecRule->setAutoTranscode ( pRule->m_autoTranscode );
323 pRecRule->setAutoMetaLookup ( pRule->m_autoMetadataLookup );
324 pRecRule->setAutoUserJob1 ( pRule->m_autoUserJob1 );
325 pRecRule->setAutoUserJob2 ( pRule->m_autoUserJob2 );
326 pRecRule->setAutoUserJob3 ( pRule->m_autoUserJob3 );
327 pRecRule->setAutoUserJob4 ( pRule->m_autoUserJob4 );
328 pRecRule->setTranscoder ( pRule->m_transcoder );
329 pRecRule->setNextRecording ( pRule->m_nextRecording );
330 pRecRule->setLastRecorded ( pRule->m_lastRecorded );
331 pRecRule->setLastDeleted ( pRule->m_lastDeleted );
332 pRecRule->setAverageDelay ( pRule->m_averageDelay );
333 pRecRule->setAutoExtend ( toString(pRule->m_autoExtend) );
334}
335
337 const QString &sInetref,
338 uint nSeason )
339{
340 ArtworkMap map = GetArtwork(sInetref, nSeason);
341 for (auto i = map.cbegin(); i != map.cend(); ++i)
342 {
343 V2ArtworkInfo *pArtInfo = pArtworkInfoList->AddNewArtworkInfo();
344 pArtInfo->setFileName(i.value().url);
345 switch (i.key())
346 {
347 case kArtworkFanart:
348 pArtInfo->setStorageGroup("Fanart");
349 pArtInfo->setType("fanart");
350 pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1"
351 "&FileName=%2")
352 .arg("Fanart",
353 QString(QUrl::toPercentEncoding(
354 QUrl(i.value().url).path()))));
355 break;
356 case kArtworkBanner:
357 pArtInfo->setStorageGroup("Banners");
358 pArtInfo->setType("banner");
359 pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1"
360 "&FileName=%2")
361 .arg("Banners",
362 QString(QUrl::toPercentEncoding(
363 QUrl(i.value().url).path()))));
364 break;
365 case kArtworkCoverart:
366 default:
367 pArtInfo->setStorageGroup("Coverart");
368 pArtInfo->setType("coverart");
369 pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1"
370 "&FileName=%2")
371 .arg("Coverart",
372 QString(QUrl::toPercentEncoding(
373 QUrl(i.value().url).path()))));
374 break;
375 }
376 }
377}
378
379void V2FillGenreList(V2GenreList* pGenreList, int videoID)
380{
381 if (!pGenreList)
382 return;
383
385 query.prepare("SELECT genre from videogenre "
386 "LEFT JOIN videometadatagenre ON videometadatagenre.idgenre = videogenre.intid "
387 "WHERE idvideo = :ID "
388 "ORDER BY genre;");
389 query.bindValue(":ID", videoID);
390
391 if (query.exec() && query.size() > 0)
392 {
393 while (query.next())
394 {
395 V2Genre *pGenre = pGenreList->AddNewGenre();
396 QString genre = query.value(0).toString();
397 pGenre->setName(genre);
398 }
399 }
400}
401
402
404 V2VideoMetadataInfo *pVideoMetadataInfo,
406 bool bDetails)
407{
408 pVideoMetadataInfo->setId(pMetadata->GetID());
409 pVideoMetadataInfo->setTitle(pMetadata->GetTitle());
410 pVideoMetadataInfo->setSubTitle(pMetadata->GetSubtitle());
411 pVideoMetadataInfo->setTagline(pMetadata->GetTagline());
412 pVideoMetadataInfo->setDirector(pMetadata->GetDirector());
413 pVideoMetadataInfo->setStudio(pMetadata->GetStudio());
414 pVideoMetadataInfo->setDescription(pMetadata->GetPlot());
415 pVideoMetadataInfo->setCertification(pMetadata->GetRating());
416 pVideoMetadataInfo->setInetref(pMetadata->GetInetRef());
417 pVideoMetadataInfo->setCollectionref(pMetadata->GetCollectionRef());
418 pVideoMetadataInfo->setHomePage(pMetadata->GetHomepage());
419#if QT_VERSION < QT_VERSION_CHECK(6,5,0)
420 pVideoMetadataInfo->setReleaseDate(
421 QDateTime(pMetadata->GetReleaseDate(),
422 QTime(0,0),Qt::LocalTime).toUTC());
423 pVideoMetadataInfo->setAddDate(
424 QDateTime(pMetadata->GetInsertdate(),
425 QTime(0,0),Qt::LocalTime).toUTC());
426#else
427 static const QTimeZone localtime(QTimeZone::LocalTime);
428 pVideoMetadataInfo->setReleaseDate(
429 QDateTime(pMetadata->GetReleaseDate(),
430 QTime(0,0),localtime).toUTC());
431 pVideoMetadataInfo->setAddDate(
432 QDateTime(pMetadata->GetInsertdate(),
433 QTime(0,0),localtime).toUTC());
434#endif
435 pVideoMetadataInfo->setUserRating(pMetadata->GetUserRating());
436 pVideoMetadataInfo->setChildID(pMetadata->GetChildID());
437 pVideoMetadataInfo->setLength(pMetadata->GetLength().count());
438 pVideoMetadataInfo->setPlayCount(pMetadata->GetPlayCount());
439 pVideoMetadataInfo->setSeason(pMetadata->GetSeason());
440 pVideoMetadataInfo->setEpisode(pMetadata->GetEpisode());
441 pVideoMetadataInfo->setParentalLevel(pMetadata->GetShowLevel());
442 pVideoMetadataInfo->setVisible(pMetadata->GetBrowse());
443 pVideoMetadataInfo->setWatched(pMetadata->GetWatched());
444 pVideoMetadataInfo->setProcessed(pMetadata->GetProcessed());
445 pVideoMetadataInfo->setContentType(ContentTypeToString(
446 pMetadata->GetContentType()));
447 pVideoMetadataInfo->setFileName(pMetadata->GetFilename());
448 pVideoMetadataInfo->setHash(pMetadata->GetHash());
449 pVideoMetadataInfo->setHostName(pMetadata->GetHost());
450 pVideoMetadataInfo->setCoverart(pMetadata->GetCoverFile());
451 pVideoMetadataInfo->setFanart(pMetadata->GetFanart());
452 pVideoMetadataInfo->setBanner(pMetadata->GetBanner());
453 pVideoMetadataInfo->setScreenshot(pMetadata->GetScreenshot());
454 pVideoMetadataInfo->setTrailer(pMetadata->GetTrailer());
455 pVideoMetadataInfo->setCategory(pMetadata->GetCategoryID());
456
457 if (bDetails)
458 {
459 if (!pMetadata->GetFanart().isEmpty())
460 {
461 V2ArtworkInfo *pArtInfo =
462 pVideoMetadataInfo->Artwork()->AddNewArtworkInfo();
463 pArtInfo->setStorageGroup("Fanart");
464 pArtInfo->setType("fanart");
465 pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1"
466 "&FileName=%2")
467 .arg("Fanart",
468 QString(
469 QUrl::toPercentEncoding(pMetadata->GetFanart()))));
470 }
471 if (!pMetadata->GetCoverFile().isEmpty())
472 {
473 V2ArtworkInfo *pArtInfo =
474 pVideoMetadataInfo->Artwork()->AddNewArtworkInfo();
475 pArtInfo->setStorageGroup("Coverart");
476 pArtInfo->setType("coverart");
477 pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1"
478 "&FileName=%2")
479 .arg("Coverart",
480 QString(
481 QUrl::toPercentEncoding(pMetadata->GetCoverFile()))));
482 }
483 if (!pMetadata->GetBanner().isEmpty())
484 {
485 V2ArtworkInfo *pArtInfo =
486 pVideoMetadataInfo->Artwork()->AddNewArtworkInfo();
487 pArtInfo->setStorageGroup("Banners");
488 pArtInfo->setType("banner");
489 pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1"
490 "&FileName=%2")
491 .arg("Banners",
492 QString(
493 QUrl::toPercentEncoding(pMetadata->GetBanner()))));
494 }
495 if (!pMetadata->GetScreenshot().isEmpty())
496 {
497 V2ArtworkInfo *pArtInfo =
498 pVideoMetadataInfo->Artwork()->AddNewArtworkInfo();
499 pArtInfo->setStorageGroup("Screenshots");
500 pArtInfo->setType("screenshot");
501 pArtInfo->setURL(QString("/Content/GetImageFile?StorageGroup=%1"
502 "&FileName=%2")
503 .arg("Screenshots",
504 QString(
505 QUrl::toPercentEncoding(pMetadata->GetScreenshot()))));
506 }
507 }
508
509 V2FillGenreList(pVideoMetadataInfo->Genres(), pVideoMetadataInfo->GetId());
510
511 auto castList = pMetadata->GetCast();
512 V2CastMemberList* pCastMemberList = pVideoMetadataInfo->Cast();
513
514 QString actors = QObject::tr("Actors");
515 for (const VideoMetadata::cast_entry& ent : castList )
516 {
517 V2CastMember *pCastMember = pCastMemberList->AddNewCastMember();
518 pCastMember->setTranslatedRole(actors);
519 pCastMember->setRole("ACTOR");
520 pCastMember->setName(ent.second);
521 }
522
523}
524
526//
528
530 MusicMetadata *pMetadata, bool bDetails)
531{
532 pVideoMetadataInfo->setId(pMetadata->ID());
533 pVideoMetadataInfo->setArtist(pMetadata->Artist());
534 pVideoMetadataInfo->setCompilationArtist(pMetadata->CompilationArtist());
535 pVideoMetadataInfo->setAlbum(pMetadata->Album());
536 pVideoMetadataInfo->setTitle(pMetadata->Title());
537 pVideoMetadataInfo->setTrackNo(pMetadata->Track());
538 pVideoMetadataInfo->setGenre(pMetadata->Genre());
539 pVideoMetadataInfo->setYear(pMetadata->Year());
540 pVideoMetadataInfo->setPlayCount(pMetadata->PlayCount());
541 pVideoMetadataInfo->setLength(pMetadata->Length().count());
542 pVideoMetadataInfo->setRating(pMetadata->Rating());
543 pVideoMetadataInfo->setFileName(pMetadata->Filename());
544 pVideoMetadataInfo->setHostName(pMetadata->Hostname());
545 pVideoMetadataInfo->setLastPlayed(pMetadata->LastPlay());
546 pVideoMetadataInfo->setCompilation(pMetadata->Compilation());
547
548 if (bDetails)
549 {
550 //TODO add coverart here
551 }
552}
553
554void V2FillInputInfo(V2Input* input, const InputInfo& inputInfo)
555{
556 input->setId(inputInfo.m_inputId);
557 input->setInputName(inputInfo.m_name);
558 input->setCardId(inputInfo.m_inputId);
559 input->setSourceId(inputInfo.m_sourceId);
560 input->setDisplayName(inputInfo.m_displayName);
561 input->setLiveTVOrder(inputInfo.m_liveTvOrder);
562 input->setScheduleOrder(inputInfo.m_scheduleOrder);
563 input->setRecPriority(inputInfo.m_recPriority);
564 input->setQuickTune(inputInfo.m_quickTune);
565}
566
567
568
570 ProgramInfo* pInfo)
571{
572 if (!pCastMemberList || !pInfo)
573 return;
574
576
577 QString table;
578 if (pInfo->GetFilesize() > 0) // FIXME: This shouldn't be the way to determine what is or isn't a recording!
579 table = "recordedcredits";
580 else
581 table = "credits";
582
583 query.prepare(QString("SELECT role, people.name, roles.name FROM %1"
584 " AS credits"
585 " LEFT JOIN people ON"
586 " credits.person = people.person"
587 " LEFT JOIN roles ON"
588 " credits.roleid = roles.roleid"
589 " WHERE credits.chanid = :CHANID"
590 " AND credits.starttime = :STARTTIME"
591 " ORDER BY role, priority;").arg(table));
592
593 query.bindValue(":CHANID", pInfo->GetChanID());
594 query.bindValue(":STARTTIME", pInfo->GetScheduledStartTime());
595
596 if (query.exec() && query.size() > 0)
597 {
598 QMap<QString, QString> translations;
599 translations["ACTOR"] = QObject::tr("Actors");
600 translations["DIRECTOR"] = QObject::tr("Director");
601 translations["PRODUCER"] = QObject::tr("Producer");
602 translations["EXECUTIVE_PRODUCER"] = QObject::tr("Executive Producer");
603 translations["WRITER"] = QObject::tr("Writer");
604 translations["GUEST_STAR"] = QObject::tr("Guest Star");
605 translations["HOST"] = QObject::tr("Host");
606 translations["ADAPTER"] = QObject::tr("Adapter");
607 translations["PRESENTER"] = QObject::tr("Presenter");
608 translations["COMMENTATOR"] = QObject::tr("Commentator");
609 translations["GUEST"] = QObject::tr("Guest");
610
611 while (query.next())
612 {
613 V2CastMember *pCastMember = pCastMemberList->AddNewCastMember();
614
615 QString role = query.value(0).toString();
616 pCastMember->setTranslatedRole(translations.value(role.toUpper()));
617 pCastMember->setRole(role); // role is invalid after this call.
618 /* The people.name column uses utf8_bin collation.
619 * Qt-MySQL drivers use QVariant::ByteArray for string-type
620 * MySQL fields marked with the BINARY attribute (those using a
621 * *_bin collation) and QVariant::String for all others.
622 * Since QVariant::toString() uses QString::fromAscii()
623 * (through QVariant::convert()) when the QVariant's type is
624 * QVariant::ByteArray, we have to use QString::fromUtf8()
625 * explicitly to prevent corrupting characters.
626 * The following code should be changed to use the simpler
627 * toString() approach, as above, if we do a DB update to
628 * coalesce the people.name values that differ only in case and
629 * change the collation to utf8_general_ci, to match the
630 * majority of other columns, or we'll have the same problem in
631 * reverse.
632 */
633 pCastMember->setName(QString::fromUtf8(query.value(1)
634 .toByteArray().constData()));
635 pCastMember->setCharacterName(QString::fromUtf8(query.value(2)
636 .toByteArray().constData()));
637 }
638 }
639
640}
641
642
643void V2FillCutList(V2CutList* pCutList, ProgramInfo* rInfo, int marktype, bool includeFps)
644{
645 frm_dir_map_t markMap;
646 frm_dir_map_t::const_iterator it;
647
648 if (rInfo && rInfo->GetChanID())
649 {
650 if (includeFps)
651 {
652 rInfo->QueryMarkupMap(markMap, MARK_VIDEO_RATE);
653 it = markMap.cbegin();
654 if (it != markMap.cend())
655 {
656 V2Cutting *pCutting = pCutList->AddNewCutting();
657 pCutting->setMark(*it);
658 pCutting->setOffset(it.key());
659 }
660 markMap.clear();
661 }
662 rInfo->QueryCutList(markMap);
663
664 for (it = markMap.cbegin(); it != markMap.cend(); ++it)
665 {
666 bool isend = (*it) == MARK_CUT_END || (*it) == MARK_COMM_END;
667 if (marktype == 0)
668 {
669 V2Cutting *pCutting = pCutList->AddNewCutting();
670 pCutting->setMark(*it);
671 pCutting->setOffset(it.key());
672 }
673 else if (marktype == 1)
674 {
675 uint64_t offset = 0;
676 if (rInfo->QueryKeyFramePosition(&offset, it.key(), isend))
677 {
678 V2Cutting *pCutting = pCutList->AddNewCutting();
679 pCutting->setMark(*it);
680 pCutting->setOffset(offset);
681 }
682 }
683 else if (marktype == 2)
684 {
685 uint64_t offset = 0;
686 if (rInfo->QueryKeyFrameDuration(&offset, it.key(), isend))
687 {
688 V2Cutting *pCutting = pCutList->AddNewCutting();
689 pCutting->setMark(*it);
690 pCutting->setOffset(offset);
691 }
692 }
693 }
694 }
695}
696
697void V2FillCommBreak(V2CutList* pCutList, ProgramInfo* rInfo, int marktype, bool includeFps)
698{
699 frm_dir_map_t markMap;
700 frm_dir_map_t::const_iterator it;
701
702 if (rInfo)
703 {
704 if (includeFps)
705 {
706 rInfo->QueryMarkupMap(markMap, MARK_VIDEO_RATE);
707 it = markMap.cbegin();
708 if (it != markMap.cend())
709 {
710 V2Cutting *pCutting = pCutList->AddNewCutting();
711 pCutting->setMark(*it);
712 pCutting->setOffset(it.key());
713 }
714 markMap.clear();
715 }
716 rInfo->QueryCommBreakList(markMap);
717
718 for (it = markMap.cbegin(); it != markMap.cend(); ++it)
719 {
720 bool isend = (*it) == MARK_CUT_END || (*it) == MARK_COMM_END;
721 if (marktype == 0)
722 {
723 V2Cutting *pCutting = pCutList->AddNewCutting();
724 pCutting->setMark(*it);
725 pCutting->setOffset(it.key());
726 }
727 else if (marktype == 1)
728 {
729 uint64_t offset = 0;
730 if (rInfo->QueryKeyFramePosition(&offset, it.key(), isend))
731 {
732 V2Cutting *pCutting = pCutList->AddNewCutting();
733 pCutting->setMark(*it);
734 pCutting->setOffset(offset);
735 }
736 }
737 else if (marktype == 2)
738 {
739 uint64_t offset = 0;
740 if (rInfo->QueryKeyFrameDuration(&offset, it.key(), isend))
741 {
742 V2Cutting *pCutting = pCutList->AddNewCutting();
743 pCutting->setMark(*it);
744 pCutting->setOffset(offset);
745 }
746 }
747 }
748 }
749}
750
752//
754
755void V2FillSeek(V2CutList* pCutList, RecordingInfo* rInfo, MarkTypes marktype)
756{
757 frm_pos_map_t markMap;
758 frm_pos_map_t::const_iterator it;
759
760 if (rInfo && rInfo->GetChanID())
761 {
762 rInfo->QueryPositionMap(markMap, marktype);
763
764 for (it = markMap.cbegin(); it != markMap.cend(); ++it)
765 {
766 V2Cutting *pCutting = pCutList->AddNewCutting();
767 pCutting->setMark(it.key());
768 pCutting->setOffset(it.value());
769 }
770 }
771}
772
773void FillEncoderList(QVariantList &list, QObject* parent)
774{
775 QReadLocker tvlocker(&TVRec::s_inputsLock);
776 QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo(true);
777 for (auto * elink : std::as_const(gTVList))
778 {
779 if (elink != nullptr)
780 {
781 // V2Encoder *pEncoder = list->AddNewEncoder();
782 auto *pEncoder = new V2Encoder( parent );
783 list.append( QVariant::fromValue<QObject *>( pEncoder ));
784
785 pEncoder->setId ( elink->GetInputID() );
786 pEncoder->setState ( elink->GetState() );
787 pEncoder->setLocal ( elink->IsLocal() );
788 pEncoder->setConnected ( elink->IsConnected() );
789 pEncoder->setSleepStatus ( elink->GetSleepStatus() );
790
791 if (pEncoder->GetLocal())
792 pEncoder->setHostName( gCoreContext->GetHostName() );
793 else
794 pEncoder->setHostName( elink->GetHostName() );
795
796 for (const auto & inputInfo : std::as_const(inputInfoList))
797 {
798 if (inputInfo.m_inputId == static_cast<uint>(elink->GetInputID()))
799 {
800 V2Input *input = pEncoder->AddNewInput();
801 V2FillInputInfo(input, inputInfo);
802 }
803 }
804
805 bool progFound = false;
806 V2Program *pProgram = pEncoder->Recording();
807 switch ( pEncoder->GetState() )
808 {
812 {
813 ProgramInfo *pInfo = elink->GetRecording();
814
815 if (pInfo)
816 {
817 progFound= true;
818 V2FillProgramInfo( pProgram, pInfo, true, true );
819 delete pInfo;
820 }
821
822 break;
823 }
824
825 default:
826 break;
827 }
828 if (!progFound)
829 pProgram->setProperty("isNull",QVariant(true));
830 }
831 }
832}
833
834// Note - special value -999 for nRecStatus means all values less than 0.
835// This is needed by BackendStatus API
836int FillUpcomingList(QVariantList &list, QObject* parent,
837 int& nStartIndex,
838 int& nCount,
839 bool bShowAll,
840 int nRecordId,
841 int nRecStatus,
842 const QString &Sort,
843 const QString &RecGroup )
844{
845 RecordingList recordingList; // Auto-delete deque
846 RecList tmpList; // Standard deque, objects must be deleted
847
848 if (nRecordId <= 0)
849 nRecordId = -1;
850
851 // For nRecStatus to be effective, showAll must be true.
852 if (nRecStatus != 0)
853 bShowAll = true;
854
855 // NOTE: Fetching this information directly from the schedule is
856 // significantly faster than using ProgramInfo::LoadFromScheduler()
857 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
858 if (scheduler)
859 scheduler->GetAllPending(tmpList, nRecordId);
860
861 // Sort the upcoming into only those which will record
862 // NOLINTNEXTLINE(modernize-loop-convert)
863 for (auto it = tmpList.begin(); it < tmpList.end(); ++it)
864 {
865 if ((nRecStatus == -999
866 && (*it)->GetRecordingStatus() >= 0)
867 || (nRecStatus != 0 && nRecStatus != -999
868 && (*it)->GetRecordingStatus() != nRecStatus))
869 {
870 delete *it;
871 *it = nullptr;
872 continue;
873 }
874
875 if (!RecGroup.isEmpty())
876 {
877 if ( (*it)-> GetRecordingGroup() != RecGroup )
878 {
879 delete *it;
880 *it = nullptr;
881 continue;
882 }
883 }
884
885 if (!bShowAll && ((((*it)->GetRecordingStatus() >= RecStatus::Pending) &&
886 ((*it)->GetRecordingStatus() <= RecStatus::WillRecord)) ||
887 ((*it)->GetRecordingStatus() == RecStatus::Offline) ||
888 ((*it)->GetRecordingStatus() == RecStatus::Conflict)) &&
889 ((*it)->GetRecordingEndTime() > MythDate::current()))
890 { // NOLINT(bugprone-branch-clone)
891 recordingList.push_back(new RecordingInfo(**it));
892 }
893 else if (bShowAll &&
894 ((*it)->GetRecordingEndTime() > MythDate::current()))
895 {
896 recordingList.push_back(new RecordingInfo(**it));
897 }
898
899 delete *it;
900 *it = nullptr;
901 }
902
903 // Sort the list
904
905 int sortType = 0;
906 if (Sort.startsWith("channum", Qt::CaseInsensitive))
907 sortType = 10;
908 else if (Sort.startsWith("title", Qt::CaseInsensitive))
909 sortType = 20;
910 else if (Sort.startsWith("length", Qt::CaseInsensitive))
911 sortType = 30;
912 else if (Sort.startsWith("status", Qt::CaseInsensitive))
913 sortType = 40;
914 if (Sort.endsWith("desc", Qt::CaseInsensitive))
915 sortType += 1;
916
917 static QRegularExpression regex("[_-]");
918
919 auto comp = [sortType](const RecordingInfo *First, const RecordingInfo *Second)
920 {
921 switch (sortType)
922 {
923 case 0:
924 return First->GetScheduledStartTime() < Second->GetScheduledStartTime();
925 case 1:
926 return First->GetScheduledStartTime() > Second->GetScheduledStartTime();
927 case 10:
928 return First->GetChanNum().replace(regex,".").toDouble()
929 < Second->GetChanNum().replace(regex,".").toDouble();
930 case 11:
931 return First->GetChanNum().replace(regex,".").toDouble()
932 > Second->GetChanNum().replace(regex,".").toDouble();
933 case 20:
934 return QString::compare(First->GetSortTitle(), Second->GetSortTitle(), Qt::CaseInsensitive) < 0 ;
935 case 21:
936 return QString::compare(First->GetSortTitle(), Second->GetSortTitle(), Qt::CaseInsensitive) > 0 ;
937 case 30:
938 {
939 qint64 time1 = First->GetScheduledStartTime().msecsTo( First->GetScheduledEndTime());
940 qint64 time2 = Second->GetScheduledStartTime().msecsTo( Second->GetScheduledEndTime());
941 return time1 < time2 ;
942 }
943 case 31:
944 {
945 qint64 time1 = First->GetScheduledStartTime().msecsTo( First->GetScheduledEndTime());
946 qint64 time2 = Second->GetScheduledStartTime().msecsTo( Second->GetScheduledEndTime());
947 return time1 > time2 ;
948 }
949 case 40:
950 return QString::compare(RecStatus::toString(First->GetRecordingStatus()),
951 RecStatus::toString(Second->GetRecordingStatus()),
952 Qt::CaseInsensitive) < 0 ;
953 case 41:
954 return QString::compare(RecStatus::toString(First->GetRecordingStatus()),
955 RecStatus::toString(Second->GetRecordingStatus()),
956 Qt::CaseInsensitive) > 0 ;
957 }
958 return false;
959 };
960
961 // no need to sort when zero because that is the default order from the scheduler
962 if (sortType > 0)
963 std::ranges::stable_sort(recordingList, comp);
964
965 // ----------------------------------------------------------------------
966 // Build Response
967 // ----------------------------------------------------------------------
968
969 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)recordingList.size() ) : 0;
970 nCount = (nCount > 0) ? std::min( nCount, (int)recordingList.size() ) : recordingList.size();
971 int nEndIndex = std::min((nStartIndex + nCount), (int)recordingList.size() );
972
973 for( int n = nStartIndex; n < nEndIndex; n++)
974 {
975 ProgramInfo *pInfo = recordingList[ n ];
976 auto *pProgram = new V2Program( parent );
977 list.append( QVariant::fromValue<QObject *>( pProgram ));
978 V2FillProgramInfo( pProgram, pInfo, true );
979 }
980
981 return recordingList.size();
982}
983
984void FillFrontendList(QVariantList &list, QObject* parent, bool OnLine)
985{
986 QMap<QString, Frontend*> frontends;
987 if (OnLine)
989 else
990 frontends = gBackendContext->GetFrontends();
991
992 for (auto * fe : std::as_const(frontends))
993 {
994 auto *pFrontend = new V2Frontend( parent );
995 list.append( QVariant::fromValue<QObject *>( pFrontend ));
996 pFrontend->setName(fe->m_name);
997 pFrontend->setIP(fe->m_ip.toString());
998 int port = gCoreContext->GetNumSettingOnHost("FrontendStatusPort",
999 fe->m_name, 6547);
1000 pFrontend->setPort(port);
1001 pFrontend->setOnLine(fe->m_connectionCount > 0);
1002 }
1003}
1004
1005
1006int V2CreateRecordingGroup(const QString& groupName)
1007{
1008 int groupID = -1;
1010
1011 query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
1012 "displayname = :DISPLAYNAME");
1013 query.bindValue(":NAME", groupName);
1014 query.bindValue(":DISPLAYNAME", groupName);
1015
1016 if (query.exec())
1017 groupID = query.lastInsertId().toInt();
1018
1019 if (groupID <= 0)
1020 LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
1021 "Does it already exist?").arg(groupName));
1022
1023 return groupID;
1024}
1025
1026DBCredits * V2jsonCastToCredits(const QJsonObject &cast)
1027{
1028 int priority = 1;
1029 auto* credits = new DBCredits;
1030
1031 QJsonArray members = cast["CastMembers"].toArray();
1032 for (const auto & m : std::as_const(members))
1033 {
1034 QJsonObject actor = m.toObject();
1035 QString name = actor.value("Name").toString("");
1036 QString character = actor.value("CharacterName").toString("");
1037 QString role = actor.value("Role").toString("");
1038
1039 credits->emplace_back(role, name, priority++, character);
1040 }
1041
1042 return credits;
1043}
1044
1045// Code copied from class VideoDevice
1046V2CaptureDeviceList* getV4l2List ( const QRegularExpression &driver, const QString & cardType )
1047{
1048 auto* pList = new V2CaptureDeviceList();
1049 uint minor_min = 0;
1050 uint minor_max = 15;
1051 QString card = QString();
1052
1053 // /dev/v4l/video*
1054 QDir dev("/dev/v4l", "video*", QDir::Name, QDir::System);
1055 fillSelectionsFromDir(dev, minor_min, minor_max,
1056 card, driver, false, pList, cardType);
1057
1058 // /dev/video*
1059 dev.setPath("/dev");
1060 fillSelectionsFromDir(dev, minor_min, minor_max,
1061 card, driver, false, pList, cardType);
1062
1063 // /dev/dtv/video*
1064 dev.setPath("/dev/dtv");
1065 fillSelectionsFromDir(dev, minor_min, minor_max,
1066 card, driver, false, pList, cardType);
1067
1068 // /dev/dtv*
1069 dev.setPath("/dev");
1070 dev.setNameFilters(QStringList("dtv*"));
1071 fillSelectionsFromDir(dev, minor_min, minor_max,
1072 card, driver, false, pList, cardType);
1073
1074 return pList;
1075}
1076
1078 uint minor_min, uint minor_max,
1079 const QString& card, const QRegularExpression& driver,
1080 bool allow_duplicates, V2CaptureDeviceList *pList,
1081 const QString & cardType)
1082{
1083 uint cnt = 0;
1084 QMap<uint, uint> minorlist;
1085 QFileInfoList entries = dir.entryInfoList();
1086 for (const auto & fi : std::as_const(entries))
1087 {
1088 struct stat st {};
1089 QString filepath = fi.absoluteFilePath();
1090 int err = lstat(filepath.toLocal8Bit().constData(), &st);
1091
1092 if (err)
1093 {
1094 LOG(VB_GENERAL, LOG_ERR,
1095 QString("Could not stat file: %1").arg(filepath));
1096 continue;
1097 }
1098
1099 // is this is a character device?
1100 if (!S_ISCHR(st.st_mode))
1101 continue;
1102
1103 // is this device is in our minor range?
1104 uint minor_num = minor(st.st_rdev);
1105 if (minor_min > minor_num || minor_max < minor_num)
1106 continue;
1107
1108 // ignore duplicates if allow_duplicates not set
1109 if (!allow_duplicates && minorlist[minor_num])
1110 continue;
1111
1112 // if the driver returns any info add this device to our list
1113 QByteArray tmp = filepath.toLatin1();
1114 int videofd = open(tmp.constData(), O_RDWR);
1115 if (videofd >= 0)
1116 {
1117 QString card_name;
1118 QString driver_name;
1119 if (CardUtil::GetV4LInfo(videofd, card_name, driver_name))
1120 {
1121 auto match = driver.match(driver_name);
1122 if ((!driver.pattern().isEmpty() || match.hasMatch()) &&
1123 (card.isEmpty() || (card_name == card)))
1124 {
1125 auto* pDev = pList->AddCaptureDevice();
1126 pDev->setCardType (cardType);
1127 pDev->setVideoDevice (filepath);
1128 pDev->setFrontendName(card_name);
1129 QStringList inputs;
1130 CardUtil::GetDeviceInputNames(filepath, cardType, inputs);
1131 pDev->setInputNames(inputs);
1132 inputs = CardUtil::ProbeAudioInputs(filepath, cardType);
1133 pDev->setAudioDevices(inputs);
1134 if (cardType == "HDPVR")
1135 pDev->setChannelTimeout ( 15000 );
1136 cnt++;
1137 }
1138 }
1139 close(videofd);
1140 }
1141 // add to list of minors discovered to avoid duplicates
1142 minorlist[minor_num] = 1;
1143 }
1144
1145 return cnt;
1146}
1147
1148V2CaptureDeviceList* getFirewireList ([[maybe_unused]] const QString & cardType)
1149{
1150 auto* pList = new V2CaptureDeviceList();
1151
1152#if CONFIG_FIREWIRE
1153 std::vector<AVCInfo> list = FirewireDevice::GetSTBList();
1154 for (auto & info : list)
1155 {
1156 auto* pDev = pList->AddCaptureDevice();
1157 pDev->setCardType (cardType);
1158 QString guid = info.GetGUIDString();
1159 pDev->setVideoDevice (guid);
1160 QString model = FirewireDevice::GetModelName(info.m_vendorid, info.m_modelid);
1161 pDev->setFirewireModel(model);
1162 pDev->setDescription(info.m_product_name);
1163 pDev->setSignalTimeout ( 2000 );
1164 pDev->setChannelTimeout ( 9000 );
1165 }
1166#endif // CONFIG_FIREWIRE
1167 return pList;
1168}
QMap< int, EncoderLink * > gTVList
BackendContext * gBackendContext
QString toRawString(ChannelVisibleType type)
@ kChannelNotVisible
Definition: channelinfo.h:23
void push_back(T info)
size_t size(void) const
QMap< QString, Frontend * > GetFrontends() const
QMap< QString, Frontend * > GetConnectedFrontends() const
static void GetDeviceInputNames(const QString &device, const QString &inputtype, QStringList &inputs)
Definition: cardutil.cpp:2676
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2369
static QList< InputInfo > GetAllInputInfo(bool virtTuners)
Definition: cardutil.cpp:1745
static QStringList ProbeAudioInputs(const QString &device, const QString &inputtype=QString())
Definition: cardutil.cpp:2558
QList< uint > GetGroupIds() const
Definition: channelinfo.h:56
QString m_chanNum
Definition: channelinfo.h:85
uint m_chanId
Definition: channelinfo.h:84
int m_fineTune
Definition: channelinfo.h:94
QString m_tvFormat
Definition: channelinfo.h:104
QString m_name
Definition: channelinfo.h:91
QString m_icon
Definition: channelinfo.h:92
uint m_atscMinorChan
Definition: channelinfo.h:113
uint m_serviceType
Definition: channelinfo.h:111
QString m_freqId
Definition: channelinfo.h:86
bool m_useOnAirGuide
Definition: channelinfo.h:107
int m_commMethod
Definition: channelinfo.h:118
QList< uint > GetInputIds() const
Definition: channelinfo.h:66
ChannelVisibleType m_visible
Definition: channelinfo.h:105
bool Load(uint lchanid=-1)
uint m_atscMajorChan
Definition: channelinfo.h:112
uint m_serviceId
Definition: channelinfo.h:110
int m_recPriority
Definition: channelinfo.h:97
QString m_defaultAuthority
Definition: channelinfo.h:117
QString m_callSign
Definition: channelinfo.h:90
QString m_xmltvId
Definition: channelinfo.h:96
uint m_mplexId
Definition: channelinfo.h:109
uint m_sourceId
Definition: channelinfo.h:88
QString m_videoFilters
Definition: channelinfo.h:95
static std::vector< AVCInfo > GetSTBList(void)
static QString GetModelName(uint vendor_id, uint model_id)
uint m_scheduleOrder
Definition: inputinfo.h:54
int m_recPriority
Definition: inputinfo.h:53
QString m_displayName
Definition: inputinfo.h:52
QString m_name
input name
Definition: inputinfo.h:47
uint m_liveTvOrder
order for live TV use
Definition: inputinfo.h:55
uint m_inputId
unique key in DB for this input
Definition: inputinfo.h:49
uint m_sourceId
associated channel listings source
Definition: inputinfo.h:48
bool m_quickTune
Definition: inputinfo.h:56
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:838
QVariant value(int i) const
Definition: mythdbcon.h:204
int size(void) const
Definition: mythdbcon.h:214
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:889
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:936
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:813
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
int Year() const
QDateTime LastPlay() const
QString Hostname(void)
QString CompilationArtist() const
std::chrono::milliseconds Length() const
QString Title() const
int Track() const
IdType ID() const
QString Filename(bool find=true)
QString Artist() const
int Rating() const
bool Compilation() const
int PlayCount() const
QString Genre() const
QString Album() const
int GetNumSettingOnHost(const QString &key, const QString &host, int defaultval=0)
QString GetHostName(void)
MythScheduler * GetScheduler(void)
Holds information on recordings and videos.
Definition: programinfo.h:74
float GetStars(void) const
Definition: programinfo.h:453
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:380
uint GetRecordingRuleID(void) const
Definition: programinfo.h:460
RecordingDupMethodType GetDuplicateCheckMethod(void) const
What should be compared to determine if two programs are the same?
Definition: programinfo.h:470
QString GetSeriesID(void) const
Definition: programinfo.h:446
QString GetAudioPropertyNames(void) const
uint GetVideoProperties(void) const
Definition: programinfo.h:507
QString GetCategoryTypeString(void) const
Returns catType as a string.
uint GetEpisode(void) const
Definition: programinfo.h:374
uint GetSubtitleType(void) const
Definition: programinfo.h:505
QString GetProgramID(void) const
Definition: programinfo.h:447
QString GetRecordingGroup(void) const
Definition: programinfo.h:427
QString GetProgramFlagNames(void) const
uint GetRecordingID(void) const
Definition: programinfo.h:457
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:405
QString GetInetRef(void) const
Definition: programinfo.h:448
RecordingDupInType GetDuplicateCheckSource(void) const
Where should we check for duplicates?
Definition: programinfo.h:466
bool QueryKeyFrameDuration(uint64_t *duration, uint64_t keyframe, bool backwards) const
void QueryCommBreakList(frm_dir_map_t &frames) const
uint GetAudioProperties(void) const
Definition: programinfo.h:509
bool IsRepeat(void) const
Definition: programinfo.h:499
void QueryPositionMap(frm_pos_map_t &posMap, MarkTypes type) const
QString GetHostname(void) const
Definition: programinfo.h:429
QString GetPlaybackGroup(void) const
Definition: programinfo.h:428
QString GetDescription(void) const
Definition: programinfo.h:372
QDateTime GetLastModifiedTime(void) const
Definition: programinfo.h:440
QString GetStorageGroup(void) const
Definition: programinfo.h:430
QString GetTitle(void) const
Definition: programinfo.h:368
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:412
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:398
bool QueryCutList(frm_dir_map_t &delMap, bool loadAutosave=false) const
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:384
QString GetSubtitleTypeNames(void) const
uint GetYearOfInitialRelease(void) const
Definition: programinfo.h:431
QString GetInputName(void) const
Definition: programinfo.h:475
QString GetSortTitle(void) const
Definition: programinfo.h:369
int GetRecordingPriority(void) const
Definition: programinfo.h:451
QString GetPathname(void) const
Definition: programinfo.h:350
bool QueryKeyFramePosition(uint64_t *position, uint64_t keyframe, bool backwards) const
QDate GetOriginalAirDate(void) const
Definition: programinfo.h:439
uint GetInputID(void) const
Definition: programinfo.h:474
void QueryMarkupMap(frm_dir_map_t &marks, MarkTypes type, bool merge=false) const
QString GetVideoPropertyNames(void) const
virtual uint64_t GetFilesize(void) const
uint32_t GetProgramFlags(void) const
Definition: programinfo.h:481
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:458
QString GetRecTypeStatus(bool showrerecord) const
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:420
QString GetSubtitle(void) const
Definition: programinfo.h:370
QString GetCategory(void) const
Definition: programinfo.h:377
uint GetSeason(void) const
Definition: programinfo.h:373
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:462
uint GetEpisodeTotal(void) const
Definition: programinfo.h:375
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:36
static QString GetRecgroupString(uint recGroupID)
Temporary helper during transition from string to ID.
QString GetProgramRecordingProfile(void) const
Returns recording profile name that will be, or was used, for this program, creating "record" field i...
uint64_t GetFilesize(void) const override
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:30
RecordingType m_type
QString m_station
Definition: recordingrule.h:99
QString m_programid
Definition: recordingrule.h:86
QString m_category
Definition: recordingrule.h:83
int m_findday
Day of the week for once per week etc.
QString m_inetref
Definition: recordingrule.h:88
RecSearchType m_searchType
unsigned m_filter
QTime m_findtime
Time for timeslot rules.
QString m_description
Definition: recordingrule.h:82
QString m_storageGroup
QDateTime m_nextRecording
int m_recordID
Unique Recording Rule ID.
Definition: recordingrule.h:71
RecordingDupInType m_dupIn
QString m_title
Definition: recordingrule.h:78
int m_channelid
callsign?
QString m_recProfile
bool m_isInactive
Recording rule is enabled?
Definition: recordingrule.h:75
QString m_playGroup
QString m_subtitle
Definition: recordingrule.h:80
RecordingDupMethodType m_dupMethod
QDateTime m_lastDeleted
QString m_seriesid
Definition: recordingrule.h:85
QDateTime m_lastRecorded
bool m_autoMetadataLookup
AutoExtendType m_autoExtend
bool GetAllPending(RecList &retList, int recRuleId=0) const
Definition: scheduler.cpp:1756
static QReadWriteLock s_inputsLock
Definition: tv_rec.h:434
V2ArtworkInfo * AddNewArtworkInfo()
V2CaptureDevice * AddCaptureDevice()
V2CastMember * AddNewCastMember()
V2Cutting * AddNewCutting()
Definition: v2cutList.h:43
V2Genre * AddNewGenre()
Definition: v2genreList.h:48
QObject * Recording
QObject * Channel
QObject * Artwork
std::pair< int, QString > cast_entry
Definition: videometadata.h:31
unsigned int uint
Definition: compat.h:60
#define close
Definition: compat.h:28
#define lstat
Definition: compat.h:65
#define minor(X)
Definition: compat.h:58
ArtworkMap GetArtwork(const QString &inetref, uint season, bool strict)
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
@ kArtworkFanart
@ kArtworkBanner
@ kArtworkCoverart
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
std::deque< RecordingInfo * > RecList
Definition: mythscheduler.h:12
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
dictionary info
Definition: azlyrics.py:7
std::vector< DBPerson > DBCredits
Definition: programdata.h:73
MarkTypes
Definition: programtypes.h:46
@ MARK_CUT_END
Definition: programtypes.h:54
@ MARK_VIDEO_RATE
Definition: programtypes.h:72
@ MARK_COMM_END
Definition: programtypes.h:59
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:117
QMap< long long, long long > frm_pos_map_t
Frame # -> File offset map.
Definition: programtypes.h:44
bool newEpifromDupIn(RecordingDupInType recdupin)
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:87
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:66
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
Definition: tv.h:83
void FillEncoderList(QVariantList &list, QObject *parent)
void V2FillInputInfo(V2Input *input, const InputInfo &inputInfo)
void V2FillCastMemberList(V2CastMemberList *pCastMemberList, ProgramInfo *pInfo)
void FillFrontendList(QVariantList &list, QObject *parent, bool OnLine)
void V2FillCommBreak(V2CutList *pCutList, ProgramInfo *rInfo, int marktype, bool includeFps)
V2CaptureDeviceList * getV4l2List(const QRegularExpression &driver, const QString &cardType)
void V2FillGenreList(V2GenreList *pGenreList, int videoID)
void V2FillMusicMetadataInfo(V2MusicMetadataInfo *pVideoMetadataInfo, MusicMetadata *pMetadata, bool bDetails)
DBCredits * V2jsonCastToCredits(const QJsonObject &cast)
void V2FillChannelGroup(V2ChannelGroup *pGroup, const ChannelGroupItem &pGroupItem)
void V2FillArtworkInfoList(V2ArtworkInfoList *pArtworkInfoList, const QString &sInetref, uint nSeason)
void V2FillRecRuleInfo(V2RecRule *pRecRule, RecordingRule *pRule)
void V2FillProgramInfo(V2Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast, bool bIncArtwork, bool bIncRecording)
bool V2FillChannelInfo(V2ChannelInfo *pChannel, uint nChanID, bool bDetails)
V2CaptureDeviceList * getFirewireList(const QString &cardType)
int FillUpcomingList(QVariantList &list, QObject *parent, int &nStartIndex, int &nCount, bool bShowAll, int nRecordId, int nRecStatus, const QString &Sort, const QString &RecGroup)
void V2FillSeek(V2CutList *pCutList, RecordingInfo *rInfo, MarkTypes marktype)
int V2CreateRecordingGroup(const QString &groupName)
void V2FillVideoMetadataInfo(V2VideoMetadataInfo *pVideoMetadataInfo, const VideoMetadataListManager::VideoMetadataPtr &pMetadata, bool bDetails)
void V2FillCutList(V2CutList *pCutList, ProgramInfo *rInfo, int marktype, bool includeFps)
uint fillSelectionsFromDir(const QDir &dir, uint minor_min, uint minor_max, const QString &card, const QRegularExpression &driver, bool allow_duplicates, V2CaptureDeviceList *pList, const QString &cardType)
QString ContentTypeToString(VideoContentType type)
Definition: videoutils.cpp:301