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 
185  const QString &Sort,
186  bool bDescending,
187  int nStartIndex,
188  int nCount )
189 {
190  QString fields = "title,director,studio,plot,rating,year,releasedate,"
191  "userrating,length,playcount,filename,hash,showlevel,"
192  "coverfile,inetref,collectionref,homepage,childid,browse,watched,"
193  "playcommand,category,intid,trailer,screenshot,banner,fanart,"
194  "subtitle,tagline,season,episode,host,insertdate,processed,contenttype";
195 
196  QStringList sortFields = fields.split(',');
197 
199 
200  QString sql = "";
201  if (!Folder.isEmpty())
202  sql.append(" WHERE filename LIKE '" + Folder + "%'");
203  sql.append(" ORDER BY ");
204  QString sort = Sort.toLower();
205  if (sort == "added")
206  sql.append("insertdate");
207  else if (sort == "released")
208  sql.append("releasedate");
209  else if (sortFields.contains(sort))
210  sql.append(sort);
211  else
212  sql.append("intid");
213 
214  if (bDescending)
215  sql += " DESC";
217 
218  std::vector<VideoMetadataListManager::VideoMetadataPtr> videos(videolist.begin(), videolist.end());
219 
220  // ----------------------------------------------------------------------
221  // Build Response
222  // ----------------------------------------------------------------------
223 
224  auto *pVideoMetadataInfos = new V2VideoMetadataInfoList();
225 
226  nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)videos.size() ) : 0;
227  nCount = (nCount > 0) ? std::min( nCount, (int)videos.size() ) : videos.size();
228  int nEndIndex = std::min((nStartIndex + nCount), (int)videos.size() );
229 
230  for( int n = nStartIndex; n < nEndIndex; n++ )
231  {
232  V2VideoMetadataInfo *pVideoMetadataInfo = pVideoMetadataInfos->AddNewVideoMetadataInfo();
233 
234  VideoMetadataListManager::VideoMetadataPtr metadata = videos[n];
235 
236  if (metadata)
237  V2FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true );
238  }
239 
240  int curPage = 0;
241  int totalPages = 0;
242  if (nCount == 0)
243  totalPages = 1;
244  else
245  totalPages = (int)ceil((float)videos.size() / nCount);
246 
247  if (totalPages == 1)
248  curPage = 1;
249  else
250  {
251  curPage = (int)ceil((float)nStartIndex / nCount) + 1;
252  }
253 
254  pVideoMetadataInfos->setStartIndex ( nStartIndex );
255  pVideoMetadataInfos->setCount ( nCount );
256  pVideoMetadataInfos->setCurrentPage ( curPage );
257  pVideoMetadataInfos->setTotalPages ( totalPages );
258  pVideoMetadataInfos->setTotalAvailable( videos.size() );
259  pVideoMetadataInfos->setAsOf ( MythDate::current() );
260  pVideoMetadataInfos->setVersion ( MYTH_BINARY_VERSION );
261  pVideoMetadataInfos->setProtoVer ( MYTH_PROTO_VERSION );
262 
263  return pVideoMetadataInfos;
264 }
265 
266 
268  const QString &Subtitle,
269  const QString &Inetref,
270  int Season,
271  int Episode,
272  const QString &GrabberType,
273  bool AllowGeneric )
274 {
275  auto *pVideoLookups = new V2VideoLookupList();
276 
277  MetadataLookupList list;
278 
279  auto *factory = new MetadataFactory(nullptr);
280 
281  if (factory)
282  {
283  list = factory->SynchronousLookup(Title, Subtitle,
284  Inetref, Season, Episode,
285  GrabberType, AllowGeneric);
286  }
287 
288  if ( list.empty() )
289  return pVideoLookups;
290 
291  //MetadataLookupList is a reference counted list.
292  //it will delete all its content at its end of life
293  for(const auto & lookup : qAsConst(list))
294  {
295  V2VideoLookup *pVideoLookup = pVideoLookups->AddNewVideoLookup();
296 
297  if (lookup)
298  {
299  pVideoLookup->setTitle(lookup->GetTitle());
300  pVideoLookup->setSubTitle(lookup->GetSubtitle());
301  pVideoLookup->setSeason(lookup->GetSeason());
302  pVideoLookup->setEpisode(lookup->GetEpisode());
303  pVideoLookup->setYear(lookup->GetYear());
304  pVideoLookup->setTagline(lookup->GetTagline());
305  pVideoLookup->setDescription(lookup->GetDescription());
306  pVideoLookup->setCertification(lookup->GetCertification());
307  pVideoLookup->setInetref(lookup->GetInetref());
308  pVideoLookup->setCollectionref(lookup->GetCollectionref());
309  pVideoLookup->setHomePage(lookup->GetHomepage());
310  pVideoLookup->setReleaseDate(
311  QDateTime(lookup->GetReleaseDate(),
312  QTime(0,0),Qt::LocalTime).toUTC());
313  pVideoLookup->setUserRating(lookup->GetUserRating());
314  pVideoLookup->setLength(lookup->GetRuntime().count());
315  pVideoLookup->setLanguage(lookup->GetLanguage());
316  pVideoLookup->setCountries(lookup->GetCountries());
317  pVideoLookup->setPopularity(lookup->GetPopularity());
318  pVideoLookup->setBudget(lookup->GetBudget());
319  pVideoLookup->setRevenue(lookup->GetRevenue());
320  pVideoLookup->setIMDB(lookup->GetIMDB());
321  pVideoLookup->setTMSRef(lookup->GetTMSref());
322 
323  ArtworkList coverartlist = lookup->GetArtwork(kArtworkCoverart);
324  ArtworkList::iterator c;
325  for (c = coverartlist.begin(); c != coverartlist.end(); ++c)
326  {
327  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
328  art->setType("coverart");
329  art->setUrl((*c).url);
330  art->setThumbnail((*c).thumbnail);
331  art->setWidth((*c).width);
332  art->setHeight((*c).height);
333  }
334  ArtworkList fanartlist = lookup->GetArtwork(kArtworkFanart);
335  ArtworkList::iterator f;
336  for (f = fanartlist.begin(); f != fanartlist.end(); ++f)
337  {
338  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
339  art->setType("fanart");
340  art->setUrl((*f).url);
341  art->setThumbnail((*f).thumbnail);
342  art->setWidth((*f).width);
343  art->setHeight((*f).height);
344  }
345  ArtworkList bannerlist = lookup->GetArtwork(kArtworkBanner);
346  ArtworkList::iterator b;
347  for (b = bannerlist.begin(); b != bannerlist.end(); ++b)
348  {
349  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
350  art->setType("banner");
351  art->setUrl((*b).url);
352  art->setThumbnail((*b).thumbnail);
353  art->setWidth((*b).width);
354  art->setHeight((*b).height);
355  }
356  ArtworkList screenshotlist = lookup->GetArtwork(kArtworkScreenshot);
357  ArtworkList::iterator s;
358  for (s = screenshotlist.begin(); s != screenshotlist.end(); ++s)
359  {
360  V2ArtworkItem *art = pVideoLookup->AddNewArtwork();
361  art->setType("screenshot");
362  art->setUrl((*s).url);
363  art->setThumbnail((*s).thumbnail);
364  art->setWidth((*s).width);
365  art->setHeight((*s).height);
366  }
367  }
368  }
369 
370  pVideoLookups->setCount ( list.count() );
371  pVideoLookups->setAsOf ( MythDate::current() );
372  pVideoLookups->setVersion ( MYTH_BINARY_VERSION );
373  pVideoLookups->setProtoVer ( MYTH_PROTO_VERSION );
374 
375  delete factory;
376 
377  return pVideoLookups;
378 }
379 
380 
382 {
383  bool bResult = false;
384 
387  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
388  mlm->setList(videolist);
389  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(Id);
390 
391  if (metadata)
392  bResult = metadata->DeleteFromDatabase();
393 
394  return bResult;
395 }
396 
397 bool V2Video::AddVideo( const QString &sFileName,
398  const QString &sHostName )
399 {
400  if ( sHostName.isEmpty() )
401  throw( QString( "Host not provided! Local storage is deprecated and "
402  "is not supported by the API." ));
403 
404  if ( sFileName.isEmpty() ||
405  (sFileName.contains("/../")) ||
406  (sFileName.startsWith("../")) )
407  {
408  throw( QString( "Filename not provided, or fails sanity checks!" ));
409  }
410 
411  StorageGroup sgroup("Videos", sHostName);
412 
413  QString fullname = sgroup.FindFile(sFileName);
414 
415  if ( !QFile::exists(fullname) )
416  throw( QString( "Provided filename does not exist!" ));
417 
418  QString hash = FileHash(fullname);
419 
420  if (hash == "NULL")
421  {
422  LOG(VB_GENERAL, LOG_ERR, "Video Hash Failed. Unless this is a DVD or "
423  "Blu-ray, something has probably gone wrong.");
424  hash = "";
425  }
426 
427  VideoMetadata newFile(sFileName, QString(), hash,
433  QString(), QString(), QString(), QString(),
434  QString(), VIDEO_YEAR_DEFAULT,
435  QDate::fromString("0000-00-00","YYYY-MM-DD"),
436  VIDEO_INETREF_DEFAULT, 0, QString(),
438  0.0, VIDEO_RATING_DEFAULT, 0, 0,
439  0, 0,
440  MythDate::current().date(), 0,
442 
443  newFile.SetHost(sHostName);
444  newFile.SaveToDatabase();
445 
446  return true;
447 }
448 
450 //
452 
454  bool bWatched )
455 {
458  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
459  mlm->setList(videolist);
460  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId);
461 
462  if ( !metadata )
463  return false;
464 
465  metadata->SetWatched(bWatched);
466  metadata->UpdateDatabase();
467 
468  return true;
469 }
470 
472  const QString &sTitle,
473  const QString &sSubTitle,
474  const QString &sTagLine,
475  const QString &sDirector,
476  const QString &sStudio,
477  const QString &sPlot,
478  const QString &sRating,
479  const QString &sInetref,
480  int nCollectionRef,
481  const QString &sHomePage,
482  int nYear,
483  QDate sReleasedate,
484  float fUserRating,
485  int nLength,
486  int nPlayCount,
487  int nSeason,
488  int nEpisode,
489  int nShowLevel,
490  const QString &sFileName,
491  const QString &sHash,
492  const QString &sCoverFile,
493  int nChildID,
494  bool bBrowse,
495  bool bWatched,
496  bool bProcessed,
497  const QString &sPlayCommand,
498  int nCategory,
499  const QString &sTrailer,
500  const QString &sHost,
501  const QString &sScreenshot,
502  const QString &sBanner,
503  const QString &sFanart,
504  QDate sInsertDate,
505  const QString &sContentType,
506  const QString &sGenres,
507  const QString &sCast,
508  const QString &sCountries)
509 {
510  bool update_required = false;
513  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
514  mlm->setList(videolist);
515  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId);
516 
517  if (!metadata)
518  {
519  LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Id=%1 not found")
520  .arg(nId));
521  return false;
522  }
523 
524  if (HAS_PARAMv2("Title"))
525  {
526  metadata->SetTitle(sTitle);
527  update_required = true;
528  }
529 
530  if (HAS_PARAMv2("SubTitle"))
531  {
532  metadata->SetSubtitle(sSubTitle);
533  update_required = true;
534  }
535 
536  if (HAS_PARAMv2("TagLine"))
537  {
538  metadata->SetTagline(sTagLine);
539  update_required = true;
540  }
541 
542  if (HAS_PARAMv2("Director"))
543  {
544  metadata->SetDirector(sDirector);
545  update_required = true;
546  }
547 
548  if (HAS_PARAMv2("Studio"))
549  {
550  metadata->SetStudio(sStudio);
551  update_required = true;
552  }
553 
554  if (HAS_PARAMv2("Plot"))
555  {
556  metadata->SetPlot(sPlot);
557  update_required = true;
558  }
559 
560  if (HAS_PARAMv2("UserRating"))
561  {
562  metadata->SetUserRating(fUserRating);
563  update_required = true;
564  }
565 
566  if (HAS_PARAMv2("Inetref"))
567  {
568  metadata->SetInetRef(sInetref);
569  update_required = true;
570  }
571 
572  if (HAS_PARAMv2("CollectionRef"))
573  {
574  metadata->SetCollectionRef(nCollectionRef);
575  update_required = true;
576  }
577 
578  if (HAS_PARAMv2("HomePage"))
579  {
580  metadata->SetHomepage(sHomePage);
581  update_required = true;
582  }
583 
584  if (HAS_PARAMv2("Year"))
585  {
586  metadata->SetYear(nYear);
587  update_required = true;
588  }
589 
590  if (HAS_PARAMv2("ReleaseDate"))
591  {
592  metadata->SetReleaseDate(sReleasedate);
593  update_required = true;
594  }
595 
596  if (HAS_PARAMv2("Rating"))
597  {
598  metadata->SetRating(sRating);
599  update_required = true;
600  }
601 
602  if (HAS_PARAMv2("Length"))
603  {
604  metadata->SetLength(std::chrono::minutes(nLength));
605  update_required = true;
606  }
607 
608  if (HAS_PARAMv2("PlayCount"))
609  {
610  metadata->SetPlayCount(nPlayCount);
611  update_required = true;
612  }
613 
614  if (HAS_PARAMv2("Season"))
615  {
616  metadata->SetSeason(nSeason);
617  update_required = true;
618  }
619 
620  if (HAS_PARAMv2("Episode"))
621  {
622  metadata->SetEpisode(nEpisode);
623  update_required = true;
624  }
625 
626  if (HAS_PARAMv2("ShowLevel"))
627  {
628  metadata->SetShowLevel(ParentalLevel::Level(nShowLevel));
629  update_required = true;
630  }
631 
632  if (HAS_PARAMv2("FileName"))
633  {
634  metadata->SetFilename(sFileName);
635  update_required = true;
636  }
637 
638  if (HAS_PARAMv2("Hash"))
639  {
640  metadata->SetHash(sHash);
641  update_required = true;
642  }
643 
644  if (HAS_PARAMv2("CoverFile"))
645  {
646  metadata->SetCoverFile(sCoverFile);
647  update_required = true;
648  }
649 
650  if (HAS_PARAMv2("ChildID"))
651  {
652  metadata->SetChildID(nChildID);
653  update_required = true;
654  }
655 
656  if (HAS_PARAMv2("Browse"))
657  {
658  metadata->SetBrowse(bBrowse);
659  update_required = true;
660  }
661 
662  if (HAS_PARAMv2("Watched"))
663  {
664  metadata->SetWatched(bWatched);
665  update_required = true;
666  }
667 
668  if (HAS_PARAMv2("Processed"))
669  {
670  metadata->SetProcessed(bProcessed);
671  update_required = true;
672  }
673 
674  if (HAS_PARAMv2("PlayCommand"))
675  {
676  metadata->SetPlayCommand(sPlayCommand);
677  update_required = true;
678  }
679 
680  if (HAS_PARAMv2("Category"))
681  {
682  metadata->SetCategoryID(nCategory);
683  update_required = true;
684  }
685 
686  if (HAS_PARAMv2("Trailer"))
687  {
688  metadata->SetTrailer(sTrailer);
689  update_required = true;
690  }
691 
692  if (HAS_PARAMv2("Host"))
693  {
694  metadata->SetHost(sHost);
695  update_required = true;
696  }
697 
698  if (HAS_PARAMv2("Screenshot"))
699  {
700  metadata->SetScreenshot(sScreenshot);
701  update_required = true;
702  }
703 
704  if (HAS_PARAMv2("Banner"))
705  {
706  metadata->SetBanner(sBanner);
707  update_required = true;
708  }
709 
710  if (HAS_PARAMv2("Fanart"))
711  {
712  metadata->SetFanart(sFanart);
713  update_required = true;
714  }
715 
716  if (HAS_PARAMv2("InsertDate"))
717  {
718  metadata->SetInsertdate(sInsertDate);
719  update_required = true;
720  }
721 
722  if (HAS_PARAMv2("ContentType"))
723  {
724  // valid values for ContentType are 'MOVIE','TELEVISION','ADULT','MUSICVIDEO','HOMEVIDEO'
725  VideoContentType contentType = kContentUnknown;
726  if (sContentType == "MOVIE")
727  contentType = kContentMovie;
728 
729  if (sContentType == "TELEVISION")
730  contentType = kContentTelevision;
731 
732  if (sContentType == "ADULT")
733  contentType = kContentAdult;
734 
735  if (sContentType == "MUSICVIDEO")
736  contentType = kContentMusicVideo;
737 
738  if (sContentType == "HOMEVIDEO")
739  contentType = kContentHomeMovie;
740 
741  if (contentType != kContentUnknown)
742  {
743  metadata->SetContentType(contentType);
744  update_required = true;
745  }
746  else
747  LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Ignoring unknown ContentType: %1").arg(sContentType));
748  }
749 
750  if (HAS_PARAMv2("Genres"))
751  {
753 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
754  QStringList genresList = sGenres.split(',', QString::SkipEmptyParts);
755 #else
756  QStringList genresList = sGenres.split(',', Qt::SkipEmptyParts);
757 #endif
758 
759  std::transform(genresList.cbegin(), genresList.cend(), std::back_inserter(genres),
760  [](const QString& name)
761  {return VideoMetadata::genre_list::value_type(-1, name.simplified());} );
762 
763  metadata->SetGenres(genres);
764  update_required = true;
765  }
766 
767  if (HAS_PARAMv2("Cast"))
768  {
770 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
771  QStringList castList = sCast.split(',', QString::SkipEmptyParts);
772 #else
773  QStringList castList = sCast.split(',', Qt::SkipEmptyParts);
774 #endif
775 
776  std::transform(castList.cbegin(), castList.cend(), std::back_inserter(cast),
777  [](const QString& name)
778  {return VideoMetadata::cast_list::value_type(-1, name.simplified());} );
779 
780  metadata->SetCast(cast);
781  update_required = true;
782  }
783 
784  if (HAS_PARAMv2("Countries"))
785  {
786  VideoMetadata::country_list countries;
787 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
788  QStringList countryList = sCountries.split(',', QString::SkipEmptyParts);
789 #else
790  QStringList countryList = sCountries.split(',', Qt::SkipEmptyParts);
791 #endif
792 
793  std::transform(countryList.cbegin(), countryList.cend(), std::back_inserter(countries),
794  [](const QString& name)
795  {return VideoMetadata::country_list::value_type(-1, name.simplified());} );
796 
797  metadata->SetCountries(countries);
798  update_required = true;
799  }
800 
801  if (update_required)
802  metadata->UpdateDatabase();
803 
804  return true;
805 }
806 
808 // Set bookmark of a video as a frame number.
810 
811 bool V2Video::SetSavedBookmark( int Id, long Offset )
812 {
813  MSqlQuery query(MSqlQuery::InitCon());
814 
815  query.prepare("SELECT filename "
816  "FROM videometadata "
817  "WHERE intid = :ID ");
818  query.bindValue(":ID", Id);
819 
820  if (!query.exec())
821  {
822  MythDB::DBError("Video::SetSavedBookmark", query);
823  return false;
824  }
825 
826  QString fileName;
827 
828  if (query.next())
829  fileName = query.value(0).toString();
830  else
831  {
832  LOG(VB_GENERAL, LOG_ERR, QString("Video/SetSavedBookmark Video id %1 Not found.").arg(Id));
833  return false;
834  }
835 
836  ProgramInfo pi(fileName,
837  nullptr, // _plot,
838  nullptr, // _title,
839  nullptr, // const QString &_sortTitle,
840  nullptr, // const QString &_subtitle,
841  nullptr, // const QString &_sortSubtitle,
842  nullptr, // const QString &_director,
843  0, // int _season,
844  0, // int _episode,
845  nullptr, // const QString &_inetref,
846  0min, // uint _length_in_minutes,
847  0, // uint _year,
848  nullptr); //const QString &_programid);
849 
850  pi.SaveBookmark(Offset);
851  return true;
852 }
853 
855 // Set bookmark of a video as a frame number.
857 
858 bool V2Video::SetLastPlayPos( int Id, long Offset )
859 {
860  MSqlQuery query(MSqlQuery::InitCon());
861 
862  query.prepare("SELECT filename "
863  "FROM videometadata "
864  "WHERE intid = :ID ");
865  query.bindValue(":ID", Id);
866 
867  if (!query.exec())
868  {
869  MythDB::DBError("Video::SetLastPlayPos", query);
870  return false;
871  }
872 
873  QString fileName;
874 
875  if (query.next())
876  fileName = query.value(0).toString();
877  else
878  {
879  LOG(VB_GENERAL, LOG_ERR, QString("Video/SetLastPlayPos Video id %1 Not found.").arg(Id));
880  return false;
881  }
882 
883  ProgramInfo pi(fileName,
884  nullptr, // _plot,
885  nullptr, // _title,
886  nullptr, // const QString &_sortTitle,
887  nullptr, // const QString &_subtitle,
888  nullptr, // const QString &_sortSubtitle,
889  nullptr, // const QString &_director,
890  0, // int _season,
891  0, // int _episode,
892  nullptr, // const QString &_inetref,
893  0min, // uint _length_in_minutes,
894  0, // uint _year,
895  nullptr); //const QString &_programid);
896 
897  pi.SaveLastPlayPos(Offset);
898  return true;
899 }
900 
901 
902 V2BlurayInfo* V2Video::GetBluray( const QString &sPath )
903 {
904  QString path = sPath;
905 
906  if (sPath.isEmpty())
907  path = gCoreContext->GetSetting( "BluRayMountpoint", "/media/cdrom");
908 
909  LOG(VB_GENERAL, LOG_NOTICE,
910  QString("Parsing Blu-ray at path: %1 ").arg(path));
911 
912  auto *bdmeta = new BlurayMetadata(path);
913 
914  if ( !bdmeta )
915  throw( QString( "Unable to open Blu-ray Metadata Parser!" ));
916 
917  if ( !bdmeta->OpenDisc() )
918  throw( QString( "Unable to open Blu-ray Disc/Path!" ));
919 
920  if ( !bdmeta->ParseDisc() )
921  throw( QString( "Unable to parse metadata from Blu-ray Disc/Path!" ));
922 
923  auto *pBlurayInfo = new V2BlurayInfo();
924 
925  pBlurayInfo->setPath(path);
926  pBlurayInfo->setTitle(bdmeta->GetTitle());
927  pBlurayInfo->setAltTitle(bdmeta->GetAlternateTitle());
928  pBlurayInfo->setDiscLang(bdmeta->GetDiscLanguage());
929  pBlurayInfo->setDiscNum(bdmeta->GetCurrentDiscNumber());
930  pBlurayInfo->setTotalDiscNum(bdmeta->GetTotalDiscNumber());
931  pBlurayInfo->setTitleCount(bdmeta->GetTitleCount());
932  pBlurayInfo->setThumbCount(bdmeta->GetThumbnailCount());
933  pBlurayInfo->setTopMenuSupported(bdmeta->GetTopMenuSupported());
934  pBlurayInfo->setFirstPlaySupported(bdmeta->GetFirstPlaySupported());
935  pBlurayInfo->setNumHDMVTitles(bdmeta->GetNumHDMVTitles());
936  pBlurayInfo->setNumBDJTitles(bdmeta->GetNumBDJTitles());
937  pBlurayInfo->setNumUnsupportedTitles(bdmeta->GetNumUnsupportedTitles());
938  pBlurayInfo->setAACSDetected(bdmeta->GetAACSDetected());
939  pBlurayInfo->setLibAACSDetected(bdmeta->GetLibAACSDetected());
940  pBlurayInfo->setAACSHandled(bdmeta->GetAACSHandled());
941  pBlurayInfo->setBDPlusDetected(bdmeta->GetBDPlusDetected());
942  pBlurayInfo->setLibBDPlusDetected(bdmeta->GetLibBDPlusDetected());
943  pBlurayInfo->setBDPlusHandled(bdmeta->GetBDPlusHandled());
944 
945  QStringList thumbs = bdmeta->GetThumbnails();
946  if (!thumbs.empty())
947  pBlurayInfo->setThumbPath(thumbs.at(0));
948 
949  delete bdmeta;
950 
951  return pBlurayInfo;
952 }
953 
954 
956 // Jun 3, 2020
957 // Service to get stream info for all streams in a media file.
958 // This gets some basic info. If anything more is needed it can be added,
959 // depending on whether it is available from ffmpeg avformat apis.
960 // See the MythStreamInfoList class for the code that uses avformat to
961 // extract the information.
963 
965  ( const QString &storageGroup,
966  const QString &FileName )
967 {
968 
969  // Search for the filename
970 
971  StorageGroup storage( storageGroup );
972  QString sFullFileName = storage.FindFile( FileName );
973  MythStreamInfoList infos(sFullFileName);
974 
975  // The constructor of this class reads the file and gets the needed
976  // information.
977  auto *pVideoStreamInfos = new V2VideoStreamInfoList();
978 
979  pVideoStreamInfos->setCount ( infos.m_streamInfoList.size() );
980  pVideoStreamInfos->setAsOf ( MythDate::current() );
981  pVideoStreamInfos->setVersion ( MYTH_BINARY_VERSION );
982  pVideoStreamInfos->setProtoVer ( MYTH_PROTO_VERSION );
983  pVideoStreamInfos->setErrorCode ( infos.m_errorCode );
984  pVideoStreamInfos->setErrorMsg ( infos.m_errorMsg );
985 
986  for (const auto & info : qAsConst(infos.m_streamInfoList))
987  {
988  V2VideoStreamInfo *pVideoStreamInfo = pVideoStreamInfos->AddNewVideoStreamInfo();
989  pVideoStreamInfo->setCodecType ( QString(QChar(info.m_codecType)) );
990  pVideoStreamInfo->setCodecName ( info.m_codecName );
991  pVideoStreamInfo->setWidth ( info.m_width );
992  pVideoStreamInfo->setHeight ( info.m_height );
993  pVideoStreamInfo->setAspectRatio ( info.m_SampleAspectRatio );
994  pVideoStreamInfo->setFieldOrder ( info.m_fieldOrder );
995  pVideoStreamInfo->setFrameRate ( info.m_frameRate );
996  pVideoStreamInfo->setAvgFrameRate ( info.m_avgFrameRate );
997  pVideoStreamInfo->setChannels ( info.m_channels );
998  pVideoStreamInfo->setDuration ( info.m_duration );
999 
1000  }
1001  return pVideoStreamInfos;
1002 }
1003 
1005 // October 26,2022
1006 // Support for Cut List for Videos
1008 
1010  const QString &offsettype )
1011 {
1012  MSqlQuery query(MSqlQuery::InitCon());
1013 
1014  query.prepare("SELECT filename "
1015  "FROM videometadata "
1016  "WHERE intid = :ID ");
1017  query.bindValue(":ID", Id);
1018 
1019  if (!query.exec())
1020  {
1021  MythDB::DBError("V2Video::GetVideoCommBreak", query);
1022  throw QString("Database Error.");
1023  }
1024 
1025  QString fileName;
1026 
1027  if (query.next())
1028  fileName = query.value(0).toString();
1029  else
1030  {
1031  LOG(VB_GENERAL, LOG_ERR, QString("V2Video/GetVideoCommBreak Video id %1 Not found.").arg(Id));
1032  throw QString("Video Not Found.");
1033  }
1034 
1035  ProgramInfo pi(fileName,
1036  nullptr, // _plot,
1037  nullptr, // _title,
1038  nullptr, // const QString &_sortTitle,
1039  nullptr, // const QString &_subtitle,
1040  nullptr, // const QString &_sortSubtitle,
1041  nullptr, // const QString &_director,
1042  0, // int _season,
1043  0, // int _episode,
1044  nullptr, // const QString &_inetref,
1045  0min, // uint _length_in_minutes,
1046  0, // uint _year,
1047  nullptr); //const QString &_programid);
1048 
1049 
1050  int marktype = 0;
1051 
1052  auto* pCutList = new V2CutList();
1053  if (offsettype.toLower() == "position")
1054  marktype = 1;
1055  else if (offsettype.toLower() == "duration")
1056  marktype = 2;
1057  else
1058  marktype = 0;
1059 
1060  V2FillCutList(pCutList, &pi, marktype);
1061 
1062  return pCutList;
1063 }
1064 
1066 // October 26,2022
1067 // Support for Commercial Break List for Videos
1069 
1071  const QString &offsettype )
1072 {
1073  MSqlQuery query(MSqlQuery::InitCon());
1074 
1075  query.prepare("SELECT filename "
1076  "FROM videometadata "
1077  "WHERE intid = :ID ");
1078  query.bindValue(":ID", Id);
1079 
1080  if (!query.exec())
1081  {
1082  MythDB::DBError("V2Video::GetVideoCommBreak", query);
1083  throw QString("Database Error.");
1084  }
1085 
1086  QString fileName;
1087 
1088  if (query.next())
1089  fileName = query.value(0).toString();
1090  else
1091  {
1092  LOG(VB_GENERAL, LOG_ERR, QString("V2Video/GetVideoCommBreak Video id %1 Not found.").arg(Id));
1093  throw QString("Video Not Found.");
1094  }
1095 
1096  ProgramInfo pi(fileName,
1097  nullptr, // _plot,
1098  nullptr, // _title,
1099  nullptr, // const QString &_sortTitle,
1100  nullptr, // const QString &_subtitle,
1101  nullptr, // const QString &_sortSubtitle,
1102  nullptr, // const QString &_director,
1103  0, // int _season,
1104  0, // int _episode,
1105  nullptr, // const QString &_inetref,
1106  0min, // uint _length_in_minutes,
1107  0, // uint _year,
1108  nullptr); //const QString &_programid);
1109 
1110 
1111  int marktype = 0;
1112 
1113  auto* pCutList = new V2CutList();
1114  if (offsettype.toLower() == "position")
1115  marktype = 1;
1116  else if (offsettype.toLower() == "duration")
1117  marktype = 2;
1118  else
1119  marktype = 0;
1120 
1121  V2FillCommBreak(pCutList, &pi, marktype);
1122 
1123  return pCutList;
1124 }
MythHTTPService::HAS_PARAMv2
bool HAS_PARAMv2(const QString &p)
Definition: mythhttpservice.h:36
V2VideoLookup::AddNewArtwork
V2ArtworkItem * AddNewArtwork()
Definition: v2videoLookupInfo.h:129
MythStreamInfoList::m_errorMsg
QString m_errorMsg
Definition: mythavutil.h:110
BlurayMetadata
Definition: bluraymetadata.h:25
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:811
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
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:397
GrabberType
GrabberType
Definition: metadatagrabber.h:20
V2Video::GetVideoCommBreak
static V2CutList * GetVideoCommBreak(int Id, const QString &OffsetType)
Definition: v2video.cpp:1070
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:2677
ParentalLevel::plLowest
@ plLowest
Definition: parentalcontrols.h:12
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:267
VideoMetadataListManager
Definition: videometadatalistmanager.h:10
V2FillCommBreak
void V2FillCommBreak(V2CutList *pCutList, ProgramInfo *rInfo, int marktype)
Definition: v2serviceUtil.cpp:635
simple_ref_ptr
Definition: quicksp.h:24
V2Video::GetBluray
static V2BlurayInfo * GetBluray(const QString &Path)
Definition: v2video.cpp:902
ArtworkList
QList< ArtworkInfo > ArtworkList
Definition: metadataimagehelper.h:30
V2FillVideoMetadataInfo
void V2FillVideoMetadataInfo(V2VideoMetadataInfo *pVideoMetadataInfo, const VideoMetadataListManager::VideoMetadataPtr &pMetadata, bool bDetails)
Definition: v2serviceUtil.cpp:377
StorageGroup::FindFile
QString FindFile(const QString &filename)
Definition: storagegroup.cpp:602
MythStreamInfoList
Definition: mythavutil.h:106
V2BlurayInfo
Definition: v2blurayInfo.h:20
V2ArtworkItem
Definition: v2videoLookupInfo.h:22
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:205
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:858
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:617
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
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
VideoMetadataListManager::loadAllFromDatabase
static void loadAllFromDatabase(metadata_list &items, const QString &sql="")
Load videometadata database into memory.
Definition: videometadatalistmanager.cpp:128
V2VideoStreamInfo
Definition: v2videoStreamInfo.h:21
V2VideoLookup
Definition: v2videoLookupInfo.h:58
ProgramInfo::QueryBookmark
uint64_t QueryBookmark(void) const
Gets any bookmark position in database, unless the ignore bookmark flag is set.
Definition: programinfo.cpp:2801
MythStreamInfoList::m_errorCode
int m_errorCode
Definition: mythavutil.h:109
V2Video::GetStreamInfo
static V2VideoStreamInfoList * GetStreamInfo(const QString &StorageGroup, const QString &FileName)
Definition: v2video.cpp:965
V2Video::SetSavedBookmark
static bool SetSavedBookmark(int Id, long Offset)
Definition: v2video.cpp:811
programinfo.h
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:471
v2serviceUtil.h
ParentalLevel::Level
Level
Definition: parentalcontrols.h:12
globals.h
RefCountedList< MetadataLookup >
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:549
V2Video::RemoveVideoFromDB
static bool RemoveVideoFromDB(int Id)
Definition: v2video.cpp:381
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:227
VideoMetadata::SaveToDatabase
void SaveToDatabase()
Definition: videometadata.cpp:1951
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
kArtworkFanart
@ kArtworkFanart
Definition: metadataimagehelper.h:12
kContentTelevision
@ kContentTelevision
Definition: metadatacommon.h:62
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:54
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:34
v2artworkInfoList.h
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
VideoContentType
VideoContentType
Definition: metadatacommon.h:60
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:453
mythcorecontext.h
VideoMetadata::cast_list
std::vector< cast_entry > cast_list
Definition: videometadata.h:34
VideoMetadata::SetHost
void SetHost(const QString &host)
Definition: videometadata.cpp:1841
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:887
VIDEO_RATING_DEFAULT
const QString VIDEO_RATING_DEFAULT
Definition: globals.cpp:30
V2FillCutList
void V2FillCutList(V2CutList *pCutList, ProgramInfo *rInfo, int marktype)
Definition: v2serviceUtil.cpp:593
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
kContentAdult
@ kContentAdult
Definition: metadatacommon.h:63
V2VideoMetadataInfoList
Definition: v2videoMetadataInfoList.h:20
kArtworkBanner
@ kArtworkBanner
Definition: metadataimagehelper.h:13
kContentMusicVideo
@ kContentMusicVideo
Definition: metadatacommon.h:64
VIDEO_YEAR_DEFAULT
@ VIDEO_YEAR_DEFAULT
Definition: videometadata.h:18
kContentMovie
@ kContentMovie
Definition: metadatacommon.h:61
VideoMetadataListManager::metadata_list
std::list< VideoMetadataPtr > metadata_list
Definition: videometadatalistmanager.h:14
v2genreList.h
ProgramInfo::QueryLastPlayPos
uint64_t QueryLastPlayPos(void) const
Gets any lastplaypos position in database, unless the ignore lastplaypos flag is set.
Definition: programinfo.cpp:2828
kContentUnknown
@ kContentUnknown
Definition: metadatacommon.h:66
VIDEO_BANNER_DEFAULT
const QString VIDEO_BANNER_DEFAULT
Definition: globals.cpp:28
kArtworkScreenshot
@ kArtworkScreenshot
Definition: metadataimagehelper.h:14
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:549
V2Video::GetSavedBookmark
static long GetSavedBookmark(int Id)
Definition: v2video.cpp:93
V2Video::GetVideoList
static V2VideoMetadataInfoList * GetVideoList(const QString &Folder, const QString &Sort, bool Descending, int StartIndex, int Count)
Definition: v2video.cpp:184
v2castMemberList.h
kArtworkCoverart
@ kArtworkCoverart
Definition: metadataimagehelper.h:11
MythHTTPMetaService
Definition: mythhttpmetaservice.h:10
VIDEO_DIRECTOR_DEFAULT
const QString VIDEO_DIRECTOR_DEFAULT
Definition: globals.cpp:23
V2Video::GetVideoCutList
static V2CutList * GetVideoCutList(int Id, const QString &OffsetType)
Definition: v2video.cpp:1009
ProgramInfo::SaveLastPlayPos
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
Definition: programinfo.cpp:2714
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:896
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:836
MythStreamInfoList::m_streamInfoList
QVector< MythStreamInfo > m_streamInfoList
Definition: mythavutil.h:111