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/providers/PVRProvider.h"
49 #include "pvr/recordings/PVRRecording.h"
50 #include "pvr/timers/PVRTimerInfoTag.h"
51 #include "settings/AdvancedSettings.h"
52 #include "settings/SettingUtils.h"
53 #include "settings/Settings.h"
54 #include "settings/SettingsComponent.h"
55 #include "settings/lib/Setting.h"
56 #include "utils/Archive.h"
57 #include "utils/ArtUtils.h"
58 #include "utils/FileExtensionProvider.h"
59 #include "utils/Mime.h"
60 #include "utils/RegExp.h"
61 #include "utils/StringUtils.h"
62 #include "utils/URIUtils.h"
63 #include "utils/Variant.h"
64 #include "utils/log.h"
65 #include "video/Bookmark.h"
66 #include "video/VideoDatabase.h"
67 #include "video/VideoFileItemClassify.h"
68 #include "video/VideoInfoTag.h"
69 #include "video/VideoUtils.h"
75 using namespace XFILE
;
76 using namespace PLAYLIST
;
77 using namespace MUSIC_INFO
;
81 CFileItem::CFileItem(const CSong
& song
)
87 CFileItem::CFileItem(const CSong
& song
, const CMusicInfoTag
& music
)
91 *GetMusicInfoTag() = music
;
94 CFileItem::CFileItem(const CURL
&url
, const CAlbum
& album
)
98 m_strPath
= url
.Get();
99 URIUtils::AddSlashAtEnd(m_strPath
);
103 CFileItem::CFileItem(const std::string
&path
, const CAlbum
& album
)
108 URIUtils::AddSlashAtEnd(m_strPath
);
112 CFileItem::CFileItem(const CMusicInfoTag
& music
)
115 SetLabel(music
.GetTitle());
116 m_strPath
= music
.GetURL();
117 m_bIsFolder
= URIUtils::HasSlashAtEnd(m_strPath
);
118 *GetMusicInfoTag() = music
;
119 ART::FillInDefaultIcon(*this);
120 FillInMimeType(false);
123 CFileItem::CFileItem(const CVideoInfoTag
& movie
)
126 SetFromVideoInfoTag(movie
);
129 void CFileItem::FillMusicInfoTag(const std::shared_ptr
<const CPVREpgInfoTag
>& tag
)
131 CMusicInfoTag
* musictag
= GetMusicInfoTag(); // create (!) the music tag.
133 musictag
->SetTitle(CServiceBroker::GetPVRManager().Get
<PVR::GUI::EPG
>().GetTitleForEpgTag(tag
));
137 musictag
->SetGenre(tag
->Genre());
138 musictag
->SetDuration(tag
->GetDuration());
139 musictag
->SetURL(tag
->Path());
142 musictag
->SetLoaded(true);
145 CFileItem::CFileItem(const std::shared_ptr
<CPVREpgInfoTag
>& tag
)
151 m_strPath
= tag
->Path();
153 SetLabel(CServiceBroker::GetPVRManager().Get
<PVR::GUI::EPG
>().GetTitleForEpgTag(tag
));
154 m_dateTime
= tag
->StartAsLocalTime();
156 if (!tag
->IconPath().empty())
158 SetArt("icon", tag
->IconPath());
162 const std::string iconPath
= tag
->ChannelIconPath();
163 if (!iconPath
.empty())
164 SetArt("icon", iconPath
);
165 else if (tag
->IsRadio())
166 SetArt("icon", "DefaultMusicSongs.png");
168 SetArt("icon", "DefaultTVShows.png");
171 // Speedup FillInDefaultIcon()
172 SetProperty("icon_never_overlay", true);
174 if (tag
->IsRadio() && !HasMusicInfoTag())
175 FillMusicInfoTag(tag
);
177 FillInMimeType(false);
180 CFileItem::CFileItem(const std::shared_ptr
<PVR::CPVREpgSearchFilter
>& filter
)
185 m_epgSearchFilter
= filter
;
186 m_strPath
= filter
->GetPath();
188 SetLabel(filter
->GetTitle());
190 const CDateTime lastExec
= filter
->GetLastExecutedDateTime();
191 if (lastExec
.IsValid())
192 m_dateTime
.SetFromUTCDateTime(lastExec
);
194 const std::string iconPath
= filter
->GetIconPath();
195 if (!iconPath
.empty())
196 SetArt("icon", iconPath
);
198 SetArt("icon", "DefaultPVRSearch.png");
200 // Speedup FillInDefaultIcon()
201 SetProperty("icon_never_overlay", true);
203 FillInMimeType(false);
206 CFileItem::CFileItem(const std::shared_ptr
<CPVRChannelGroupMember
>& channelGroupMember
)
210 const std::shared_ptr
<const CPVRChannel
> channel
= channelGroupMember
->Channel();
212 m_pvrChannelGroupMemberInfoTag
= channelGroupMember
;
214 m_strPath
= channelGroupMember
->Path();
217 SetLabel(channel
->ChannelName());
219 if (!channel
->IconPath().empty())
220 SetArt("icon", channel
->IconPath());
221 else if (channel
->IsRadio())
222 SetArt("icon", "DefaultMusicSongs.png");
224 SetArt("icon", "DefaultTVShows.png");
226 SetProperty("channelid", channel
->ChannelID());
227 SetProperty("path", channelGroupMember
->Path());
228 SetArt("thumb", channel
->IconPath());
230 // Speedup FillInDefaultIcon()
231 SetProperty("icon_never_overlay", true);
233 if (channel
->IsRadio() && !HasMusicInfoTag())
235 const std::shared_ptr
<const CPVREpgInfoTag
> epgNow
= channel
->GetEPGNow();
236 FillMusicInfoTag(epgNow
);
238 FillInMimeType(false);
241 CFileItem::CFileItem(const std::shared_ptr
<CPVRRecording
>& record
)
246 m_pvrRecordingInfoTag
= record
;
247 m_strPath
= record
->m_strFileNameAndPath
;
248 SetLabel(record
->m_strTitle
);
249 m_dateTime
= record
->RecordingTimeAsLocalTime();
250 m_dwSize
= record
->GetSizeInBytes();
254 if (!record
->IconPath().empty())
255 SetArt("icon", record
->IconPath());
258 const std::shared_ptr
<const CPVRChannel
> channel
= record
->Channel();
259 if (channel
&& !channel
->IconPath().empty())
260 SetArt("icon", channel
->IconPath());
261 else if (record
->IsRadio())
262 SetArt("icon", "DefaultMusicSongs.png");
264 SetArt("icon", "DefaultTVShows.png");
267 if (!record
->ThumbnailPath().empty())
268 SetArt("thumb", record
->ThumbnailPath());
270 if (!record
->FanartPath().empty())
271 SetArt("fanart", record
->FanartPath());
273 // Speedup FillInDefaultIcon()
274 SetProperty("icon_never_overlay", true);
276 FillInMimeType(false);
279 CFileItem::CFileItem(const std::shared_ptr
<CPVRTimerInfoTag
>& timer
)
283 m_bIsFolder
= timer
->IsTimerRule();
284 m_pvrTimerInfoTag
= timer
;
285 m_strPath
= timer
->Path();
286 SetLabel(timer
->Title());
287 m_dateTime
= timer
->StartAsLocalTime();
290 if (!timer
->ChannelIcon().empty())
291 SetArt("icon", timer
->ChannelIcon());
292 else if (timer
->IsRadio())
293 SetArt("icon", "DefaultMusicSongs.png");
295 SetArt("icon", "DefaultTVShows.png");
297 // Speedup FillInDefaultIcon()
298 SetProperty("icon_never_overlay", true);
300 FillInMimeType(false);
303 CFileItem::CFileItem(const std::string
& path
, const std::shared_ptr
<CPVRProvider
>& provider
)
309 m_pvrProviderInfoTag
= provider
;
310 SetLabel(provider
->GetName());
314 if (!provider
->GetIconPath().empty())
315 SetArt("icon", provider
->GetIconPath());
317 SetArt("icon", "DefaultPVRProvider.png");
319 if (!provider
->GetThumbPath().empty())
320 SetArt("thumb", provider
->GetThumbPath());
322 // Speedup FillInDefaultIcon()
323 SetProperty("icon_never_overlay", true);
325 FillInMimeType(false);
328 CFileItem::CFileItem(const CArtist
& artist
)
331 SetLabel(artist
.strArtist
);
332 m_strPath
= artist
.strArtist
;
334 URIUtils::AddSlashAtEnd(m_strPath
);
335 GetMusicInfoTag()->SetArtist(artist
);
336 FillInMimeType(false);
339 CFileItem::CFileItem(const CGenre
& genre
)
342 SetLabel(genre
.strGenre
);
343 m_strPath
= genre
.strGenre
;
345 URIUtils::AddSlashAtEnd(m_strPath
);
346 GetMusicInfoTag()->SetGenre(genre
.strGenre
);
347 FillInMimeType(false);
350 CFileItem::CFileItem(const CFileItem
& item
)
351 : CGUIListItem(item
),
352 m_musicInfoTag(NULL
),
353 m_videoInfoTag(NULL
),
354 m_pictureInfoTag(NULL
),
360 CFileItem::CFileItem(const CGUIListItem
& item
)
363 // not particularly pretty, but it gets around the issue of Initialize() defaulting
364 // parameters in the CGUIListItem base class.
365 *static_cast<CGUIListItem
*>(this) = item
;
367 FillInMimeType(false);
370 CFileItem::CFileItem(void)
375 CFileItem::CFileItem(const std::string
& strLabel
)
381 CFileItem::CFileItem(const char* strLabel
)
384 SetLabel(std::string(strLabel
));
387 CFileItem::CFileItem(const CURL
& path
, bool bIsFolder
)
390 m_strPath
= path
.Get();
391 m_bIsFolder
= bIsFolder
;
392 if (m_bIsFolder
&& !m_strPath
.empty() && !IsFileFolder())
393 URIUtils::AddSlashAtEnd(m_strPath
);
394 FillInMimeType(false);
397 CFileItem::CFileItem(const std::string
& strPath
, bool bIsFolder
)
401 m_bIsFolder
= bIsFolder
;
402 if (m_bIsFolder
&& !m_strPath
.empty() && !IsFileFolder())
403 URIUtils::AddSlashAtEnd(m_strPath
);
404 FillInMimeType(false);
407 CFileItem::CFileItem(const CMediaSource
& share
)
411 m_bIsShareOrDrive
= true;
412 m_strPath
= share
.strPath
;
413 if (!IsRSS()) // no slash at end for rss feeds
414 URIUtils::AddSlashAtEnd(m_strPath
);
415 std::string label
= share
.strName
;
416 if (!share
.strStatus
.empty())
417 label
= StringUtils::Format("{} ({})", share
.strName
, share
.strStatus
);
419 m_iLockMode
= share
.m_iLockMode
;
420 m_strLockCode
= share
.m_strLockCode
;
421 m_iHasLock
= share
.m_iHasLock
;
422 m_iBadPwdCount
= share
.m_iBadPwdCount
;
423 m_iDriveType
= share
.m_iDriveType
;
424 SetArt("thumb", share
.m_strThumbnailImage
);
425 SetLabelPreformatted(true);
427 GetVideoInfoTag()->m_strFileNameAndPath
= share
.strDiskUniqueId
; // share.strDiskUniqueId contains disc unique id
428 FillInMimeType(false);
431 CFileItem::CFileItem(std::shared_ptr
<const ADDON::IAddon
> addonInfo
) : m_addonInfo(std::move(addonInfo
))
436 CFileItem::CFileItem(const EventPtr
& eventLogEntry
)
440 m_eventLogEntry
= eventLogEntry
;
441 SetLabel(eventLogEntry
->GetLabel());
442 m_dateTime
= eventLogEntry
->GetDateTime();
443 if (!eventLogEntry
->GetIcon().empty())
444 SetArt("icon", eventLogEntry
->GetIcon());
447 CFileItem::~CFileItem(void)
449 delete m_musicInfoTag
;
450 delete m_videoInfoTag
;
451 delete m_pictureInfoTag
;
452 delete m_gameInfoTag
;
454 m_musicInfoTag
= NULL
;
455 m_videoInfoTag
= NULL
;
456 m_pictureInfoTag
= NULL
;
457 m_gameInfoTag
= NULL
;
460 CFileItem
& CFileItem::operator=(const CFileItem
& item
)
465 CGUIListItem::operator=(item
);
466 m_bLabelPreformatted
=item
.m_bLabelPreformatted
;
468 m_strPath
= item
.m_strPath
;
469 m_strDynPath
= item
.m_strDynPath
;
470 m_bIsParentFolder
= item
.m_bIsParentFolder
;
471 m_iDriveType
= item
.m_iDriveType
;
472 m_bIsShareOrDrive
= item
.m_bIsShareOrDrive
;
473 m_dateTime
= item
.m_dateTime
;
474 m_dwSize
= item
.m_dwSize
;
476 if (item
.m_musicInfoTag
)
479 *m_musicInfoTag
= *item
.m_musicInfoTag
;
481 m_musicInfoTag
= new MUSIC_INFO::CMusicInfoTag(*item
.m_musicInfoTag
);
485 delete m_musicInfoTag
;
486 m_musicInfoTag
= NULL
;
489 if (item
.m_videoInfoTag
)
492 *m_videoInfoTag
= *item
.m_videoInfoTag
;
494 m_videoInfoTag
= new CVideoInfoTag(*item
.m_videoInfoTag
);
498 delete m_videoInfoTag
;
499 m_videoInfoTag
= NULL
;
502 if (item
.m_pictureInfoTag
)
504 if (m_pictureInfoTag
)
505 *m_pictureInfoTag
= *item
.m_pictureInfoTag
;
507 m_pictureInfoTag
= new CPictureInfoTag(*item
.m_pictureInfoTag
);
511 delete m_pictureInfoTag
;
512 m_pictureInfoTag
= NULL
;
515 if (item
.m_gameInfoTag
)
518 *m_gameInfoTag
= *item
.m_gameInfoTag
;
520 m_gameInfoTag
= new CGameInfoTag(*item
.m_gameInfoTag
);
524 delete m_gameInfoTag
;
525 m_gameInfoTag
= NULL
;
528 m_epgInfoTag
= item
.m_epgInfoTag
;
529 m_epgSearchFilter
= item
.m_epgSearchFilter
;
530 m_pvrChannelGroupMemberInfoTag
= item
.m_pvrChannelGroupMemberInfoTag
;
531 m_pvrRecordingInfoTag
= item
.m_pvrRecordingInfoTag
;
532 m_pvrTimerInfoTag
= item
.m_pvrTimerInfoTag
;
533 m_pvrProviderInfoTag
= item
.m_pvrProviderInfoTag
;
534 m_addonInfo
= item
.m_addonInfo
;
535 m_eventLogEntry
= item
.m_eventLogEntry
;
537 m_lStartOffset
= item
.m_lStartOffset
;
538 m_lStartPartNumber
= item
.m_lStartPartNumber
;
539 m_lEndOffset
= item
.m_lEndOffset
;
540 m_strDVDLabel
= item
.m_strDVDLabel
;
541 m_strTitle
= item
.m_strTitle
;
542 m_iprogramCount
= item
.m_iprogramCount
;
543 m_idepth
= item
.m_idepth
;
544 m_iLockMode
= item
.m_iLockMode
;
545 m_strLockCode
= item
.m_strLockCode
;
546 m_iHasLock
= item
.m_iHasLock
;
547 m_iBadPwdCount
= item
.m_iBadPwdCount
;
548 m_bCanQueue
=item
.m_bCanQueue
;
549 m_mimetype
= item
.m_mimetype
;
550 m_extrainfo
= item
.m_extrainfo
;
551 m_specialSort
= item
.m_specialSort
;
552 m_bIsAlbum
= item
.m_bIsAlbum
;
553 m_doContentLookup
= item
.m_doContentLookup
;
557 void CFileItem::Initialize()
559 m_musicInfoTag
= NULL
;
560 m_videoInfoTag
= NULL
;
561 m_pictureInfoTag
= NULL
;
562 m_gameInfoTag
= NULL
;
563 m_bLabelPreformatted
= false;
566 m_bIsParentFolder
= false;
567 m_bIsShareOrDrive
= false;
568 m_iDriveType
= CMediaSource::SOURCE_TYPE_UNKNOWN
;
570 m_lStartPartNumber
= 1;
574 m_iLockMode
= LOCK_MODE_EVERYONE
;
576 m_iHasLock
= LOCK_STATE_NO_LOCK
;
578 m_specialSort
= SortSpecialNone
;
579 m_doContentLookup
= true;
582 void CFileItem::Reset()
584 // CGUIListItem members...
588 m_overlayIcon
= ICON_OVERLAY_NONE
;
592 m_strDVDLabel
.clear();
595 m_strDynPath
.clear();
597 m_strLockCode
.clear();
599 delete m_musicInfoTag
;
601 delete m_videoInfoTag
;
603 m_epgInfoTag
.reset();
604 m_epgSearchFilter
.reset();
605 m_pvrChannelGroupMemberInfoTag
.reset();
606 m_pvrRecordingInfoTag
.reset();
607 m_pvrTimerInfoTag
.reset();
608 m_pvrProviderInfoTag
.reset();
609 delete m_pictureInfoTag
;
610 m_pictureInfoTag
=NULL
;
611 delete m_gameInfoTag
;
612 m_gameInfoTag
= NULL
;
615 m_eventLogEntry
.reset();
621 // do not archive dynamic path
622 void CFileItem::Archive(CArchive
& ar
)
624 CGUIListItem::Archive(ar
);
628 ar
<< m_bIsParentFolder
;
629 ar
<< m_bLabelPreformatted
;
631 ar
<< m_bIsShareOrDrive
;
637 ar
<< m_iprogramCount
;
639 ar
<< m_lStartOffset
;
640 ar
<< m_lStartPartNumber
;
644 ar
<< m_iBadPwdCount
;
650 ar
<< m_doContentLookup
;
655 ar
<< *m_musicInfoTag
;
662 ar
<< *m_videoInfoTag
;
666 if (m_pictureInfoTag
)
669 ar
<< *m_pictureInfoTag
;
676 ar
<< *m_gameInfoTag
;
683 ar
>> m_bIsParentFolder
;
684 ar
>> m_bLabelPreformatted
;
686 ar
>> m_bIsShareOrDrive
;
692 ar
>> m_iprogramCount
;
694 ar
>> m_lStartOffset
;
695 ar
>> m_lStartPartNumber
;
699 m_iLockMode
= (LockType
)temp
;
701 ar
>> m_iBadPwdCount
;
707 m_specialSort
= (SortSpecial
)temp
;
708 ar
>> m_doContentLookup
;
713 ar
>> *GetMusicInfoTag();
716 ar
>> *GetVideoInfoTag();
719 ar
>> *GetPictureInfoTag();
722 ar
>> *GetGameInfoTag();
728 void CFileItem::Serialize(CVariant
& value
) const
730 //CGUIListItem::Serialize(value["CGUIListItem"]);
732 value
["strPath"] = m_strPath
;
733 value
["dateTime"] = (m_dateTime
.IsValid()) ? m_dateTime
.GetAsRFC1123DateTime() : "";
734 value
["lastmodified"] = m_dateTime
.IsValid() ? m_dateTime
.GetAsDBDateTime() : "";
735 value
["size"] = m_dwSize
;
736 value
["DVDLabel"] = m_strDVDLabel
;
737 value
["title"] = m_strTitle
;
738 value
["mimetype"] = m_mimetype
;
739 value
["extrainfo"] = m_extrainfo
;
742 (*m_musicInfoTag
).Serialize(value
["musicInfoTag"]);
745 (*m_videoInfoTag
).Serialize(value
["videoInfoTag"]);
747 if (m_pictureInfoTag
)
748 (*m_pictureInfoTag
).Serialize(value
["pictureInfoTag"]);
751 (*m_gameInfoTag
).Serialize(value
["gameInfoTag"]);
753 if (!m_mapProperties
.empty())
755 auto& customProperties
= value
["customproperties"];
756 for (const auto& prop
: m_mapProperties
)
757 customProperties
[prop
.first
] = prop
.second
;
761 void CFileItem::ToSortable(SortItem
&sortable
, Field field
) const
766 sortable
[FieldPath
] = m_strPath
;
769 sortable
[FieldDate
] = (m_dateTime
.IsValid()) ? m_dateTime
.GetAsDBDateTime() : "";
772 sortable
[FieldSize
] = m_dwSize
;
775 sortable
[FieldDriveType
] = m_iDriveType
;
777 case FieldStartOffset
:
778 sortable
[FieldStartOffset
] = m_lStartOffset
;
781 sortable
[FieldEndOffset
] = m_lEndOffset
;
783 case FieldProgramCount
:
784 sortable
[FieldProgramCount
] = m_iprogramCount
;
787 sortable
[FieldBitrate
] = m_dwSize
;
790 sortable
[FieldTitle
] = m_strTitle
;
793 // If there's ever a need to convert more properties from CGUIListItem it might be
794 // worth to make CGUIListItem implement ISortable as well and call it from here
800 if (HasMusicInfoTag())
801 GetMusicInfoTag()->ToSortable(sortable
, field
);
803 if (HasVideoInfoTag())
804 GetVideoInfoTag()->ToSortable(sortable
, field
);
806 if (HasPictureInfoTag())
807 GetPictureInfoTag()->ToSortable(sortable
, field
);
809 if (HasPVRChannelInfoTag())
810 GetPVRChannelInfoTag()->ToSortable(sortable
, field
);
812 if (HasPVRChannelGroupMemberInfoTag())
813 GetPVRChannelGroupMemberInfoTag()->ToSortable(sortable
, field
);
815 if (HasPVRProviderInfoTag())
816 GetPVRProviderInfoTag()->ToSortable(sortable
, field
);
822 case FieldInstallDate
:
823 sortable
[FieldInstallDate
] = GetAddonInfo()->InstallDate().GetAsDBDateTime();
825 case FieldLastUpdated
:
826 sortable
[FieldLastUpdated
] = GetAddonInfo()->LastUpdated().GetAsDBDateTime();
829 sortable
[FieldLastUsed
] = GetAddonInfo()->LastUsed().GetAsDBDateTime();
836 if (HasGameInfoTag())
837 GetGameInfoTag()->ToSortable(sortable
, field
);
840 m_eventLogEntry
->ToSortable(sortable
, field
);
844 if (field
== FieldUserPreference
)
845 sortable
[FieldUserPreference
] = GetProperty("favourite.index").asString();
849 void CFileItem::ToSortable(SortItem
&sortable
, const Fields
&fields
) const
851 Fields::const_iterator it
;
852 for (it
= fields
.begin(); it
!= fields
.end(); ++it
)
853 ToSortable(sortable
, *it
);
855 /* FieldLabel is used as a fallback by all sorters and therefore has to be present as well */
856 sortable
[FieldLabel
] = GetLabel();
857 /* FieldSortSpecial and FieldFolder are required in conjunction with all other sorters as well */
858 sortable
[FieldSortSpecial
] = m_specialSort
;
859 sortable
[FieldFolder
] = m_bIsFolder
;
862 bool CFileItem::Exists(bool bUseCache
/* = true */) const
864 if (m_strPath
.empty() || IsPath("add") || NETWORK::IsInternetStream(*this) || IsParentFolder() ||
865 IsVirtualDirectoryRoot() || IsPlugin() || IsPVR())
868 if (VIDEO::IsVideoDb(*this) && HasVideoInfoTag())
870 CFileItem
dbItem(m_bIsFolder
? GetVideoInfoTag()->m_strPath
: GetVideoInfoTag()->m_strFileNameAndPath
, m_bIsFolder
);
871 return dbItem
.Exists();
874 std::string strPath
= m_strPath
;
876 if (URIUtils::IsMultiPath(strPath
))
877 strPath
= CMultiPathDirectory::GetFirstPath(strPath
);
879 if (URIUtils::IsStack(strPath
))
880 strPath
= CStackDirectory::GetFirstStackedFile(strPath
);
883 return CDirectory::Exists(strPath
, bUseCache
);
885 return CFile::Exists(strPath
, bUseCache
);
890 bool CFileItem::IsEPG() const
892 return HasEPGInfoTag();
895 bool CFileItem::IsPVRChannel() const
897 return HasPVRChannelInfoTag();
900 bool CFileItem::IsPVRChannelGroup() const
902 return URIUtils::IsPVRChannelGroup(m_strPath
);
905 bool CFileItem::IsPVRRecording() const
907 return HasPVRRecordingInfoTag();
910 bool CFileItem::IsUsablePVRRecording() const
912 return (m_pvrRecordingInfoTag
&& !m_pvrRecordingInfoTag
->IsDeleted());
915 bool CFileItem::IsDeletedPVRRecording() const
917 return (m_pvrRecordingInfoTag
&& m_pvrRecordingInfoTag
->IsDeleted());
920 bool CFileItem::IsInProgressPVRRecording() const
922 return (m_pvrRecordingInfoTag
&& m_pvrRecordingInfoTag
->IsInProgress());
925 bool CFileItem::IsPVRTimer() const
927 return HasPVRTimerInfoTag();
930 bool CFileItem::IsPVRProvider() const
932 return HasPVRProviderInfoTag();
935 bool CFileItem::IsDeleted() const
937 if (HasPVRRecordingInfoTag())
938 return GetPVRRecordingInfoTag()->IsDeleted();
943 bool CFileItem::IsGame() const
945 if (HasGameInfoTag())
948 if (HasVideoInfoTag())
951 if (HasMusicInfoTag())
954 if (HasPictureInfoTag())
961 return CGameUtils::IsStandaloneGame(std::const_pointer_cast
<ADDON::IAddon
>(GetAddonInfo()));
963 return CGameUtils::HasGameExtension(m_strPath
);
966 bool CFileItem::IsPicture() const
968 if (StringUtils::StartsWithNoCase(m_mimetype
, "image/"))
971 if (HasPictureInfoTag())
974 if (HasGameInfoTag())
977 if (HasMusicInfoTag())
980 if (HasVideoInfoTag())
983 if (HasPVRTimerInfoTag() || HasPVRChannelInfoTag() || HasPVRChannelGroupMemberInfoTag() ||
984 HasPVRRecordingInfoTag() || HasEPGInfoTag() || HasEPGSearchFilter() ||
985 HasPVRProviderInfoTag())
988 if (!m_strPath
.empty())
989 return CUtil::IsPicture(m_strPath
);
994 bool CFileItem::IsFileFolder(EFileFolderType types
) const
996 EFileFolderType always_type
= EFILEFOLDER_TYPE_ALWAYS
;
998 /* internet streams are not directly expanded */
999 if (NETWORK::IsInternetStream(*this))
1000 always_type
= EFILEFOLDER_TYPE_ONCLICK
;
1002 // strm files are not browsable
1003 if (IsType(".strm") && (types
& EFILEFOLDER_TYPE_ONBROWSE
))
1006 if (types
& always_type
)
1008 if (PLAYLIST::IsSmartPlayList(*this) ||
1009 (PLAYLIST::IsPlayList(*this) &&
1010 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_playlistAsFolders
) ||
1011 IsAPK() || IsZIP() || IsRAR() || IsRSS() || MUSIC::IsAudioBook(*this) ||
1012 IsType(".ogg|.oga|.xbt")
1013 #if defined(TARGET_ANDROID)
1020 if (CServiceBroker::IsAddonInterfaceUp() &&
1021 IsType(CServiceBroker::GetFileExtensionProvider().GetFileFolderExtensions().c_str()) &&
1022 CServiceBroker::GetFileExtensionProvider().CanOperateExtension(m_strPath
))
1025 if(types
& EFILEFOLDER_TYPE_ONBROWSE
)
1027 if ((PLAYLIST::IsPlayList(*this) &&
1028 !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_playlistAsFolders
) ||
1036 bool CFileItem::IsLibraryFolder() const
1038 if (HasProperty("library.filter") && GetProperty("library.filter").asBoolean())
1041 return URIUtils::IsLibraryFolder(m_strPath
);
1044 bool CFileItem::IsPythonScript() const
1046 return URIUtils::HasExtension(m_strPath
, ".py");
1049 bool CFileItem::IsType(const char *ext
) const
1051 if (!m_strDynPath
.empty())
1052 return URIUtils::HasExtension(m_strDynPath
, ext
);
1054 return URIUtils::HasExtension(m_strPath
, ext
);
1057 bool CFileItem::IsNFO() const
1059 return URIUtils::HasExtension(m_strPath
, ".nfo");
1062 bool CFileItem::IsDiscImage() const
1064 return URIUtils::IsDiscImage(GetDynPath());
1067 bool CFileItem::IsOpticalMediaFile() const
1069 if (VIDEO::IsDVDFile(*this, false, true))
1072 return VIDEO::IsBDFile(*this);
1075 bool CFileItem::IsRAR() const
1077 return URIUtils::IsRAR(m_strPath
);
1080 bool CFileItem::IsAPK() const
1082 return URIUtils::IsAPK(m_strPath
);
1085 bool CFileItem::IsZIP() const
1087 return URIUtils::IsZIP(m_strPath
);
1090 bool CFileItem::IsCBZ() const
1092 return URIUtils::HasExtension(m_strPath
, ".cbz");
1095 bool CFileItem::IsCBR() const
1097 return URIUtils::HasExtension(m_strPath
, ".cbr");
1100 bool CFileItem::IsRSS() const
1102 return StringUtils::StartsWithNoCase(m_strPath
, "rss://") || URIUtils::HasExtension(m_strPath
, ".rss")
1103 || StringUtils::StartsWithNoCase(m_strPath
, "rsss://")
1104 || m_mimetype
== "application/rss+xml";
1107 bool CFileItem::IsAndroidApp() const
1109 return URIUtils::IsAndroidApp(m_strPath
);
1112 bool CFileItem::IsStack() const
1114 return URIUtils::IsStack(GetDynPath());
1117 bool CFileItem::IsFavourite() const
1119 return URIUtils::IsFavourite(m_strPath
);
1122 bool CFileItem::IsPlugin() const
1124 return URIUtils::IsPlugin(m_strPath
);
1127 bool CFileItem::IsScript() const
1129 return URIUtils::IsScript(m_strPath
);
1132 bool CFileItem::IsAddonsPath() const
1134 return URIUtils::IsAddonsPath(m_strPath
);
1137 bool CFileItem::IsSourcesPath() const
1139 return URIUtils::IsSourcesPath(m_strPath
);
1142 bool CFileItem::IsMultiPath() const
1144 return URIUtils::IsMultiPath(m_strPath
);
1147 bool CFileItem::IsBluray() const
1149 if (URIUtils::IsBluray(m_strPath
))
1152 CFileItem item
= CFileItem(VIDEO::UTILS::GetOpticalMediaPath(*this), false);
1154 return VIDEO::IsBDFile(item
);
1157 bool CFileItem::IsDVD() const
1159 return URIUtils::IsDVD(m_strPath
) || m_iDriveType
== CMediaSource::SOURCE_TYPE_DVD
;
1162 bool CFileItem::IsOnDVD() const
1164 return URIUtils::IsOnDVD(m_strPath
) || m_iDriveType
== CMediaSource::SOURCE_TYPE_DVD
;
1167 bool CFileItem::IsNfs() const
1169 return URIUtils::IsNfs(m_strPath
);
1172 bool CFileItem::IsISO9660() const
1174 return URIUtils::IsISO9660(m_strPath
);
1177 bool CFileItem::IsSmb() const
1179 return URIUtils::IsSmb(m_strPath
);
1182 bool CFileItem::IsURL() const
1184 return URIUtils::IsURL(m_strPath
);
1187 bool CFileItem::IsPVR() const
1189 return URIUtils::IsPVR(m_strPath
);
1192 bool CFileItem::IsLiveTV() const
1194 return URIUtils::IsLiveTV(m_strPath
);
1197 bool CFileItem::IsHD() const
1199 return URIUtils::IsHD(m_strPath
);
1202 bool CFileItem::IsVirtualDirectoryRoot() const
1204 return (m_bIsFolder
&& m_strPath
.empty());
1207 bool CFileItem::IsRemovable() const
1209 return IsOnDVD() || MUSIC::IsCDDA(*this) || m_iDriveType
== CMediaSource::SOURCE_TYPE_REMOVABLE
;
1212 bool CFileItem::IsReadOnly() const
1214 if (IsParentFolder())
1217 if (m_bIsShareOrDrive
)
1220 return !CUtil::SupportsWriteFileOperations(m_strPath
);
1223 void CFileItem::RemoveExtension()
1228 std::string strLabel
= GetLabel();
1229 URIUtils::RemoveExtension(strLabel
);
1233 void CFileItem::CleanString()
1238 std::string strLabel
= GetLabel();
1239 std::string strTitle
, strTitleAndYear
, strYear
;
1240 CUtil::CleanString(strLabel
, strTitle
, strTitleAndYear
, strYear
, true);
1241 SetLabel(strTitleAndYear
);
1244 void CFileItem::SetLabel(const std::string
&strLabel
)
1246 if (strLabel
== "..")
1248 m_bIsParentFolder
= true;
1250 m_specialSort
= SortSpecialOnTop
;
1251 SetLabelPreformatted(true);
1253 CGUIListItem::SetLabel(strLabel
);
1256 void CFileItem::SetFileSizeLabel()
1258 if(m_bIsFolder
&& m_dwSize
== 0)
1261 SetLabel2(StringUtils::SizeToString(m_dwSize
));
1264 bool CFileItem::CanQueue() const
1269 void CFileItem::SetCanQueue(bool bYesNo
)
1271 m_bCanQueue
= bYesNo
;
1274 bool CFileItem::IsParentFolder() const
1276 return m_bIsParentFolder
;
1279 void CFileItem::FillInMimeType(bool lookup
/*= true*/)
1281 //! @todo adapt this to use CMime::GetMimeType()
1282 if (m_mimetype
.empty())
1285 m_mimetype
= "x-directory/normal";
1286 else if (HasPVRChannelInfoTag())
1287 m_mimetype
= GetPVRChannelInfoTag()->MimeType();
1288 else if (StringUtils::StartsWithNoCase(GetDynPath(), "shout://") ||
1289 StringUtils::StartsWithNoCase(GetDynPath(), "http://") ||
1290 StringUtils::StartsWithNoCase(GetDynPath(), "https://"))
1292 // If lookup is false, bail out early to leave mime type empty
1296 CCurlFile::GetMimeType(GetDynURL(), m_mimetype
);
1298 // try to get mime-type again but with an NSPlayer User-Agent
1299 // in order for server to provide correct mime-type. Allows us
1300 // to properly detect an MMS stream
1301 if (StringUtils::StartsWithNoCase(m_mimetype
, "video/x-ms-"))
1302 CCurlFile::GetMimeType(GetDynURL(), m_mimetype
, "NSPlayer/11.00.6001.7000");
1304 // make sure there are no options set in mime-type
1305 // mime-type can look like "video/x-ms-asf ; charset=utf8"
1306 size_t i
= m_mimetype
.find(';');
1307 if(i
!= std::string::npos
)
1308 m_mimetype
.erase(i
, m_mimetype
.length() - i
);
1309 StringUtils::Trim(m_mimetype
);
1312 m_mimetype
= CMime::GetMimeType(*this);
1314 // if it's still empty set to an unknown type
1315 if (m_mimetype
.empty())
1316 m_mimetype
= "application/octet-stream";
1319 // change protocol to mms for the following mime-type. Allows us to create proper FileMMS.
1320 if(StringUtils::StartsWithNoCase(m_mimetype
, "application/vnd.ms.wms-hdr.asfv1") ||
1321 StringUtils::StartsWithNoCase(m_mimetype
, "application/x-mms-framed"))
1323 if (m_strDynPath
.empty())
1324 m_strDynPath
= m_strPath
;
1326 StringUtils::Replace(m_strDynPath
, "http:", "mms:");
1330 void CFileItem::UpdateMimeType(bool lookup
/*= true*/)
1332 //! @todo application/octet-stream might actually have been set by a web lookup. Currently we
1333 //! cannot distinguish between set as fallback only (see FillInMimeType) or as an actual value.
1334 if (m_mimetype
== "application/octet-stream")
1337 FillInMimeType(lookup
);
1340 void CFileItem::SetMimeTypeForInternetFile()
1342 if (m_doContentLookup
&& NETWORK::IsInternetStream(*this))
1345 FillInMimeType(true);
1349 bool CFileItem::IsSamePath(const CFileItem
*item
) const
1354 if (!m_strPath
.empty() && item
->GetPath() == m_strPath
)
1356 if (item
->HasProperty("item_start") || HasProperty("item_start"))
1357 return (item
->GetProperty("item_start") == GetProperty("item_start"));
1358 // See if we have associated a bluray playlist
1359 if (VIDEO::IsBlurayPlaylist(*this) || VIDEO::IsBlurayPlaylist(*item
))
1360 return (GetDynPath() == item
->GetDynPath());
1363 if (HasMusicInfoTag() && item
->HasMusicInfoTag())
1365 if (GetMusicInfoTag()->GetDatabaseId() != -1 && item
->GetMusicInfoTag()->GetDatabaseId() != -1)
1366 return ((GetMusicInfoTag()->GetDatabaseId() == item
->GetMusicInfoTag()->GetDatabaseId()) &&
1367 (GetMusicInfoTag()->GetType() == item
->GetMusicInfoTag()->GetType()));
1369 if (HasVideoInfoTag() && item
->HasVideoInfoTag())
1371 const CVideoInfoTag
* myTag
{GetVideoInfoTag()};
1372 const CVideoInfoTag
* otherTag
{item
->GetVideoInfoTag()};
1373 if (myTag
->m_iDbId
!= -1 && otherTag
->m_iDbId
!= -1)
1375 if ((myTag
->m_iDbId
== otherTag
->m_iDbId
) && (myTag
->m_type
== otherTag
->m_type
))
1377 // for movies with multiple versions, wie need also to check the file id
1378 if (HasVideoVersions() && item
->HasVideoVersions() && myTag
->m_iFileId
!= -1 &&
1379 otherTag
->m_iFileId
!= -1)
1380 return myTag
->m_iFileId
== otherTag
->m_iFileId
;
1385 if (MUSIC::IsMusicDb(*this) && HasMusicInfoTag())
1387 CFileItem
dbItem(m_musicInfoTag
->GetURL(), false);
1388 if (HasProperty("item_start"))
1389 dbItem
.SetProperty("item_start", GetProperty("item_start"));
1390 return dbItem
.IsSamePath(item
);
1392 if (VIDEO::IsVideoDb(*this) && HasVideoInfoTag())
1394 CFileItem
dbItem(GetVideoInfoTag()->m_strFileNameAndPath
, false);
1395 if (HasProperty("item_start"))
1396 dbItem
.SetProperty("item_start", GetProperty("item_start"));
1397 return dbItem
.IsSamePath(item
);
1399 if (MUSIC::IsMusicDb(*item
) && item
->HasMusicInfoTag())
1401 CFileItem
dbItem(item
->m_musicInfoTag
->GetURL(), false);
1402 if (item
->HasProperty("item_start"))
1403 dbItem
.SetProperty("item_start", item
->GetProperty("item_start"));
1404 return IsSamePath(&dbItem
);
1406 if (VIDEO::IsVideoDb(*item
) && item
->HasVideoInfoTag())
1408 CFileItem
dbItem(item
->GetVideoInfoTag()->m_strFileNameAndPath
, false);
1409 if (item
->HasProperty("item_start"))
1410 dbItem
.SetProperty("item_start", item
->GetProperty("item_start"));
1411 return IsSamePath(&dbItem
);
1413 if (HasProperty("original_listitem_url"))
1414 return (GetProperty("original_listitem_url") == item
->GetPath());
1418 bool CFileItem::IsAlbum() const
1423 void CFileItem::UpdateInfo(const CFileItem
&item
, bool replaceLabels
/*=true*/)
1425 if (item
.HasVideoInfoTag())
1426 { // copy info across
1427 //! @todo premiered info is normally stored in m_dateTime by the db
1429 if (item
.m_videoInfoTag
)
1432 *m_videoInfoTag
= *item
.m_videoInfoTag
;
1434 m_videoInfoTag
= new CVideoInfoTag(*item
.m_videoInfoTag
);
1439 delete m_videoInfoTag
;
1441 m_videoInfoTag
= new CVideoInfoTag
;
1444 m_pvrRecordingInfoTag
= item
.m_pvrRecordingInfoTag
;
1446 SetOverlayImage(GetVideoInfoTag()->GetPlayCount() > 0 ? CGUIListItem::ICON_OVERLAY_WATCHED
1447 : CGUIListItem::ICON_OVERLAY_UNWATCHED
);
1450 if (item
.HasMusicInfoTag())
1452 *GetMusicInfoTag() = *item
.GetMusicInfoTag();
1455 if (item
.HasPictureInfoTag())
1457 *GetPictureInfoTag() = *item
.GetPictureInfoTag();
1460 if (item
.HasGameInfoTag())
1462 *GetGameInfoTag() = *item
.GetGameInfoTag();
1465 if (item
.HasPVRChannelGroupMemberInfoTag())
1467 m_pvrChannelGroupMemberInfoTag
= item
.GetPVRChannelGroupMemberInfoTag();
1470 if (item
.HasPVRTimerInfoTag())
1472 m_pvrTimerInfoTag
= item
.m_pvrTimerInfoTag
;
1475 if (item
.HasPVRProviderInfoTag())
1477 m_pvrProviderInfoTag
= item
.m_pvrProviderInfoTag
;
1480 if (item
.HasEPGInfoTag())
1482 m_epgInfoTag
= item
.m_epgInfoTag
;
1485 if (item
.HasEPGSearchFilter())
1487 m_epgSearchFilter
= item
.m_epgSearchFilter
;
1490 SetDynPath(item
.GetDynPath());
1491 if (replaceLabels
&& !item
.GetLabel().empty())
1492 SetLabel(item
.GetLabel());
1493 if (replaceLabels
&& !item
.GetLabel2().empty())
1494 SetLabel2(item
.GetLabel2());
1495 if (!item
.GetArt().empty())
1496 SetArt(item
.GetArt());
1497 AppendProperties(item
);
1499 SetContentLookup(item
.m_doContentLookup
);
1500 SetMimeType(item
.m_mimetype
);
1501 UpdateMimeType(m_doContentLookup
);
1504 void CFileItem::MergeInfo(const CFileItem
& item
)
1506 // TODO: Currently merge the metadata/art info is implemented for video case only
1507 if (item
.HasVideoInfoTag())
1509 if (item
.m_videoInfoTag
)
1512 m_videoInfoTag
->Merge(*item
.m_videoInfoTag
);
1514 m_videoInfoTag
= new CVideoInfoTag(*item
.m_videoInfoTag
);
1517 m_pvrRecordingInfoTag
= item
.m_pvrRecordingInfoTag
;
1519 SetOverlayImage(GetVideoInfoTag()->GetPlayCount() > 0 ? CGUIListItem::ICON_OVERLAY_WATCHED
1520 : CGUIListItem::ICON_OVERLAY_UNWATCHED
);
1523 if (item
.HasMusicInfoTag())
1525 *GetMusicInfoTag() = *item
.GetMusicInfoTag();
1528 if (item
.HasPictureInfoTag())
1530 *GetPictureInfoTag() = *item
.GetPictureInfoTag();
1533 if (item
.HasGameInfoTag())
1535 *GetGameInfoTag() = *item
.GetGameInfoTag();
1538 if (item
.HasPVRChannelGroupMemberInfoTag())
1540 m_pvrChannelGroupMemberInfoTag
= item
.GetPVRChannelGroupMemberInfoTag();
1543 if (item
.HasPVRTimerInfoTag())
1545 m_pvrTimerInfoTag
= item
.m_pvrTimerInfoTag
;
1548 if (item
.HasPVRProviderInfoTag())
1550 m_pvrProviderInfoTag
= item
.m_pvrProviderInfoTag
;
1553 if (item
.HasEPGInfoTag())
1555 m_epgInfoTag
= item
.m_epgInfoTag
;
1558 if (item
.HasEPGSearchFilter())
1560 m_epgSearchFilter
= item
.m_epgSearchFilter
;
1563 SetDynPath(item
.GetDynPath());
1564 if (!item
.GetLabel().empty())
1565 SetLabel(item
.GetLabel());
1566 if (!item
.GetLabel2().empty())
1567 SetLabel2(item
.GetLabel2());
1568 if (!item
.GetArt().empty())
1570 if (VIDEO::IsVideo(item
))
1571 AppendArt(item
.GetArt());
1573 SetArt(item
.GetArt());
1575 AppendProperties(item
);
1577 SetContentLookup(item
.m_doContentLookup
);
1578 SetMimeType(item
.m_mimetype
);
1579 UpdateMimeType(m_doContentLookup
);
1582 void CFileItem::SetFromVideoInfoTag(const CVideoInfoTag
&video
)
1584 if (!video
.m_strTitle
.empty())
1585 SetLabel(video
.m_strTitle
);
1586 if (video
.m_strFileNameAndPath
.empty())
1588 m_strPath
= video
.m_strPath
;
1589 URIUtils::AddSlashAtEnd(m_strPath
);
1594 m_strPath
= video
.m_strFileNameAndPath
;
1595 m_bIsFolder
= false;
1599 *m_videoInfoTag
= video
;
1601 m_videoInfoTag
= new CVideoInfoTag(video
);
1603 if (video
.m_iSeason
== 0)
1604 SetProperty("isspecial", "true");
1605 ART::FillInDefaultIcon(*this);
1606 FillInMimeType(false);
1611 class CPropertySaveHelper
1614 CPropertySaveHelper(CFileItem
& item
, const std::string
& property
, const std::string
& value
)
1615 : m_item(item
), m_property(property
), m_value(value
)
1619 bool NeedsSave() const { return !m_value
.empty() || m_item
.HasProperty(m_property
); }
1621 std::string
GetValueToSave(const std::string
& currentValue
) const
1625 if (!m_value
.empty())
1627 // Overwrite whatever we have; remember what we had originally.
1628 if (!m_item
.HasProperty(m_property
))
1629 m_item
.SetProperty(m_property
, currentValue
);
1633 else if (m_item
.HasProperty(m_property
))
1635 // Restore original value
1636 value
= m_item
.GetProperty(m_property
).asString();
1637 m_item
.ClearProperty(m_property
);
1645 const std::string m_property
;
1646 const std::string m_value
;
1648 } // unnamed namespace
1650 void CFileItem::SetFromMusicInfoTag(const MUSIC_INFO::CMusicInfoTag
& music
)
1652 const std::string path
= GetPath();
1655 SetPath(music
.GetURL());
1659 const CPropertySaveHelper
dynpath(*this, "OriginalDynPath", music
.GetURL());
1660 if (dynpath
.NeedsSave())
1661 SetDynPath(dynpath
.GetValueToSave(m_strDynPath
));
1664 const CPropertySaveHelper
label(*this, "OriginalLabel", music
.GetTitle());
1665 if (label
.NeedsSave())
1666 SetLabel(label
.GetValueToSave(GetLabel()));
1668 const CPropertySaveHelper
thumb(*this, "OriginalThumb", music
.GetStationArt());
1669 if (thumb
.NeedsSave())
1670 SetArt("thumb", thumb
.GetValueToSave(GetArt("thumb")));
1672 *GetMusicInfoTag() = music
;
1673 ART::FillInDefaultIcon(*this);
1674 FillInMimeType(false);
1677 void CFileItem::SetFromAlbum(const CAlbum
&album
)
1679 if (!album
.strAlbum
.empty())
1680 SetLabel(album
.strAlbum
);
1682 m_strLabel2
= album
.GetAlbumArtistString();
1683 GetMusicInfoTag()->SetAlbum(album
);
1685 if (album
.art
.empty())
1686 SetArt("icon", "DefaultAlbumCover.png");
1691 CMusicDatabase::SetPropertiesFromAlbum(*this,album
);
1692 FillInMimeType(false);
1695 void CFileItem::SetFromSong(const CSong
&song
)
1697 if (!song
.strTitle
.empty())
1698 SetLabel(song
.strTitle
);
1699 if (song
.idSong
> 0)
1701 std::string strExt
= URIUtils::GetExtension(song
.strFileName
);
1702 m_strPath
= StringUtils::Format("musicdb://songs/{}{}", song
.idSong
, strExt
);
1704 else if (!song
.strFileName
.empty())
1705 m_strPath
= song
.strFileName
;
1706 GetMusicInfoTag()->SetSong(song
);
1707 m_lStartOffset
= song
.iStartOffset
;
1708 m_lStartPartNumber
= 1;
1709 SetProperty("item_start", song
.iStartOffset
);
1710 m_lEndOffset
= song
.iEndOffset
;
1711 if (!song
.strThumb
.empty())
1712 SetArt("thumb", song
.strThumb
);
1713 FillInMimeType(false);
1717 * @todo Ideally this (and SetPath) would not be available outside of construction
1718 * for CFileItem objects, or at least restricted to essentially be equivalent
1719 * to construction. This would require re-formulating a bunch of CFileItem
1720 * construction, and also allowing CFileItemList to have its own (public)
1721 * SetURL() function, so for now we give direct access.
1723 void CFileItem::SetURL(const CURL
& url
)
1725 m_strPath
= url
.Get();
1728 const CURL
CFileItem::GetURL() const
1730 CURL
url(m_strPath
);
1734 bool CFileItem::IsURL(const CURL
& url
) const
1736 return IsPath(url
.Get());
1739 bool CFileItem::IsPath(const std::string
& path
, bool ignoreURLOptions
/* = false */) const
1741 return URIUtils::PathEquals(m_strPath
, path
, false, ignoreURLOptions
);
1744 void CFileItem::SetDynURL(const CURL
& url
)
1746 m_strDynPath
= url
.Get();
1749 const CURL
CFileItem::GetDynURL() const
1751 if (!m_strDynPath
.empty())
1753 CURL
url(m_strDynPath
);
1758 CURL
url(m_strPath
);
1763 const std::string
&CFileItem::GetDynPath() const
1765 if (!m_strDynPath
.empty())
1766 return m_strDynPath
;
1771 void CFileItem::SetDynPath(const std::string
&path
)
1773 m_strDynPath
= path
;
1776 std::string
CFileItem::GetBlurayPath() const
1778 if (VIDEO::IsBlurayPlaylist(*this))
1780 CURL
url(GetDynPath());
1781 CURL
url2(url
.GetHostName()); // strip bluray://
1782 if (url2
.IsProtocol("udf"))
1784 return url2
.GetHostName(); // strip udf://
1785 else if (url
.IsProtocol("bluray"))
1787 return url2
.Get() + "BDMV/index.bdmv";
1789 return GetDynPath();
1792 void CFileItem::SetCueDocument(const CCueDocumentPtr
& cuePtr
)
1794 m_cueDocument
= cuePtr
;
1797 void CFileItem::LoadEmbeddedCue()
1799 CMusicInfoTag
& tag
= *GetMusicInfoTag();
1803 const std::string embeddedCue
= tag
.GetCueSheet();
1804 if (!embeddedCue
.empty())
1806 CCueDocumentPtr
cuesheet(new CCueDocument
);
1807 if (cuesheet
->ParseTag(embeddedCue
))
1809 std::vector
<std::string
> MediaFileVec
;
1810 cuesheet
->GetMediaFiles(MediaFileVec
);
1811 for (std::vector
<std::string
>::iterator itMedia
= MediaFileVec
.begin();
1812 itMedia
!= MediaFileVec
.end(); ++itMedia
)
1813 cuesheet
->UpdateMediaFile(*itMedia
, GetPath());
1814 SetCueDocument(cuesheet
);
1816 // Clear cuesheet tag having added it to item
1817 tag
.SetCueSheet("");
1821 bool CFileItem::HasCueDocument() const
1823 return (m_cueDocument
.get() != nullptr);
1826 bool CFileItem::LoadTracksFromCueDocument(CFileItemList
& scannedItems
)
1831 bool result
= m_cueDocument
->LoadTracks(scannedItems
, *this);
1832 m_cueDocument
.reset();
1837 std::string
CFileItem::GetUserMusicThumb(bool alwaysCheckRemote
/* = false */, bool fallbackToFolder
/* = false */) const
1839 if (m_strPath
.empty() || StringUtils::StartsWithNoCase(m_strPath
, "newsmartplaylist://") ||
1840 StringUtils::StartsWithNoCase(m_strPath
, "newplaylist://") || m_bIsShareOrDrive
||
1841 NETWORK::IsInternetStream(*this) || URIUtils::IsUPnP(m_strPath
) ||
1842 (URIUtils::IsFTP(m_strPath
) &&
1843 !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_bFTPThumbs
) ||
1844 IsPlugin() || IsAddonsPath() || IsLibraryFolder() || IsParentFolder() ||
1845 MUSIC::IsMusicDb(*this))
1848 // we first check for <filename>.tbn or <foldername>.tbn
1849 std::string
fileThumb(ART::GetTBNFile(*this));
1850 if (CFile::Exists(fileThumb
))
1853 // Fall back to folder thumb, if requested
1854 if (!m_bIsFolder
&& fallbackToFolder
)
1856 CFileItem
item(URIUtils::GetDirectory(m_strPath
), true);
1857 return item
.GetUserMusicThumb(alwaysCheckRemote
);
1860 // if a folder, check for folder.jpg
1861 if (m_bIsFolder
&& !IsFileFolder() &&
1862 (!NETWORK::IsRemote(*this) || alwaysCheckRemote
||
1863 CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
1864 CSettings::SETTING_MUSICFILES_FINDREMOTETHUMBS
)))
1866 std::vector
<CVariant
> thumbs
= CServiceBroker::GetSettingsComponent()->GetSettings()->GetList(
1867 CSettings::SETTING_MUSICLIBRARY_MUSICTHUMBS
);
1868 for (const auto& i
: thumbs
)
1870 std::string strFileName
= i
.asString();
1871 std::string
folderThumb(ART::GetFolderThumb(*this, strFileName
));
1872 if (CFile::Exists(folderThumb
)) // folder.jpg
1874 size_t period
= strFileName
.find_last_of('.');
1875 if (period
!= std::string::npos
)
1878 std::string name
= strFileName
;
1879 std::string folderThumb1
= folderThumb
;
1881 ext
= strFileName
.substr(period
);
1882 StringUtils::ToUpper(ext
);
1883 StringUtils::Replace(folderThumb1
, strFileName
, name
+ ext
);
1884 if (CFile::Exists(folderThumb1
)) // folder.JPG
1885 return folderThumb1
;
1887 folderThumb1
= folderThumb
;
1888 std::string firstletter
= name
.substr(0, 1);
1889 StringUtils::ToUpper(firstletter
);
1890 name
.replace(0, 1, firstletter
);
1891 StringUtils::Replace(folderThumb1
, strFileName
, name
+ ext
);
1892 if (CFile::Exists(folderThumb1
)) // Folder.JPG
1893 return folderThumb1
;
1895 folderThumb1
= folderThumb
;
1896 StringUtils::ToLower(ext
);
1897 StringUtils::Replace(folderThumb1
, strFileName
, name
+ ext
);
1898 if (CFile::Exists(folderThumb1
)) // Folder.jpg
1899 return folderThumb1
;
1907 bool CFileItem::SkipLocalArt() const
1909 return (m_strPath
.empty() || StringUtils::StartsWithNoCase(m_strPath
, "newsmartplaylist://") ||
1910 StringUtils::StartsWithNoCase(m_strPath
, "newplaylist://") || m_bIsShareOrDrive
||
1911 NETWORK::IsInternetStream(*this) || URIUtils::IsUPnP(m_strPath
) ||
1912 (URIUtils::IsFTP(m_strPath
) &&
1913 !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_bFTPThumbs
) ||
1914 IsPlugin() || IsAddonsPath() || IsLibraryFolder() || IsParentFolder() || IsLiveTV() ||
1915 IsPVRRecording() || IsDVD());
1918 std::string
CFileItem::GetThumbHideIfUnwatched(const CFileItem
* item
) const
1920 const std::shared_ptr
<CSettingList
> setting(std::dynamic_pointer_cast
<CSettingList
>(
1921 CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(
1922 CSettings::SETTING_VIDEOLIBRARY_SHOWUNWATCHEDPLOTS
)));
1923 if (setting
&& item
->HasVideoInfoTag() && item
->GetVideoInfoTag()->m_type
== MediaTypeEpisode
&&
1924 item
->GetVideoInfoTag()->GetPlayCount() == 0 &&
1925 !CSettingUtils::FindIntInList(setting
,
1926 CSettings::VIDEOLIBRARY_THUMB_SHOW_UNWATCHED_EPISODE
) &&
1927 item
->HasArt("thumb"))
1929 std::string fanArt
= item
->GetArt("fanart");
1931 return "OverlaySpoiler.png";
1936 return item
->GetArt("thumb");
1939 std::string
CFileItem::FindLocalArt(const std::string
&artFile
, bool useFolder
) const
1947 thumb
= GetLocalArt(artFile
, false);
1948 if (!thumb
.empty() && CFile::Exists(thumb
))
1951 if ((useFolder
|| (m_bIsFolder
&& !IsFileFolder())) && !artFile
.empty())
1953 std::string thumb2
= GetLocalArt(artFile
, true);
1954 if (!thumb2
.empty() && thumb2
!= thumb
&& CFile::Exists(thumb2
))
1960 std::string
CFileItem::GetLocalArtBaseFilename() const
1962 bool useFolder
= false;
1963 return GetLocalArtBaseFilename(useFolder
);
1966 std::string
CFileItem::GetLocalArtBaseFilename(bool& useFolder
) const
1968 std::string strFile
;
1971 std::string strPath
;
1972 URIUtils::GetParentPath(m_strPath
,strPath
);
1973 strFile
= URIUtils::AddFileToFolder(
1974 strPath
, URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(m_strPath
)));
1977 std::string file
= strFile
.empty() ? m_strPath
: strFile
;
1978 if (URIUtils::IsInRAR(file
) || URIUtils::IsInZIP(file
))
1980 std::string strPath
= URIUtils::GetDirectory(file
);
1981 std::string strParent
;
1982 URIUtils::GetParentPath(strPath
,strParent
);
1983 strFile
= URIUtils::AddFileToFolder(strParent
, URIUtils::GetFileName(file
));
1987 strFile
= CMultiPathDirectory::GetFirstPath(m_strPath
);
1989 if (IsOpticalMediaFile())
1990 { // optical media files should be treated like folders
1992 strFile
= GetLocalMetadataPath();
1994 else if (useFolder
&& !(m_bIsFolder
&& !IsFileFolder()))
1996 file
= strFile
.empty() ? m_strPath
: strFile
;
1997 strFile
= URIUtils::GetDirectory(file
);
2000 if (strFile
.empty())
2001 strFile
= GetDynPath();
2006 std::string
CFileItem::GetLocalArt(const std::string
& artFile
, bool useFolder
) const
2008 // no retrieving of empty art files from folders
2009 if (useFolder
&& artFile
.empty())
2012 std::string strFile
= GetLocalArtBaseFilename(useFolder
);
2013 if (strFile
.empty()) // empty filepath -> nothing to find
2018 if (!artFile
.empty())
2019 return URIUtils::AddFileToFolder(strFile
, artFile
);
2023 if (artFile
.empty()) // old thumbnail matching
2024 return URIUtils::ReplaceExtension(strFile
, ".tbn");
2026 return URIUtils::ReplaceExtension(strFile
, "-" + artFile
);
2031 std::string
CFileItem::GetMovieName(bool bUseFolderNames
/* = false */) const
2033 if (IsPlugin() && HasVideoInfoTag() && !GetVideoInfoTag()->m_strTitle
.empty())
2034 return GetVideoInfoTag()->m_strTitle
;
2036 if (IsLabelPreformatted())
2039 if (m_pvrRecordingInfoTag
)
2040 return m_pvrRecordingInfoTag
->m_strTitle
;
2041 else if (URIUtils::IsPVRRecording(m_strPath
))
2043 std::string title
= CPVRRecording::GetTitleFromURL(m_strPath
);
2048 std::string strMovieName
;
2049 if (URIUtils::IsStack(m_strPath
))
2050 strMovieName
= CStackDirectory::GetStackedTitlePath(m_strPath
);
2052 strMovieName
= GetBaseMoviePath(bUseFolderNames
);
2054 URIUtils::RemoveSlashAtEnd(strMovieName
);
2056 return CURL::Decode(URIUtils::GetFileName(strMovieName
));
2059 std::string
CFileItem::GetBaseMoviePath(bool bUseFolderNames
) const
2061 std::string strMovieName
= m_strPath
;
2064 strMovieName
= CMultiPathDirectory::GetFirstPath(m_strPath
);
2066 if (IsOpticalMediaFile())
2067 return GetLocalMetadataPath();
2069 if (bUseFolderNames
&&
2070 (!m_bIsFolder
|| URIUtils::IsInArchive(m_strPath
) ||
2071 (HasVideoInfoTag() && GetVideoInfoTag()->m_iDbId
> 0 && !CMediaTypes::IsContainer(GetVideoInfoTag()->m_type
))))
2073 std::string
name2(strMovieName
);
2074 URIUtils::GetParentPath(name2
,strMovieName
);
2075 if (URIUtils::IsInArchive(m_strPath
))
2077 // Try to get archive itself, if empty take path before
2078 name2
= CURL(m_strPath
).GetHostName();
2080 name2
= strMovieName
;
2082 URIUtils::GetParentPath(name2
, strMovieName
);
2085 // Remove trailing 'Disc n' path segment to get actual movie title
2086 strMovieName
= CUtil::RemoveTrailingDiscNumberSegmentFromPath(strMovieName
);
2089 return strMovieName
;
2092 std::string
CFileItem::GetLocalMetadataPath() const
2094 if (m_bIsFolder
&& !IsFileFolder())
2097 std::string parent
{};
2098 if (VIDEO::IsBlurayPlaylist(*this))
2099 parent
= URIUtils::GetParentPath(GetBlurayPath());
2101 parent
= URIUtils::GetParentPath(m_strPath
);
2102 std::string
parentFolder(parent
);
2103 URIUtils::RemoveSlashAtEnd(parentFolder
);
2104 parentFolder
= URIUtils::GetFileName(parentFolder
);
2105 if (StringUtils::EqualsNoCase(parentFolder
, "VIDEO_TS") || StringUtils::EqualsNoCase(parentFolder
, "BDMV"))
2106 { // go back up another one
2107 parent
= URIUtils::GetParentPath(parent
);
2112 bool CFileItem::LoadMusicTag()
2115 if (!MUSIC::IsAudio(*this))
2118 if (HasMusicInfoTag() && m_musicInfoTag
->Loaded())
2121 CMusicDatabase musicDatabase
;
2122 if (musicDatabase
.Open())
2125 if (musicDatabase
.GetSongByFileName(m_strPath
, song
))
2127 GetMusicInfoTag()->SetSong(song
);
2130 musicDatabase
.Close();
2132 // load tag from file
2133 CLog::Log(LOGDEBUG
, "{}: loading tag information for file: {}", __FUNCTION__
, m_strPath
);
2134 CMusicInfoTagLoaderFactory factory
;
2135 std::unique_ptr
<IMusicInfoTagLoader
> pLoader (factory
.CreateLoader(*this));
2138 if (pLoader
->Load(m_strPath
, *GetMusicInfoTag()))
2141 // no tag - try some other things
2142 if (MUSIC::IsCDDA(*this))
2144 // we have the tracknumber...
2145 int iTrack
= GetMusicInfoTag()->GetTrackNumber();
2148 std::string strText
= g_localizeStrings
.Get(554); // "Track"
2149 if (!strText
.empty() && strText
[strText
.size() - 1] != ' ')
2151 std::string strTrack
= StringUtils::Format((strText
+ "{}"), iTrack
);
2152 GetMusicInfoTag()->SetTitle(strTrack
);
2153 GetMusicInfoTag()->SetLoaded(true);
2159 std::string fileName
= URIUtils::GetFileName(m_strPath
);
2160 URIUtils::RemoveExtension(fileName
);
2161 for (const std::string
& fileFilter
: CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicTagsFromFileFilters
)
2163 CLabelFormatter
formatter(fileFilter
, "");
2164 if (formatter
.FillMusicTag(fileName
, GetMusicInfoTag()))
2166 GetMusicInfoTag()->SetLoaded(true);
2174 bool CFileItem::LoadGameTag()
2177 if (HasGameInfoTag() && m_gameInfoTag
->IsLoaded())
2183 m_gameInfoTag
->SetLoaded(true);
2188 bool CFileItem::LoadDetails()
2190 if (VIDEO::IsVideoDb(*this))
2192 if (HasVideoInfoTag())
2198 CLog::LogF(LOGERROR
, "Error opening video database");
2202 VIDEODATABASEDIRECTORY::CQueryParams params
;
2203 VIDEODATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(GetPath(), params
);
2206 auto tag
{std::make_unique
<CVideoInfoTag
>()};
2207 if (params
.GetMovieId() >= 0)
2208 ret
= db
.GetMovieInfo({}, *tag
, static_cast<int>(params
.GetMovieId()),
2209 static_cast<int>(params
.GetVideoVersionId()));
2210 else if (params
.GetMVideoId() >= 0)
2211 ret
= db
.GetMusicVideoInfo({}, *tag
, static_cast<int>(params
.GetMVideoId()));
2212 else if (params
.GetEpisodeId() >= 0)
2213 ret
= db
.GetEpisodeInfo({}, *tag
, static_cast<int>(params
.GetEpisodeId()));
2214 else if (params
.GetSetId() >= 0) // movie set
2215 ret
= db
.GetSetInfo(static_cast<int>(params
.GetSetId()), *tag
, this);
2216 else if (params
.GetTvShowId() >= 0)
2218 if (params
.GetSeason() >= 0)
2220 const int idSeason
= db
.GetSeasonId(static_cast<int>(params
.GetTvShowId()),
2221 static_cast<int>(params
.GetSeason()));
2223 ret
= db
.GetSeasonInfo(idSeason
, *tag
, this);
2226 ret
= db
.GetTvShowInfo({}, *tag
, static_cast<int>(params
.GetTvShowId()), this);
2231 const CFileItem loadedItem
{*tag
};
2232 UpdateInfo(loadedItem
);
2239 const std::shared_ptr
<CFileItem
> loadedItem
{
2240 CServiceBroker::GetPVRManager().Get
<PVR::GUI::Utils
>().LoadItem(*this)};
2243 UpdateInfo(*loadedItem
);
2246 CLog::LogF(LOGERROR
, "Error filling PVR item details (path={})", GetPath());
2250 if (!PLAYLIST::IsPlayList(*this) && VIDEO::IsVideo(*this))
2252 if (HasVideoInfoTag())
2258 CLog::LogF(LOGERROR
, "Error opening video database");
2262 auto tag
{std::make_unique
<CVideoInfoTag
>()};
2263 if (db
.LoadVideoInfo(GetDynPath(), *tag
))
2265 const CFileItem loadedItem
{*tag
};
2266 UpdateInfo(loadedItem
);
2270 CLog::LogF(LOGERROR
, "Error filling item details (path={})", GetPath());
2274 if (PLAYLIST::IsPlayList(*this) && IsType(".strm"))
2276 const std::unique_ptr
<PLAYLIST::CPlayList
> playlist(PLAYLIST::CPlayListFactory::Create(*this));
2279 if (playlist
->Load(GetPath()) && playlist
->size() == 1)
2281 const auto item
{(*playlist
)[0]};
2282 if (VIDEO::IsVideo(*item
))
2287 CLog::LogF(LOGERROR
, "Error opening video database");
2292 if (db
.LoadVideoInfo(GetDynPath(), tag
))
2295 *GetVideoInfoTag() = tag
;
2299 else if (MUSIC::IsAudio(*item
))
2301 if (item
->LoadMusicTag())
2309 CLog::LogF(LOGERROR
, "Error loading strm file details (path={})", GetPath());
2313 if (MUSIC::IsAudio(*this))
2315 return LoadMusicTag();
2318 if (MUSIC::IsMusicDb(*this))
2320 if (HasMusicInfoTag())
2326 CLog::LogF(LOGERROR
, "Error opening music database");
2330 MUSICDATABASEDIRECTORY::CQueryParams params
;
2331 MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(GetPath(), params
);
2333 if (params
.GetSongId() >= 0)
2336 if (db
.GetSong(params
.GetSongId(), song
))
2338 GetMusicInfoTag()->SetSong(song
);
2342 else if (params
.GetAlbumId() >= 0)
2346 if (db
.GetAlbum(params
.GetAlbumId(), album
, false))
2348 GetMusicInfoTag()->SetAlbum(album
);
2352 else if (params
.GetArtistId() >= 0)
2356 if (db
.GetArtist(params
.GetArtistId(), artist
, false))
2358 GetMusicInfoTag()->SetArtist(artist
);
2365 //! @todo add support for other types on demand.
2366 CLog::LogF(LOGDEBUG
, "Unsupported item type (path={})", GetPath());
2370 bool CFileItem::HasVideoInfoTag() const
2372 // Note: CPVRRecording is derived from CVideoInfoTag
2373 return m_pvrRecordingInfoTag
.get() != nullptr || m_videoInfoTag
!= nullptr;
2376 CVideoInfoTag
* CFileItem::GetVideoInfoTag()
2378 // Note: CPVRRecording is derived from CVideoInfoTag
2379 if (m_pvrRecordingInfoTag
)
2380 return m_pvrRecordingInfoTag
.get();
2381 else if (!m_videoInfoTag
)
2382 m_videoInfoTag
= new CVideoInfoTag
;
2384 return m_videoInfoTag
;
2387 const CVideoInfoTag
* CFileItem::GetVideoInfoTag() const
2389 // Note: CPVRRecording is derived from CVideoInfoTag
2390 return m_pvrRecordingInfoTag
? m_pvrRecordingInfoTag
.get() : m_videoInfoTag
;
2393 CPictureInfoTag
* CFileItem::GetPictureInfoTag()
2395 if (!m_pictureInfoTag
)
2396 m_pictureInfoTag
= new CPictureInfoTag
;
2398 return m_pictureInfoTag
;
2401 MUSIC_INFO::CMusicInfoTag
* CFileItem::GetMusicInfoTag()
2403 if (!m_musicInfoTag
)
2404 m_musicInfoTag
= new MUSIC_INFO::CMusicInfoTag
;
2406 return m_musicInfoTag
;
2409 CGameInfoTag
* CFileItem::GetGameInfoTag()
2412 m_gameInfoTag
= new CGameInfoTag
;
2414 return m_gameInfoTag
;
2417 bool CFileItem::HasPVRChannelInfoTag() const
2419 return m_pvrChannelGroupMemberInfoTag
&& m_pvrChannelGroupMemberInfoTag
->Channel() != nullptr;
2422 const std::shared_ptr
<PVR::CPVRChannel
> CFileItem::GetPVRChannelInfoTag() const
2424 return m_pvrChannelGroupMemberInfoTag
? m_pvrChannelGroupMemberInfoTag
->Channel()
2425 : std::shared_ptr
<CPVRChannel
>();
2428 std::string
CFileItem::FindTrailer() const
2430 std::string strFile2
;
2431 std::string strFile
= m_strPath
;
2434 std::string strPath
;
2435 URIUtils::GetParentPath(m_strPath
,strPath
);
2436 CStackDirectory dir
;
2437 std::string strPath2
;
2438 strPath2
= dir
.GetStackedTitlePath(strFile
);
2439 strFile
= URIUtils::AddFileToFolder(strPath
,URIUtils::GetFileName(strPath2
));
2440 CFileItem
item(dir
.GetFirstStackedFile(m_strPath
),false);
2441 std::string
strTBNFile(URIUtils::ReplaceExtension(ART::GetTBNFile(item
), "-trailer"));
2442 strFile2
= URIUtils::AddFileToFolder(strPath
,URIUtils::GetFileName(strTBNFile
));
2444 if (URIUtils::IsInRAR(strFile
) || URIUtils::IsInZIP(strFile
))
2446 std::string strPath
= URIUtils::GetDirectory(strFile
);
2447 std::string strParent
;
2448 URIUtils::GetParentPath(strPath
,strParent
);
2449 strFile
= URIUtils::AddFileToFolder(strParent
,URIUtils::GetFileName(m_strPath
));
2452 // no local trailer available for these
2453 if (NETWORK::IsInternetStream(*this) || URIUtils::IsUPnP(strFile
) ||
2454 URIUtils::IsBluray(strFile
) || IsLiveTV() || IsPlugin() || IsDVD())
2457 std::string strDir
= URIUtils::GetDirectory(strFile
);
2458 CFileItemList items
;
2459 CDirectory::GetDirectory(strDir
, items
, CServiceBroker::GetFileExtensionProvider().GetVideoExtensions(), DIR_FLAG_READ_CACHE
| DIR_FLAG_NO_FILE_INFO
| DIR_FLAG_NO_FILE_DIRS
);
2460 URIUtils::RemoveExtension(strFile
);
2461 strFile
+= "-trailer";
2462 std::string strFile3
= URIUtils::AddFileToFolder(strDir
, "movie-trailer");
2464 // Precompile our REs
2465 VECCREGEXP matchRegExps
;
2466 CRegExp
tmpRegExp(true, CRegExp::autoUtf8
);
2467 const std::vector
<std::string
>& strMatchRegExps
= CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_trailerMatchRegExps
;
2469 std::vector
<std::string
>::const_iterator strRegExp
= strMatchRegExps
.begin();
2470 while (strRegExp
!= strMatchRegExps
.end())
2472 if (tmpRegExp
.RegComp(*strRegExp
))
2474 matchRegExps
.push_back(tmpRegExp
);
2479 std::string strTrailer
;
2480 for (int i
= 0; i
< items
.Size(); i
++)
2482 std::string strCandidate
= items
[i
]->m_strPath
;
2483 URIUtils::RemoveExtension(strCandidate
);
2484 if (StringUtils::EqualsNoCase(strCandidate
, strFile
) ||
2485 StringUtils::EqualsNoCase(strCandidate
, strFile2
) ||
2486 StringUtils::EqualsNoCase(strCandidate
, strFile3
))
2488 strTrailer
= items
[i
]->m_strPath
;
2493 VECCREGEXP::iterator expr
= matchRegExps
.begin();
2495 while (expr
!= matchRegExps
.end())
2497 if (expr
->RegFind(strCandidate
) != -1)
2499 strTrailer
= items
[i
]->m_strPath
;
2511 VideoDbContentType
CFileItem::GetVideoContentType() const
2513 VideoDbContentType type
= VideoDbContentType::MOVIES
;
2514 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeTvShow
)
2515 type
= VideoDbContentType::TVSHOWS
;
2516 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeEpisode
)
2517 return VideoDbContentType::EPISODES
;
2518 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeMusicVideo
)
2519 return VideoDbContentType::MUSICVIDEOS
;
2520 if (HasVideoInfoTag() && GetVideoInfoTag()->m_type
== MediaTypeAlbum
)
2521 return VideoDbContentType::MUSICALBUMS
;
2523 CVideoDatabaseDirectory dir
;
2524 VIDEODATABASEDIRECTORY::CQueryParams params
;
2525 dir
.GetQueryParams(m_strPath
, params
);
2526 if (params
.GetSetId() != -1 && params
.GetMovieId() == -1) // movie set
2527 return VideoDbContentType::MOVIE_SETS
;
2532 CFileItem
CFileItem::GetItemToPlay() const
2534 if (HasEPGInfoTag())
2536 const std::shared_ptr
<CPVRChannelGroupMember
> groupMember
=
2537 CServiceBroker::GetPVRManager().Get
<PVR::GUI::Channels
>().GetChannelGroupMember(*this);
2539 return CFileItem(groupMember
);
2544 CBookmark
CFileItem::GetResumePoint() const
2546 if (HasVideoInfoTag())
2547 return GetVideoInfoTag()->GetResumePoint();
2551 bool CFileItem::IsResumePointSet() const
2553 return GetResumePoint().IsSet();
2556 double CFileItem::GetCurrentResumeTime() const
2558 return lrint(GetResumePoint().timeInSeconds
);
2561 bool CFileItem::GetCurrentResumeTimeAndPartNumber(int64_t& startOffset
, int& partNumber
) const
2563 CBookmark
resumePoint(GetResumePoint());
2564 if (resumePoint
.IsSet())
2566 startOffset
= llrint(resumePoint
.timeInSeconds
);
2567 partNumber
= resumePoint
.partNumber
;
2573 bool CFileItem::IsResumable() const
2577 int64_t watched
= 0;
2578 int64_t inprogress
= 0;
2580 if (HasProperty("inprogressepisodes"))
2583 watched
= GetProperty("watchedepisodes").asInteger();
2584 inprogress
= GetProperty("inprogressepisodes").asInteger();
2585 total
= GetProperty("totalepisodes").asInteger();
2587 else if (HasProperty("inprogress"))
2590 watched
= GetProperty("watched").asInteger();
2591 inprogress
= GetProperty("inprogress").asInteger();
2592 total
= GetProperty("total").asInteger();
2595 return ((total
!= watched
) && (inprogress
> 0 || watched
!= 0));
2599 return HasVideoInfoTag() && GetVideoInfoTag()->GetResumePoint().IsPartWay();
2603 bool CFileItem::HasVideoVersions() const
2605 if (HasVideoInfoTag())
2607 return GetVideoInfoTag()->HasVideoVersions();
2612 bool CFileItem::HasVideoExtras() const
2614 if (HasVideoInfoTag())
2616 return GetVideoInfoTag()->HasVideoExtras();