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