1 /*
2  *  Copyright (C) 2012-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "guilib/guiinfo/VideoGUIInfo.h"
10 
11 #include "Application.h"
12 #include "FileItem.h"
13 #include "PlayListPlayer.h"
14 #include "ServiceBroker.h"
15 #include "URL.h"
16 #include "cores/DataCacheCore.h"
17 #include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h"
18 #include "guilib/GUIComponent.h"
19 #include "guilib/GUIWindowManager.h"
20 #include "guilib/LocalizeStrings.h"
21 #include "guilib/StereoscopicsManager.h"
22 #include "guilib/WindowIDs.h"
23 #include "guilib/guiinfo/GUIInfo.h"
24 #include "guilib/guiinfo/GUIInfoHelper.h"
25 #include "guilib/guiinfo/GUIInfoLabels.h"
26 #include "playlists/PlayList.h"
27 #include "settings/AdvancedSettings.h"
28 #include "settings/SettingUtils.h"
29 #include "settings/Settings.h"
30 #include "settings/SettingsComponent.h"
31 #include "settings/lib/Setting.h"
32 #include "utils/StringUtils.h"
33 #include "utils/URIUtils.h"
34 #include "utils/log.h"
35 #include "video/VideoInfoTag.h"
36 #include "video/VideoThumbLoader.h"
37 
38 #include <math.h>
39 
40 using namespace KODI::GUILIB;
41 using namespace KODI::GUILIB::GUIINFO;
42 
GetPercentPlayed(const CVideoInfoTag * tag) const43 int CVideoGUIInfo::GetPercentPlayed(const CVideoInfoTag* tag) const
44 {
45   CBookmark bookmark = tag->GetResumePoint();
46   if (bookmark.IsPartWay())
47     return std::lrintf(static_cast<float>(bookmark.timeInSeconds) / bookmark.totalTimeInSeconds * 100.0f);
48   else
49     return 0;
50 }
51 
InitCurrentItem(CFileItem * item)52 bool CVideoGUIInfo::InitCurrentItem(CFileItem *item)
53 {
54   if (item && item->IsVideo())
55   {
56     // special case where .strm is used to start an audio stream
57     if (item->IsInternetStream() && g_application.GetAppPlayer().IsPlayingAudio())
58       return false;
59 
60     CLog::Log(LOGDEBUG,"CVideoGUIInfo::InitCurrentItem(%s)", CURL::GetRedacted(item->GetPath()).c_str());
61 
62     // Find a thumb for this file.
63     if (!item->HasArt("thumb"))
64     {
65       CVideoThumbLoader loader;
66       loader.LoadItem(item);
67     }
68 
69     // find a thumb for this stream
70     if (item->IsInternetStream())
71     {
72       if (!g_application.m_strPlayListFile.empty())
73       {
74         CLog::Log(LOGDEBUG,"Streaming media detected... using %s to find a thumb", g_application.m_strPlayListFile.c_str());
75         CFileItem thumbItem(g_application.m_strPlayListFile,false);
76 
77         CVideoThumbLoader loader;
78         if (loader.FillThumb(thumbItem))
79           item->SetArt("thumb", thumbItem.GetArt("thumb"));
80       }
81     }
82     return true;
83   }
84   return false;
85 }
86 
GetLabel(std::string & value,const CFileItem * item,int contextWindow,const CGUIInfo & info,std::string * fallback) const87 bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const
88 {
89   // For videoplayer "offset" and "position" info labels check playlist
90   if (info.GetData1() && ((info.m_info >= VIDEOPLAYER_OFFSET_POSITION_FIRST &&
91       info.m_info <= VIDEOPLAYER_OFFSET_POSITION_LAST) ||
92       (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST)))
93     return GetPlaylistInfo(value, info);
94 
95   const CVideoInfoTag* tag = item->GetVideoInfoTag();
96   if (tag)
97   {
98     switch (info.m_info)
99     {
100       /////////////////////////////////////////////////////////////////////////////////////////////
101       // PLAYER_* / VIDEOPLAYER_* / LISTITEM_*
102       /////////////////////////////////////////////////////////////////////////////////////////////
103       case PLAYER_PATH:
104       case PLAYER_FILENAME:
105       case PLAYER_FILEPATH:
106         if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag
107           break;
108 
109         value = tag->m_strFileNameAndPath;
110         if (value.empty())
111           value = item->GetPath();
112         value = GUIINFO::GetFileInfoLabelValueFromPath(info.m_info, value);
113         return true;
114       case PLAYER_TITLE:
115         value = tag->m_strTitle;
116         return !value.empty();
117       case VIDEOPLAYER_TITLE:
118         value = tag->m_strTitle;
119         return !value.empty();
120       case LISTITEM_TITLE:
121         value = tag->m_strTitle;
122         return true;
123       case VIDEOPLAYER_ORIGINALTITLE:
124       case LISTITEM_ORIGINALTITLE:
125         value = tag->m_strOriginalTitle;
126         return true;
127       case VIDEOPLAYER_GENRE:
128       case LISTITEM_GENRE:
129         value = StringUtils::Join(tag->m_genre, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
130         return true;
131       case VIDEOPLAYER_DIRECTOR:
132       case LISTITEM_DIRECTOR:
133         value = StringUtils::Join(tag->m_director, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
134         return true;
135       case VIDEOPLAYER_IMDBNUMBER:
136       case LISTITEM_IMDBNUMBER:
137         value = tag->GetUniqueID();
138         return true;
139       case VIDEOPLAYER_DBID:
140       case LISTITEM_DBID:
141         if (tag->m_iDbId > -1)
142         {
143           value = StringUtils::Format("%i", tag->m_iDbId);
144           return true;
145         }
146         break;
147       case VIDEOPLAYER_TVSHOWDBID:
148       case LISTITEM_TVSHOWDBID:
149         if (tag->m_iIdShow > -1)
150         {
151           value = StringUtils::Format("%i", tag->m_iIdShow);
152           return true;
153         }
154         break;
155       case VIDEOPLAYER_UNIQUEID:
156       case LISTITEM_UNIQUEID:
157         if (!info.GetData3().empty())
158           value = tag->GetUniqueID(info.GetData3());
159         return true;
160       case VIDEOPLAYER_RATING:
161       case LISTITEM_RATING:
162       {
163         float rating = tag->GetRating(info.GetData3()).rating;
164         if (rating > 0.f)
165         {
166           value = StringUtils::FormatNumber(rating);
167           return true;
168         }
169         break;
170       }
171       case VIDEOPLAYER_RATING_AND_VOTES:
172       case LISTITEM_RATING_AND_VOTES:
173       {
174         CRating rating = tag->GetRating(info.GetData3());
175         if (rating.rating >= 0.f)
176         {
177           if (rating.rating > 0.f && rating.votes == 0)
178             value = StringUtils::FormatNumber(rating.rating);
179           else if (rating.votes > 0)
180             value = StringUtils::Format(g_localizeStrings.Get(20350).c_str(),
181                                         StringUtils::FormatNumber(rating.rating).c_str(),
182                                         StringUtils::FormatNumber(rating.votes).c_str());
183           else
184             break;
185           return true;
186         }
187         break;
188       }
189       case VIDEOPLAYER_USER_RATING:
190       case LISTITEM_USER_RATING:
191         if (tag->m_iUserRating > 0)
192         {
193           value = StringUtils::Format("%i", tag->m_iUserRating);
194           return true;
195         }
196         break;
197       case VIDEOPLAYER_VOTES:
198       case LISTITEM_VOTES:
199         value = StringUtils::FormatNumber(tag->GetRating(info.GetData3()).votes);
200         return true;
201       case VIDEOPLAYER_YEAR:
202       case LISTITEM_YEAR:
203         if (tag->HasYear())
204         {
205           value = StringUtils::Format("%i", tag->GetYear());
206           return true;
207         }
208         break;
209       case VIDEOPLAYER_PREMIERED:
210       case LISTITEM_PREMIERED:
211       {
212         CDateTime dateTime;
213         if (tag->m_firstAired.IsValid())
214           dateTime = tag->m_firstAired;
215         else if (tag->HasPremiered())
216           dateTime = tag->GetPremiered();
217 
218         if (dateTime.IsValid())
219         {
220           value = dateTime.GetAsLocalizedDate();
221           return true;
222         }
223         break;
224       }
225       case VIDEOPLAYER_PLOT:
226         value = tag->m_strPlot;
227         return true;
228       case VIDEOPLAYER_TRAILER:
229       case LISTITEM_TRAILER:
230         value = tag->m_strTrailer;
231         return true;
232       case VIDEOPLAYER_PLOT_OUTLINE:
233       case LISTITEM_PLOT_OUTLINE:
234         value = tag->m_strPlotOutline;
235         return true;
236       case VIDEOPLAYER_EPISODE:
237       case LISTITEM_EPISODE:
238       {
239         int iEpisode = -1;
240         if (tag->m_iEpisode > 0)
241         {
242           iEpisode = tag->m_iEpisode;
243         }
244 
245         if (iEpisode >= 0)
246         {
247           value = StringUtils::Format("%d", iEpisode);
248           return true;
249         }
250         break;
251       }
252       case VIDEOPLAYER_SEASON:
253       case LISTITEM_SEASON:
254         if (tag->m_iSeason >= 0)
255         {
256           value = StringUtils::Format("%d", tag->m_iSeason);
257           return true;
258         }
259         break;
260       case VIDEOPLAYER_TVSHOW:
261       case LISTITEM_TVSHOW:
262         value = tag->m_strShowTitle;
263         return true;
264       case VIDEOPLAYER_STUDIO:
265       case LISTITEM_STUDIO:
266         value = StringUtils::Join(tag->m_studio, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
267         return true;
268       case VIDEOPLAYER_COUNTRY:
269       case LISTITEM_COUNTRY:
270         value = StringUtils::Join(tag->m_country, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
271         return true;
272       case VIDEOPLAYER_MPAA:
273       case LISTITEM_MPAA:
274         value = tag->m_strMPAARating;
275         return true;
276       case VIDEOPLAYER_TOP250:
277       case LISTITEM_TOP250:
278         if (tag->m_iTop250 > 0)
279         {
280           value = StringUtils::Format("%i", tag->m_iTop250);
281           return true;
282         }
283         break;
284       case VIDEOPLAYER_CAST:
285       case LISTITEM_CAST:
286         value = tag->GetCast();
287         return true;
288       case VIDEOPLAYER_CAST_AND_ROLE:
289       case LISTITEM_CAST_AND_ROLE:
290         value = tag->GetCast(true);
291         return true;
292       case VIDEOPLAYER_ARTIST:
293       case LISTITEM_ARTIST:
294         value = StringUtils::Join(tag->m_artist, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
295         return true;
296       case VIDEOPLAYER_ALBUM:
297       case LISTITEM_ALBUM:
298         value = tag->m_strAlbum;
299         return true;
300       case VIDEOPLAYER_WRITER:
301       case LISTITEM_WRITER:
302         value = StringUtils::Join(tag->m_writingCredits, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
303         return true;
304       case VIDEOPLAYER_TAGLINE:
305       case LISTITEM_TAGLINE:
306         value = tag->m_strTagLine;
307         return true;
308       case VIDEOPLAYER_LASTPLAYED:
309       case LISTITEM_LASTPLAYED:
310       {
311         const CDateTime dateTime = tag->m_lastPlayed;
312         if (dateTime.IsValid())
313         {
314           value = dateTime.GetAsLocalizedDate();
315           return true;
316         }
317         break;
318       }
319       case VIDEOPLAYER_PLAYCOUNT:
320       case LISTITEM_PLAYCOUNT:
321         if (tag->GetPlayCount() > 0)
322         {
323           value = StringUtils::Format("%i", tag->GetPlayCount());
324           return true;
325         }
326         break;
327 
328       /////////////////////////////////////////////////////////////////////////////////////////////
329       // LISTITEM_*
330       /////////////////////////////////////////////////////////////////////////////////////////////
331       case LISTITEM_DURATION:
332       {
333         int iDuration = tag->GetDuration();
334         if (iDuration > 0)
335         {
336           value = StringUtils::SecondsToTimeString(iDuration, static_cast<TIME_FORMAT>(info.GetData4()));
337           return true;
338         }
339         break;
340       }
341       case LISTITEM_TRACKNUMBER:
342         if (tag->m_iTrack > -1 )
343         {
344           value = StringUtils::Format("%i", tag->m_iTrack);
345           return true;
346         }
347         break;
348       case LISTITEM_PLOT:
349         {
350           std::shared_ptr<CSettingList> setting(std::dynamic_pointer_cast<CSettingList>(
351             CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(CSettings::SETTING_VIDEOLIBRARY_SHOWUNWATCHEDPLOTS)));
352           if (tag->m_type != MediaTypeTvShow && tag->m_type != MediaTypeVideoCollection &&
353               tag->GetPlayCount() == 0 && setting &&
354               ((tag->m_type == MediaTypeMovie &&
355                 !CSettingUtils::FindIntInList(
356                     setting, CSettings::VIDEOLIBRARY_PLOTS_SHOW_UNWATCHED_MOVIES)) ||
357                (tag->m_type == MediaTypeEpisode &&
358                 !CSettingUtils::FindIntInList(
359                     setting, CSettings::VIDEOLIBRARY_PLOTS_SHOW_UNWATCHED_TVSHOWEPISODES))))
360           {
361             value = g_localizeStrings.Get(20370);
362           }
363           else
364           {
365             value = tag->m_strPlot;
366           }
367           return true;
368         }
369       case LISTITEM_STATUS:
370         value = tag->m_strStatus;
371         return true;
372       case LISTITEM_TAG:
373         value = StringUtils::Join(tag->m_tags, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
374         return true;
375       case LISTITEM_SET:
376         value = tag->m_set.title;
377         return true;
378       case LISTITEM_SETID:
379         if (tag->m_set.id > 0)
380         {
381           value = StringUtils::Format("%d", tag->m_set.id);
382           return true;
383         }
384         break;
385       case LISTITEM_ENDTIME_RESUME:
386       {
387         const CDateTimeSpan duration(0, 0, 0, tag->GetDuration() - tag->GetResumePoint().timeInSeconds);
388         value = (CDateTime::GetCurrentDateTime() + duration).GetAsLocalizedTime("", false);
389         return true;
390       }
391       case LISTITEM_ENDTIME:
392       {
393         const CDateTimeSpan duration(0, 0, 0, tag->GetDuration());
394         value = (CDateTime::GetCurrentDateTime() + duration).GetAsLocalizedTime("", false);
395         return true;
396       }
397       case LISTITEM_DATE_ADDED:
398         if (tag->m_dateAdded.IsValid())
399         {
400           value = tag->m_dateAdded.GetAsLocalizedDate();
401           return true;
402         }
403         break;
404       case LISTITEM_DBTYPE:
405         value = tag->m_type;
406         return true;
407       case LISTITEM_APPEARANCES:
408         if (tag->m_relevance > -1)
409         {
410           value = StringUtils::Format("%i", tag->m_relevance);
411           return true;
412         }
413         break;
414       case LISTITEM_PERCENT_PLAYED:
415         value = StringUtils::Format("%d", GetPercentPlayed(tag));
416         return true;
417       case LISTITEM_VIDEO_CODEC:
418         value = tag->m_streamDetails.GetVideoCodec();
419         return true;
420       case LISTITEM_VIDEO_RESOLUTION:
421         value = CStreamDetails::VideoDimsToResolutionDescription(tag->m_streamDetails.GetVideoWidth(), tag->m_streamDetails.GetVideoHeight());
422         return true;
423       case LISTITEM_VIDEO_ASPECT:
424         value = CStreamDetails::VideoAspectToAspectDescription(tag->m_streamDetails.GetVideoAspect());
425         return true;
426       case LISTITEM_AUDIO_CODEC:
427         value = tag->m_streamDetails.GetAudioCodec();
428         return true;
429       case LISTITEM_AUDIO_CHANNELS:
430       {
431         int iChannels = tag->m_streamDetails.GetAudioChannels();
432         if (iChannels > 0)
433         {
434           value = StringUtils::Format("%i", iChannels);
435           return true;
436         }
437         break;
438       }
439       case LISTITEM_AUDIO_LANGUAGE:
440         value = tag->m_streamDetails.GetAudioLanguage();
441         return true;
442       case LISTITEM_SUBTITLE_LANGUAGE:
443         value = tag->m_streamDetails.GetSubtitleLanguage();
444         return true;
445       case LISTITEM_FILENAME:
446       case LISTITEM_FILE_EXTENSION:
447         if (item->IsVideoDb())
448           value = URIUtils::GetFileName(tag->m_strFileNameAndPath);
449         else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag
450           break;
451         else
452           value = URIUtils::GetFileName(item->GetPath());
453 
454         if (info.m_info == LISTITEM_FILE_EXTENSION)
455         {
456           std::string strExtension = URIUtils::GetExtension(value);
457           value = StringUtils::TrimLeft(strExtension, ".");
458         }
459         return true;
460       case LISTITEM_FOLDERNAME:
461       case LISTITEM_PATH:
462         if (item->IsVideoDb())
463         {
464           if (item->m_bIsFolder)
465             value = tag->m_strPath;
466           else
467             URIUtils::GetParentPath(tag->m_strFileNameAndPath, value);
468         }
469         else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag
470           break;
471         else
472           URIUtils::GetParentPath(item->GetPath(), value);
473 
474         value = CURL(value).GetWithoutUserDetails();
475 
476         if (info.m_info == LISTITEM_FOLDERNAME)
477         {
478           URIUtils::RemoveSlashAtEnd(value);
479           value = URIUtils::GetFileName(value);
480         }
481         return true;
482       case LISTITEM_FILENAME_AND_PATH:
483         if (item->IsVideoDb())
484           value = tag->m_strFileNameAndPath;
485         else if (item->HasMusicInfoTag()) // special handling for music videos, which have both a videotag and a musictag
486           break;
487         else
488           value = item->GetPath();
489 
490         value = CURL(value).GetWithoutUserDetails();
491         return true;
492     }
493   }
494 
495   switch (info.m_info)
496   {
497     ///////////////////////////////////////////////////////////////////////////////////////////////
498     // VIDEOPLAYER_*
499     ///////////////////////////////////////////////////////////////////////////////////////////////
500     case VIDEOPLAYER_PLAYLISTLEN:
501       if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST_VIDEO)
502       {
503         value = GUIINFO::GetPlaylistLabel(PLAYLIST_LENGTH);
504         return true;
505       }
506       break;
507     case VIDEOPLAYER_PLAYLISTPOS:
508       if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST_VIDEO)
509       {
510         value = GUIINFO::GetPlaylistLabel(PLAYLIST_POSITION);
511         return true;
512       }
513       break;
514     case VIDEOPLAYER_VIDEO_ASPECT:
515       value = CStreamDetails::VideoAspectToAspectDescription(CServiceBroker::GetDataCacheCore().GetVideoDAR());
516       return true;
517     case VIDEOPLAYER_STEREOSCOPIC_MODE:
518       value = CServiceBroker::GetDataCacheCore().GetVideoStereoMode();
519       return true;
520     case VIDEOPLAYER_SUBTITLES_LANG:
521       value = m_subtitleInfo.language;
522       return true;
523       break;
524     case VIDEOPLAYER_COVER:
525       if (g_application.GetAppPlayer().IsPlayingVideo())
526       {
527         if (fallback)
528           *fallback = "DefaultVideoCover.png";
529 
530         value = item->HasArt("thumb") ? item->GetArt("thumb") : "DefaultVideoCover.png";
531         return true;
532       }
533       break;
534 
535     ///////////////////////////////////////////////////////////////////////////////////////////////
536     // LISTITEM_*
537     ///////////////////////////////////////////////////////////////////////////////////////////////
538     case LISTITEM_STEREOSCOPIC_MODE:
539       value = item->GetProperty("stereomode").asString();
540       if (value.empty() && tag)
541         value = CStereoscopicsManager::NormalizeStereoMode(tag->m_streamDetails.GetStereoMode());
542       return true;
543 
544     ///////////////////////////////////////////////////////////////////////////////////////////////
545     // VIDEOPLAYER_*
546     ///////////////////////////////////////////////////////////////////////////////////////////////
547     case VIDEOPLAYER_VIDEO_CODEC:
548       value = m_videoInfo.codecName;
549       return true;
550     case VIDEOPLAYER_VIDEO_RESOLUTION:
551       value = CStreamDetails::VideoDimsToResolutionDescription(m_videoInfo.width, m_videoInfo.height);
552       return true;
553     case VIDEOPLAYER_AUDIO_CODEC:
554       value = m_audioInfo.codecName;
555       return true;
556     case VIDEOPLAYER_AUDIO_CHANNELS:
557     {
558       int iChannels = m_audioInfo.channels;
559       if (iChannels > 0)
560       {
561         value = StringUtils::Format("%i", iChannels);
562         return true;
563       }
564       break;
565     }
566     case VIDEOPLAYER_AUDIO_BITRATE:
567     {
568       int iBitrate = m_audioInfo.bitrate;
569       if (iBitrate > 0)
570       {
571         value = StringUtils::Format("%li", std::lrint(static_cast<double>(iBitrate) / 1000.0));
572         return true;
573       }
574       break;
575     }
576     case VIDEOPLAYER_VIDEO_BITRATE:
577     {
578       int iBitrate = m_videoInfo.bitrate;
579       if (iBitrate > 0)
580       {
581         value = StringUtils::Format("%li", std::lrint(static_cast<double>(iBitrate) / 1000.0));
582         return true;
583       }
584       break;
585     }
586     case VIDEOPLAYER_AUDIO_LANG:
587       value = m_audioInfo.language;
588       return true;
589   }
590 
591   return false;
592 }
593 
GetPlaylistInfo(std::string & value,const CGUIInfo & info) const594 bool CVideoGUIInfo::GetPlaylistInfo(std::string& value, const CGUIInfo& info) const
595 {
596   PLAYLIST::CPlayList& playlist = CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST_VIDEO);
597   if (playlist.size() < 1)
598     return false;
599 
600   int index = info.GetData2();
601   if (info.GetData1() == 1)
602   { // relative index (requires current playlist is PLAYLIST_VIDEO)
603     if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != PLAYLIST_VIDEO)
604       return false;
605 
606     index = CServiceBroker::GetPlaylistPlayer().GetNextSong(index);
607   }
608 
609   if (index < 0 || index >= playlist.size())
610     return false;
611 
612   const CFileItemPtr playlistItem = playlist[index];
613   // try to set a thumbnail
614   if (!playlistItem->HasArt("thumb"))
615   {
616     CVideoThumbLoader loader;
617     loader.LoadItem(playlistItem.get());
618     // still no thumb? then just the set the default cover
619     if (!playlistItem->HasArt("thumb"))
620       playlistItem->SetArt("thumb", "DefaultVideoCover.png");
621   }
622   if (info.m_info == VIDEOPLAYER_PLAYLISTPOS)
623   {
624     value = StringUtils::Format("%i", index + 1);
625     return true;
626   }
627   else if (info.m_info == VIDEOPLAYER_COVER)
628   {
629     value = playlistItem->GetArt("thumb");
630     return true;
631   }
632 
633   return GetLabel(value, playlistItem.get(), 0, CGUIInfo(info.m_info), nullptr);
634 }
635 
GetFallbackLabel(std::string & value,const CFileItem * item,int contextWindow,const CGUIInfo & info,std::string * fallback)636 bool CVideoGUIInfo::GetFallbackLabel(std::string& value,
637                                      const CFileItem* item,
638                                      int contextWindow,
639                                      const CGUIInfo& info,
640                                      std::string* fallback)
641 {
642   // No fallback for videoplayer "offset" and "position" info labels
643   if (info.GetData1() && ((info.m_info >= VIDEOPLAYER_OFFSET_POSITION_FIRST &&
644       info.m_info <= VIDEOPLAYER_OFFSET_POSITION_LAST) ||
645       (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST)))
646     return false;
647 
648   const CVideoInfoTag* tag = item->GetVideoInfoTag();
649   if (tag)
650   {
651     switch (info.m_info)
652     {
653       /////////////////////////////////////////////////////////////////////////////////////////////
654       // VIDEOPLAYER_*
655       /////////////////////////////////////////////////////////////////////////////////////////////
656       case VIDEOPLAYER_TITLE:
657         value = item->GetLabel();
658         if (value.empty())
659           value = CUtil::GetTitleFromPath(item->GetPath());
660         return true;
661       default:
662         break;
663     }
664   }
665   return false;
666 }
667 
GetInt(int & value,const CGUIListItem * gitem,int contextWindow,const CGUIInfo & info) const668 bool CVideoGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const
669 {
670   if (!gitem->IsFileItem())
671     return false;
672 
673   const CFileItem *item = static_cast<const CFileItem*>(gitem);
674   const CVideoInfoTag* tag = item->GetVideoInfoTag();
675   if (tag)
676   {
677     switch (info.m_info)
678     {
679       /////////////////////////////////////////////////////////////////////////////////////////////
680       // LISTITEM_*
681       /////////////////////////////////////////////////////////////////////////////////////////////
682       case LISTITEM_PERCENT_PLAYED:
683         value = GetPercentPlayed(tag);
684         return true;
685     }
686   }
687 
688   return false;
689 }
690 
GetBool(bool & value,const CGUIListItem * gitem,int contextWindow,const CGUIInfo & info) const691 bool CVideoGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const
692 {
693   if (!gitem->IsFileItem())
694     return false;
695 
696   const CFileItem *item = static_cast<const CFileItem*>(gitem);
697   const CVideoInfoTag* tag = item->GetVideoInfoTag();
698   if (tag)
699   {
700     switch (info.m_info)
701     {
702       /////////////////////////////////////////////////////////////////////////////////////////////
703       // VIDEOPLAYER_*
704       /////////////////////////////////////////////////////////////////////////////////////////////
705       case VIDEOPLAYER_HAS_INFO:
706         value = !tag->IsEmpty();
707         return true;
708 
709       /////////////////////////////////////////////////////////////////////////////////////////////
710       // LISTITEM_*
711       /////////////////////////////////////////////////////////////////////////////////////////////
712       case LISTITEM_IS_RESUMABLE:
713         value = tag->GetResumePoint().timeInSeconds > 0;
714         return true;
715       case LISTITEM_IS_COLLECTION:
716         value = tag->m_type == MediaTypeVideoCollection;
717         return true;
718     }
719   }
720 
721   switch (info.m_info)
722   {
723     ///////////////////////////////////////////////////////////////////////////////////////////////
724     // VIDEOPLAYER_*
725     ///////////////////////////////////////////////////////////////////////////////////////////////
726     case VIDEOPLAYER_CONTENT:
727     {
728       std::string strContent = "files";
729       if (tag)
730       {
731         if (tag->m_type == MediaTypeMovie)
732           strContent = "movies";
733         else if (tag->m_type == MediaTypeEpisode)
734           strContent = "episodes";
735         else if (tag->m_type == MediaTypeMusicVideo)
736           strContent = "musicvideos";
737       }
738       value = StringUtils::EqualsNoCase(info.GetData3(), strContent);
739       return value; // if no match for this provider, other providers shall be asked.
740     }
741     case VIDEOPLAYER_USING_OVERLAYS:
742       value = (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_VIDEOPLAYER_RENDERMETHOD) == RENDER_OVERLAYS);
743       return true;
744     case VIDEOPLAYER_ISFULLSCREEN:
745       value = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
746               CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_FULLSCREEN_GAME;
747       return true;
748     case VIDEOPLAYER_HASMENU:
749       value = g_application.GetAppPlayer().HasMenu();
750       return true;
751     case VIDEOPLAYER_HASTELETEXT:
752       if (g_application.GetAppPlayer().GetTeletextCache())
753       {
754         value = true;
755         return true;
756       }
757       break;
758     case VIDEOPLAYER_HASSUBTITLES:
759       value = g_application.GetAppPlayer().GetSubtitleCount() > 0;
760       return true;
761     case VIDEOPLAYER_SUBTITLESENABLED:
762       value = g_application.GetAppPlayer().GetSubtitleVisible();
763       return true;
764     case VIDEOPLAYER_IS_STEREOSCOPIC:
765       value = !CServiceBroker::GetDataCacheCore().GetVideoStereoMode().empty();
766       return true;
767 
768     ///////////////////////////////////////////////////////////////////////////////////////////////
769     // LISTITEM_*
770     ///////////////////////////////////////////////////////////////////////////////////////////////
771     case LISTITEM_IS_STEREOSCOPIC:
772     {
773       std::string stereoMode = item->GetProperty("stereomode").asString();
774       if (stereoMode.empty() && tag)
775         stereoMode = CStereoscopicsManager::NormalizeStereoMode(tag->m_streamDetails.GetStereoMode());
776       if (!stereoMode.empty() && stereoMode != "mono")
777         value = true;
778       return true;
779     }
780   }
781 
782   return false;
783 }
784