MythTV  master
v2video.cpp
Go to the documentation of this file.
1 // MythTV
4 #include "libmythbase/mythdb.h"
8 #include "libmythbase/mythversion.h"
15 #include "libmythtv/mythavutil.h"
16 
17 // MythBackend
18 #include "v2artworkInfoList.h"
19 #include "v2castMemberList.h"
20 #include "v2genreList.h"
21 #include "v2serviceUtil.h"
22 #include "v2video.h"
23 
24 
25 // This will be initialised in a thread safe manner on first use
27  (VIDEO_HANDLE, V2Video::staticMetaObject, &V2Video::RegisterCustomTypes))
28 
30 {
31  qRegisterMetaType<V2VideoMetadataInfo*>("V2VideoMetadataInfo");
32  qRegisterMetaType<V2VideoMetadataInfoList*>("V2VideoMetadataInfoList");
33  qRegisterMetaType<V2VideoLookupList*>("V2VideoLookupList");
34  qRegisterMetaType<V2BlurayInfo*>("V2BlurayInfo");
35  qRegisterMetaType<V2VideoStreamInfoList*>("V2VideoStreamInfoList");
36  qRegisterMetaType<V2VideoStreamInfo*>("V2VideoStreamInfo");
37  qRegisterMetaType<V2ArtworkInfoList*>("V2ArtworkInfoList");
38  qRegisterMetaType<V2ArtworkInfo*>("V2ArtworkInfo");
39  qRegisterMetaType<V2CastMemberList*>("V2CastMemberList");
40  qRegisterMetaType<V2CastMember*>("V2CastMember");
41  qRegisterMetaType<V2GenreList*>("V2GenreList");
42  qRegisterMetaType<V2Genre*>("V2Genre");
43  qRegisterMetaType<V2VideoLookupList*>("V2VideoLookupList");
44  qRegisterMetaType<V2VideoLookup*>("V2VideoLookup");
45  qRegisterMetaType<V2ArtworkItem*>("V2ArtworkItem");
46  qRegisterMetaType<V2CutList*>("V2CutList");
47  qRegisterMetaType<V2Cutting*>("V2Cutting");
48 }
49 
51  : MythHTTPService(s_service)
52 {
53 }
54 
56 {
59 
60  if ( !metadata )
61  throw( QString( "No metadata found for selected ID!." ));
62 
63  auto *pVideoMetadataInfo = new V2VideoMetadataInfo();
64 
65  V2FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true );
66 
67  return pVideoMetadataInfo;
68 }
69 
71 {
74  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
75  mlm->setList(videolist);
76  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byFilename(FileName);
77 
78  if ( !metadata )
79  throw( QString( "No metadata found for selected filename!." ));
80 
81  auto *pVideoMetadataInfo = new V2VideoMetadataInfo();
82 
83  V2FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true );
84 
85  return pVideoMetadataInfo;
86 }
87 
88 
90 // Get bookmark of a video as a frame number.
92 
94 {
96 
97  query.prepare("SELECT filename "
98  "FROM videometadata "
99  "WHERE intid = :ID ");
100  query.bindValue(":ID", Id);
101 
102  if (!query.exec())
103  {
104  MythDB::DBError("V2Video::GetSavedBookmark", query);
105  return 0;
106  }
107 
108  QString fileName;
109 
110  if (query.next())
111  fileName = query.value(0).toString();
112  else
113  {
114  LOG(VB_GENERAL, LOG_ERR, QString("V2Video/GetSavedBookmark Video id %1 Not found.").arg(Id));
115  return -1;
116  }
117 
118  ProgramInfo pi(fileName,
119  nullptr, // _plot,
120  nullptr, // _title,
121  nullptr, // const QString &_sortTitle,
122  nullptr, // const QString &_subtitle,
123  nullptr, // const QString &_sortSubtitle,
124  nullptr, // const QString &_director,
125  0, // int _season,
126  0, // int _episode,
127  nullptr, // const QString &_inetref,
128  0min, // uint _length_in_minutes,
129  0, // uint _year,
130  nullptr); //const QString &_programid);
131 
132  long ret = pi.QueryBookmark();
133  return ret;
134 }
135 
137 // Get last play pos of a video as a frame number.
139 
141 {
142  MSqlQuery query(MSqlQuery::InitCon());
143 
144  query.prepare("SELECT filename "
145  "FROM videometadata "
146  "WHERE intid = :ID ");
147  query.bindValue(":ID", Id);
148 
149  if (!query.exec())
150  {
151  MythDB::DBError("V2Video::GetLastPlayPos", query);
152  return 0;
153  }
154 
155  QString fileName;
156 
157  if (query.next())
158  fileName = query.value(0).toString();
159  else
160  {
161  LOG(VB_GENERAL, LOG_ERR, QString("V2Video/GetLastPlayPos Video id %1 Not found.").arg(Id));
162  return -1;
163  }
164 
165  ProgramInfo pi(fileName,
166  nullptr, // _plot,
167  nullptr, // _title,
168  nullptr, // const QString &_sortTitle,
169  nullptr, // const QString &_subtitle,
170  nullptr, // const QString &_sortSubtitle,
171  nullptr, // const QString &_director,
172  0, // int _season,
173  0, // int _episode,
174  nullptr, // const QString &_inetref,
175  0min, // uint _length_in_minutes,
176  0, // uint _year,
177  nullptr); //const QString &_programid);
178 
179  long ret = pi.QueryLastPlayPos();
180  return ret;
181 }
182 
183 
184 // If CollapseSubDirs is true, then files in subdirectories are not returned.
185 // Instead, one row is returned for each subdirectory, with the full
186 // directory name in FileName and the lowest part of the directory name
187 // in Title. These directories are returned at the beginning of the list.
188 //
189 // Example: If the database has these files:
190 // one.mkv
191 // dir1/two.mkv
192 // dir1/dir2/two.mkv
193 //
194 // With no Folder name and CollapseSubDirs=true, you get
195 // one.mkv
196 // dir1 Title=dir1
197 //
198 // With Folder=dir1 and CollapseSubDirs=true, you get
199 // dir1/two.mkv
200 // dir1/dir2 Title=dir2
201 
203  const QString &Sort,
204  bool bDescending,
205  int nStartIndex,
206  int nCount,
207  bool CollapseSubDirs )
208 {
209  QString fields = "title,director,studio,plot,rating,year,releasedate,"
210  "userrating,length,playcount,filename,hash,showlevel,"
211  "coverfile,inetref,collectionref,homepage,childid,browse,watched,"
212  "playcommand,category,intid,trailer,screenshot,banner,fanart,"
213  "subtitle,tagline,season,episode,host,insertdate,processed,contenttype";
214 
215  QStringList sortFields = fields.split(',');
216 
218 
219  QString sql = "";
220  QString folder;
221  QString bindValue;
222  if (!Folder.isEmpty())
223  {
224  if (Folder.endsWith('/'))
225  folder = Folder;
226  else
227  folder = Folder + "/";
228  bindValue = folder + "%";
229  sql.append(" WHERE filename LIKE :BINDVALUE ");
230  }
231  sql.append(" ORDER BY ");
232  QString defSeq = " ASC";
233  if (bDescending)
234  defSeq = " DESC";
235 
236  QStringList sortList = Sort.toLower().split(',',Qt::SkipEmptyParts);
237  bool next = false;
238  for (const auto & item : std::as_const(sortList))
239  {
240  QStringList partList = item.split(' ',Qt::SkipEmptyParts);
241  if (partList.empty())
242  continue;
243  QString sort = partList[0];
244  if (sort == "added")
245  sort = "insertdate";
246  else if (sort == "released")
247  sort = "releasedate";
248  if (sortFields.contains(sort))
249  {
250  if (next)
251  sql.append(",");
252  sql.append(sort);
253  if (partList.length() > 1 && partList[1].compare("DESC",Qt::CaseInsensitive) == 0)
254  sql.append(" DESC");
255  else if (partList.length() > 1 && partList[1].compare("ASC",Qt::CaseInsensitive) == 0)
256  sql.append(" ASC");
257  else
258  sql.append(defSeq);
259  next = true;
260  }
261  }
262  if (!next)
263  {
264  sql.append("intid");
265  sql.append(defSeq);
266  }
267 
268  VideoMetadataListManager::loadAllFromDatabase(videolist, sql, bindValue);
269  std::vector<VideoMetadataListManager::VideoMetadataPtr> videos(videolist.begin(), videolist.end());
270 
271  // ----------------------------------------------------------------------
272  // Build Response
273  // ----------------------------------------------------------------------
274 
275  auto *pVideoMetadataInfos = new V2VideoMetadataInfoList();
276  QMap<QString, QString> map;
277  int folderlen = folder.length();
278 
279  nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)videos.size() ) : 0;
280  int selectedCount = 0;
281  int totalCount = 0;
282  QString dir;
283 
284  // Make directory list
285  if (CollapseSubDirs)
286  {
287  for( const auto& metadata : videos )
288  {
289  if (!metadata)
290  break;
291  QString fnPart = metadata->GetFilename().mid(folderlen);
292  int slashPos = fnPart.indexOf('/',1);
293  if (slashPos >= 0)
294  {
295  dir = fnPart.mid(0, slashPos);
296  if (!map.contains(dir))
297  {
298  // use toLower here so that lower case are sorted in with
299  // upper case rather than separately at the end.
300  map.insert(dir.toLower(), dir);
301  }
302  }
303  }
304  // Insert directory entries at the front of the list, ordered ascending
305  // or descending, depending on the value of bDescending
306  QMapIterator<QString, QString> it(map);
307  if (bDescending)
308  it.toBack();
309 
310  while (bDescending? it.hasPrevious() : it.hasNext())
311  {
312  if (bDescending)
313  it.previous();
314  else
315  it.next();
316  if (totalCount >= nStartIndex && (nCount == 0 || selectedCount < nCount)) {
317  V2VideoMetadataInfo *pVideoMetadataInfo =
318  pVideoMetadataInfos->AddNewVideoMetadataInfo();
319  pVideoMetadataInfo->setContentType("DIRECTORY");
320  pVideoMetadataInfo->setFileName(folder + it.value());
321  pVideoMetadataInfo->setTitle(it.value());
322  selectedCount++;
323  }
324  totalCount++;
325  }
326  }
327 
328  for( const auto& metadata : videos )
329  {
330  if (!metadata)
331  break;
332 
333  if (CollapseSubDirs)
334  {
335  QString fnPart = metadata->GetFilename().mid(folderlen);
336  int slashPos = fnPart.indexOf('/',1);
337  if (slashPos >= 0)
338  continue;
339  }
340 
341  if (totalCount >= nStartIndex && (nCount == 0 || selectedCount < nCount)) {
342  V2VideoMetadataInfo *pVideoMetadataInfo = pVideoMetadataInfos->AddNewVideoMetadataInfo();
343  V2FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true );
344  selectedCount++;
345  }
346  totalCount++;
347  }
348 
349  int curPage = 0;
350  int totalPages = 0;
351  if (nCount == 0)
352  totalPages = 1;
353  else
354  totalPages = (int)ceil((float)totalCount / nCount);
355 
356  if (totalPages == 1)
357  curPage = 1;
358  else
359  {
360  curPage = (int)ceil((float)nStartIndex / nCount) + 1;
361  }
362 
363  pVideoMetadataInfos->setStartIndex ( nStartIndex );
364  pVideoMetadataInfos->setCount ( selectedCount );
365  pVideoMetadataInfos->setCurrentPage ( curPage );
366  pVideoMetadataInfos->setTotalPages ( totalPages );
367  pVideoMetadataInfos->setTotalAvailable( totalCount );
368  pVideoMetadataInfos->setAsOf ( MythDate::current() );
369  pVideoMetadataInfos->setVersion ( MYTH_BINARY_VERSION );
370  pVideoMetadataInfos->setProtoVer ( MYTH_PROTO_VERSION );
371 
372  return pVideoMetadataInfos;
373 }
374 
375 
377  const QString &Subtitle,
378  const QString &Inetref,
379  int Season,
380  int Episode,
381  const QString &GrabberType,
382  bool AllowGeneric )
383 {
384  auto *pVideoLookups = new V2VideoLookupList();
385 
386  MetadataLookupList list;
387 
388  auto *factory = new MetadataFactory(nullptr);
389 
390  if (factory)
391  {
392  list = factory->SynchronousLookup(Title, Subtitle,
393  Inetref, Season, Episode,
394  GrabberType, AllowGeneric);
395  }
396 
397  if ( list.empty() )
398  return pVideoLookups;
399 
400  //MetadataLookupList is a reference counted list.
401  //it will delete all its content at its end of life
402  for(const auto & lookup : std::as_const(list))
403  {
404  V2VideoLookup *pVideoLookup = pVideoLookups->AddNewVideoLookup();
405 
406  if (lookup)
407  {
408  pVideoLookup->setTitle(lookup->GetTitle());
409  pVideoLookup->setSubTitle(lookup->GetSubtitle());
410  pVideoLookup->setSeason(lookup->GetSeason());
411  pVideoLookup->setEpisode(lookup->GetEpisode());
412  pVideoLookup->setYear(lookup->GetYear());
413  pVideoLookup->setTagline(lookup->GetTagline());
414  pVideoLookup->setDescription(lookup->GetDescription());
415  pVideoLookup->setCertification(lookup->GetCertification());
416  pVideoLookup->setInetref(lookup->GetInetref());
417  pVideoLookup->setCollectionref(lookup->GetCollectionref());
418  pVideoLookup->setHomePage(lookup->GetHomepage());
419 #if QT_VERSION < QT_VERSION_CHECK(6,5,0)
420  pVideoLookup->setReleaseDate(
421  QDateTime(lookup->GetReleaseDate(),
422  QTime(0,0),Qt::LocalTime).toUTC());
423 #else
424  pVideoLookup->setReleaseDate(
425  QDateTime(lookup->GetReleaseDate(),
426  QTime(0,0),
427  QTimeZone(QTimeZone::LocalTime)).toUTC());
428 #endif
429  pVideoLookup->setUserRating(lookup->GetUserRating());
430  pVideoLookup->setLength(lookup->GetRuntime().count());
431  pVideoLookup->setLanguage(lookup->GetLanguage());
432  pVideoLookup->setCountries(lookup->GetCountries());
433  pVideoLookup->setPopularity(lookup->GetPopularity());
434  pVideoLookup->setBudget(lookup->GetBudget());
435  pVideoLookup->setRevenue(lookup->GetRevenue());
436  pVideoLookup->setIMDB(lookup->GetIMDB());
437  pVideoLookup->setTMSRef(lookup->GetTMSref());
438 
439  ArtworkList coverartlist = lookup->GetArtwork(kArtworkCoverart);
440  ArtworkList::iterator c;
441  for (c = coverartlist.begin(); c != coverartlist.end(); ++c)
442  {
443  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
444  art->setType("coverart");
445  art->setUrl((*c).url);
446  art->setThumbnail((*c).thumbnail);
447  art->setWidth((*c).width);
448  art->setHeight((*c).height);
449  }
450  ArtworkList fanartlist = lookup->GetArtwork(kArtworkFanart);
451  ArtworkList::iterator f;
452  for (f = fanartlist.begin(); f != fanartlist.end(); ++f)
453  {
454  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
455  art->setType("fanart");
456  art->setUrl((*f).url);
457  art->setThumbnail((*f).thumbnail);
458  art->setWidth((*f).width);
459  art->setHeight((*f).height);
460  }
461  ArtworkList bannerlist = lookup->GetArtwork(kArtworkBanner);
462  ArtworkList::iterator b;
463  for (b = bannerlist.begin(); b != bannerlist.end(); ++b)
464  {
465  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
466  art->setType("banner");
467  art->setUrl((*b).url);
468  art->setThumbnail((*b).thumbnail);
469  art->setWidth((*b).width);
470  art->setHeight((*b).height);
471  }
472  ArtworkList screenshotlist = lookup->GetArtwork(kArtworkScreenshot);
473  ArtworkList::iterator s;
474  for (s = screenshotlist.begin(); s != screenshotlist.end(); ++s)
475  {
476  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
477  art->setType("screenshot");
478  art->setUrl((*s).url);
479  art->setThumbnail((*s).thumbnail);
480  art->setWidth((*s).width);
481  art->setHeight((*s).height);
482  }
483  }
484  }
485 
486  pVideoLookups->setCount ( list.count() );
487  pVideoLookups->setAsOf ( MythDate::current() );
488  pVideoLookups->setVersion ( MYTH_BINARY_VERSION );
489  pVideoLookups->setProtoVer ( MYTH_PROTO_VERSION );
490 
491  delete factory;
492 
493  return pVideoLookups;
494 }
495 
496 
498 {
499  bool bResult = false;
500 
503  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
504  mlm->setList(videolist);
505  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(Id);
506 
507  if (metadata)
508  bResult = metadata->DeleteFromDatabase();
509 
510  return bResult;
511 }
512 
513 bool V2Video::AddVideo( const QString &sFileName,
514  const QString &sHostName )
515 {
516  if ( sHostName.isEmpty() )
517  throw( QString( "Host not provided! Local storage is deprecated and "
518  "is not supported by the API." ));
519 
520  if ( sFileName.isEmpty() ||
521  (sFileName.contains("/../")) ||
522  (sFileName.startsWith("../")) )
523  {
524  throw( QString( "Filename not provided, or fails sanity checks!" ));
525  }
526 
527  StorageGroup sgroup("Videos", sHostName);
528 
529  QString fullname = sgroup.FindFile(sFileName);
530 
531  if ( !QFile::exists(fullname) )
532  throw( QString( "Provided filename does not exist!" ));
533 
534  QString hash = FileHash(fullname);
535 
536  if (hash == "NULL")
537  {
538  LOG(VB_GENERAL, LOG_ERR, "Video Hash Failed. Unless this is a DVD or "
539  "Blu-ray, something has probably gone wrong.");
540  hash = "";
541  }
542 
543  VideoMetadata newFile(sFileName, QString(), hash,
549  QString(), QString(), QString(), QString(),
550  QString(), VIDEO_YEAR_DEFAULT,
551  QDate::fromString("0000-00-00","YYYY-MM-DD"),
552  VIDEO_INETREF_DEFAULT, 0, QString(),
554  0.0, VIDEO_RATING_DEFAULT, 0, 0,
555  0, 0,
556  MythDate::current().date(), 0,
558 
559  newFile.SetHost(sHostName);
560  newFile.SaveToDatabase();
561 
562  return true;
563 }
564 
566 //
568 
570  bool bWatched )
571 {
574  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
575  mlm->setList(videolist);
576  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId);
577 
578  if ( !metadata )
579  return false;
580 
581  metadata->SetWatched(bWatched);
582  metadata->UpdateDatabase();
583 
584  return true;
585 }
586 
588  const QString &sTitle,
589  const QString &sSubTitle,
590  const QString &sTagLine,
591  const QString &sDirector,
592  const QString &sStudio,
593  const QString &sPlot,
594  const QString &sRating,
595  const QString &sInetref,
596  int nCollectionRef,
597  const QString &sHomePage,
598  int nYear,
599  QDate sReleasedate,
600  float fUserRating,
601  int nLength,
602  int nPlayCount,
603  int nSeason,
604  int nEpisode,
605  int nShowLevel,
606  const QString &sFileName,
607  const QString &sHash,
608  const QString &sCoverFile,
609  int nChildID,
610  bool bBrowse,
611  bool bWatched,
612  bool bProcessed,
613  const QString &sPlayCommand,
614  int nCategory,
615  const QString &sTrailer,
616  const QString &sHost,
617  const QString &sScreenshot,
618  const QString &sBanner,
619  const QString &sFanart,
620  QDate sInsertDate,
621  const QString &sContentType,
622  const QString &sGenres,
623  const QString &sCast,
624  const QString &sCountries)
625 {
626  bool update_required = false;
629  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
630  mlm->setList(videolist);
631  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId);
632 
633  if (!metadata)
634  {
635  LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Id=%1 not found")
636  .arg(nId));
637  return false;
638  }
639 
640  if (HAS_PARAMv2("Title"))
641  {
642  metadata->SetTitle(sTitle);
643  update_required = true;
644  }
645 
646  if (HAS_PARAMv2("SubTitle"))
647  {
648  metadata->SetSubtitle(sSubTitle);
649  update_required = true;
650  }
651 
652  if (HAS_PARAMv2("TagLine"))
653  {
654  metadata->SetTagline(sTagLine);
655  update_required = true;
656  }
657 
658  if (HAS_PARAMv2("Director"))
659  {
660  metadata->SetDirector(sDirector);
661  update_required = true;
662  }
663 
664  if (HAS_PARAMv2("Studio"))
665  {
666  metadata->SetStudio(sStudio);
667  update_required = true;
668  }
669 
670  if (HAS_PARAMv2("Plot"))
671  {
672  metadata->SetPlot(sPlot);
673  update_required = true;
674  }
675 
676  if (HAS_PARAMv2("UserRating"))
677  {
678  metadata->SetUserRating(fUserRating);
679  update_required = true;
680  }
681 
682  if (HAS_PARAMv2("Inetref"))
683  {
684  metadata->SetInetRef(sInetref);
685  update_required = true;
686  }
687 
688  if (HAS_PARAMv2("CollectionRef"))
689  {
690  metadata->SetCollectionRef(nCollectionRef);
691  update_required = true;
692  }
693 
694  if (HAS_PARAMv2("HomePage"))
695  {
696  metadata->SetHomepage(sHomePage);
697  update_required = true;
698  }
699 
700  if (HAS_PARAMv2("Year"))
701  {
702  metadata->SetYear(nYear);
703  update_required = true;
704  }
705 
706  if (HAS_PARAMv2("ReleaseDate"))
707  {
708  metadata->SetReleaseDate(sReleasedate);
709  update_required = true;
710  }
711 
712  if (HAS_PARAMv2("Rating"))
713  {
714  metadata->SetRating(sRating);
715  update_required = true;
716  }
717 
718  if (HAS_PARAMv2("Length"))
719  {
720  metadata->SetLength(std::chrono::minutes(nLength));
721  update_required = true;
722  }
723 
724  if (HAS_PARAMv2("PlayCount"))
725  {
726  metadata->SetPlayCount(nPlayCount);
727  update_required = true;
728  }
729 
730  if (HAS_PARAMv2("Season"))
731  {
732  metadata->SetSeason(nSeason);
733  update_required = true;
734  }
735 
736  if (HAS_PARAMv2("Episode"))
737  {
738  metadata->SetEpisode(nEpisode);
739  update_required = true;
740  }
741 
742  if (HAS_PARAMv2("ShowLevel"))
743  {
744  metadata->SetShowLevel(ParentalLevel::Level(nShowLevel));
745  update_required = true;
746  }
747 
748  if (HAS_PARAMv2("FileName"))
749  {
750  metadata->SetFilename(sFileName);
751  update_required = true;
752  }
753 
754  if (HAS_PARAMv2("Hash"))
755  {
756  metadata->SetHash(sHash);
757  update_required = true;
758  }
759 
760  if (HAS_PARAMv2("CoverFile"))
761  {
762  metadata->SetCoverFile(sCoverFile);
763  update_required = true;
764  }
765 
766  if (HAS_PARAMv2("ChildID"))
767  {
768  metadata->SetChildID(nChildID);
769  update_required = true;
770  }
771 
772  if (HAS_PARAMv2("Browse"))
773  {
774  metadata->SetBrowse(bBrowse);
775  update_required = true;
776  }
777 
778  if (HAS_PARAMv2("Watched"))
779  {
780  metadata->SetWatched(bWatched);
781  update_required = true;
782  }
783 
784  if (HAS_PARAMv2("Processed"))
785  {
786  metadata->SetProcessed(bProcessed);
787  update_required = true;
788  }
789 
790  if (HAS_PARAMv2("PlayCommand"))
791  {
792  metadata->SetPlayCommand(sPlayCommand);
793  update_required = true;
794  }
795 
796  if (HAS_PARAMv2("Category"))
797  {
798  metadata->SetCategoryID(nCategory);
799  update_required = true;
800  }
801 
802  if (HAS_PARAMv2("Trailer"))
803  {
804  metadata->SetTrailer(sTrailer);
805  update_required = true;
806  }
807 
808  if (HAS_PARAMv2("Host"))
809  {
810  metadata->SetHost(sHost);
811  update_required = true;
812  }
813 
814  if (HAS_PARAMv2("Screenshot"))
815  {
816  metadata->SetScreenshot(sScreenshot);
817  update_required = true;
818  }
819 
820  if (HAS_PARAMv2("Banner"))
821  {
822  metadata->SetBanner(sBanner);
823  update_required = true;
824  }
825 
826  if (HAS_PARAMv2("Fanart"))
827  {
828  metadata->SetFanart(sFanart);
829  update_required = true;
830  }
831 
832  if (HAS_PARAMv2("InsertDate"))
833  {
834  metadata->SetInsertdate(sInsertDate);
835  update_required = true;
836  }
837 
838  if (HAS_PARAMv2("ContentType"))
839  {
840  // valid values for ContentType are 'MOVIE','TELEVISION','ADULT','MUSICVIDEO','HOMEVIDEO'
841  VideoContentType contentType = kContentUnknown;
842  if (sContentType == "MOVIE")
843  contentType = kContentMovie;
844 
845  if (sContentType == "TELEVISION")
846  contentType = kContentTelevision;
847 
848  if (sContentType == "ADULT")
849  contentType = kContentAdult;
850 
851  if (sContentType == "MUSICVIDEO")
852  contentType = kContentMusicVideo;
853 
854  if (sContentType == "HOMEVIDEO")
855  contentType = kContentHomeMovie;
856 
857  if (contentType != kContentUnknown)
858  {
859  metadata->SetContentType(contentType);
860  update_required = true;
861  }
862  else
863  {
864  LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Ignoring unknown ContentType: %1").arg(sContentType));
865  }
866  }
867 
868  if (HAS_PARAMv2("Genres"))
869  {
871  QStringList genresList = sGenres.split(',', Qt::SkipEmptyParts);
872  std::transform(genresList.cbegin(), genresList.cend(), std::back_inserter(genres),
873  [](const QString& name)
874  {return VideoMetadata::genre_list::value_type(-1, name.simplified());} );
875 
876  metadata->SetGenres(genres);
877  update_required = true;
878  }
879 
880  if (HAS_PARAMv2("Cast"))
881  {
883  QStringList castList = sCast.split(',', Qt::SkipEmptyParts);
884  std::transform(castList.cbegin(), castList.cend(), std::back_inserter(cast),
885  [](const QString& name)
886  {return VideoMetadata::cast_list::value_type(-1, name.simplified());} );
887 
888  metadata->SetCast(cast);
889  update_required = true;
890  }
891 
892  if (HAS_PARAMv2("Countries"))
893  {
894  VideoMetadata::country_list countries;
895  QStringList countryList = sCountries.split(',', Qt::SkipEmptyParts);
896  std::transform(countryList.cbegin(), countryList.cend(), std::back_inserter(countries),
897  [](const QString& name)
898  {return VideoMetadata::country_list::value_type(-1, name.simplified());} );
899 
900  metadata->SetCountries(countries);
901  update_required = true;
902  }
903 
904  if (update_required)
905  metadata->UpdateDatabase();
906 
907  return true;
908 }
909 
911 // Set bookmark of a video as a frame number.
913 
914 bool V2Video::SetSavedBookmark( int Id, long Offset )
915 {
916  MSqlQuery query(MSqlQuery::InitCon());
917 
918  query.prepare("SELECT filename "
919  "FROM videometadata "
920  "WHERE intid = :ID ");
921  query.bindValue(":ID", Id);
922 
923  if (!query.exec())
924  {
925  MythDB::DBError("Video::SetSavedBookmark", query);
926  return false;
927  }
928 
929  QString fileName;
930 
931  if (query.next())
932  fileName = query.value(0).toString();
933  else
934  {
935  LOG(VB_GENERAL, LOG_ERR, QString("Video/SetSavedBookmark Video id %1 Not found.").arg(Id));
936  return false;
937  }
938 
939  ProgramInfo pi(fileName,
940  nullptr, // _plot,
941  nullptr, // _title,
942  nullptr, // const QString &_sortTitle,
943  nullptr, // const QString &_subtitle,
944  nullptr, // const QString &_sortSubtitle,
945  nullptr, // const QString &_director,
946  0, // int _season,
947  0, // int _episode,
948  nullptr, // const QString &_inetref,
949  0min, // uint _length_in_minutes,
950  0, // uint _year,
951  nullptr); //const QString &_programid);
952 
953  pi.SaveBookmark(Offset);
954  return true;
955 }
956 
958 // Set bookmark of a video as a frame number.
960 
961 bool V2Video::SetLastPlayPos( int Id, long Offset )
962 {
963  MSqlQuery query(MSqlQuery::InitCon());
964 
965  query.prepare("SELECT filename "
966  "FROM videometadata "
967  "WHERE intid = :ID ");
968  query.bindValue(":ID", Id);
969 
970  if (!query.exec())
971  {
972  MythDB::DBError("Video::SetLastPlayPos", query);
973  return false;
974  }
975 
976  QString fileName;
977 
978  if (query.next())
979  fileName = query.value(0).toString();
980  else
981  {
982  LOG(VB_GENERAL, LOG_ERR, QString("Video/SetLastPlayPos Video id %1 Not found.").arg(Id));
983  return false;
984  }
985 
986  ProgramInfo pi(fileName,
987  nullptr, // _plot,
988  nullptr, // _title,
989  nullptr, // const QString &_sortTitle,
990  nullptr, // const QString &_subtitle,
991  nullptr, // const QString &_sortSubtitle,
992  nullptr, // const QString &_director,
993  0, // int _season,
994  0, // int _episode,
995  nullptr, // const QString &_inetref,
996  0min, // uint _length_in_minutes,
997  0, // uint _year,
998  nullptr); //const QString &_programid);
999 
1000  pi.SaveLastPlayPos(Offset);
1001  return true;
1002 }
1003 
1004 
1005 V2BlurayInfo* V2Video::GetBluray( const QString &sPath )
1006 {
1007  QString path = sPath;
1008 
1009  if (sPath.isEmpty())
1010  path = gCoreContext->GetSetting( "BluRayMountpoint", "/media/cdrom");
1011 
1012  LOG(VB_GENERAL, LOG_NOTICE,
1013  QString("Parsing Blu-ray at path: %1 ").arg(path));
1014 
1015  auto *bdmeta = new BlurayMetadata(path);
1016 
1017  if ( !bdmeta )
1018  throw( QString( "Unable to open Blu-ray Metadata Parser!" ));
1019 
1020  if ( !bdmeta->OpenDisc() )
1021  throw( QString( "Unable to open Blu-ray Disc/Path!" ));
1022 
1023  if ( !bdmeta->ParseDisc() )
1024  throw( QString( "Unable to parse metadata from Blu-ray Disc/Path!" ));
1025 
1026  auto *pBlurayInfo = new V2BlurayInfo();
1027 
1028  pBlurayInfo->setPath(path);
1029  pBlurayInfo->setTitle(bdmeta->GetTitle());
1030  pBlurayInfo->setAltTitle(bdmeta->GetAlternateTitle());
1031  pBlurayInfo->setDiscLang(bdmeta->GetDiscLanguage());
1032  pBlurayInfo->setDiscNum(bdmeta->GetCurrentDiscNumber());
1033  pBlurayInfo->setTotalDiscNum(bdmeta->GetTotalDiscNumber());
1034  pBlurayInfo->setTitleCount(bdmeta->GetTitleCount());
1035  pBlurayInfo->setThumbCount(bdmeta->GetThumbnailCount());
1036  pBlurayInfo->setTopMenuSupported(bdmeta->GetTopMenuSupported());
1037  pBlurayInfo->setFirstPlaySupported(bdmeta->GetFirstPlaySupported());
1038  pBlurayInfo->setNumHDMVTitles(bdmeta->GetNumHDMVTitles());
1039  pBlurayInfo->setNumBDJTitles(bdmeta->GetNumBDJTitles());
1040  pBlurayInfo->setNumUnsupportedTitles(bdmeta->GetNumUnsupportedTitles());
1041  pBlurayInfo->setAACSDetected(bdmeta->GetAACSDetected());
1042  pBlurayInfo->setLibAACSDetected(bdmeta->GetLibAACSDetected());
1043  pBlurayInfo->setAACSHandled(bdmeta->GetAACSHandled());
1044  pBlurayInfo->setBDPlusDetected(bdmeta->GetBDPlusDetected());
1045  pBlurayInfo->setLibBDPlusDetected(bdmeta->GetLibBDPlusDetected());
1046  pBlurayInfo->setBDPlusHandled(bdmeta->GetBDPlusHandled());
1047 
1048  QStringList thumbs = bdmeta->GetThumbnails();
1049  if (!thumbs.empty())
1050  pBlurayInfo->setThumbPath(thumbs.at(0));
1051 
1052  delete bdmeta;
1053 
1054  return pBlurayInfo;
1055 }
1056 
1057 
1059 // Jun 3, 2020
1060 // Service to get stream info for all streams in a media file.
1061 // This gets some basic info. If anything more is needed it can be added,
1062 // depending on whether it is available from ffmpeg avformat apis.
1063 // See the MythStreamInfoList class for the code that uses avformat to
1064 // extract the information.
1066 
1068  ( const QString &storageGroup,
1069  const QString &FileName )
1070 {
1071 
1072  // Search for the filename
1073 
1074  StorageGroup storage( storageGroup );
1075  QString sFullFileName = storage.FindFile( FileName );
1076  MythStreamInfoList infos(sFullFileName);
1077 
1078  // The constructor of this class reads the file and gets the needed
1079  // information.
1080  auto *pVideoStreamInfos = new V2VideoStreamInfoList();
1081 
1082  pVideoStreamInfos->setCount ( infos.m_streamInfoList.size() );
1083  pVideoStreamInfos->setAsOf ( MythDate::current() );
1084  pVideoStreamInfos->setVersion ( MYTH_BINARY_VERSION );
1085  pVideoStreamInfos->setProtoVer ( MYTH_PROTO_VERSION );
1086  pVideoStreamInfos->setErrorCode ( infos.m_errorCode );
1087  pVideoStreamInfos->setErrorMsg ( infos.m_errorMsg );
1088 
1089  for (const auto & info : std::as_const(infos.m_streamInfoList))
1090  {
1091  V2VideoStreamInfo *pVideoStreamInfo = pVideoStreamInfos->AddNewVideoStreamInfo();
1092  pVideoStreamInfo->setCodecType ( QString(QChar(info.m_codecType)) );
1093  pVideoStreamInfo->setCodecName ( info.m_codecName );
1094  pVideoStreamInfo->setWidth ( info.m_width );
1095  pVideoStreamInfo->setHeight ( info.m_height );
1096  pVideoStreamInfo->setAspectRatio ( info.m_SampleAspectRatio );
1097  pVideoStreamInfo->setFieldOrder ( info.m_fieldOrder );
1098  pVideoStreamInfo->setFrameRate ( info.m_frameRate );
1099  pVideoStreamInfo->setAvgFrameRate ( info.m_avgFrameRate );
1100  pVideoStreamInfo->setChannels ( info.m_channels );
1101  pVideoStreamInfo->setDuration ( info.m_duration );
1102 
1103  }
1104  return pVideoStreamInfos;
1105 }
1106 
1108 // October 26,2022
1109 // Support for Cut List for Videos
1111 
1113  const QString &offsettype,
1114  bool includeFps )
1115 {
1116  MSqlQuery query(MSqlQuery::InitCon());
1117 
1118  query.prepare("SELECT filename "
1119  "FROM videometadata "
1120  "WHERE intid = :ID ");
1121  query.bindValue(":ID", Id);
1122 
1123  if (!query.exec())
1124  {
1125  MythDB::DBError("V2Video::GetVideoCommBreak", query);
1126  throw QString("Database Error.");
1127  }
1128 
1129  QString fileName;
1130 
1131  if (query.next())
1132  fileName = query.value(0).toString();
1133  else
1134  {
1135  LOG(VB_GENERAL, LOG_ERR, QString("V2Video/GetVideoCommBreak Video id %1 Not found.").arg(Id));
1136  throw QString("Video Not Found.");
1137  }
1138 
1139  ProgramInfo pi(fileName,
1140  nullptr, // _plot,
1141  nullptr, // _title,
1142  nullptr, // const QString &_sortTitle,
1143  nullptr, // const QString &_subtitle,
1144  nullptr, // const QString &_sortSubtitle,
1145  nullptr, // const QString &_director,
1146  0, // int _season,
1147  0, // int _episode,
1148  nullptr, // const QString &_inetref,
1149  0min, // uint _length_in_minutes,
1150  0, // uint _year,
1151  nullptr); //const QString &_programid);
1152 
1153 
1154  int marktype = 0;
1155 
1156  auto* pCutList = new V2CutList();
1157  if (offsettype.toLower() == "position")
1158  marktype = 1;
1159  else if (offsettype.toLower() == "duration")
1160  marktype = 2;
1161  else
1162  marktype = 0;
1163 
1164  V2FillCutList(pCutList, &pi, marktype, includeFps);
1165 
1166  return pCutList;
1167 }
1168 
1170 // October 26,2022
1171 // Support for Commercial Break List for Videos
1173 
1175  const QString &offsettype,
1176  bool includeFps )
1177 {
1178  MSqlQuery query(MSqlQuery::InitCon());
1179 
1180  query.prepare("SELECT filename "
1181  "FROM videometadata "
1182  "WHERE intid = :ID ");
1183  query.bindValue(":ID", Id);
1184 
1185  if (!query.exec())
1186  {
1187  MythDB::DBError("V2Video::GetVideoCommBreak", query);
1188  throw QString("Database Error.");
1189  }
1190 
1191  QString fileName;
1192 
1193  if (query.next())
1194  fileName = query.value(0).toString();
1195  else
1196  {
1197  LOG(VB_GENERAL, LOG_ERR, QString("V2Video/GetVideoCommBreak Video id %1 Not found.").arg(Id));
1198  throw QString("Video Not Found.");
1199  }
1200 
1201  ProgramInfo pi(fileName,
1202  nullptr, // _plot,
1203  nullptr, // _title,
1204  nullptr, // const QString &_sortTitle,
1205  nullptr, // const QString &_subtitle,
1206  nullptr, // const QString &_sortSubtitle,
1207  nullptr, // const QString &_director,
1208  0, // int _season,
1209  0, // int _episode,
1210  nullptr, // const QString &_inetref,
1211  0min, // uint _length_in_minutes,
1212  0, // uint _year,
1213  nullptr); //const QString &_programid);
1214 
1215 
1216  int marktype = 0;
1217 
1218  auto* pCutList = new V2CutList();
1219  if (offsettype.toLower() == "position")
1220  marktype = 1;
1221  else if (offsettype.toLower() == "duration")
1222  marktype = 2;
1223  else
1224  marktype = 0;
1225 
1226  V2FillCommBreak(pCutList, &pi, marktype, includeFps);
1227 
1228  return pCutList;
1229 }
MythHTTPService::HAS_PARAMv2
bool HAS_PARAMv2(const QString &p)
Definition: mythhttpservice.h:36
V2VideoLookup::AddNewArtwork
V2ArtworkItem * AddNewArtwork()
Definition: v2videoLookupInfo.h:119
MythStreamInfoList::m_errorMsg
QString m_errorMsg
Definition: mythavutil.h:104
BlurayMetadata
Definition: bluraymetadata.h:25
kContentAdult
@ kContentAdult
Definition: metadatacommon.h:63
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
VideoMetadata
Definition: videometadata.h:24
V2VideoStreamInfoList
Definition: v2videoStreamInfoList.h:20
v2video.h
V2Video::AddVideo
static bool AddVideo(const QString &FileName, const QString &HostName)
Definition: v2video.cpp:513
ProgramInfo::SaveBookmark
void SaveBookmark(uint64_t frame)
Clears any existing bookmark in DB and if frame is greater than 0 sets a new bookmark.
Definition: programinfo.cpp:2680
V2VideoLookupList
Definition: v2videoLookupInfoList.h:21
videometadata.h
mythdb.h
V2Video::LookupVideo
static V2VideoLookupList * LookupVideo(const QString &Title, const QString &Subtitle, const QString &Inetref, int Season, int Episode, const QString &GrabberType, bool AllowGeneric)
Definition: v2video.cpp:376
VideoMetadataListManager
Definition: videometadatalistmanager.h:10
simple_ref_ptr
Definition: quicksp.h:24
V2Video::GetBluray
static V2BlurayInfo * GetBluray(const QString &Path)
Definition: v2video.cpp:1005
ArtworkList
QList< ArtworkInfo > ArtworkList
Definition: metadataimagehelper.h:30
V2FillVideoMetadataInfo
void V2FillVideoMetadataInfo(V2VideoMetadataInfo *pVideoMetadataInfo, const VideoMetadataListManager::VideoMetadataPtr &pMetadata, bool bDetails)
Definition: v2serviceUtil.cpp:398
StorageGroup::FindFile
QString FindFile(const QString &filename)
Definition: storagegroup.cpp:597
MythStreamInfoList
Definition: mythavutil.h:100
V2BlurayInfo
Definition: v2blurayInfo.h:20
V2ArtworkItem
Definition: v2videoLookupInfo.h:22
kContentMusicVideo
@ kContentMusicVideo
Definition: metadatacommon.h:64
xbmcvfs.exists
bool exists(str path)
Definition: xbmcvfs.py:51
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
mythdbcon.h
VideoMetadata::country_list
std::vector< country_entry > country_list
Definition: videometadata.h:33
mythhttpmetaservice.h
V2Video::SetLastPlayPos
static bool SetLastPlayPos(int Id, long Offset)
Definition: v2video.cpp:961
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
V2Video::GetVideo
static V2VideoMetadataInfo * GetVideo(int Id)
Definition: v2video.cpp:55
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
VideoMetadata::genre_list
std::vector< genre_entry > genre_list
Definition: videometadata.h:32
V2Video::GetVideoCommBreak
static V2CutList * GetVideoCommBreak(int Id, const QString &OffsetType, bool IncludeFps)
Definition: v2video.cpp:1174
GrabberType
GrabberType
Definition: metadatagrabber.h:20
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
V2VideoStreamInfo
Definition: v2videoStreamInfo.h:21
V2VideoLookup
Definition: v2videoLookupInfo.h:56
kArtworkScreenshot
@ kArtworkScreenshot
Definition: metadataimagehelper.h:14
VideoMetadataListManager::loadAllFromDatabase
static void loadAllFromDatabase(metadata_list &items, const QString &sql="", const QString &bindValue="")
Load videometadata database into memory.
Definition: videometadatalistmanager.cpp:128
ProgramInfo::QueryBookmark
uint64_t QueryBookmark(void) const
Gets any bookmark position in database, unless the ignore bookmark flag is set.
Definition: programinfo.cpp:2804
V2FillCommBreak
void V2FillCommBreak(V2CutList *pCutList, ProgramInfo *rInfo, int marktype, bool includeFps)
Definition: v2serviceUtil.cpp:691
MythStreamInfoList::m_errorCode
int m_errorCode
Definition: mythavutil.h:103
V2Video::GetStreamInfo
static V2VideoStreamInfoList * GetStreamInfo(const QString &StorageGroup, const QString &FileName)
Definition: v2video.cpp:1068
V2Video::SetSavedBookmark
static bool SetSavedBookmark(int Id, long Offset)
Definition: v2video.cpp:914
ParentalLevel::plLowest
@ plLowest
Definition: parentalcontrols.h:13
kArtworkCoverart
@ kArtworkCoverart
Definition: metadataimagehelper.h:11
programinfo.h
kArtworkFanart
@ kArtworkFanart
Definition: metadataimagehelper.h:12
mythlogging.h
V2Video::UpdateVideoMetadata
bool UpdateVideoMetadata(int Id, const QString &Title, const QString &SubTitle, const QString &TagLine, const QString &Director, const QString &Studio, const QString &Plot, const QString &Rating, const QString &Inetref, int CollectionRef, const QString &HomePage, int Year, QDate ReleaseDate, float UserRating, int Length, int PlayCount, int Season, int Episode, int ShowLevel, const QString &FileName, const QString &Hash, const QString &CoverFile, int ChildID, bool Browse, bool Watched, bool Processed, const QString &PlayCommand, int Category, const QString &Trailer, const QString &Host, const QString &Screenshot, const QString &Banner, const QString &Fanart, QDate InsertDate, const QString &ContentType, const QString &Genres, const QString &Cast, const QString &Countries)
Definition: v2video.cpp:587
v2serviceUtil.h
V2Video::GetVideoCutList
static V2CutList * GetVideoCutList(int Id, const QString &OffsetType, bool IncludeFps)
Definition: v2video.cpp:1112
globals.h
RefCountedList< MetadataLookup >
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
kArtworkBanner
@ kArtworkBanner
Definition: metadataimagehelper.h:13
V2Video::RemoveVideoFromDB
static bool RemoveVideoFromDB(int Id)
Definition: v2video.cpp:497
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
VideoMetadata::SaveToDatabase
void SaveToDatabase()
Definition: videometadata.cpp:1949
V2Video::GetVideoList
static V2VideoMetadataInfoList * GetVideoList(const QString &Folder, const QString &Sort, bool Descending, int StartIndex, int Count, bool CollapseSubDirs)
Definition: v2video.cpp:202
VIDEO_COVERFILE_DEFAULT
const QString VIDEO_COVERFILE_DEFAULT
Definition: globals.cpp:25
Q_GLOBAL_STATIC_WITH_ARGS
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(VIDEO_HANDLE, V2Video::staticMetaObject, &V2Video::RegisterCustomTypes)) void V2Video
Definition: v2video.cpp:26
VIDEO_PLOT_DEFAULT
const QString VIDEO_PLOT_DEFAULT
Definition: globals.cpp:32
VIDEO_HANDLE
#define VIDEO_HANDLE
Definition: v2video.h:14
V2CutList
Definition: v2cutList.h:21
storagegroup.h
VIDEO_TRAILER_DEFAULT
const QString VIDEO_TRAILER_DEFAULT
Definition: globals.cpp:26
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MythHTTPService
Definition: mythhttpservice.h:19
V2Video::V2Video
V2Video()
Definition: v2video.cpp:50
VIDEO_INETREF_DEFAULT
const QString VIDEO_INETREF_DEFAULT
Definition: globals.cpp:24
VIDEO_FANART_DEFAULT
const QString VIDEO_FANART_DEFAULT
Definition: globals.cpp:29
MetadataFactory
Definition: metadatafactory.h:85
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
v2artworkInfoList.h
kContentUnknown
@ kContentUnknown
Definition: metadatacommon.h:66
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
V2Video::GetLastPlayPos
static long GetLastPlayPos(int Id)
Definition: v2video.cpp:140
mythmiscutil.h
V2Video::UpdateVideoWatchedStatus
static bool UpdateVideoWatchedStatus(int Id, bool Watched)
Definition: v2video.cpp:569
mythcorecontext.h
VideoMetadata::cast_list
std::vector< cast_entry > cast_list
Definition: videometadata.h:34
kContentTelevision
@ kContentTelevision
Definition: metadatacommon.h:62
VideoMetadata::SetHost
void SetHost(const QString &host)
Definition: videometadata.cpp:1839
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
VIDEO_RATING_DEFAULT
const QString VIDEO_RATING_DEFAULT
Definition: globals.cpp:30
VideoMetadataListManager::loadOneFromDatabase
static VideoMetadataPtr loadOneFromDatabase(uint id)
Definition: videometadatalistmanager.cpp:111
bluraymetadata.h
mythavutil.h
V2Video::RegisterCustomTypes
static void RegisterCustomTypes()
metadatafactory.h
StorageGroup
Definition: storagegroup.h:11
V2VideoMetadataInfoList
Definition: v2videoMetadataInfoList.h:20
VideoContentType
VideoContentType
Definition: metadatacommon.h:60
VideoMetadataListManager::metadata_list
std::list< VideoMetadataPtr > metadata_list
Definition: videometadatalistmanager.h:14
v2genreList.h
azlyrics.info
dictionary info
Definition: azlyrics.py:7
ProgramInfo::QueryLastPlayPos
uint64_t QueryLastPlayPos(void) const
Gets any lastplaypos position in database, unless the ignore lastplaypos flag is set.
Definition: programinfo.cpp:2831
VIDEO_YEAR_DEFAULT
static constexpr uint16_t VIDEO_YEAR_DEFAULT
Definition: videometadata.h:18
VIDEO_BANNER_DEFAULT
const QString VIDEO_BANNER_DEFAULT
Definition: globals.cpp:28
ParentalLevel::Level
Level
Definition: parentalcontrols.h:12
V2FillCutList
void V2FillCutList(V2CutList *pCutList, ProgramInfo *rInfo, int marktype, bool includeFps)
Definition: v2serviceUtil.cpp:637
kContentHomeMovie
@ kContentHomeMovie
Definition: metadatacommon.h:65
V2Video::GetVideoByFileName
static V2VideoMetadataInfo * GetVideoByFileName(const QString &FileName)
Definition: v2video.cpp:70
FileHash
QString FileHash(const QString &filename)
Definition: mythmiscutil.cpp:548
V2Video::GetSavedBookmark
static long GetSavedBookmark(int Id)
Definition: v2video.cpp:93
v2castMemberList.h
MythHTTPMetaService
Definition: mythhttpmetaservice.h:10
VIDEO_DIRECTOR_DEFAULT
const QString VIDEO_DIRECTOR_DEFAULT
Definition: globals.cpp:23
kContentMovie
@ kContentMovie
Definition: metadatacommon.h:61
ProgramInfo::SaveLastPlayPos
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
Definition: programinfo.cpp:2717
VIDEO_SCREENSHOT_DEFAULT
const QString VIDEO_SCREENSHOT_DEFAULT
Definition: globals.cpp:27
V2VideoMetadataInfo
Definition: v2videoMetadataInfo.h:9
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:902
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
MythStreamInfoList::m_streamInfoList
QVector< MythStreamInfo > m_streamInfoList
Definition: mythavutil.h:105