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