MythTV  master
video.cpp
Go to the documentation of this file.
1 // Program Name: video.cpp
3 // Created : Apr. 21, 2011
4 //
5 // Copyright (c) 2011 Robert McNamara <rmcnamara@mythtv.org>
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //
25 
26 // C++
27 #include <cmath>
28 
29 // Qt
30 #include <QList>
31 #include <QFile>
32 #include <QMutex>
33 
34 // MythTV
35 #include "libmythbase/compat.h"
37 #include "libmythbase/mythdate.h"
40 #include "libmythbase/remotefile.h"
46 #include "libmythtv/mythavutil.h"
47 
48 // MythBackend
49 #include "serviceUtil.h"
50 #include "video.h"
51 
53 //
55 
57  const QString &Sort,
58  bool bDescending,
59  int nStartIndex,
60  int nCount )
61 {
62  QString fields = "title,director,studio,plot,rating,year,releasedate,"
63  "userrating,length,playcount,filename,hash,showlevel,"
64  "coverfile,inetref,collectionref,homepage,childid,browse,watched,"
65  "playcommand,category,intid,trailer,screenshot,banner,fanart,"
66  "subtitle,tagline,season,episode,host,insertdate,processed,contenttype";
67 
68  QStringList sortFields = fields.split(',');
69 
71 
72  QString sql = "";
73  if (!Folder.isEmpty())
74  sql.append(" WHERE filename LIKE '" + Folder + "%'");
75 
76  sql.append(" ORDER BY ");
77  QString sort = Sort.toLower();
78  if (sort == "added")
79  sql.append("insertdate");
80  else if (sort == "released")
81  sql.append("releasedate");
82  else if (sortFields.contains(sort))
83  sql.append(sort);
84  else
85  sql.append("intid");
86 
87  if (bDescending)
88  sql += " DESC";
90 
91  std::vector<VideoMetadataListManager::VideoMetadataPtr> videos(videolist.begin(), videolist.end());
92 
93  // ----------------------------------------------------------------------
94  // Build Response
95  // ----------------------------------------------------------------------
96 
97  auto *pVideoMetadataInfos = new DTC::VideoMetadataInfoList();
98 
99  nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)videos.size() ) : 0;
100  nCount = (nCount > 0) ? std::min( nCount, (int)videos.size() ) : videos.size();
101  int nEndIndex = std::min((nStartIndex + nCount), (int)videos.size() );
102 
103  for( int n = nStartIndex; n < nEndIndex; n++ )
104  {
105  DTC::VideoMetadataInfo *pVideoMetadataInfo = pVideoMetadataInfos->AddNewVideoMetadataInfo();
106 
107  VideoMetadataListManager::VideoMetadataPtr metadata = videos[n];
108 
109  if (metadata)
110  FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true );
111  }
112 
113  int curPage = 0;
114  int totalPages = 0;
115  if (nCount == 0)
116  totalPages = 1;
117  else
118  totalPages = (int)ceil((float)videos.size() / nCount);
119 
120  if (totalPages == 1)
121  curPage = 1;
122  else
123  {
124  curPage = (int)ceil((float)nStartIndex / nCount) + 1;
125  }
126 
127  pVideoMetadataInfos->setStartIndex ( nStartIndex );
128  pVideoMetadataInfos->setCount ( nCount );
129  pVideoMetadataInfos->setCurrentPage ( curPage );
130  pVideoMetadataInfos->setTotalPages ( totalPages );
131  pVideoMetadataInfos->setTotalAvailable( videos.size() );
132  pVideoMetadataInfos->setAsOf ( MythDate::current() );
133  pVideoMetadataInfos->setVersion ( MYTH_BINARY_VERSION );
134  pVideoMetadataInfos->setProtoVer ( MYTH_PROTO_VERSION );
135 
136  return pVideoMetadataInfos;
137 }
138 
140 //
142 
144 {
147 
148  if ( !metadata )
149  throw( QString( "No metadata found for selected ID!." ));
150 
151  auto *pVideoMetadataInfo = new DTC::VideoMetadataInfo();
152 
153  FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true );
154 
155  return pVideoMetadataInfo;
156 }
157 
159 //
161 
163 {
166  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
167  mlm->setList(videolist);
168  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byFilename(FileName);
169 
170  if ( !metadata )
171  throw( QString( "No metadata found for selected filename!." ));
172 
173  auto *pVideoMetadataInfo = new DTC::VideoMetadataInfo();
174 
175  FillVideoMetadataInfo ( pVideoMetadataInfo, metadata, true );
176 
177  return pVideoMetadataInfo;
178 }
179 
181 //
183 
185  const QString &Subtitle,
186  const QString &Inetref,
187  int Season,
188  int Episode,
189  const QString &GrabberType,
190  bool AllowGeneric )
191 {
192  auto *pVideoLookups = new DTC::VideoLookupList();
193 
194  MetadataLookupList list;
195 
196  auto *factory = new MetadataFactory(nullptr);
197 
198  if (factory)
199  {
200  list = factory->SynchronousLookup(Title, Subtitle,
201  Inetref, Season, Episode,
202  GrabberType, AllowGeneric);
203  }
204 
205  if ( list.empty() )
206  return pVideoLookups;
207 
208  //MetadataLookupList is a reference counted list.
209  //it will delete all its content at its end of life
210  for( int n = 0; n < list.size(); n++ )
211  {
212  DTC::VideoLookup *pVideoLookup = pVideoLookups->AddNewVideoLookup();
213 
214  MetadataLookup *lookup = list[n];
215 
216  if (lookup)
217  {
218  pVideoLookup->setTitle(lookup->GetTitle());
219  pVideoLookup->setSubTitle(lookup->GetSubtitle());
220  pVideoLookup->setSeason(lookup->GetSeason());
221  pVideoLookup->setEpisode(lookup->GetEpisode());
222  pVideoLookup->setYear(lookup->GetYear());
223  pVideoLookup->setTagline(lookup->GetTagline());
224  pVideoLookup->setDescription(lookup->GetDescription());
225  pVideoLookup->setCertification(lookup->GetCertification());
226  pVideoLookup->setInetref(lookup->GetInetref());
227  pVideoLookup->setCollectionref(lookup->GetCollectionref());
228  pVideoLookup->setHomePage(lookup->GetHomepage());
229  pVideoLookup->setReleaseDate(
230  QDateTime(lookup->GetReleaseDate(),
231  QTime(0,0),Qt::LocalTime).toUTC());
232  pVideoLookup->setUserRating(lookup->GetUserRating());
233  pVideoLookup->setLength(lookup->GetRuntime().count());
234  pVideoLookup->setLanguage(lookup->GetLanguage());
235  pVideoLookup->setCountries(lookup->GetCountries());
236  pVideoLookup->setPopularity(lookup->GetPopularity());
237  pVideoLookup->setBudget(lookup->GetBudget());
238  pVideoLookup->setRevenue(lookup->GetRevenue());
239  pVideoLookup->setIMDB(lookup->GetIMDB());
240  pVideoLookup->setTMSRef(lookup->GetTMSref());
241 
242  ArtworkList coverartlist = lookup->GetArtwork(kArtworkCoverart);
243  ArtworkList::iterator c;
244  for (c = coverartlist.begin(); c != coverartlist.end(); ++c)
245  {
246  DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork();
247  art->setType("coverart");
248  art->setUrl((*c).url);
249  art->setThumbnail((*c).thumbnail);
250  art->setWidth((*c).width);
251  art->setHeight((*c).height);
252  }
253  ArtworkList fanartlist = lookup->GetArtwork(kArtworkFanart);
254  ArtworkList::iterator f;
255  for (f = fanartlist.begin(); f != fanartlist.end(); ++f)
256  {
257  DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork();
258  art->setType("fanart");
259  art->setUrl((*f).url);
260  art->setThumbnail((*f).thumbnail);
261  art->setWidth((*f).width);
262  art->setHeight((*f).height);
263  }
264  ArtworkList bannerlist = lookup->GetArtwork(kArtworkBanner);
265  ArtworkList::iterator b;
266  for (b = bannerlist.begin(); b != bannerlist.end(); ++b)
267  {
268  DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork();
269  art->setType("banner");
270  art->setUrl((*b).url);
271  art->setThumbnail((*b).thumbnail);
272  art->setWidth((*b).width);
273  art->setHeight((*b).height);
274  }
275  ArtworkList screenshotlist = lookup->GetArtwork(kArtworkScreenshot);
276  ArtworkList::iterator s;
277  for (s = screenshotlist.begin(); s != screenshotlist.end(); ++s)
278  {
279  DTC::ArtworkItem *art = pVideoLookup->AddNewArtwork();
280  art->setType("screenshot");
281  art->setUrl((*s).url);
282  art->setThumbnail((*s).thumbnail);
283  art->setWidth((*s).width);
284  art->setHeight((*s).height);
285  }
286  }
287  }
288 
289  pVideoLookups->setCount ( list.count() );
290  pVideoLookups->setAsOf ( MythDate::current() );
291  pVideoLookups->setVersion ( MYTH_BINARY_VERSION );
292  pVideoLookups->setProtoVer ( MYTH_PROTO_VERSION );
293 
294  delete factory;
295 
296  return pVideoLookups;
297 }
298 
300 //
302 
304 {
305  bool bResult = false;
306 
309  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
310  mlm->setList(videolist);
311  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(Id);
312 
313  if (metadata)
314  bResult = metadata->DeleteFromDatabase();
315 
316  return bResult;
317 }
318 
320 //
322 
323 bool Video::AddVideo( const QString &sFileName,
324  const QString &sHostName )
325 {
326  if ( sHostName.isEmpty() )
327  throw( QString( "Host not provided! Local storage is deprecated and "
328  "is not supported by the API." ));
329 
330  if ( sFileName.isEmpty() ||
331  (sFileName.contains("/../")) ||
332  (sFileName.startsWith("../")) )
333  {
334  throw( QString( "Filename not provided, or fails sanity checks!" ));
335  }
336 
337  StorageGroup sgroup("Videos", sHostName);
338 
339  QString fullname = sgroup.FindFile(sFileName);
340 
341  if ( !QFile::exists(fullname) )
342  throw( QString( "Provided filename does not exist!" ));
343 
344  QString hash = FileHash(fullname);
345 
346  if (hash == "NULL")
347  {
348  LOG(VB_GENERAL, LOG_ERR, "Video Hash Failed. Unless this is a DVD or "
349  "Blu-ray, something has probably gone wrong.");
350  hash = "";
351  }
352 
353  VideoMetadata newFile(sFileName, QString(), hash,
359  QString(), QString(), QString(), QString(),
360  QString(), VIDEO_YEAR_DEFAULT,
361  QDate::fromString("0000-00-00","YYYY-MM-DD"),
362  VIDEO_INETREF_DEFAULT, 0, QString(),
364  0.0, VIDEO_RATING_DEFAULT, 0, 0,
365  0, 0,
366  MythDate::current().date(), 0,
368 
369  newFile.SetHost(sHostName);
370  newFile.SaveToDatabase();
371 
372  return true;
373 }
374 
376 //
378 
380  bool bWatched )
381 {
384  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
385  mlm->setList(videolist);
386  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId);
387 
388  if ( !metadata )
389  return false;
390 
391  metadata->SetWatched(bWatched);
392  metadata->UpdateDatabase();
393 
394  return true;
395 }
396 
398 //
400 
401 DTC::BlurayInfo* Video::GetBluray( const QString &sPath )
402 {
403  QString path = sPath;
404 
405  if (sPath.isEmpty())
406  path = gCoreContext->GetSetting( "BluRayMountpoint", "/media/cdrom");
407 
408  LOG(VB_GENERAL, LOG_NOTICE,
409  QString("Parsing Blu-ray at path: %1 ").arg(path));
410 
411  auto *bdmeta = new BlurayMetadata(path);
412 
413  if ( !bdmeta )
414  throw( QString( "Unable to open Blu-ray Metadata Parser!" ));
415 
416  if ( !bdmeta->OpenDisc() )
417  throw( QString( "Unable to open Blu-ray Disc/Path!" ));
418 
419  if ( !bdmeta->ParseDisc() )
420  throw( QString( "Unable to parse metadata from Blu-ray Disc/Path!" ));
421 
422  auto *pBlurayInfo = new DTC::BlurayInfo();
423 
424  pBlurayInfo->setPath(path);
425  pBlurayInfo->setTitle(bdmeta->GetTitle());
426  pBlurayInfo->setAltTitle(bdmeta->GetAlternateTitle());
427  pBlurayInfo->setDiscLang(bdmeta->GetDiscLanguage());
428  pBlurayInfo->setDiscNum(bdmeta->GetCurrentDiscNumber());
429  pBlurayInfo->setTotalDiscNum(bdmeta->GetTotalDiscNumber());
430  pBlurayInfo->setTitleCount(bdmeta->GetTitleCount());
431  pBlurayInfo->setThumbCount(bdmeta->GetThumbnailCount());
432  pBlurayInfo->setTopMenuSupported(bdmeta->GetTopMenuSupported());
433  pBlurayInfo->setFirstPlaySupported(bdmeta->GetFirstPlaySupported());
434  pBlurayInfo->setNumHDMVTitles(bdmeta->GetNumHDMVTitles());
435  pBlurayInfo->setNumBDJTitles(bdmeta->GetNumBDJTitles());
436  pBlurayInfo->setNumUnsupportedTitles(bdmeta->GetNumUnsupportedTitles());
437  pBlurayInfo->setAACSDetected(bdmeta->GetAACSDetected());
438  pBlurayInfo->setLibAACSDetected(bdmeta->GetLibAACSDetected());
439  pBlurayInfo->setAACSHandled(bdmeta->GetAACSHandled());
440  pBlurayInfo->setBDPlusDetected(bdmeta->GetBDPlusDetected());
441  pBlurayInfo->setLibBDPlusDetected(bdmeta->GetLibBDPlusDetected());
442  pBlurayInfo->setBDPlusHandled(bdmeta->GetBDPlusHandled());
443 
444  QStringList thumbs = bdmeta->GetThumbnails();
445  if (!thumbs.empty())
446  pBlurayInfo->setThumbPath(thumbs.at(0));
447 
448  delete bdmeta;
449 
450  return pBlurayInfo;
451 }
452 
454 //
456 
458  const QString &sTitle,
459  const QString &sSubTitle,
460  const QString &sTagLine,
461  const QString &sDirector,
462  const QString &sStudio,
463  const QString &sPlot,
464  const QString &sRating,
465  const QString &sInetref,
466  int nCollectionRef,
467  const QString &sHomePage,
468  int nYear,
469  const QDate &sReleasedate,
470  float fUserRating,
471  int nLength,
472  int nPlayCount,
473  int nSeason,
474  int nEpisode,
475  int nShowLevel,
476  const QString &sFileName,
477  const QString &sHash,
478  const QString &sCoverFile,
479  int nChildID,
480  bool bBrowse,
481  bool bWatched,
482  bool bProcessed,
483  const QString &sPlayCommand,
484  int nCategory,
485  const QString &sTrailer,
486  const QString &sHost,
487  const QString &sScreenshot,
488  const QString &sBanner,
489  const QString &sFanart,
490  const QDate &sInsertDate,
491  const QString &sContentType,
492  const QString &sGenres,
493  const QString &sCast,
494  const QString &sCountries)
495 {
496  bool update_required = false;
499  QScopedPointer<VideoMetadataListManager> mlm(new VideoMetadataListManager());
500  mlm->setList(videolist);
501  VideoMetadataListManager::VideoMetadataPtr metadata = mlm->byID(nId);
502 
503  if (!metadata)
504  {
505  LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Id=%1 not found")
506  .arg(nId));
507  return false;
508  }
509 
510  if (m_parsedParams.contains("title"))
511  {
512  metadata->SetTitle(sTitle);
513  update_required = true;
514  }
515 
516  if (m_parsedParams.contains("subtitle"))
517  {
518  metadata->SetSubtitle(sSubTitle);
519  update_required = true;
520  }
521 
522  if (m_parsedParams.contains("tagline"))
523  {
524  metadata->SetTagline(sTagLine);
525  update_required = true;
526  }
527 
528  if (m_parsedParams.contains("director"))
529  {
530  metadata->SetDirector(sDirector);
531  update_required = true;
532  }
533 
534  if (m_parsedParams.contains("studio"))
535  {
536  metadata->SetStudio(sStudio);
537  update_required = true;
538  }
539 
540  if (m_parsedParams.contains("plot"))
541  {
542  metadata->SetPlot(sPlot);
543  update_required = true;
544  }
545 
546  if (m_parsedParams.contains("userrating"))
547  {
548  metadata->SetUserRating(fUserRating);
549  update_required = true;
550  }
551 
552  if (m_parsedParams.contains("inetref"))
553  {
554  metadata->SetInetRef(sInetref);
555  update_required = true;
556  }
557 
558  if (m_parsedParams.contains("collectionref"))
559  {
560  metadata->SetCollectionRef(nCollectionRef);
561  update_required = true;
562  }
563 
564  if (m_parsedParams.contains("homepage"))
565  {
566  metadata->SetHomepage(sHomePage);
567  update_required = true;
568  }
569 
570  if (m_parsedParams.contains("year"))
571  {
572  metadata->SetYear(nYear);
573  update_required = true;
574  }
575 
576  if (m_parsedParams.contains("releasedate"))
577  {
578  metadata->SetReleaseDate(sReleasedate);
579  update_required = true;
580  }
581 
582  if (m_parsedParams.contains("rating"))
583  {
584  metadata->SetRating(sRating);
585  update_required = true;
586  }
587 
588  if (m_parsedParams.contains("length"))
589  {
590  metadata->SetLength(std::chrono::minutes(nLength));
591  update_required = true;
592  }
593 
594  if (m_parsedParams.contains("playcount"))
595  {
596  metadata->SetPlayCount(nPlayCount);
597  update_required = true;
598  }
599 
600  if (m_parsedParams.contains("season"))
601  {
602  metadata->SetSeason(nSeason);
603  update_required = true;
604  }
605 
606  if (m_parsedParams.contains("episode"))
607  {
608  metadata->SetEpisode(nEpisode);
609  update_required = true;
610  }
611 
612  if (m_parsedParams.contains("showlevel"))
613  {
614  metadata->SetShowLevel(ParentalLevel::Level(nShowLevel));
615  update_required = true;
616  }
617 
618  if (m_parsedParams.contains("filename"))
619  {
620  metadata->SetFilename(sFileName);
621  update_required = true;
622  }
623 
624  if (m_parsedParams.contains("hash"))
625  {
626  metadata->SetHash(sHash);
627  update_required = true;
628  }
629 
630  if (m_parsedParams.contains("coverfile"))
631  {
632  metadata->SetCoverFile(sCoverFile);
633  update_required = true;
634  }
635 
636  if (m_parsedParams.contains("childid"))
637  {
638  metadata->SetChildID(nChildID);
639  update_required = true;
640  }
641 
642  if (m_parsedParams.contains("browse"))
643  {
644  metadata->SetBrowse(bBrowse);
645  update_required = true;
646  }
647 
648  if (m_parsedParams.contains("watched"))
649  {
650  metadata->SetWatched(bWatched);
651  update_required = true;
652  }
653 
654  if (m_parsedParams.contains("processed"))
655  {
656  metadata->SetProcessed(bProcessed);
657  update_required = true;
658  }
659 
660  if (m_parsedParams.contains("playcommand"))
661  {
662  metadata->SetPlayCommand(sPlayCommand);
663  update_required = true;
664  }
665 
666  if (m_parsedParams.contains("category"))
667  {
668  metadata->SetCategoryID(nCategory);
669  update_required = true;
670  }
671 
672  if (m_parsedParams.contains("trailer"))
673  {
674  metadata->SetTrailer(sTrailer);
675  update_required = true;
676  }
677 
678  if (m_parsedParams.contains("host"))
679  {
680  metadata->SetHost(sHost);
681  update_required = true;
682  }
683 
684  if (m_parsedParams.contains("screenshot"))
685  {
686  metadata->SetScreenshot(sScreenshot);
687  update_required = true;
688  }
689 
690  if (m_parsedParams.contains("banner"))
691  {
692  metadata->SetBanner(sBanner);
693  update_required = true;
694  }
695 
696  if (m_parsedParams.contains("fanart"))
697  {
698  metadata->SetFanart(sFanart);
699  update_required = true;
700  }
701 
702  if (m_parsedParams.contains("insertdate"))
703  {
704  metadata->SetInsertdate(sInsertDate);
705  update_required = true;
706  }
707 
708  if (m_parsedParams.contains("contenttype"))
709  {
710  // valid values for ContentType are 'MOVIE','TELEVISION','ADULT','MUSICVIDEO','HOMEVIDEO'
711  VideoContentType contentType = kContentUnknown;
712  if (sContentType == "MOVIE")
713  contentType = kContentMovie;
714 
715  if (sContentType == "TELEVISION")
716  contentType = kContentTelevision;
717 
718  if (sContentType == "ADULT")
719  contentType = kContentAdult;
720 
721  if (sContentType == "MUSICVIDEO")
722  contentType = kContentMusicVideo;
723 
724  if (sContentType == "HOMEVIDEO")
725  contentType = kContentHomeMovie;
726 
727  if (contentType != kContentUnknown)
728  {
729  metadata->SetContentType(contentType);
730  update_required = true;
731  }
732  else
733  LOG(VB_GENERAL, LOG_ERR, QString("UpdateVideoMetadata: Ignoring unknown ContentType: %1").arg(sContentType));
734  }
735 
736  if (m_parsedParams.contains("genres"))
737  {
739 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
740  QStringList genresList = sGenres.split(',', QString::SkipEmptyParts);
741 #else
742  QStringList genresList = sGenres.split(',', Qt::SkipEmptyParts);
743 #endif
744 
745  std::transform(genresList.cbegin(), genresList.cend(), std::back_inserter(genres),
746  [](const QString& name)
747  {return VideoMetadata::genre_list::value_type(-1, name.simplified());} );
748 
749  metadata->SetGenres(genres);
750  update_required = true;
751  }
752 
753  if (m_parsedParams.contains("cast"))
754  {
756 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
757  QStringList castList = sCast.split(',', QString::SkipEmptyParts);
758 #else
759  QStringList castList = sCast.split(',', Qt::SkipEmptyParts);
760 #endif
761 
762  std::transform(castList.cbegin(), castList.cend(), std::back_inserter(cast),
763  [](const QString& name)
764  {return VideoMetadata::cast_list::value_type(-1, name.simplified());} );
765 
766  metadata->SetCast(cast);
767  update_required = true;
768  }
769 
770  if (m_parsedParams.contains("countries"))
771  {
772  VideoMetadata::country_list countries;
773 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
774  QStringList countryList = sCountries.split(',', QString::SkipEmptyParts);
775 #else
776  QStringList countryList = sCountries.split(',', Qt::SkipEmptyParts);
777 #endif
778 
779  std::transform(countryList.cbegin(), countryList.cend(), std::back_inserter(countries),
780  [](const QString& name)
781  {return VideoMetadata::country_list::value_type(-1, name.simplified());} );
782 
783  metadata->SetCountries(countries);
784  update_required = true;
785  }
786 
787  if (update_required)
788  metadata->UpdateDatabase();
789 
790  return true;
791 }
792 
794 // Jun 3, 2020
795 // Service to get stream info for all streams in a media file.
796 // This gets some basic info. If anything more is needed it can be added,
797 // depending on whether it is available from ffmpeg avformat apis.
798 // See the MythStreamInfoList class for the code that uses avformat to
799 // extract the information.
801 
803  ( const QString &storageGroup,
804  const QString &FileName )
805 {
806 
807  // Search for the filename
808 
809  StorageGroup storage( storageGroup );
810  QString sFullFileName = storage.FindFile( FileName );
811  MythStreamInfoList infos(sFullFileName);
812 
813  // The constructor of this class reads the file and gets the needed
814  // information.
815  auto *pVideoStreamInfos = new DTC::VideoStreamInfoList();
816 
817  pVideoStreamInfos->setCount ( infos.m_streamInfoList.size() );
818  pVideoStreamInfos->setAsOf ( MythDate::current() );
819  pVideoStreamInfos->setVersion ( MYTH_BINARY_VERSION );
820  pVideoStreamInfos->setProtoVer ( MYTH_PROTO_VERSION );
821  pVideoStreamInfos->setErrorCode ( infos.m_errorCode );
822  pVideoStreamInfos->setErrorMsg ( infos.m_errorMsg );
823 
824  for (const auto & info : qAsConst(infos.m_streamInfoList))
825  {
826  DTC::VideoStreamInfo *pVideoStreamInfo = pVideoStreamInfos->AddNewVideoStreamInfo();
827  pVideoStreamInfo->setCodecType ( QString(QChar(info.m_codecType)) );
828  pVideoStreamInfo->setCodecName ( info.m_codecName );
829  pVideoStreamInfo->setWidth ( info.m_width );
830  pVideoStreamInfo->setHeight ( info.m_height );
831  pVideoStreamInfo->setAspectRatio ( info.m_SampleAspectRatio );
832  pVideoStreamInfo->setFieldOrder ( info.m_fieldOrder );
833  pVideoStreamInfo->setFrameRate ( info.m_frameRate );
834  pVideoStreamInfo->setAvgFrameRate ( info.m_avgFrameRate );
835  pVideoStreamInfo->setChannels ( info.m_channels );
836  pVideoStreamInfo->setDuration ( info.m_duration );
837 
838  }
839  return pVideoStreamInfos;
840 }
841 
843 // Get bookmark of a video as a frame number.
845 
847 {
848  MSqlQuery query(MSqlQuery::InitCon());
849 
850  query.prepare("SELECT filename "
851  "FROM videometadata "
852  "WHERE intid = :ID ");
853  query.bindValue(":ID", Id);
854 
855  if (!query.exec())
856  {
857  MythDB::DBError("Video::GetSavedBookmark", query);
858  return 0;
859  }
860 
861  QString fileName;
862 
863  if (query.next())
864  fileName = query.value(0).toString();
865  else
866  {
867  LOG(VB_GENERAL, LOG_ERR, QString("Video/GetSavedBookmark Video id %1 Not found.").arg(Id));
868  return -1;
869  }
870 
871  ProgramInfo pi(fileName,
872  nullptr, // _plot,
873  nullptr, // _title,
874  nullptr, // const QString &_sortTitle,
875  nullptr, // const QString &_subtitle,
876  nullptr, // const QString &_sortSubtitle,
877  nullptr, // const QString &_director,
878  0, // int _season,
879  0, // int _episode,
880  nullptr, // const QString &_inetref,
881  0min, // uint _length_in_minutes,
882  0, // uint _year,
883  nullptr); //const QString &_programid);
884 
885  long ret = pi.QueryBookmark();
886  return ret;
887 }
888 
890 // Set bookmark of a video as a frame number.
892 
893 bool Video::SetSavedBookmark( int Id, long Offset )
894 {
895  MSqlQuery query(MSqlQuery::InitCon());
896 
897  query.prepare("SELECT filename "
898  "FROM videometadata "
899  "WHERE intid = :ID ");
900  query.bindValue(":ID", Id);
901 
902  if (!query.exec())
903  {
904  MythDB::DBError("Video::SetSavedBookmark", query);
905  return false;
906  }
907 
908  QString fileName;
909 
910  if (query.next())
911  fileName = query.value(0).toString();
912  else
913  {
914  LOG(VB_GENERAL, LOG_ERR, QString("Video/SetSavedBookmark Video id %1 Not found.").arg(Id));
915  return false;
916  }
917 
918  ProgramInfo pi(fileName,
919  nullptr, // _plot,
920  nullptr, // _title,
921  nullptr, // const QString &_sortTitle,
922  nullptr, // const QString &_subtitle,
923  nullptr, // const QString &_sortSubtitle,
924  nullptr, // const QString &_director,
925  0, // int _season,
926  0, // int _episode,
927  nullptr, // const QString &_inetref,
928  0min, // uint _length_in_minutes,
929  0, // uint _year,
930  nullptr); //const QString &_programid);
931 
932  pi.SaveBookmark(Offset);
933  return true;
934 }
935 
937 //
serviceUtil.h
MythStreamInfoList::m_errorMsg
QString m_errorMsg
Definition: mythavutil.h:107
BlurayMetadata
Definition: bluraymetadata.h:25
DTC::VideoLookup::AddNewArtwork
ArtworkItem * AddNewArtwork()
Definition: videoLookupInfo.h:165
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:807
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
VideoMetadata
Definition: videometadata.h:24
GrabberType
GrabberType
Definition: metadatagrabber.h:20
FillVideoMetadataInfo
void FillVideoMetadataInfo(DTC::VideoMetadataInfo *pVideoMetadataInfo, const VideoMetadataListManager::VideoMetadataPtr &pMetadata, bool bDetails)
Definition: serviceUtil.cpp:412
MetadataLookup::GetTMSref
QString GetTMSref() const
Definition: metadatacommon.h:359
Video::GetVideoList
DTC::VideoMetadataInfoList * GetVideoList(const QString &Folder, const QString &Sort, bool Descending, int StartIndex, int Count) override
Definition: video.cpp:56
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
ParentalLevel::plLowest
@ plLowest
Definition: parentalcontrols.h:12
videometadata.h
DTC::VideoLookup
Definition: videoLookupInfo.h:68
DTC::VideoStreamInfo
Definition: videoStreamInfo.h:25
MetadataLookup::GetTitle
QString GetTitle() const
Definition: metadatacommon.h:299
VideoMetadataListManager
Definition: videometadatalistmanager.h:10
simple_ref_ptr
Definition: quicksp.h:24
ArtworkList
QList< ArtworkInfo > ArtworkList
Definition: metadataimagehelper.h:30
StorageGroup::FindFile
QString FindFile(const QString &filename)
Definition: storagegroup.cpp:602
MetadataLookup::GetLanguage
QString GetLanguage() const
Definition: metadatacommon.h:304
Video::GetStreamInfo
DTC::VideoStreamInfoList * GetStreamInfo(const QString &StorageGroup, const QString &FileName) override
Definition: video.cpp:803
video.h
MythStreamInfoList
Definition: mythavutil.h:103
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:205
VideoMetadata::country_list
std::vector< country_entry > country_list
Definition: videometadata.h:33
DTC::VideoLookupList
Definition: videoLookupInfoList.h:24
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:608
MetadataLookup::GetArtwork
ArtworkList GetArtwork(VideoArtworkType type) const
Definition: metadatacommon.cpp:330
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
VideoMetadata::genre_list
std::vector< genre_entry > genre_list
Definition: videometadata.h:32
MetadataLookup::GetCertification
QString GetCertification() const
Definition: metadatacommon.h:335
MetadataLookup::GetBudget
uint GetBudget() const
Definition: metadatacommon.h:338
DTC::VideoStreamInfoList
Definition: videoStreamInfoList.h:24
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
mythversion.h
MetadataLookup
Definition: metadatacommon.h:87
ProgramInfo::QueryBookmark
uint64_t QueryBookmark(void) const
Gets any bookmark position in database, unless the ignore bookmark flag is set.
Definition: programinfo.cpp:2804
MythStreamInfoList::m_errorCode
int m_errorCode
Definition: mythavutil.h:106
mythdate.h
DTC::BlurayInfo
Definition: blurayInfo.h:24
MetadataLookup::GetEpisode
uint GetEpisode() const
Definition: metadatacommon.h:315
MetadataLookup::GetDescription
QString GetDescription() const
Definition: metadatacommon.h:312
MetadataLookup::GetIMDB
QString GetIMDB() const
Definition: metadatacommon.h:358
Video::LookupVideo
DTC::VideoLookupList * LookupVideo(const QString &Title, const QString &Subtitle, const QString &Inetref, int Season, int Episode, const QString &GrabberType, bool AllowGeneric) override
Definition: video.cpp:184
remotefile.h
ParentalLevel::Level
Level
Definition: parentalcontrols.h:12
globals.h
Video::GetVideo
DTC::VideoMetadataInfo * GetVideo(int Id) override
Definition: video.cpp:143
RefCountedList< MetadataLookup >
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:540
compat.h
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:227
VideoMetadata::SaveToDatabase
void SaveToDatabase()
Definition: videometadata.cpp:1952
VIDEO_COVERFILE_DEFAULT
const QString VIDEO_COVERFILE_DEFAULT
Definition: globals.cpp:25
VIDEO_PLOT_DEFAULT
const QString VIDEO_PLOT_DEFAULT
Definition: globals.cpp:32
kArtworkFanart
@ kArtworkFanart
Definition: metadataimagehelper.h:12
MetadataLookup::GetSubtitle
QString GetSubtitle() const
Definition: metadatacommon.h:310
kContentTelevision
@ kContentTelevision
Definition: metadatacommon.h:62
Video::GetVideoByFileName
DTC::VideoMetadataInfo * GetVideoByFileName(const QString &FileName) override
Definition: video.cpp:162
DTC::ArtworkItem
Definition: videoLookupInfo.h:25
MetadataLookup::GetCountries
QStringList GetCountries() const
Definition: metadatacommon.h:336
Service::m_parsedParams
QList< QString > m_parsedParams
Definition: service.h:67
storagegroup.h
MetadataLookup::GetYear
uint GetYear() const
Definition: metadatacommon.h:349
MetadataLookup::GetCollectionref
QString GetCollectionref() const
Definition: metadatacommon.h:357
VIDEO_TRAILER_DEFAULT
const QString VIDEO_TRAILER_DEFAULT
Definition: globals.cpp:26
MetadataLookup::GetUserRating
float GetUserRating() const
Definition: metadatacommon.h:302
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:59
Video::GetSavedBookmark
long GetSavedBookmark(int Id) override
Definition: video.cpp:846
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
Video::UpdateVideoWatchedStatus
bool UpdateVideoWatchedStatus(int Id, bool Watched) override
Definition: video.cpp:379
MetadataLookup::GetSeason
uint GetSeason() const
Definition: metadatacommon.h:314
Video::RemoveVideoFromDB
bool RemoveVideoFromDB(int Id) override
Definition: video.cpp:303
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
Video::AddVideo
bool AddVideo(const QString &FileName, const QString &HostName) override
Definition: video.cpp:323
MetadataLookup::GetPopularity
float GetPopularity() const
Definition: metadatacommon.h:337
MYTH_BINARY_VERSION
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
MYTH_PROTO_VERSION
#define MYTH_PROTO_VERSION
Increment this whenever the MythTV network protocol changes.
Definition: mythversion.h:47
MetadataLookup::GetRuntime
std::chrono::minutes GetRuntime() const
Definition: metadatacommon.h:352
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
VideoContentType
VideoContentType
Definition: metadatacommon.h:60
mythmiscutil.h
mythcorecontext.h
MetadataLookup::GetTagline
QString GetTagline() const
Definition: metadatacommon.h:311
VideoMetadata::cast_list
std::vector< cast_entry > cast_list
Definition: videometadata.h:34
VideoMetadata::SetHost
void SetHost(const QString &host)
Definition: videometadata.cpp:1842
MetadataLookup::GetRevenue
uint GetRevenue() const
Definition: metadatacommon.h:339
MetadataLookup::GetInetref
QString GetInetref() const
Definition: metadatacommon.h:356
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:883
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
Video::SetSavedBookmark
bool SetSavedBookmark(int Id, long Offset) override
Definition: video.cpp:893
mythavutil.h
DTC::VideoMetadataInfo
Definition: videoMetadataInfo.h:29
metadatafactory.h
StorageGroup
Definition: storagegroup.h:11
kContentAdult
@ kContentAdult
Definition: metadatacommon.h:63
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
Video::GetBluray
DTC::BlurayInfo * GetBluray(const QString &Path) override
Definition: video.cpp:401
VideoMetadataListManager::metadata_list
std::list< VideoMetadataPtr > metadata_list
Definition: videometadatalistmanager.h:14
MetadataLookup::GetReleaseDate
QDate GetReleaseDate() const
Definition: metadatacommon.h:350
kContentUnknown
@ kContentUnknown
Definition: metadatacommon.h:66
VIDEO_BANNER_DEFAULT
const QString VIDEO_BANNER_DEFAULT
Definition: globals.cpp:28
DTC::VideoMetadataInfoList
Definition: videoMetadataInfoList.h:24
kArtworkScreenshot
@ kArtworkScreenshot
Definition: metadataimagehelper.h:14
MetadataLookup::GetHomepage
QString GetHomepage() const
Definition: metadatacommon.h:367
kContentHomeMovie
@ kContentHomeMovie
Definition: metadatacommon.h:65
FileHash
QString FileHash(const QString &filename)
Definition: mythmiscutil.cpp:553
kArtworkCoverart
@ kArtworkCoverart
Definition: metadataimagehelper.h:11
VIDEO_DIRECTOR_DEFAULT
const QString VIDEO_DIRECTOR_DEFAULT
Definition: globals.cpp:23
VIDEO_SCREENSHOT_DEFAULT
const QString VIDEO_SCREENSHOT_DEFAULT
Definition: globals.cpp:27
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:832
Video::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, const 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, const QDate &InsertDate, const QString &ContentType, const QString &Genres, const QString &Cast, const QString &Countries) override
Definition: video.cpp:457
MythStreamInfoList::m_streamInfoList
QVector< MythStreamInfo > m_streamInfoList
Definition: mythavutil.h:108