2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
11 #include "CueDocument.h"
12 #include "FileItemList.h"
13 #include "ServiceBroker.h"
16 #include "events/IEvent.h"
17 #include "filesystem/CurlFile.h"
18 #include "filesystem/Directory.h"
19 #include "filesystem/File.h"
20 #include "filesystem/MultiPathDirectory.h"
21 #include "filesystem/MusicDatabaseDirectory/QueryParams.h"
22 #include "filesystem/StackDirectory.h"
23 #include "filesystem/VideoDatabaseDirectory.h"
24 #include "filesystem/VideoDatabaseDirectory/QueryParams.h"
25 #include "games/GameUtils.h"
26 #include "games/tags/GameInfoTag.h"
27 #include "guilib/LocalizeStrings.h"
28 #include "media/MediaLockState.h"
29 #include "music/Album.h"
30 #include "music/Artist.h"
31 #include "music/MusicDatabase.h"
32 #include "music/MusicFileItemClassify.h"
33 #include "music/tags/MusicInfoTag.h"
34 #include "music/tags/MusicInfoTagLoaderFactory.h"
35 #include "network/NetworkFileItemClassify.h"
36 #include "pictures/PictureInfoTag.h"
37 #include "playlists/PlayList.h"
38 #include "playlists/PlayListFactory.h"
39 #include "playlists/PlayListFileItemClassify.h"
40 #include "pvr/PVRManager.h"
41 #include "pvr/channels/PVRChannel.h"
42 #include "pvr/channels/PVRChannelGroupMember.h"
43 #include "pvr/epg/EpgInfoTag.h"
44 #include "pvr/epg/EpgSearchFilter.h"
45 #include "pvr/guilib/PVRGUIActionsChannels.h"
46 #include "pvr/guilib/PVRGUIActionsEPG.h"
47 #include "pvr/guilib/PVRGUIActionsUtils.h"
48 #include "pvr/recordings/PVRRecording.h"
49 #include "pvr/timers/PVRTimerInfoTag.h"
50 #include "settings/AdvancedSettings.h"
51 #include "settings/SettingUtils.h"
52 #include "settings/Settings.h"
53 #include "settings/SettingsComponent.h"
54 #include "settings/lib/Setting.h"
55 #include "utils/Archive.h"
56 #include "utils/ArtUtils.h"
57 #include "utils/FileExtensionProvider.h"
58 #include "utils/Mime.h"
59 #include "utils/RegExp.h"
60 #include "utils/StringUtils.h"
61 #include "utils/URIUtils.h"
62 #include "utils/Variant.h"
63 #include "utils/log.h"
64 #include "video/Bookmark.h"
65 #include "video/VideoDatabase.h"
66 #include "video/VideoFileItemClassify.h"
67 #include "video/VideoInfoTag.h"
68 #include "video/VideoUtils.h"
74 using namespace XFILE
;
75 using namespace PLAYLIST
;
76 using namespace MUSIC_INFO
;
80 CFileItem::CFileItem(const CSong
& song
)
86 CFileItem::CFileItem(const CSong
& song
, const CMusicInfoTag
& music
)
90 *GetMusicInfoTag() = music
;
93 CFileItem::CFileItem(const CURL
&url
, const CAlbum
& album
)
97 m_strPath
= url
.Get();
98 URIUtils::AddSlashAtEnd(m_strPath
);
102 CFileItem::CFileItem(const std::string
&path
, const CAlbum
& album
)
107 URIUtils::AddSlashAtEnd(m_strPath
);
111 CFileItem::CFileItem(const CMusicInfoTag
& music
)
114 SetLabel(music
.GetTitle());
115 m_strPath
= music
.GetURL();
116 m_bIsFolder
= URIUtils::HasSlashAtEnd(m_strPath
);
117 *GetMusicInfoTag() = music
;
119 FillInMimeType(false);
122 CFileItem::CFileItem(const CVideoInfoTag
& movie
)
125 SetFromVideoInfoTag(movie
);
128 void CFileItem::FillMusicInfoTag(const std::shared_ptr
<const CPVREpgInfoTag
>& tag
)
130 CMusicInfoTag
* musictag
= GetMusicInfoTag(); // create (!) the music tag.
132 musictag
->SetTitle(CServiceBroker::GetPVRManager().Get
<PVR::GUI::EPG
>().GetTitleForEpgTag(tag
));
136 musictag
->SetGenre(tag
->Genre());
137 musictag
->SetDuration(tag
->GetDuration());
138 musictag
->SetURL(tag
->Path());
141 musictag
->SetLoaded(true);
144 CFileItem::CFileItem(const std::shared_ptr
<CPVREpgInfoTag
>& tag
)
150 m_strPath
= tag
->Path();
152 SetLabel(CServiceBroker::GetPVRManager().Get
<PVR::GUI::EPG
>().GetTitleForEpgTag(tag
));
153 m_dateTime
= tag
->StartAsLocalTime();
155 if (!tag
->IconPath().empty())
157 SetArt("icon", tag
->IconPath());
161 const std::string iconPath
= tag
->ChannelIconPath();
162 if (!iconPath
.empty())
163 SetArt("icon", iconPath
);
164 else if (tag
->IsRadio())
165 SetArt("icon", "DefaultMusicSongs.png");
167 SetArt("icon", "DefaultTVShows.png");
170 // Speedup FillInDefaultIcon()
171 SetProperty("icon_never_overlay", true);
173 if (tag
->IsRadio() && !HasMusicInfoTag())
174 FillMusicInfoTag(tag
);
176 FillInMimeType(false);
179 CFileItem::CFileItem(const std::shared_ptr
<PVR::CPVREpgSearchFilter
>& filter
)
184 m_epgSearchFilter
= filter
;
185 m_strPath
= filter
->GetPath();
187 SetLabel(filter
->GetTitle());
189 const CDateTime lastExec
= filter
->GetLastExecutedDateTime();
190 if (lastExec
.IsValid())
191 m_dateTime
.SetFromUTCDateTime(lastExec
);
193 SetArt("icon", "DefaultPVRSearch.png");
195 // Speedup FillInDefaultIcon()
196 SetProperty("icon_never_overlay", true);
198 FillInMimeType(false);
201 CFileItem::CFileItem(const std::shared_ptr
<CPVRChannelGroupMember
>& channelGroupMember
)
205 const std::shared_ptr
<const CPVRChannel
> channel
= channelGroupMember
->Channel();
207 m_pvrChannelGroupMemberInfoTag
= channelGroupMember
;
209 m_strPath
= channelGroupMember
->Path();
212 SetLabel(channel
->ChannelName());
214 if (!channel
->IconPath().empty())
215 SetArt("icon", channel
->IconPath());
216 else if (channel
->IsRadio())
217 SetArt("icon", "DefaultMusicSongs.png");
219 SetArt("icon", "DefaultTVShows.png");
221 SetProperty("channelid", channel
->ChannelID());
222 SetProperty("path", channelGroupMember
->Path());
223 SetArt("thumb", channel
->IconPath());
225 // Speedup FillInDefaultIcon()
226 SetProperty("icon_never_overlay", true);
228 if (channel
->IsRadio() && !HasMusicInfoTag())
230 const std::shared_ptr
<const CPVREpgInfoTag
> epgNow
= channel
->GetEPGNow();
231 FillMusicInfoTag(epgNow
);
233 FillInMimeType(false);
236 CFileItem::CFileItem(const std::shared_ptr
<CPVRRecording
>& record
)
241 m_pvrRecordingInfoTag
= record
;
242 m_strPath
= record
->m_strFileNameAndPath
;
243 SetLabel(record
->m_strTitle
);
244 m_dateTime
= record
->RecordingTimeAsLocalTime();
245 m_dwSize
= record
->GetSizeInBytes();
249 if (!record
->IconPath().empty())
250 SetArt("icon", record
->IconPath());
253 const std::shared_ptr
<const CPVRChannel
> channel
= record
->Channel();
254 if (channel
&& !channel
->IconPath().empty())
255 SetArt("icon", channel
->IconPath());
256 else if (record
->IsRadio())
257 SetArt("icon", "DefaultMusicSongs.png");
259 SetArt("icon", "DefaultTVShows.png");
262 if (!record
->ThumbnailPath().empty())
263 SetArt("thumb", record
->ThumbnailPath());
265 if (!record
->FanartPath().empty())
266 SetArt("fanart", record
->FanartPath());
268 // Speedup FillInDefaultIcon()
269 SetProperty("icon_never_overlay", true);
271 FillInMimeType(false);
274 CFileItem::CFileItem(const std::shared_ptr
<CPVRTimerInfoTag
>& timer
)
278 m_bIsFolder
= timer
->IsTimerRule();
279 m_pvrTimerInfoTag
= timer
;
280 m_strPath
= timer
->Path();
281 SetLabel(timer
->Title());
282 m_dateTime
= timer
->StartAsLocalTime();
285 if (!timer
->ChannelIcon().empty())
286 SetArt("icon", timer
->ChannelIcon());
287 else if (timer
->IsRadio())
288 SetArt("icon", "DefaultMusicSongs.png");
290 SetArt("icon", "DefaultTVShows.png");
292 // Speedup FillInDefaultIcon()
293 SetProperty("icon_never_overlay", true);
295 FillInMimeType(false);
298 CFileItem::CFileItem(const CArtist
& artist
)
301 SetLabel(artist
.strArtist
);
302 m_strPath
= artist
.strArtist
;
304 URIUtils::AddSlashAtEnd(m_strPath
);
305 GetMusicInfoTag()->SetArtist(artist
);
306 FillInMimeType(false);
309 CFileItem::CFileItem(const CGenre
& genre
)
312 SetLabel(genre
.strGenre
);
313 m_strPath
= genre
.strGenre
;
315 URIUtils::AddSlashAtEnd(m_strPath
);
316 GetMusicInfoTag()->SetGenre(genre
.strGenre
);
317 FillInMimeType(false);
320 CFileItem::CFileItem(const CFileItem
& item
)
321 : CGUIListItem(item
),
322 m_musicInfoTag(NULL
),
323 m_videoInfoTag(NULL
),
324 m_pictureInfoTag(NULL
),
330 CFileItem::CFileItem(const CGUIListItem
& item
)
333 // not particularly pretty, but it gets around the issue of Initialize() defaulting
334 // parameters in the CGUIListItem base class.
335 *static_cast<CGUIListItem
*>(this) = item
;
337 FillInMimeType(false);
340 CFileItem::CFileItem(void)
345 CFileItem::CFileItem(const std::string
& strLabel
)
351 CFileItem::CFileItem(const char* strLabel
)
354 SetLabel(std::string(strLabel
));
357 CFileItem::CFileItem(const CURL
& path
, bool bIsFolder
)
360 m_strPath
= path
.Get();
361 m_bIsFolder
= bIsFolder
;
362 if (m_bIsFolder
&& !m_strPath
.empty() && !IsFileFolder())
363 URIUtils::AddSlashAtEnd(m_strPath
);
364 FillInMimeType(false);
367 CFileItem::CFileItem(const std::string
& strPath
, bool bIsFolder
)
371 m_bIsFolder
= bIsFolder
;
372 if (m_bIsFolder
&& !m_strPath
.empty() && !IsFileFolder())
373 URIUtils::AddSlashAtEnd(m_strPath
);
374 FillInMimeType(false);
377 CFileItem::CFileItem(const CMediaSource
& share
)
381 m_bIsShareOrDrive
= true;
382 m_strPath
= share
.strPath
;
383 if (!IsRSS()) // no slash at end for rss feeds
384 URIUtils::AddSlashAtEnd(m_strPath
);
385 std::string label
= share
.strName
;
386 if (!share
.strStatus
.empty())
387 label
= StringUtils::Format("{} ({})", share
.strName
, share
.strStatus
);
389 m_iLockMode
= share
.m_iLockMode
;
390 m_strLockCode
= share
.m_strLockCode
;
391 m_iHasLock
= share
.m_iHasLock
;
392 m_iBadPwdCount
= share
.m_iBadPwdCount
;
393 m_iDriveType
= share
.m_iDriveType
;
394 SetArt("thumb", share
.m_strThumbnailImage
);
395 SetLabelPreformatted(true);
397 GetVideoInfoTag()->m_strFileNameAndPath
= share
.strDiskUniqueId
; // share.strDiskUniqueId contains disc unique id
398 FillInMimeType(false);
401 CFileItem::CFileItem(std::shared_ptr
<const ADDON::IAddon
> addonInfo
) : m_addonInfo(std::move(addonInfo
))
406 CFileItem::CFileItem(const EventPtr
& eventLogEntry
)
410 m_eventLogEntry
= eventLogEntry
;
411 SetLabel(eventLogEntry
->GetLabel());
412 m_dateTime
= eventLogEntry
->GetDateTime();
413 if (!eventLogEntry
->GetIcon().empty())
414 SetArt("icon", eventLogEntry
->GetIcon());
417 CFileItem::~CFileItem(void)
419 delete m_musicInfoTag
;
420 delete m_videoInfoTag
;
421 delete m_pictureInfoTag
;
422 delete m_gameInfoTag
;
424 m_musicInfoTag
= NULL
;
425 m_videoInfoTag
= NULL
;
426 m_pictureInfoTag
= NULL
;
427 m_gameInfoTag
= NULL
;
430 CFileItem
& CFileItem::operator=(const CFileItem
& item
)
435 CGUIListItem::operator=(item
);
436 m_bLabelPreformatted
=item
.m_bLabelPreformatted
;
438 m_strPath
= item
.m_strPath
;
439 m_strDynPath
= item
.m_strDynPath
;
440 m_bIsParentFolder
= item
.m_bIsParentFolder
;
441 m_iDriveType
= item
.m_iDriveType
;
442 m_bIsShareOrDrive
= item
.m_bIsShareOrDrive
;
443 m_dateTime
= item
.m_dateTime
;
444 m_dwSize
= item
.m_dwSize
;
446 if (item
.m_musicInfoTag
)
449 *m_musicInfoTag
= *item
.m_musicInfoTag
;
451 m_musicInfoTag
= new MUSIC_INFO::CMusicInfoTag(*item
.m_musicInfoTag
);
455 delete m_musicInfoTag
;
456 m_musicInfoTag
= NULL
;
459 if (item
.m_videoInfoTag
)
462 *m_videoInfoTag
= *item
.m_videoInfoTag
;
464 m_videoInfoTag
= new CVideoInfoTag(*item
.m_videoInfoTag
);
468 delete m_videoInfoTag
;
469 m_videoInfoTag
= NULL
;
472 if (item
.m_pictureInfoTag
)
474 if (m_pictureInfoTag
)
475 *m_pictureInfoTag
= *item
.m_pictureInfoTag
;
477 m_pictureInfoTag
= new CPictureInfoTag(*item
.m_pictureInfoTag
);
481 delete m_pictureInfoTag
;
482 m_pictureInfoTag
= NULL
;
485 if (item
.m_gameInfoTag
)
488 *m_gameInfoTag
= *item
.m_gameInfoTag
;
490 m_gameInfoTag
= new CGameInfoTag(*item
.m_gameInfoTag
);
494 delete m_gameInfoTag
;
495 m_gameInfoTag
= NULL
;
498 m_epgInfoTag
= item
.m_epgInfoTag
;
499 m_epgSearchFilter
= item
.m_epgSearchFilter
;
500 m_pvrChannelGroupMemberInfoTag
= item
.m_pvrChannelGroupMemberInfoTag
;
501 m_pvrRecordingInfoTag
= item
.m_pvrRecordingInfoTag
;
502 m_pvrTimerInfoTag
= item
.m_pvrTimerInfoTag
;
503 m_addonInfo
= item
.m_addonInfo
;
504 m_eventLogEntry
= item
.m_eventLogEntry
;
506 m_lStartOffset
= item
.m_lStartOffset
;
507 m_lStartPartNumber
= item
.m_lStartPartNumber
;
508 m_lEndOffset
= item
.m_lEndOffset
;
509 m_strDVDLabel
= item
.m_strDVDLabel
;
510 m_strTitle
= item
.m_strTitle
;
511 m_iprogramCount
= item
.m_iprogramCount
;
512 m_idepth
= item
.m_idepth
;
513 m_iLockMode
= item
.m_iLockMode
;
514 m_strLockCode
= item
.m_strLockCode
;
515 m_iHasLock
= item
.m_iHasLock
;
516 m_iBadPwdCount
= item
.m_iBadPwdCount
;
517 m_bCanQueue
=item
.m_bCanQueue
;
518 m_mimetype
= item
.m_mimetype
;
519 m_extrainfo
= item
.m_extrainfo
;
520 m_specialSort
= item
.m_specialSort
;
521 m_bIsAlbum
= item
.m_bIsAlbum
;
522 m_doContentLookup
= item
.m_doContentLookup
;
526 void CFileItem::Initialize()
528 m_musicInfoTag
= NULL
;
529 m_videoInfoTag
= NULL
;
530 m_pictureInfoTag
= NULL
;
531 m_gameInfoTag
= NULL
;
532 m_bLabelPreformatted
= false;
535 m_bIsParentFolder
= false;
536 m_bIsShareOrDrive
= false;
537 m_iDriveType
= CMediaSource::SOURCE_TYPE_UNKNOWN
;
539 m_lStartPartNumber
= 1;
543 m_iLockMode
= LOCK_MODE_EVERYONE
;
545 m_iHasLock
= LOCK_STATE_NO_LOCK
;
547 m_specialSort
= SortSpecialNone
;
548 m_doContentLookup
= true;
551 void CFileItem::Reset()
553 // CGUIListItem members...
557 m_overlayIcon
= ICON_OVERLAY_NONE
;
561 m_strDVDLabel
.clear();
564 m_strDynPath
.clear();
566 m_strLockCode
.clear();
568 delete m_musicInfoTag
;
570 delete m_videoInfoTag
;
572 m_epgInfoTag
.reset();
573 m_epgSearchFilter
.reset();
574 m_pvrChannelGroupMemberInfoTag
.reset();
575 m_pvrRecordingInfoTag
.reset();
576 m_pvrTimerInfoTag
.reset();
577 delete m_pictureInfoTag
;
578 m_pictureInfoTag
=NULL
;
579 delete m_gameInfoTag
;
580 m_gameInfoTag
= NULL
;
583 m_eventLogEntry
.reset();
589 // do not archive dynamic path
590 void CFileItem::Archive(CArchive
& ar
)
592 CGUIListItem::Archive(ar
);
596 ar
<< m_bIsParentFolder
;
597 ar
<< m_bLabelPreformatted
;
599 ar
<< m_bIsShareOrDrive
;
605 ar
<< m_iprogramCount
;
607 ar
<< m_lStartOffset
;
608 ar
<< m_lStartPartNumber
;
612 ar
<< m_iBadPwdCount
;
618 ar
<< m_doContentLookup
;
623 ar
<< *m_musicInfoTag
;
630 ar
<< *m_videoInfoTag
;
634 if (m_pictureInfoTag
)
637 ar
<< *m_pictureInfoTag
;
644 ar
<< *m_gameInfoTag
;
651 ar
>> m_bIsParentFolder
;
652 ar
>> m_bLabelPreformatted
;
654 ar
>> m_bIsShareOrDrive
;
660 ar
>> m_iprogramCount
;
662 ar
>> m_lStartOffset
;
663 ar
>> m_lStartPartNumber
;
667 m_iLockMode
= (LockType
)temp
;
669 ar
>> m_iBadPwdCount
;
675 m_specialSort
= (SortSpecial
)temp
;
676 ar
>> m_doContentLookup
;
681 ar
>> *GetMusicInfoTag();
684 ar
>> *GetVideoInfoTag();
687 ar
>> *GetPictureInfoTag();
690 ar
>> *GetGameInfoTag();
696 void CFileItem::Serialize(CVariant
& value
) const
698 //CGUIListItem::Serialize(value["CGUIListItem"]);
700 value
["strPath"] = m_strPath
;
701 value
["dateTime"] = (m_dateTime
.IsValid()) ? m_dateTime
.GetAsRFC1123DateTime() : "";
702 value
["lastmodified"] = m_dateTime
.IsValid() ? m_dateTime
.GetAsDBDateTime() : "";
703 value
["size"] = m_dwSize
;
704 value
["DVDLabel"] = m_strDVDLabel
;
705 value
["title"] = m_strTitle
;
706 value
["mimetype"] = m_mimetype
;
707 value
["extrainfo"] = m_extrainfo
;
710 (*m_musicInfoTag
).Serialize(value
["musicInfoTag"]);
713 (*m_videoInfoTag
).Serialize(value
["videoInfoTag"]);
715 if (m_pictureInfoTag
)
716 (*m_pictureInfoTag
).Serialize(value
["pictureInfoTag"]);
719 (*m_gameInfoTag
).Serialize(value
["gameInfoTag"]);
721 if (!m_mapProperties
.empty())
723 auto& customProperties
= value
["customproperties"];
724 for (const auto& prop
: m_mapProperties
)
725 customProperties
[prop
.first
] = prop
.second
;
729 void CFileItem::ToSortable(SortItem
&sortable
, Field field
) const
734 sortable
[FieldPath
] = m_strPath
;
737 sortable
[FieldDate
] = (m_dateTime
.IsValid()) ? m_dateTime
.GetAsDBDateTime() : "";
740 sortable
[FieldSize
] = m_dwSize
;
743 sortable
[FieldDriveType
] = m_iDriveType
;
745 case FieldStartOffset
:
746 sortable
[FieldStartOffset
] = m_lStartOffset
;
749 sortable
[FieldEndOffset
] = m_lEndOffset
;
751 case FieldProgramCount
:
752 sortable
[FieldProgramCount
] = m_iprogramCount
;
755 sortable
[FieldBitrate
] = m_dwSize
;
758 sortable
[FieldTitle
] = m_strTitle
;
761 // If there's ever a need to convert more properties from CGUIListItem it might be
762 // worth to make CGUIListItem implement ISortable as well and call it from here
768 if (HasMusicInfoTag())
769 GetMusicInfoTag()->ToSortable(sortable
, field
);
771 if (HasVideoInfoTag())
772 GetVideoInfoTag()->ToSortable(sortable
, field
);
774 if (HasPictureInfoTag())
775 GetPictureInfoTag()->ToSortable(sortable
, field
);
777 if (HasPVRChannelInfoTag())
778 GetPVRChannelInfoTag()->ToSortable(sortable
, field
);
780 if (HasPVRChannelGroupMemberInfoTag())
781 GetPVRChannelGroupMemberInfoTag()->ToSortable(sortable
, field
);
787 case FieldInstallDate
:
788 sortable
[FieldInstallDate
] = GetAddonInfo()->InstallDate().GetAsDBDateTime();
790 case FieldLastUpdated
:
791 sortable
[FieldLastUpdated
] = GetAddonInfo()->LastUpdated().GetAsDBDateTime();
794 sortable
[FieldLastUsed
] = GetAddonInfo()->LastUsed().GetAsDBDateTime();
801 if (HasGameInfoTag())
802 GetGameInfoTag()->ToSortable(sortable
, field
);
805 m_eventLogEntry
->ToSortable(sortable
, field
);
809 if (field
== FieldUserPreference
)
810 sortable
[FieldUserPreference
] = GetProperty("favourite.index").asString();
814 void CFileItem::ToSortable(SortItem
&sortable
, const Fields
&fields
) const
816 Fields::const_iterator it
;
817 for (it
= fields
.begin(); it
!= fields
.end(); ++it
)
818 ToSortable(sortable
, *it
);
820 /* FieldLabel is used as a fallback by all sorters and therefore has to be present as well */
821 sortable
[FieldLabel
] = GetLabel();
822 /* FieldSortSpecial and FieldFolder are required in conjunction with all other sorters as well */
823 sortable
[FieldSortSpecial
] = m_specialSort
;
824 sortable
[FieldFolder
] = m_bIsFolder
;
827 bool CFileItem::Exists(bool bUseCache
/* = true */) const
829 if (m_strPath
.empty() || IsPath("add") || NETWORK::IsInternetStream(*this) || IsParentFolder() ||
830 IsVirtualDirectoryRoot() || IsPlugin() || IsPVR())
833 if (VIDEO::IsVideoDb(*this) && HasVideoInfoTag())
835 CFileItem
dbItem(m_bIsFolder
? GetVideoInfoTag()->m_strPath
: GetVideoInfoTag()->m_strFileNameAndPath
, m_bIsFolder
);
836 return dbItem
.Exists();
839 std::string strPath
= m_strPath
;
841 if (URIUtils::IsMultiPath(strPath
))
842 strPath
= CMultiPathDirectory::GetFirstPath(strPath
);
844 if (URIUtils::IsStack(strPath
))
845 strPath
= CStackDirectory::GetFirstStackedFile(strPath
);
848 return CDirectory::Exists(strPath
, bUseCache
);
850 return CFile::Exists(strPath
, bUseCache
);
855 bool CFileItem::IsEPG() const
857 return HasEPGInfoTag();
860 bool CFileItem::IsPVRChannel() const
862 return HasPVRChannelInfoTag();
865 bool CFileItem::IsPVRChannelGroup() const
867 return URIUtils::IsPVRChannelGroup(m_strPath
);
870 bool CFileItem::IsPVRRecording() const
872 return HasPVRRecordingInfoTag();
875 bool CFileItem::IsUsablePVRRecording() const
877 return (m_pvrRecordingInfoTag
&& !m_pvrRecordingInfoTag
->IsDeleted());
880 bool CFileItem::IsDeletedPVRRecording() const
882 return (m_pvrRecordingInfoTag
&& m_pvrRecordingInfoTag
->IsDeleted());
885 bool CFileItem::IsInProgressPVRRecording() const
887 return (m_pvrRecordingInfoTag
&& m_pvrRecordingInfoTag
->IsInProgress());
890 bool CFileItem::IsPVRTimer() const
892 return HasPVRTimerInfoTag();
895 bool CFileItem::IsDeleted() const
897 if (HasPVRRecordingInfoTag())
898 return GetPVRRecordingInfoTag()->IsDeleted();
903 bool CFileItem::IsGame() const
905 if (HasGameInfoTag())
908 if (HasVideoInfoTag())
911 if (HasMusicInfoTag())
914 if (HasPictureInfoTag())
921 return CGameUtils::IsStandaloneGame(std::const_pointer_cast
<ADDON::IAddon
>(GetAddonInfo()));
923 return CGameUtils::HasGameExtension(m_strPath
);
926 bool CFileItem::IsPicture() const
928 if (StringUtils::StartsWithNoCase(m_mimetype
, "image/"))
931 if (HasPictureInfoTag())
934 if (HasGameInfoTag())
937 if (HasMusicInfoTag())
940 if (HasVideoInfoTag())
943 if (HasPVRTimerInfoTag() || HasPVRChannelInfoTag() || HasPVRChannelGroupMemberInfoTag() ||
944 HasPVRRecordingInfoTag() || HasEPGInfoTag() || HasEPGSearchFilter())
947 if (!m_strPath
.empty())
948 return CUtil::IsPicture(m_strPath
);
953 bool CFileItem::IsFileFolder(EFileFolderType types
) const
955 EFileFolderType always_type
= EFILEFOLDER_TYPE_ALWAYS
;
957 /* internet streams are not directly expanded */
958 if (NETWORK::IsInternetStream(*this))
959 always_type
= EFILEFOLDER_TYPE_ONCLICK
;
961 // strm files are not browsable
962 if (IsType(".strm") && (types
& EFILEFOLDER_TYPE_ONBROWSE
))
965 if (types
& always_type
)
967 if (PLAYLIST::IsSmartPlayList(*this) ||
968 (PLAYLIST::IsPlayList(*this) &&
969 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_playlistAsFolders
) ||
970 IsAPK() || IsZIP() || IsRAR() || IsRSS() || MUSIC::IsAudioBook(*this) ||
971 IsType(".ogg|.oga|.xbt")
972 #if defined(TARGET_ANDROID)
979 if (CServiceBroker::IsAddonInterfaceUp() &&
980 IsType(CServiceBroker::GetFileExtensionProvider().GetFileFolderExtensions().c_str()) &&
981 CServiceBroker::GetFileExtensionProvider().CanOperateExtension(m_strPath
))
984 if(types
& EFILEFOLDER_TYPE_ONBROWSE
)
986 if ((PLAYLIST::IsPlayList(*this) &&
987 !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_playlistAsFolders
) ||
995 bool CFileItem::IsLibraryFolder() const
997 if (HasProperty("library.filter") && GetProperty("library.filter").asBoolean())
1000 return URIUtils::IsLibraryFolder(m_strPath
);
1003 bool CFileItem::IsPythonScript() const
1005 return URIUtils::HasExtension(m_strPath
, ".py");
1008 bool CFileItem::IsType(const char *ext
) const
1010 if (!m_strDynPath
.empty())
1011 return URIUtils::HasExtension(m_strDynPath
, ext
);
1013 return URIUtils::HasExtension(m_strPath
, ext
);
1016 bool CFileItem::IsNFO() const
1018 return URIUtils::HasExtension(m_strPath
, ".nfo");
1021 bool CFileItem::IsDiscImage() const
1023 return URIUtils::IsDiscImage(GetDynPath());
1026 bool CFileItem::IsOpticalMediaFile() const
1028 if (VIDEO::IsDVDFile(*this, false, true))
1031 return VIDEO::IsBDFile(*this);
1034 bool CFileItem::IsRAR() const
1036 return URIUtils::IsRAR(m_strPath
);
1039 bool CFileItem::IsAPK() const
1041 return URIUtils::IsAPK(m_strPath
);
1044 bool CFileItem::IsZIP() const
1046 return URIUtils::IsZIP(m_strPath
);
1049 bool CFileItem::IsCBZ() const
1051 return URIUtils::HasExtension(m_strPath
, ".cbz");
1054 bool CFileItem::IsCBR() const
1056 return URIUtils::HasExtension(m_strPath
, ".cbr");
1059 bool CFileItem::IsRSS() const
1061 return StringUtils::StartsWithNoCase(m_strPath
, "rss://") || URIUtils::HasExtension(m_strPath
, ".rss")
1062 || StringUtils::StartsWithNoCase(m_strPath
, "rsss://")
1063 || m_mimetype
== "application/rss+xml";
1066 bool CFileItem::IsAndroidApp() const
1068 return URIUtils::IsAndroidApp(m_strPath
);
1071 bool CFileItem::IsStack() const
1073 return URIUtils::IsStack(GetDynPath());
1076 bool CFileItem::IsFavourite() const
1078 return URIUtils::IsFavourite(m_strPath
);
1081 bool CFileItem::IsPlugin() const
1083 return URIUtils::IsPlugin(m_strPath
);
1086 bool CFileItem::IsScript() const
1088 return URIUtils::IsScript(m_strPath
);
1091 bool CFileItem::IsAddonsPath() const
1093 return URIUtils::IsAddonsPath(m_strPath
);
1096 bool CFileItem::IsSourcesPath() const
1098 return URIUtils::IsSourcesPath(m_strPath
);
1101 bool CFileItem::IsMultiPath() const
1103 return URIUtils::IsMultiPath(m_strPath
);
1106 bool CFileItem::IsBluray() const
1108 if (URIUtils::IsBluray(m_strPath
))
1111 CFileItem item
= CFileItem(VIDEO::UTILS::GetOpticalMediaPath(*this), false);
1113 return VIDEO::IsBDFile(item
);
1116 bool CFileItem::IsDVD() const
1118 return URIUtils::IsDVD(m_strPath
) || m_iDriveType
== CMediaSource::SOURCE_TYPE_DVD
;
1121 bool CFileItem::IsOnDVD() const
1123 return URIUtils::IsOnDVD(m_strPath
) || m_iDriveType
== CMediaSource::SOURCE_TYPE_DVD
;
1126 bool CFileItem::IsNfs() const
1128 return URIUtils::IsNfs(m_strPath
);
1131 bool CFileItem::IsISO9660() const
1133 return URIUtils::IsISO9660(m_strPath
);
1136 bool CFileItem::IsSmb() const
1138 return URIUtils::IsSmb(m_strPath
);
1141 bool CFileItem::IsURL() const
1143 return URIUtils::IsURL(m_strPath
);
1146 bool CFileItem::IsPVR() const
1148 return URIUtils::IsPVR(m_strPath
);
1151 bool CFileItem::IsLiveTV() const
1153 return URIUtils::IsLiveTV(m_strPath
);
1156 bool CFileItem::IsHD() const
1158 return URIUtils::IsHD(m_strPath
);
1161 bool CFileItem::IsVirtualDirectoryRoot() const
1163 return (m_bIsFolder
&& m_strPath
.empty());
1166 bool CFileItem::IsRemovable() const
1168 return IsOnDVD() || MUSIC::IsCDDA(*this) || m_iDriveType
== CMediaSource::SOURCE_TYPE_REMOVABLE
;
1171 bool CFileItem::IsReadOnly() const
1173 if (IsParentFolder())
1176 if (m_bIsShareOrDrive
)
1179 return !CUtil::SupportsWriteFileOperations(m_strPath
);
1182 void CFileItem::FillInDefaultIcon()
1184 if (URIUtils::IsPVRGuideItem(m_strPath
))
1186 // epg items never have a default icon. no need to execute this expensive method.
1187 // when filling epg grid window, easily tens of thousands of epg items are processed.
1191 //CLog::Log(LOGINFO, "FillInDefaultIcon({})", pItem->GetLabel());
1192 // find the default icon for a file or folder item
1193 // for files this can be the (depending on the file type)
1194 // default picture for photo's
1195 // default picture for songs
1196 // default picture for videos
1197 // default picture for shortcuts
1198 // default picture for playlists
1201 // for .. folders the default picture for parent folder
1202 // for other folders the defaultFolder.png
1204 if (GetArt("icon").empty())
1208 /* To reduce the average runtime of this code, this list should
1209 * be ordered with most frequently seen types first. Also bear
1210 * in mind the complexity of the code behind the check in the
1211 * case of IsWhatever() returns false.
1215 if (GetPVRChannelInfoTag()->IsRadio())
1216 SetArt("icon", "DefaultMusicSongs.png");
1218 SetArt("icon", "DefaultTVShows.png");
1220 else if ( IsLiveTV() )
1223 SetArt("icon", "DefaultTVShows.png");
1225 else if ( URIUtils::IsArchive(m_strPath
) )
1227 SetArt("icon", "DefaultFile.png");
1229 else if ( IsUsablePVRRecording() )
1232 SetArt("icon", "DefaultVideo.png");
1234 else if ( IsDeletedPVRRecording() )
1236 // PVR deleted recording
1237 SetArt("icon", "DefaultVideoDeleted.png");
1239 else if (PLAYLIST::IsPlayList(*this) || PLAYLIST::IsSmartPlayList(*this))
1241 SetArt("icon", "DefaultPlaylist.png");
1243 else if (MUSIC::IsAudio(*this))
1246 SetArt("icon", "DefaultAudio.png");
1248 else if (VIDEO::IsVideo(*this))
1251 SetArt("icon", "DefaultVideo.png");
1253 else if (IsPVRTimer())
1255 SetArt("icon", "DefaultVideo.png");
1257 else if ( IsPicture() )
1260 SetArt("icon", "DefaultPicture.png");
1262 else if ( IsPythonScript() )
1264 SetArt("icon", "DefaultScript.png");
1266 else if (IsFavourite())
1268 SetArt("icon", "DefaultFavourites.png");
1272 // default icon for unknown file type
1273 SetArt("icon", "DefaultFile.png");
1278 if (PLAYLIST::IsPlayList(*this) || PLAYLIST::IsSmartPlayList(*this))
1280 SetArt("icon", "DefaultPlaylist.png");
1282 else if (IsParentFolder())
1284 SetArt("icon", "DefaultFolderBack.png");
1288 SetArt("icon", "DefaultFolder.png");
1292 // Set the icon overlays (if applicable)
1293 if (!HasOverlay() && !HasProperty("icon_never_overlay"))
1295 if (URIUtils::IsInRAR(m_strPath
))
1296 SetOverlayImage(CGUIListItem::ICON_OVERLAY_RAR
);
1297 else if (URIUtils::IsInZIP(m_strPath
))
1298 SetOverlayImage(CGUIListItem::ICON_OVERLAY_ZIP
);
1302 void CFileItem::RemoveExtension()
1307 std::string strLabel
= GetLabel();
1308 URIUtils::RemoveExtension(strLabel
);
1312 void CFileItem::CleanString()
1317 std::string strLabel
= GetLabel();
1318 std::string strTitle
, strTitleAndYear
, strYear
;
1319 CUtil::CleanString(strLabel
, strTitle
, strTitleAndYear
, strYear
, true);
1320 SetLabel(strTitleAndYear
);
1323 void CFileItem::SetLabel(const std::string
&strLabel
)
1325 if (strLabel
== "..")
1327 m_bIsParentFolder
= true;
1329 m_specialSort
= SortSpecialOnTop
;
1330 SetLabelPreformatted(true);
1332 CGUIListItem::SetLabel(strLabel
);
1335 void CFileItem::SetFileSizeLabel()
1337 if(m_bIsFolder
&& m_dwSize
== 0)
1340 SetLabel2(StringUtils::SizeToString(m_dwSize
));
1343 bool CFileItem::CanQueue() const
1348 void CFileItem::SetCanQueue(bool bYesNo
)
1350 m_bCanQueue
= bYesNo
;
1353 bool CFileItem::IsParentFolder() const
1355 return m_bIsParentFolder
;
1358 void CFileItem::FillInMimeType(bool lookup
/*= true*/)
1360 //! @todo adapt this to use CMime::GetMimeType()
1361 if (m_mimetype
.empty())
1364 m_mimetype
= "x-directory/normal";
1365 else if (HasPVRChannelInfoTag())
1366 m_mimetype
= GetPVRChannelInfoTag()->MimeType();
1367 else if (StringUtils::StartsWithNoCase(GetDynPath(), "shout://") ||
1368 StringUtils::StartsWithNoCase(GetDynPath(), "http://") ||
1369 StringUtils::StartsWithNoCase(GetDynPath(), "https://"))
1371 // If lookup is false, bail out early to leave mime type empty
1375 CCurlFile::GetMimeType(GetDynURL(), m_mimetype
);
1377 // try to get mime-type again but with an NSPlayer User-Agent
1378 // in order for server to provide correct mime-type. Allows us
1379 // to properly detect an MMS stream
1380 if (StringUtils::StartsWithNoCase(m_mimetype
, "video/x-ms-"))
1381 CCurlFile::GetMimeType(GetDynURL(), m_mimetype
, "NSPlayer/11.00.6001.7000");
1383 // make sure there are no options set in mime-type
1384 // mime-type can look like "video/x-ms-asf ; charset=utf8"
1385 size_t i
= m_mimetype
.find(';');
1386 if(i
!= std::string::npos
)
1387 m_mimetype
.erase(i
, m_mimetype
.length() - i
);
1388 StringUtils::Trim(m_mimetype
);
1391 m_mimetype
= CMime::GetMimeType(*this);
1393 // if it's still empty set to an unknown type
1394 if (m_mimetype
.empty())
1395 m_mimetype
= "application/octet-stream";
1398 // change protocol to mms for the following mime-type. Allows us to create proper FileMMS.
1399 if(StringUtils::StartsWithNoCase(m_mimetype
, "application/vnd.ms.wms-hdr.asfv1") ||
1400 StringUtils::StartsWithNoCase(m_mimetype
, "application/x-mms-framed"))
1402 if (m_strDynPath
.empty())
1403 m_strDynPath
= m_strPath
;
1405 StringUtils::Replace(m_strDynPath
, "http:", "mms:");
1409 void CFileItem::UpdateMimeType(bool lookup
/*= true*/)
1411 //! @todo application/octet-stream might actually have been set by a web lookup. Currently we
1412 //! cannot distinguish between set as fallback only (see FillInMimeType) or as an actual value.
1413 if (m_mimetype
== "application/octet-stream")
1416 FillInMimeType(lookup
);
1419 void CFileItem::SetMimeTypeForInternetFile()
1421 if (m_doContentLookup
&& NETWORK::IsInternetStream(*this))
1424 FillInMimeType(true);
1428 bool CFileItem::IsSamePath(const CFileItem
*item
) const
1433 if (!m_strPath
.empty() && item
->GetPath() == m_strPath
)
1435 if (item
->HasProperty("item_start") || HasProperty("item_start"))
1436 return (item
->GetProperty("item_start") == GetProperty("item_start"));
1437 // See if we have associated a bluray playlist
1438 if (VIDEO::IsBlurayPlaylist(*this) || VIDEO::IsBlurayPlaylist(*item
))
1439 return (GetDynPath() == item
->GetDynPath());
1442 if (HasMusicInfoTag() && item
->HasMusicInfoTag())
1444 if (GetMusicInfoTag()->GetDatabaseId() != -1 && item
->GetMusicInfoTag()->GetDatabaseId() != -1)
1445 return ((GetMusicInfoTag()->GetDatabaseId() == item
->GetMusicInfoTag()->GetDatabaseId()) &&
1446 (GetMusicInfoTag()->GetType() == item
->GetMusicInfoTag()->GetType()));
1448 if (HasVideoInfoTag() && item
->HasVideoInfoTag())
1450 const CVideoInfoTag
* myTag
{GetVideoInfoTag()};
1451 const CVideoInfoTag
* otherTag
{item
->GetVideoInfoTag()};
1452 if (myTag
->m_iDbId
!= -1 && otherTag
->m_iDbId
!= -1)
1454 if ((myTag
->m_iDbId
== otherTag
->m_iDbId
) && (myTag
->m_type
== otherTag
->m_type
))
1456 // for movies with multiple versions, wie need also to check the file id
1457 if (HasVideoVersions() && item
->HasVideoVersions() && myTag
->m_iFileId
!= -1 &&
1458 otherTag
->m_iFileId
!= -1)
1459 return myTag
->m_iFileId
== otherTag
->m_iFileId
;
1464 if (MUSIC::IsMusicDb(*this) && HasMusicInfoTag())
1466 CFileItem
dbItem(m_musicInfoTag
->GetURL(), false);
1467 if (HasProperty("item_start"))
1468 dbItem
.SetProperty("item_start", GetProperty("item_start"));
1469 return dbItem
.IsSamePath(item
);
1471 if (VIDEO::IsVideoDb(*this) && HasVideoInfoTag())
1473 CFileItem
dbItem(GetVideoInfoTag()->m_strFileNameAndPath
, false);
1474 if (HasProperty("item_start"))
1475 dbItem
.SetProperty("item_start", GetProperty("item_start"));
1476 return dbItem
.IsSamePath(item
);
1478 if (MUSIC::IsMusicDb(*item
) && item
->HasMusicInfoTag())
1480 CFileItem
dbItem(item
->m_musicInfoTag
->GetURL(), false);
1481 if (item
->HasProperty("item_start"))
1482 dbItem
.SetProperty("item_start", item
->GetProperty("item_start"));
1483 return IsSamePath(&dbItem
);
1485 if (VIDEO::IsVideoDb(*item
) && item
->HasVideoInfoTag())
1487 CFileItem
dbItem(item
->GetVideoInfoTag()->m_strFileNameAndPath
, false);
1488 if (item
->HasProperty("item_start"))
1489 dbItem
.SetProperty("item_start", item
->GetProperty("item_start"));
1490 return IsSamePath(&dbItem
);
1492 if (HasProperty("original_listitem_url"))
1493 return (GetProperty("original_listitem_url") == item
->GetPath());
1497 bool CFileItem::IsAlbum() const
1502 void CFileItem::UpdateInfo(const CFileItem
&item
, bool replaceLabels
/*=true*/)
1504 if (item
.HasVideoInfoTag())
1505 { // copy info across
1506 //! @todo premiered info is normally stored in m_dateTime by the db
1508 if (item
.m_videoInfoTag
)
1511 *m_videoInfoTag
= *item
.m_videoInfoTag
;
1513 m_videoInfoTag
= new CVideoInfoTag(*item
.m_videoInfoTag
);
1518 delete m_videoInfoTag
;
1520 m_videoInfoTag
= new CVideoInfoTag
;
1523 m_pvrRecordingInfoTag
= item
.m_pvrRecordingInfoTag
;
1525 SetOverlayImage(GetVideoInfoTag()->GetPlayCount() > 0 ? CGUIListItem::ICON_OVERLAY_WATCHED
1526 : CGUIListItem::ICON_OVERLAY_UNWATCHED
);
1529 if (item
.HasMusicInfoTag())
1531 *GetMusicInfoTag() = *item
.GetMusicInfoTag();
1534 if (item
.HasPictureInfoTag())
1536 *GetPictureInfoTag() = *item
.GetPictureInfoTag();
1539 if (item
.HasGameInfoTag())
1541 *GetGameInfoTag() = *item
.GetGameInfoTag();
1544 if (item
.HasPVRChannelGroupMemberInfoTag())
1546 m_pvrChannelGroupMemberInfoTag
= item
.GetPVRChannelGroupMemberInfoTag();
1549 if (item
.HasPVRTimerInfoTag())
1551 m_pvrTimerInfoTag
= item
.m_pvrTimerInfoTag
;
1554 if (item
.HasEPGInfoTag())
1556 m_epgInfoTag
= item
.m_epgInfoTag
;
1559 if (item
.HasEPGSearchFilter())
1561 m_epgSearchFilter
= item
.m_epgSearchFilter
;
1564 SetDynPath(item
.GetDynPath());
1565 if (replaceLabels
&& !item
.GetLabel().empty())
1566 SetLabel(item
.GetLabel());
1567 if (replaceLabels
&& !item
.GetLabel2().empty())
1568 SetLabel2(item
.GetLabel2());
1569 if (!item
.GetArt().empty())
1570 SetArt(item
.GetArt());
1571 AppendProperties(item
);
1573 SetContentLookup(item
.m_doContentLookup
);
1574 SetMimeType(item
.m_mimetype
);
1575 UpdateMimeType(m_doContentLookup
);
1578 void CFileItem::MergeInfo(const CFileItem
& item
)
1580 // TODO: Currently merge the metadata/art info is implemented for video case only
1581 if (item
.HasVideoInfoTag())
1583 if (item
.m_videoInfoTag
)
1586 m_videoInfoTag
->Merge(*item
.m_videoInfoTag
);
1588 m_videoInfoTag
= new CVideoInfoTag(*item
.m_videoInfoTag
);
1591 m_pvrRecordingInfoTag
= item
.m_pvrRecordingInfoTag
;
1593 SetOverlayImage(GetVideoInfoTag()->GetPlayCount() > 0 ? CGUIListItem::ICON_OVERLAY_WATCHED
1594 : CGUIListItem::ICON_OVERLAY_UNWATCHED
);
1597 if (item
.HasMusicInfoTag())
1599 *GetMusicInfoTag() = *item
.GetMusicInfoTag();
1602 if (item
.HasPictureInfoTag())
1604 *GetPictureInfoTag() = *item
.GetPictureInfoTag();
1607 if (item
.HasGameInfoTag())
1609 *GetGameInfoTag() = *item
.GetGameInfoTag();
1612 if (item
.HasPVRChannelGroupMemberInfoTag())
1614 m_pvrChannelGroupMemberInfoTag
= item
.GetPVRChannelGroupMemberInfoTag();
1617 if (item
.HasPVRTimerInfoTag())
1619 m_pvrTimerInfoTag
= item
.m_pvrTimerInfoTag
;
1622 if (item
.HasEPGInfoTag())
1624 m_epgInfoTag
= item
.m_epgInfoTag
;
1627 if (item
.HasEPGSearchFilter())
1629 m_epgSearchFilter
= item
.m_epgSearchFilter
;
1632 SetDynPath(item
.GetDynPath());
1633 if (!item
.GetLabel().empty())
1634 SetLabel(item
.GetLabel());
1635 if (!item
.GetLabel2().empty())
1636 SetLabel2(item
.GetLabel2());
1637 if (!item
.GetArt().empty())
1639 if (VIDEO::IsVideo(item
))
1640 AppendArt(item
.GetArt());
1642 SetArt(item
.GetArt());
1644 AppendProperties(item
);
1646 SetContentLookup(item
.m_doContentLookup
);
1647 SetMimeType(item
.m_mimetype
);
1648 UpdateMimeType(m_doContentLookup
);
1651 void CFileItem::SetFromVideoInfoTag(const CVideoInfoTag
&video
)
1653 if (!video
.m_strTitle
.empty())
1654 SetLabel(video
.m_strTitle
);
1655 if (video
.m_strFileNameAndPath
.empty())
1657 m_strPath
= video
.m_strPath
;
1658 URIUtils::AddSlashAtEnd(m_strPath
);
1663 m_strPath
= video
.m_strFileNameAndPath
;
1664 m_bIsFolder
= false;
1668 *m_videoInfoTag
= video
;
1670 m_videoInfoTag
= new CVideoInfoTag(video
);
1672 if (video
.m_iSeason
== 0)
1673 SetProperty("isspecial", "true");
1674 FillInDefaultIcon();
1675 FillInMimeType(false);
1680 class CPropertySaveHelper
1683 CPropertySaveHelper(CFileItem
& item
, const std::string
& property
, const std::string
& value
)
1684 : m_item(item
), m_property(property
), m_value(value
)
1688 bool NeedsSave() const { return !m_value
.empty() || m_item
.HasProperty(m_property
); }
1690 std::string
GetValueToSave(const std::string
& currentValue
) const
1694 if (!m_value
.empty())
1696 // Overwrite whatever we have; remember what we had originally.
1697 if (!m_item
.HasProperty(m_property
))
1698 m_item
.SetProperty(m_property
, currentValue
);
1702 else if (m_item
.HasProperty(m_property
))
1704 // Restore original value
1705 value
= m_item
.GetProperty(m_property
).asString();
1706 m_item
.ClearProperty(m_property
);
1714 const std::string m_property
;
1715 const std::string m_value
;
1717 } // unnamed namespace
1719 void CFileItem::SetFromMusicInfoTag(const MUSIC_INFO::CMusicInfoTag
& music
)
1721 const std::string path
= GetPath();
1724 SetPath(music
.GetURL());
1728 const CPropertySaveHelper
dynpath(*this, "OriginalDynPath", music
.GetURL());
1729 if (dynpath
.NeedsSave())
1730 SetDynPath(dynpath
.GetValueToSave(m_strDynPath
));
1733 const CPropertySaveHelper
label(*this, "OriginalLabel", music
.GetTitle());
1734 if (label
.NeedsSave())
1735 SetLabel(label
.GetValueToSave(GetLabel()));
1737 const CPropertySaveHelper
thumb(*this, "OriginalThumb", music
.GetStationArt());
1738 if (thumb
.NeedsSave())
1739 SetArt("thumb", thumb
.GetValueToSave(GetArt("thumb")));
1741 *GetMusicInfoTag() = music
;
1742 FillInDefaultIcon();
1743 FillInMimeType(false);
1746 void CFileItem::SetFromAlbum(const CAlbum
&album
)
1748 if (!album
.strAlbum
.empty())
1749 SetLabel(album
.strAlbum
);
1751 m_strLabel2
= album
.GetAlbumArtistString();
1752 GetMusicInfoTag()->SetAlbum(album
);
1754 if (album
.art
.empty())
1755 SetArt("icon", "DefaultAlbumCover.png");
1760 CMusicDatabase::SetPropertiesFromAlbum(*this,album
);
1761 FillInMimeType(false);
1764 void CFileItem::SetFromSong(const CSong
&song
)
1766 if (!song
.strTitle
.empty())
1767 SetLabel(song
.strTitle
);
1768 if (song
.idSong
> 0)
1770 std::string strExt
= URIUtils::GetExtension(song
.strFileName
);
1771 m_strPath
= StringUtils::Format("musicdb://songs/{}{}", song
.idSong
, strExt
);
1773 else if (!song
.strFileName
.empty())
1774 m_strPath
= song
.strFileName
;
1775 GetMusicInfoTag()->SetSong(song
);
1776 m_lStartOffset
= song
.iStartOffset
;
1777 m_lStartPartNumber
= 1;
1778 SetProperty("item_start", song
.iStartOffset
);
1779 m_lEndOffset
= song
.iEndOffset
;
1780 if (!song
.strThumb
.empty())
1781 SetArt("thumb", song
.strThumb
);
1782 FillInMimeType(false);
1786 * @todo Ideally this (and SetPath) would not be available outside of construction
1787 * for CFileItem objects, or at least restricted to essentially be equivalent
1788 * to construction. This would require re-formulating a bunch of CFileItem
1789 * construction, and also allowing CFileItemList to have its own (public)
1790 * SetURL() function, so for now we give direct access.
1792 void CFileItem::SetURL(const CURL
& url
)
1794 m_strPath
= url
.Get();
1797 const CURL
CFileItem::GetURL() const
1799 CURL
url(m_strPath
);
1803 bool CFileItem::IsURL(const CURL
& url
) const
1805 return IsPath(url
.Get());
1808 bool CFileItem::IsPath(const std::string
& path
, bool ignoreURLOptions
/* = false */) const
1810 return URIUtils::PathEquals(m_strPath
, path
, false, ignoreURLOptions
);
1813 void CFileItem::SetDynURL(const CURL
& url
)
1815 m_strDynPath
= url
.Get();
1818 const CURL
CFileItem::GetDynURL() const
1820 if (!m_strDynPath
.empty())
1822 CURL
url(m_strDynPath
);
1827 CURL
url(m_strPath
);
1832 const std::string
&CFileItem::GetDynPath() const
1834 if (!m_strDynPath
.empty())
1835 return m_strDynPath
;
1840 void CFileItem::SetDynPath(const std::string
&path
)
1842 m_strDynPath
= path
;
1845 std::string
CFileItem::GetBlurayPath() const
1847 if (VIDEO::IsBlurayPlaylist(*this))
1849 CURL
url(GetDynPath());
1850 CURL
url2(url
.GetHostName()); // strip bluray://
1851 if (url2
.IsProtocol("udf"))
1853 return url2
.GetHostName(); // strip udf://
1854 else if (url
.IsProtocol("bluray"))
1856 return url2
.Get() + "BDMV/index.bdmv";
1858 return GetDynPath();
1861 void CFileItem::SetCueDocument(const CCueDocumentPtr
& cuePtr
)
1863 m_cueDocument
= cuePtr
;
1866 void CFileItem::LoadEmbeddedCue()
1868 CMusicInfoTag
& tag
= *GetMusicInfoTag();
1872 const std::string embeddedCue
= tag
.GetCueSheet();
1873 if (!embeddedCue
.empty())
1875 CCueDocumentPtr
cuesheet(new CCueDocument
);
1876 if (cuesheet
->ParseTag(embeddedCue
))
1878 std::vector
<std::string
> MediaFileVec
;
1879 cuesheet
->GetMediaFiles(MediaFileVec
);
1880 for (std::vector
<std::string
>::iterator itMedia
= MediaFileVec
.begin();
1881 itMedia
!= MediaFileVec
.end(); ++itMedia
)
1882 cuesheet
->UpdateMediaFile(*itMedia
, GetPath());
1883 SetCueDocument(cuesheet
);
1885 // Clear cuesheet tag having added it to item
1886 tag
.SetCueSheet("");
1890 bool CFileItem::HasCueDocument() const
1892 return (m_cueDocument
.get() != nullptr);
1895 bool CFileItem::LoadTracksFromCueDocument(CFileItemList
& scannedItems
)
1900 bool result
= m_cueDocument
->LoadTracks(scannedItems
, *this);
1901 m_cueDocument
.reset();
1906 std::string
CFileItem::GetUserMusicThumb(bool alwaysCheckRemote
/* = false */, bool fallbackToFolder
/* = false */) const
1908 if (m_strPath
.empty() || StringUtils::StartsWithNoCase(m_strPath
, "newsmartplaylist://") ||
1909 StringUtils::StartsWithNoCase(m_strPath
, "newplaylist://") || m_bIsShareOrDrive
||
1910 NETWORK::IsInternetStream(*this) || URIUtils::IsUPnP(m_strPath
) ||
1911 (URIUtils::IsFTP(m_strPath
) &&
1912 !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_bFTPThumbs
) ||
1913 IsPlugin() || IsAddonsPath() || IsLibraryFolder() || IsParentFolder() ||
1914 MUSIC::IsMusicDb(*this))
1917 // we first check for <filename>.tbn or <foldername>.tbn
1918 std::string
fileThumb(ART::GetTBNFile(*this));
1919 if (CFile::Exists(fileThumb
))
1922 // Fall back to folder thumb, if requested
1923 if (!m_bIsFolder
&& fallbackToFolder
)
1925 CFileItem
item(URIUtils::GetDirectory(m_strPath
), true);
1926 return item
.GetUserMusicThumb(alwaysCheckRemote
);
1929 // if a folder, check for folder.jpg
1930 if (m_bIsFolder
&& !IsFileFolder() &&
1931 (!NETWORK::IsRemote(*this) || alwaysCheckRemote
||
1932 CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
1933 CSettings::SETTING_MUSICFILES_FINDREMOTETHUMBS
)))
1935 std::vector
<CVariant
> thumbs
= CServiceBroker::GetSettingsComponent()->GetSettings()->GetList(
1936 CSettings::SETTING_MUSICLIBRARY_MUSICTHUMBS
);
1937 for (const auto& i
: thumbs
)
1939 std::string strFileName
= i
.asString();
1940 std::string
folderThumb(GetFolderThumb(strFileName
));
1941 if (CFile::Exists(folderThumb
)) // folder.jpg
1943 size_t period
= strFileName
.find_last_of('.');
1944 if (period
!= std::string::npos
)
1947 std::string name
= strFileName
;
1948 std::string folderThumb1
= folderThumb
;
1950 ext
= strFileName
.substr(period
);
1951 StringUtils::ToUpper(ext
);
1952 StringUtils::Replace(folderThumb1
, strFileName
, name
+ ext
);
1953 if (CFile::Exists(folderThumb1
)) // folder.JPG
1954 return folderThumb1
;
1956 folderThumb1
= folderThumb
;
1957 std::string firstletter
= name
.substr(0, 1);
1958 StringUtils::ToUpper(firstletter
);
1959 name
.replace(0, 1, firstletter
);
1960 StringUtils::Replace(folderThumb1
, strFileName
, name
+ ext
);
1961 if (CFile::Exists(folderThumb1
)) // Folder.JPG
1962 return folderThumb1
;
1964 folderThumb1
= folderThumb
;
1965 StringUtils::ToLower(ext
);
1966 StringUtils::Replace(folderThumb1
, strFileName
, name
+ ext
);
1967 if (CFile::Exists(folderThumb1
)) // Folder.jpg
1968 return folderThumb1
;
1976 bool CFileItem::SkipLocalArt() const
1978 return (m_strPath
.empty() || StringUtils::StartsWithNoCase(m_strPath
, "newsmartplaylist://") ||
1979 StringUtils::StartsWithNoCase(m_strPath
, "newplaylist://") || m_bIsShareOrDrive
||
1980 NETWORK::IsInternetStream(*this) || URIUtils::IsUPnP(m_strPath
) ||
1981 (URIUtils::IsFTP(m_strPath
) &&
1982 !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_bFTPThumbs
) ||
1983 IsPlugin() || IsAddonsPath() || IsLibraryFolder() || IsParentFolder() || IsLiveTV() ||
1984 IsPVRRecording() || IsDVD());
1987 std::string
CFileItem::GetThumbHideIfUnwatched(const CFileItem
* item
) const
1989 const std::shared_ptr
<CSettingList
> setting(std::dynamic_pointer_cast
<CSettingList
>(
1990 CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(
1991 CSettings::SETTING_VIDEOLIBRARY_SHOWUNWATCHEDPLOTS
)));
1992 if (setting
&& item
->HasVideoInfoTag() && item
->GetVideoInfoTag()->m_type
== MediaTypeEpisode
&&
1993 item
->GetVideoInfoTag()->GetPlayCount() == 0 &&
1994 !CSettingUtils::FindIntInList(setting
,
1995 CSettings::VIDEOLIBRARY_THUMB_SHOW_UNWATCHED_EPISODE
) &&
1996 item
->HasArt("thumb"))
1998 std::string fanArt
= item
->GetArt("fanart");
2000 return "OverlaySpoiler.png";
2005 return item
->GetArt("thumb");
2008 std::string
CFileItem::FindLocalArt(const std::string
&artFile
, bool useFolder
) const
2016 thumb
= GetLocalArt(artFile
, false);
2017 if (!thumb
.empty() && CFile::Exists(thumb
))
2020 if ((useFolder
|| (m_bIsFolder
&& !IsFileFolder())) && !artFile
.empty())
2022 std::string thumb2
= GetLocalArt(artFile
, true);
2023 if (!thumb2
.empty() && thumb2
!= thumb
&& CFile::Exists(thumb2
))
2029 std::string
CFileItem::GetLocalArtBaseFilename() const
2031 bool useFolder
= false;
2032 return GetLocalArtBaseFilename(useFolder
);
2035 std::string
CFileItem::GetLocalArtBaseFilename(bool& useFolder
) const
2037 std::string strFile
;
2040 std::string strPath
;
2041 URIUtils::GetParentPath(m_strPath
,strPath
);
2042 strFile
= URIUtils::AddFileToFolder(
2043 strPath
, URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(m_strPath
)));
2046 std::string file
= strFile
.empty() ? m_strPath
: strFile
;
2047 if (URIUtils::IsInRAR(file
) || URIUtils::IsInZIP(file
))
2049 std::string strPath
= URIUtils::GetDirectory(file
);
2050 std::string strParent
;
2051 URIUtils::GetParentPath(strPath
,strParent
);
2052 strFile
= URIUtils::AddFileToFolder(strParent
, URIUtils::GetFileName(file
));
2056 strFile
= CMultiPathDirectory::GetFirstPath(m_strPath
);
2058 if (IsOpticalMediaFile())
2059 { // optical media files should be treated like folders
2061 strFile
= GetLocalMetadataPath();
2063 else if (useFolder
&& !(m_bIsFolder
&& !IsFileFolder()))
2065 file
= strFile
.empty() ? m_strPath
: strFile
;
2066 strFile
= URIUtils::GetDirectory(file
);
2069 if (strFile
.empty())
2070 strFile
= GetDynPath();
2075 std::string
CFileItem::GetLocalArt(const std::string
& artFile
, bool useFolder
) const
2077 // no retrieving of empty art files from folders
2078 if (useFolder
&& artFile
.empty())
2081 std::string strFile
= GetLocalArtBaseFilename(useFolder
);
2082 if (strFile
.empty()) // empty filepath -> nothing to find
2087 if (!artFile
.empty())
2088 return URIUtils::AddFileToFolder(strFile
, artFile
);
2092 if (artFile
.empty()) // old thumbnail matching
2093 return URIUtils::ReplaceExtension(strFile
, ".tbn");
2095 return URIUtils::ReplaceExtension(strFile
, "-" + artFile
);
2100 std::string
CFileItem::GetFolderThumb(const std::string
&folderJPG
/* = "folder.jpg" */) const
2102 std::string strFolder
= m_strPath
;
2105 URIUtils::IsInRAR(strFolder
) ||
2106 URIUtils::IsInZIP(strFolder
))
2108 URIUtils::GetParentPath(m_strPath
,strFolder
);
2112 strFolder
= CMultiPathDirectory::GetFirstPath(m_strPath
);
2117 return URIUtils::AddFileToFolder(strFolder
, folderJPG
);
2120 std::string
CFileItem::GetMovieName(bool bUseFolderNames
/* = false */) const
2122 if (IsPlugin() && HasVideoInfoTag() && !GetVideoInfoTag()->m_strTitle
.empty())
2123 return GetVideoInfoTag()->m_strTitle
;
2125 if (IsLabelPreformatted())
2128 if (m_pvrRecordingInfoTag
)
2129 return m_pvrRecordingInfoTag
->m_strTitle
;
2130 else if (URIUtils::IsPVRRecording(m_strPath
))
2132 std::string title
= CPVRRecording::GetTitleFromURL(m_strPath
);
2137 std::string strMovieName
;
2138 if (URIUtils::IsStack(m_strPath
))
2139 strMovieName
= CStackDirectory::GetStackedTitlePath(m_strPath
);
2141 strMovieName
= GetBaseMoviePath(bUseFolderNames
);
2143 URIUtils::RemoveSlashAtEnd(strMovieName
);
2145 return CURL::Decode(URIUtils::GetFileName(strMovieName
));
2148 std::string
CFileItem::GetBaseMoviePath(bool bUseFolderNames
) const
2150 std::string strMovieName
= m_strPath
;
2153 strMovieName
= CMultiPathDirectory::GetFirstPath(m_strPath
);
2155 if (IsOpticalMediaFile())
2156 return GetLocalMetadataPath();
2158 if (bUseFolderNames
&&
2159 (!m_bIsFolder
|| URIUtils::IsInArchive(m_strPath
) ||
2160 (HasVideoInfoTag() && GetVideoInfoTag()->m_iDbId
> 0 && !CMediaTypes::IsContainer(GetVideoInfoTag()->m_type
))))
2162 std::string
name2(strMovieName
);
2163 URIUtils::GetParentPath(name2
,strMovieName
);
2164 if (URIUtils::IsInArchive(m_strPath
))
2166 // Try to get archive itself, if empty take path before
2167 name2
= CURL(m_strPath
).GetHostName();
2169 name2
= strMovieName
;
2171 URIUtils::GetParentPath(name2
, strMovieName
);
2174 // Remove trailing 'Disc n' path segment to get actual movie title
2175 strMovieName
= CUtil::RemoveTrailingDiscNumberSegmentFromPath(strMovieName
);
2178 return strMovieName
;
2181 std::string
CFileItem::GetLocalMetadataPath() const
2183 if (m_bIsFolder
&& !IsFileFolder())
2186 std::string parent
{};
2187 if (VIDEO::IsBlurayPlaylist(*this))
2188 parent
= URIUtils::GetParentPath(GetBlurayPath());
2190 parent
= URIUtils::GetParentPath(m_strPath
);
2191 std::string
parentFolder(parent
);
2192 URIUtils::RemoveSlashAtEnd(parentFolder
);
2193 parentFolder
= URIUtils::GetFileName(parentFolder
);
2194 if (StringUtils::EqualsNoCase(parentFolder
, "VIDEO_TS") || StringUtils::EqualsNoCase(parentFolder
, "BDMV"))
2195 { // go back up another one
2196 parent
= URIUtils::GetParentPath(parent
);
2201 bool CFileItem::LoadMusicTag()
2204 if (!MUSIC::IsAudio(*this))
2207 if (HasMusicInfoTag() && m_musicInfoTag
->Loaded())
2210 CMusicDatabase musicDatabase
;
2211 if (musicDatabase
.Open())
2214 if (musicDatabase
.GetSongByFileName(m_strPath
, song
))
2216 GetMusicInfoTag()->SetSong(song
);
2219 musicDatabase
.Close();
2221 // load tag from file
2222 CLog::Log(LOGDEBUG
, "{}: loading tag information for file: {}", __FUNCTION__
, m_strPath
);
2223 CMusicInfoTagLoaderFactory factory
;
2224 std::unique_ptr
<IMusicInfoTagLoader
> pLoader (factory
.CreateLoader(*this));
2227 if (pLoader
->Load(m_strPath
, *GetMusicInfoTag()))
2230 // no tag - try some other things
2231 if (MUSIC::IsCDDA(*this))
2233 // we have the tracknumber...
2234 int iTrack
= GetMusicInfoTag()->GetTrackNumber();
2237 std::string strText
= g_localizeStrings
.Get(554); // "Track"
2238 if (!strText
.empty() && strText
[strText
.size() - 1] != ' ')
2240 std::string strTrack
= StringUtils::Format((strText
+ "{}"), iTrack
);
2241 GetMusicInfoTag()->SetTitle(strTrack
);
2242 GetMusicInfoTag()->SetLoaded(true);
2248 std::string fileName
= URIUtils::GetFileName(m_strPath
);
2249 URIUtils::RemoveExtension(fileName
);
2250 for (const std::string
& fileFilter
: CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicTagsFromFileFilters
)
2252 CLabelFormatter
formatter(fileFilter
, "");
2253 if (formatter
.FillMusicTag(fileName
, GetMusicInfoTag()))
2255 GetMusicInfoTag()->SetLoaded(true);
2263 bool CFileItem::LoadGameTag()
2266 if (HasGameInfoTag() && m_gameInfoTag
->IsLoaded())
2272 m_gameInfoTag
->SetLoaded(true);
2277 bool CFileItem::LoadDetails()
2279 if (VIDEO::IsVideoDb(*this))
2281 if (HasVideoInfoTag())
2287 CLog::LogF(LOGERROR
, "Error opening video database");
2291 VIDEODATABASEDIRECTORY::CQueryParams params
;
2292 VIDEODATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(GetPath(), params
);
2295 auto tag
{std::make_unique
<CVideoInfoTag
>()};
2296 if (params
.GetMovieId() >= 0)
2297 ret
= db
.GetMovieInfo({}, *tag
, static_cast<int>(params
.GetMovieId()),
2298 static_cast<int>(params
.GetVideoVersionId()));
2299 else if (params
.GetMVideoId() >= 0)
2300 ret
= db
.GetMusicVideoInfo({}, *tag
, static_cast<int>(params
.GetMVideoId()));
2301 else if (params
.GetEpisodeId() >= 0)
2302 ret
= db
.GetEpisodeInfo({}, *tag
, static_cast<int>(params
.GetEpisodeId()));
2303 else if (params
.GetSetId() >= 0) // movie set
2304 ret
= db
.GetSetInfo(static_cast<int>(params
.GetSetId()), *tag
, this);
2305 else if (params
.GetTvShowId() >= 0)
2307 if (params
.GetSeason() >= 0)
2309 const int idSeason
= db
.GetSeasonId(static_cast<int>(params
.GetTvShowId()),
2310 static_cast<int>(params
.GetSeason()));
2312 ret
= db
.GetSeasonInfo(idSeason
, *tag
, this);
2315 ret
= db
.GetTvShowInfo({}, *tag
, static_cast<int>(params
.GetTvShowId()), this);
2320 const CFileItem loadedItem
{*tag
};
2321 UpdateInfo(loadedItem
);
2328 const std::shared_ptr
<CFileItem
> loadedItem
{
2329 CServiceBroker::GetPVRManager().Get
<PVR::GUI::Utils
>().LoadItem(*this)};
2332 UpdateInfo(*loadedItem
);
2335 CLog::LogF(LOGERROR
, "Error filling PVR item details (path={})", GetPath());
2339 if (!PLAYLIST::IsPlayList(*this) && VIDEO::IsVideo(*this))
2341 if (HasVideoInfoTag())
2347 CLog::LogF(LOGERROR
, "Error opening video database");
2351 auto tag
{std::make_unique
<CVideoInfoTag
>()};
2352 if (db
.LoadVideoInfo(GetDynPath(), *tag
))
2354 const CFileItem loadedItem
{*tag
};
2355 UpdateInfo(loadedItem
);
2359 CLog::LogF(LOGERROR
, "Error filling item details (path={})", GetPath());
2363 if (PLAYLIST::IsPlayList(*this) && IsType(".strm"))
2365 const std::unique_ptr
<PLAYLIST::CPlayList
> playlist(PLAYLIST::CPlayListFactory::Create(*this));
2368 if (playlist
->Load(GetPath()) && playlist
->size() == 1)
2370 const auto item
{(*playlist
)[0]};
2371 if (VIDEO::IsVideo(*item
))
2376 CLog::LogF(LOGERROR
, "Error opening video database");
2381 if (db
.LoadVideoInfo(GetDynPath(), tag
))
2384 *GetVideoInfoTag() = tag
;
2388 else if (MUSIC::IsAudio(*item
))
2390 if (item
->LoadMusicTag())
2398 CLog::LogF(LOGERROR
, "Error loading strm file details (path={})", GetPath());
2402 if (MUSIC::IsAudio(*this))
2404 return LoadMusicTag();
2407 if (MUSIC::IsMusicDb(*this))
2409 if (HasMusicInfoTag())
2415 CLog::LogF(LOGERROR
, "Error opening music database");
2419 MUSICDATABASEDIRECTORY::CQueryParams params
;
2420 MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(GetPath(), params
);
2422 if (params
.GetSongId() >= 0)
2425 if (db
.GetSong(params
.GetSongId(), song
))
2427 GetMusicInfoTag()->SetSong(song
);
2431 else if (params
.GetAlbumId() >= 0)
2435 if (db
.GetAlbum(params
.GetAlbumId(), album
, false))
2437 GetMusicInfoTag()->SetAlbum(album
);
2441 else if (params
.GetArtistId() >= 0)
2445 if (db
.GetArtist(params
.GetArtistId(), artist
, false))
2447 GetMusicInfoTag()->SetArtist(artist
);
2454 //! @todo add support for other types on demand.
2455 CLog::LogF(LOGDEBUG
, "Unsupported item type (path={})", GetPath());
2459 bool CFileItem::HasVideoInfoTag() const
2461 // Note: CPVRRecording is derived from CVideoInfoTag
2462 return m_pvrRecordingInfoTag
.get() != nullptr || m_videoInfoTag
!= nullptr;
2465 CVideoInfoTag
* CFileItem::GetVideoInfoTag()
2467 // Note: CPVRRecording is derived from CVideoInfoTag
2468 if (m_pvrRecordingInfoTag
)
2469 return m_pvrRecordingInfoTag
.get();
2470 else if (!m_videoInfoTag
)
2471 m_videoInfoTag
= new CVideoInfoTag
;
2473 return m_videoInfoTag
;
2476 const CVideoInfoTag
* CFileItem::GetVideoInfoTag() const
2478 // Note: CPVRRecording is derived from CVideoInfoTag
2479 return m_pvrRecordingInfoTag
? m_pvrRecordingInfoTag
.get() : m_videoInfoTag
;
2482 CPictureInfoTag
* CFileItem::GetPictureInfoTag()
2484 if (!m_pictureInfoTag
)
2485 m_pictureInfoTag
= new CPictureInfoTag
;
2487 return m_pictureInfoTag
;
2490 MUSIC_INFO::CMusicInfoTag
* CFileItem::GetMusicInfoTag()
2492 if (!m_musicInfoTag
)
2493 m_musicInfoTag
= new MUSIC_INFO::CMusicInfoTag
;
2495 return m_musicInfoTag
;
2498 CGameInfoTag
* CFileItem::GetGameInfoTag()
2501 m_gameInfoTag
= new CGameInfoTag
;
2503 return m_gameInfoTag
;
2506 bool CFileItem::HasPVRChannelInfoTag() const
2508 return m_pvrChannelGroupMemberInfoTag
&& m_pvrChannelGroupMemberInfoTag
->Channel() != nullptr;
2511 const std::shared_ptr
<PVR::CPVRChannel
> CFileItem::GetPVRChannelInfoTag() const
2513 return m_pvrChannelGroupMemberInfoTag
? m_pvrChannelGroupMemberInfoTag
->Channel()
2514 : std::shared_ptr
<CPVRChannel
>();
2517 std::string
CFileItem::FindTrailer() const
2519 std::string strFile2
;
2520 std::string strFile
= m_strPath
;
2523 std::string strPath
;
2524 URIUtils::GetParentPath(m_strPath
,strPath
);
2525 CStackDirectory dir
;
2526 std::string strPath2
;
2527 strPath2
= dir
.GetStackedTitlePath(strFile
);
2528 strFile
= URIUtils::AddFileToFolder(strPath
,URIUtils::GetFileName(strPath2
));
2529 CFileItem
item(dir
.GetFirstStackedFile(m_strPath
),false);
2530 std::string
strTBNFile(URIUtils::ReplaceExtension(ART::GetTBNFile(item
), "-trailer"));
2531 strFile2
= URIUtils::AddFileToFolder(strPath
,URIUtils::GetFileName(strTBNFile
));
2533 if (URIUtils::IsInRAR(strFile
) || URIUtils::IsInZIP(strFile
))
2535 std::string strPath
= URIUtils::GetDirectory(strFile
);
2536 std::string strParent
;
2537 URIUtils::GetParentPath(strPath
,strParent
);
2538 strFile
= URIUtils::AddFileToFolder(strParent
,URIUtils::GetFileName(m_strPath
));
2541 // no local trailer available for these
2542 if (NETWORK::IsInternetStream(*this) || URIUtils::IsUPnP(strFile
) ||
2543 URIUtils::IsBluray(strFile
) || IsLiveTV() || IsPlugin() || IsDVD())
2546 std::string strDir
= URIUtils::GetDirectory(strFile
);
2547 CFileItemList items
;
2548 CDirectory::GetDirectory(strDir
, items
, CServiceBroker::GetFileExtensionProvider().GetVideoExtensions(), DIR_FLAG_READ_CACHE
| DIR_FLAG_NO_FILE_INFO
| DIR_FLAG_NO_FILE_DIRS
);
2549 URIUtils::RemoveExtension(strFile
);
2550 strFile
+= "-trailer";
2551 std::string strFile3
= URIUtils::AddFileToFolder(strDir
, "movie-trailer");
2553 // Precompile our REs
2554 VECCREGEXP matchRegExps
;
2555 CRegExp
tmpRegExp(true, CRegExp::autoUtf8
);
2556 const std::vector
<std::string
>& strMatchRegExps
= CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_trailerMatchRegExps
;
2558 std::vector
<std::string
>::const_iterator strRegExp
= strMatchRegExps
.begin();
2559 while (strRegExp
!= strMatchRegExps
.end())
2561 if (tmpRegExp
.RegComp(*strRegExp
))
2563 matchRegExps
.push_back(tmpRegExp
);
2568 std::string strTrailer
;
2569 for (int i
= 0; i
< items
.Size(); i
++)
2571 std::string strCandidate
= items
[i
]->m_strPath
;
2572 URIUtils::RemoveExtension(strCandidate
);
2573 if (StringUtils::EqualsNoCase(strCandidate
, strFile
) ||
2574 StringUtils::EqualsNoCase(strCandidate
, strFile2
) ||
2575 StringUtils::EqualsNoCase(strCandidate
, strFile3
))
2577 strTrailer
= items
[i
]->m_strPath
;
2582 VECCREGEXP::iterator expr
= matchRegExps
.begin();
2584 while (expr
!= matchRegExps
.end())
2586 if (expr
->RegFind(strCandidate
) != -1)
2588 strTrailer
= items
[i
]->m_strPath
;
2600 VideoDbContentType
CFileItem::GetVideoContentType() const
2602 VideoDbContentType type
= VideoDbContentType::MOVIES
;
2603 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeTvShow
)
2604 type
= VideoDbContentType::TVSHOWS
;
2605 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeEpisode
)
2606 return VideoDbContentType::EPISODES
;
2607 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeMusicVideo
)
2608 return VideoDbContentType::MUSICVIDEOS
;
2609 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeAlbum
)
2610 return VideoDbContentType::MUSICALBUMS
;
2612 CVideoDatabaseDirectory dir
;
2613 VIDEODATABASEDIRECTORY::CQueryParams params
;
2614 dir
.GetQueryParams(m_strPath
, params
);
2615 if (params
.GetSetId() != -1 && params
.GetMovieId() == -1) // movie set
2616 return VideoDbContentType::MOVIE_SETS
;
2621 CFileItem
CFileItem::GetItemToPlay() const
2623 if (HasEPGInfoTag())
2625 const std::shared_ptr
<CPVRChannelGroupMember
> groupMember
=
2626 CServiceBroker::GetPVRManager().Get
<PVR::GUI::Channels
>().GetChannelGroupMember(*this);
2628 return CFileItem(groupMember
);
2633 CBookmark
CFileItem::GetResumePoint() const
2635 if (HasVideoInfoTag())
2636 return GetVideoInfoTag()->GetResumePoint();
2640 bool CFileItem::IsResumePointSet() const
2642 return GetResumePoint().IsSet();
2645 double CFileItem::GetCurrentResumeTime() const
2647 return lrint(GetResumePoint().timeInSeconds
);
2650 bool CFileItem::GetCurrentResumeTimeAndPartNumber(int64_t& startOffset
, int& partNumber
) const
2652 CBookmark
resumePoint(GetResumePoint());
2653 if (resumePoint
.IsSet())
2655 startOffset
= llrint(resumePoint
.timeInSeconds
);
2656 partNumber
= resumePoint
.partNumber
;
2662 bool CFileItem::IsResumable() const
2666 int64_t watched
= 0;
2667 int64_t inprogress
= 0;
2669 if (HasProperty("inprogressepisodes"))
2672 watched
= GetProperty("watchedepisodes").asInteger();
2673 inprogress
= GetProperty("inprogressepisodes").asInteger();
2674 total
= GetProperty("totalepisodes").asInteger();
2676 else if (HasProperty("inprogress"))
2679 watched
= GetProperty("watched").asInteger();
2680 inprogress
= GetProperty("inprogress").asInteger();
2681 total
= GetProperty("total").asInteger();
2684 return ((total
!= watched
) && (inprogress
> 0 || watched
!= 0));
2688 return HasVideoInfoTag() && GetVideoInfoTag()->GetResumePoint().IsPartWay();
2692 bool CFileItem::HasVideoVersions() const
2694 if (HasVideoInfoTag())
2696 return GetVideoInfoTag()->HasVideoVersions();
2701 bool CFileItem::HasVideoExtras() const
2703 if (HasVideoInfoTag())
2705 return GetVideoInfoTag()->HasVideoExtras();