/xbmc/FileItem.cpp
C++ | 2977 lines | 2533 code | 313 blank | 131 comment | 454 complexity | 39426c571bec4e4c90eb0b8fca756f38 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
- /*
- * Copyright (C) 2005-2008 Team XBMC
- * http://www.xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
- #include "FileItem.h"
- #include "guilib/LocalizeStrings.h"
- #include "utils/StringUtils.h"
- #include "utils/URIUtils.h"
- #include "Util.h"
- #include "playlists/PlayListFactory.h"
- #include "utils/Crc32.h"
- #include "filesystem/Directory.h"
- #include "filesystem/StackDirectory.h"
- #include "filesystem/CurlFile.h"
- #include "filesystem/MultiPathDirectory.h"
- #include "filesystem/MusicDatabaseDirectory.h"
- #include "filesystem/VideoDatabaseDirectory.h"
- #include "music/tags/MusicInfoTagLoaderFactory.h"
- #include "CueDocument.h"
- #include "video/VideoDatabase.h"
- #include "music/MusicDatabase.h"
- #include "utils/TuxBoxUtil.h"
- #include "video/VideoInfoTag.h"
- #include "threads/SingleLock.h"
- #include "music/tags/MusicInfoTag.h"
- #include "pictures/PictureInfoTag.h"
- #include "music/Artist.h"
- #include "music/Album.h"
- #include "music/Song.h"
- #include "URL.h"
- #include "settings/GUISettings.h"
- #include "settings/AdvancedSettings.h"
- #include "settings/Settings.h"
- #include "utils/RegExp.h"
- #include "utils/log.h"
- #include "utils/Variant.h"
- #include "music/karaoke/karaokelyricsfactory.h"
- #include "utils/Mime.h"
- using namespace std;
- using namespace XFILE;
- using namespace PLAYLIST;
- using namespace MUSIC_INFO;
- CFileItem::CFileItem(const CSong& song)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- SetLabel(song.strTitle);
- m_strPath = song.strFileName;
- GetMusicInfoTag()->SetSong(song);
- m_lStartOffset = song.iStartOffset;
- m_lStartPartNumber = 0;
- SetProperty("item_start", song.iStartOffset);
- m_lEndOffset = song.iEndOffset;
- m_strThumbnailImage = song.strThumb;
- }
- CFileItem::CFileItem(const CStdString &path, const CAlbum& album)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- SetLabel(album.strAlbum);
- m_strPath = path;
- m_bIsFolder = true;
- m_strLabel2 = StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator);
- URIUtils::AddSlashAtEnd(m_strPath);
- GetMusicInfoTag()->SetAlbum(album);
- m_bIsAlbum = true;
- CMusicDatabase::SetPropertiesFromAlbum(*this,album);
- }
- CFileItem::CFileItem(const CMusicInfoTag& music)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- SetLabel(music.GetTitle());
- m_strPath = music.GetURL();
- m_bIsFolder = URIUtils::HasSlashAtEnd(m_strPath);
- *GetMusicInfoTag() = music;
- FillInDefaultIcon();
- }
- CFileItem::CFileItem(const CVideoInfoTag& movie)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- SetLabel(movie.m_strTitle);
- if (movie.m_strFileNameAndPath.IsEmpty())
- {
- m_strPath = movie.m_strPath;
- URIUtils::AddSlashAtEnd(m_strPath);
- m_bIsFolder = true;
- }
- else
- {
- m_strPath = movie.m_strFileNameAndPath;
- m_bIsFolder = false;
- }
- *GetVideoInfoTag() = movie;
- if (movie.m_iSeason == 0) SetProperty("isspecial", "true");
- FillInDefaultIcon();
- }
- CFileItem::CFileItem(const CArtist& artist)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- SetLabel(artist.strArtist);
- m_strPath = artist.strArtist;
- m_bIsFolder = true;
- URIUtils::AddSlashAtEnd(m_strPath);
- GetMusicInfoTag()->SetArtist(artist.strArtist);
- }
- CFileItem::CFileItem(const CGenre& genre)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- SetLabel(genre.strGenre);
- m_strPath = genre.strGenre;
- m_bIsFolder = true;
- URIUtils::AddSlashAtEnd(m_strPath);
- GetMusicInfoTag()->SetGenre(genre.strGenre);
- }
- CFileItem::CFileItem(const CFileItem& item): CGUIListItem()
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- *this = item;
- }
- CFileItem::CFileItem(const CGUIListItem& item)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- // not particularly pretty, but it gets around the issue of Reset() defaulting
- // parameters in the CGUIListItem base class.
- *((CGUIListItem *)this) = item;
- }
- CFileItem::CFileItem(void)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- }
- CFileItem::CFileItem(const CStdString& strLabel)
- : CGUIListItem()
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- SetLabel(strLabel);
- }
- CFileItem::CFileItem(const CStdString& strPath, bool bIsFolder)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- m_strPath = strPath;
- m_bIsFolder = bIsFolder;
- // tuxbox urls cannot have a / at end
- if (m_bIsFolder && !m_strPath.IsEmpty() && !IsFileFolder() && !URIUtils::IsTuxBox(m_strPath))
- URIUtils::AddSlashAtEnd(m_strPath);
- }
- CFileItem::CFileItem(const CMediaSource& share)
- {
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- Reset();
- m_bIsFolder = true;
- m_bIsShareOrDrive = true;
- m_strPath = share.strPath;
- URIUtils::AddSlashAtEnd(m_strPath);
- CStdString label = share.strName;
- if (!share.strStatus.IsEmpty())
- label.Format("%s (%s)", share.strName.c_str(), share.strStatus.c_str());
- SetLabel(label);
- m_iLockMode = share.m_iLockMode;
- m_strLockCode = share.m_strLockCode;
- m_iHasLock = share.m_iHasLock;
- m_iBadPwdCount = share.m_iBadPwdCount;
- m_iDriveType = share.m_iDriveType;
- m_strThumbnailImage = share.m_strThumbnailImage;
- SetLabelPreformated(true);
- if (IsDVD())
- GetVideoInfoTag()->m_strFileNameAndPath = share.strDiskUniqueId; // share.strDiskUniqueId contains disc unique id
- }
- CFileItem::~CFileItem(void)
- {
- delete m_musicInfoTag;
- delete m_videoInfoTag;
- delete m_pictureInfoTag;
- m_musicInfoTag = NULL;
- m_videoInfoTag = NULL;
- m_pictureInfoTag = NULL;
- }
- const CFileItem& CFileItem::operator=(const CFileItem& item)
- {
- if (this == &item) return * this;
- CGUIListItem::operator=(item);
- m_bLabelPreformated=item.m_bLabelPreformated;
- FreeMemory();
- m_strPath = item.GetPath();
- m_bIsParentFolder = item.m_bIsParentFolder;
- m_iDriveType = item.m_iDriveType;
- m_bIsShareOrDrive = item.m_bIsShareOrDrive;
- m_dateTime = item.m_dateTime;
- m_dwSize = item.m_dwSize;
- if (item.HasMusicInfoTag())
- {
- m_musicInfoTag = GetMusicInfoTag();
- if (m_musicInfoTag)
- *m_musicInfoTag = *item.m_musicInfoTag;
- }
- else
- {
- delete m_musicInfoTag;
- m_musicInfoTag = NULL;
- }
- if (item.HasVideoInfoTag())
- {
- m_videoInfoTag = GetVideoInfoTag();
- if (m_videoInfoTag)
- *m_videoInfoTag = *item.m_videoInfoTag;
- }
- else
- {
- delete m_videoInfoTag;
- m_videoInfoTag = NULL;
- }
- if (item.HasPictureInfoTag())
- {
- m_pictureInfoTag = GetPictureInfoTag();
- if (m_pictureInfoTag)
- *m_pictureInfoTag = *item.m_pictureInfoTag;
- }
- else
- {
- delete m_pictureInfoTag;
- m_pictureInfoTag = NULL;
- }
- m_lStartOffset = item.m_lStartOffset;
- m_lStartPartNumber = item.m_lStartPartNumber;
- m_lEndOffset = item.m_lEndOffset;
- m_strDVDLabel = item.m_strDVDLabel;
- m_strTitle = item.m_strTitle;
- m_iprogramCount = item.m_iprogramCount;
- m_idepth = item.m_idepth;
- m_iLockMode = item.m_iLockMode;
- m_strLockCode = item.m_strLockCode;
- m_iHasLock = item.m_iHasLock;
- m_iBadPwdCount = item.m_iBadPwdCount;
- m_bCanQueue=item.m_bCanQueue;
- m_mimetype = item.m_mimetype;
- m_extrainfo = item.m_extrainfo;
- m_specialSort = item.m_specialSort;
- m_bIsAlbum = item.m_bIsAlbum;
- return *this;
- }
- void CFileItem::Reset()
- {
- m_strLabel2.Empty();
- SetLabel("");
- m_bLabelPreformated=false;
- FreeIcons();
- m_overlayIcon = ICON_OVERLAY_NONE;
- m_bSelected = false;
- m_bIsAlbum = false;
- m_strDVDLabel.Empty();
- m_strTitle.Empty();
- m_strPath.Empty();
- m_dwSize = 0;
- m_bIsFolder = false;
- m_bIsParentFolder=false;
- m_bIsShareOrDrive = false;
- m_dateTime.Reset();
- m_iDriveType = CMediaSource::SOURCE_TYPE_UNKNOWN;
- m_lStartOffset = 0;
- m_lStartPartNumber = 0;
- m_lEndOffset = 0;
- m_iprogramCount = 0;
- m_idepth = 1;
- m_iLockMode = LOCK_MODE_EVERYONE;
- m_strLockCode = "";
- m_iBadPwdCount = 0;
- m_iHasLock = 0;
- m_bCanQueue=true;
- m_mimetype = "";
- delete m_musicInfoTag;
- m_musicInfoTag=NULL;
- delete m_videoInfoTag;
- m_videoInfoTag=NULL;
- delete m_pictureInfoTag;
- m_pictureInfoTag=NULL;
- m_extrainfo.Empty();
- m_specialSort = SortSpecialNone;
- SetInvalid();
- }
- void CFileItem::Archive(CArchive& ar)
- {
- CGUIListItem::Archive(ar);
- if (ar.IsStoring())
- {
- ar << m_bIsParentFolder;
- ar << m_bLabelPreformated;
- ar << m_strPath;
- ar << m_bIsShareOrDrive;
- ar << m_iDriveType;
- ar << m_dateTime;
- ar << m_dwSize;
- ar << m_strDVDLabel;
- ar << m_strTitle;
- ar << m_iprogramCount;
- ar << m_idepth;
- ar << m_lStartOffset;
- ar << m_lStartPartNumber;
- ar << m_lEndOffset;
- ar << m_iLockMode;
- ar << m_strLockCode;
- ar << m_iBadPwdCount;
- ar << m_bCanQueue;
- ar << m_mimetype;
- ar << m_extrainfo;
- ar << m_specialSort;
- if (m_musicInfoTag)
- {
- ar << 1;
- ar << *m_musicInfoTag;
- }
- else
- ar << 0;
- if (m_videoInfoTag)
- {
- ar << 1;
- ar << *m_videoInfoTag;
- }
- else
- ar << 0;
- if (m_pictureInfoTag)
- {
- ar << 1;
- ar << *m_pictureInfoTag;
- }
- else
- ar << 0;
- }
- else
- {
- ar >> m_bIsParentFolder;
- ar >> m_bLabelPreformated;
- ar >> m_strPath;
- ar >> m_bIsShareOrDrive;
- ar >> m_iDriveType;
- ar >> m_dateTime;
- ar >> m_dwSize;
- ar >> m_strDVDLabel;
- ar >> m_strTitle;
- ar >> m_iprogramCount;
- ar >> m_idepth;
- ar >> m_lStartOffset;
- ar >> m_lStartPartNumber;
- ar >> m_lEndOffset;
- int temp;
- ar >> temp;
- m_iLockMode = (LockType)temp;
- ar >> m_strLockCode;
- ar >> m_iBadPwdCount;
- ar >> m_bCanQueue;
- ar >> m_mimetype;
- ar >> m_extrainfo;
- ar >> temp;
- m_specialSort = (SortSpecial)temp;
- int iType;
- ar >> iType;
- if (iType == 1)
- ar >> *GetMusicInfoTag();
- ar >> iType;
- if (iType == 1)
- ar >> *GetVideoInfoTag();
- ar >> iType;
- if (iType == 1)
- ar >> *GetPictureInfoTag();
- SetInvalid();
- }
- }
- void CFileItem::Serialize(CVariant& value)
- {
- //CGUIListItem::Serialize(value["CGUIListItem"]);
- value["strPath"] = m_strPath;
- value["dateTime"] = (m_dateTime.IsValid()) ? m_dateTime.GetAsRFC1123DateTime() : "";
- value["size"] = (int) m_dwSize / 1000;
- value["DVDLabel"] = m_strDVDLabel;
- value["title"] = m_strTitle;
- value["mimetype"] = GetMimeType();
- value["extrainfo"] = m_extrainfo;
- if (m_musicInfoTag)
- (*m_musicInfoTag).Serialize(value["musicInfoTag"]);
- if (m_videoInfoTag)
- (*m_videoInfoTag).Serialize(value["videoInfoTag"]);
- if (m_pictureInfoTag)
- (*m_pictureInfoTag).Serialize(value["pictureInfoTag"]);
- }
- void CFileItem::ToSortable(SortItem &sortable)
- {
- sortable[FieldPath] = m_strPath;
- sortable[FieldDate] = (m_dateTime.IsValid()) ? m_dateTime.GetAsDBDateTime() : "";
- sortable[FieldSize] = m_dwSize;
- sortable[FieldDriveType] = m_iDriveType;
- sortable[FieldStartOffset] = m_lStartOffset;
- sortable[FieldStartOffset] = m_lEndOffset;
- sortable[FieldProgramCount] = m_iprogramCount;
- sortable[FieldBitrate] = m_dwSize;
- sortable[FieldTitle] = m_strTitle;
- sortable[FieldSortSpecial] = m_specialSort;
- sortable[FieldFolder] = m_bIsFolder;
- // If there's ever a need to convert more properties from CGUIListItem it might be
- // worth to make CGUIListItem implement ISortable as well and call it from here
- sortable[FieldLabel] = GetLabel();
- if (HasMusicInfoTag())
- GetMusicInfoTag()->ToSortable(sortable);
-
- if (HasVideoInfoTag())
- GetVideoInfoTag()->ToSortable(sortable);
-
- if (HasPictureInfoTag())
- GetPictureInfoTag()->ToSortable(sortable);
- }
- bool CFileItem::Exists(bool bUseCache /* = true */) const
- {
- if (m_strPath.IsEmpty()
- || m_strPath.Equals("add")
- || IsInternetStream()
- || IsParentFolder()
- || IsVirtualDirectoryRoot()
- || IsPlugin())
- return true;
- if (IsVideoDb() && HasVideoInfoTag())
- {
- CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder);
- return dbItem.Exists();
- }
- CStdString strPath = m_strPath;
- if (URIUtils::IsMultiPath(strPath))
- strPath = CMultiPathDirectory::GetFirstPath(strPath);
- if (URIUtils::IsStack(strPath))
- strPath = CStackDirectory::GetFirstStackedFile(strPath);
- if (m_bIsFolder)
- return CDirectory::Exists(strPath);
- else
- return CFile::Exists(strPath, bUseCache);
- return false;
- }
- bool CFileItem::IsVideo() const
- {
- /* check preset mime type */
- if( m_mimetype.Left(6).Equals("video/") )
- return true;
- if (HasVideoInfoTag()) return true;
- if (HasMusicInfoTag()) return false;
- if (HasPictureInfoTag()) return false;
- if (IsHDHomeRun() || IsTuxBox() || URIUtils::IsDVD(m_strPath) || IsSlingbox())
- return true;
- CStdString extension;
- if( m_mimetype.Left(12).Equals("application/") )
- { /* check for some standard types */
- extension = m_mimetype.Mid(12);
- if( extension.Equals("ogg")
- || extension.Equals("mp4")
- || extension.Equals("mxf") )
- return true;
- }
- URIUtils::GetExtension(m_strPath, extension);
- if (extension.IsEmpty())
- return false;
- extension.ToLower();
- return (g_settings.m_videoExtensions.Find(extension) != -1);
- }
- bool CFileItem::IsDiscStub() const
- {
- if (IsVideoDb() && HasVideoInfoTag())
- {
- CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder);
- return dbItem.IsDiscStub();
- }
- CStdString strExtension;
- URIUtils::GetExtension(m_strPath, strExtension);
- if (strExtension.IsEmpty())
- return false;
- strExtension.ToLower();
- strExtension += '|';
- return (g_settings.m_discStubExtensions + '|').Find(strExtension) != -1;
- }
- bool CFileItem::IsAudio() const
- {
- /* check preset mime type */
- if( m_mimetype.Left(6).Equals("audio/") )
- return true;
- if (HasMusicInfoTag()) return true;
- if (HasVideoInfoTag()) return false;
- if (HasPictureInfoTag()) return false;
- if (IsCDDA()) return true;
- if (!m_bIsFolder && IsLastFM()) return true;
- CStdString extension;
- if( m_mimetype.Left(12).Equals("application/") )
- { /* check for some standard types */
- extension = m_mimetype.Mid(12);
- if( extension.Equals("ogg")
- || extension.Equals("mp4")
- || extension.Equals("mxf") )
- return true;
- }
- URIUtils::GetExtension(m_strPath, extension);
- if (extension.IsEmpty())
- return false;
- extension.ToLower();
- return (g_settings.m_musicExtensions.Find(extension) != -1);
- }
- bool CFileItem::IsKaraoke() const
- {
- if ( !IsAudio() || IsLastFM())
- return false;
- return CKaraokeLyricsFactory::HasLyrics( m_strPath );
- }
- bool CFileItem::IsPicture() const
- {
- if( m_mimetype.Left(6).Equals("image/") )
- return true;
- if (HasPictureInfoTag()) return true;
- if (HasMusicInfoTag()) return false;
- if (HasVideoInfoTag()) return false;
- return CUtil::IsPicture(m_strPath);
- }
- bool CFileItem::IsLyrics() const
- {
- return URIUtils::GetExtension(m_strPath).Equals(".cdg", false) || URIUtils::GetExtension(m_strPath).Equals(".lrc", false);
- }
- bool CFileItem::IsCUESheet() const
- {
- return URIUtils::GetExtension(m_strPath).Equals(".cue", false);
- }
- bool CFileItem::IsLastFM() const
- {
- return URIUtils::IsLastFM(m_strPath);
- }
- bool CFileItem::IsInternetStream(const bool bStrictCheck /* = false */) const
- {
- if (HasProperty("IsHTTPDirectory"))
- return false;
- return URIUtils::IsInternetStream(m_strPath, bStrictCheck);
- }
- bool CFileItem::IsFileFolder() const
- {
- return (
- IsSmartPlayList() ||
- (IsPlayList() && g_advancedSettings.m_playlistAsFolders) ||
- IsAPK() ||
- IsZIP() ||
- IsRAR() ||
- IsRSS() ||
- IsType(".ogg") ||
- IsType(".nsf") ||
- IsType(".sid") ||
- IsType(".sap")
- );
- }
- bool CFileItem::IsSmartPlayList() const
- {
- CStdString strExtension;
- URIUtils::GetExtension(m_strPath, strExtension);
- strExtension.ToLower();
- return (strExtension == ".xsp");
- }
- bool CFileItem::IsPlayList() const
- {
- return CPlayListFactory::IsPlaylist(*this);
- }
- bool CFileItem::IsPythonScript() const
- {
- return URIUtils::GetExtension(m_strPath).Equals(".py", false);
- }
- bool CFileItem::IsType(const char *ext) const
- {
- return URIUtils::GetExtension(m_strPath).Equals(ext, false);
- }
- bool CFileItem::IsNFO() const
- {
- return URIUtils::GetExtension(m_strPath).Equals(".nfo", false);
- }
- bool CFileItem::IsDVDImage() const
- {
- CStdString strExtension;
- URIUtils::GetExtension(m_strPath, strExtension);
- return (strExtension.Equals(".img") || strExtension.Equals(".iso") || strExtension.Equals(".nrg"));
- }
- bool CFileItem::IsOpticalMediaFile() const
- {
- bool found = IsDVDFile(false, true);
- if (found)
- return true;
- return IsBDFile();
- }
- bool CFileItem::IsDVDFile(bool bVobs /*= true*/, bool bIfos /*= true*/) const
- {
- CStdString strFileName = URIUtils::GetFileName(m_strPath);
- if (bIfos)
- {
- if (strFileName.Equals("video_ts.ifo")) return true;
- if (strFileName.Left(4).Equals("vts_") && strFileName.Right(6).Equals("_0.ifo") && strFileName.length() == 12) return true;
- }
- if (bVobs)
- {
- if (strFileName.Equals("video_ts.vob")) return true;
- if (strFileName.Left(4).Equals("vts_") && strFileName.Right(4).Equals(".vob")) return true;
- }
- return false;
- }
- bool CFileItem::IsBDFile() const
- {
- CStdString strFileName = URIUtils::GetFileName(m_strPath);
- return (strFileName.Equals("index.bdmv"));
- }
- bool CFileItem::IsRAR() const
- {
- return URIUtils::IsRAR(m_strPath);
- }
- bool CFileItem::IsAPK() const
- {
- return URIUtils::IsAPK(m_strPath);
- }
- bool CFileItem::IsZIP() const
- {
- return URIUtils::IsZIP(m_strPath);
- }
- bool CFileItem::IsCBZ() const
- {
- return URIUtils::GetExtension(m_strPath).Equals(".cbz", false);
- }
- bool CFileItem::IsCBR() const
- {
- return URIUtils::GetExtension(m_strPath).Equals(".cbr", false);
- }
- bool CFileItem::IsRSS() const
- {
- if (m_strPath.Left(6).Equals("rss://"))
- return true;
- return URIUtils::GetExtension(m_strPath).Equals(".rss")
- || GetMimeType() == "application/rss+xml";
- }
- bool CFileItem::IsAndroidApp() const
- {
- return URIUtils::IsAndroidApp(m_strPath);
- }
- bool CFileItem::IsStack() const
- {
- return URIUtils::IsStack(m_strPath);
- }
- bool CFileItem::IsPlugin() const
- {
- return URIUtils::IsPlugin(m_strPath);
- }
- bool CFileItem::IsScript() const
- {
- return URIUtils::IsScript(m_strPath);
- }
- bool CFileItem::IsAddonsPath() const
- {
- return URIUtils::IsAddonsPath(m_strPath);
- }
- bool CFileItem::IsSourcesPath() const
- {
- return URIUtils::IsSourcesPath(m_strPath);
- }
- bool CFileItem::IsMultiPath() const
- {
- return URIUtils::IsMultiPath(m_strPath);
- }
- bool CFileItem::IsCDDA() const
- {
- return URIUtils::IsCDDA(m_strPath);
- }
- bool CFileItem::IsDVD() const
- {
- return URIUtils::IsDVD(m_strPath) || m_iDriveType == CMediaSource::SOURCE_TYPE_DVD;
- }
- bool CFileItem::IsOnDVD() const
- {
- return URIUtils::IsOnDVD(m_strPath) || m_iDriveType == CMediaSource::SOURCE_TYPE_DVD;
- }
- bool CFileItem::IsNfs() const
- {
- return URIUtils::IsNfs(m_strPath);
- }
- bool CFileItem::IsAfp() const
- {
- return URIUtils::IsAfp(m_strPath);
- }
- bool CFileItem::IsOnLAN() const
- {
- return URIUtils::IsOnLAN(m_strPath);
- }
- bool CFileItem::IsISO9660() const
- {
- return URIUtils::IsISO9660(m_strPath);
- }
- bool CFileItem::IsRemote() const
- {
- return URIUtils::IsRemote(m_strPath);
- }
- bool CFileItem::IsSmb() const
- {
- return URIUtils::IsSmb(m_strPath);
- }
- bool CFileItem::IsURL() const
- {
- return URIUtils::IsURL(m_strPath);
- }
- bool CFileItem::IsDAAP() const
- {
- return URIUtils::IsDAAP(m_strPath);
- }
- bool CFileItem::IsTuxBox() const
- {
- return URIUtils::IsTuxBox(m_strPath);
- }
- bool CFileItem::IsMythTV() const
- {
- return URIUtils::IsMythTV(m_strPath);
- }
- bool CFileItem::IsHDHomeRun() const
- {
- return URIUtils::IsHDHomeRun(m_strPath);
- }
- bool CFileItem::IsSlingbox() const
- {
- return URIUtils::IsSlingbox(m_strPath);
- }
- bool CFileItem::IsVTP() const
- {
- return URIUtils::IsVTP(m_strPath);
- }
- bool CFileItem::IsLiveTV() const
- {
- return URIUtils::IsLiveTV(m_strPath);
- }
- bool CFileItem::IsHD() const
- {
- return URIUtils::IsHD(m_strPath);
- }
- bool CFileItem::IsMusicDb() const
- {
- CURL url(m_strPath);
- return url.GetProtocol().Equals("musicdb");
- }
- bool CFileItem::IsVideoDb() const
- {
- CURL url(m_strPath);
- return url.GetProtocol().Equals("videodb");
- }
- bool CFileItem::IsVirtualDirectoryRoot() const
- {
- return (m_bIsFolder && m_strPath.IsEmpty());
- }
- bool CFileItem::IsRemovable() const
- {
- return IsOnDVD() || IsCDDA() || m_iDriveType == CMediaSource::SOURCE_TYPE_REMOVABLE;
- }
- bool CFileItem::IsReadOnly() const
- {
- if (IsParentFolder()) return true;
- if (m_bIsShareOrDrive) return true;
- return !CUtil::SupportsFileOperations(m_strPath);
- }
- void CFileItem::FillInDefaultIcon()
- {
- //CLog::Log(LOGINFO, "FillInDefaultIcon(%s)", pItem->GetLabel().c_str());
- // find the default icon for a file or folder item
- // for files this can be the (depending on the file type)
- // default picture for photo's
- // default picture for songs
- // default picture for videos
- // default picture for shortcuts
- // default picture for playlists
- // or the icon embedded in an .xbe
- //
- // for folders
- // for .. folders the default picture for parent folder
- // for other folders the defaultFolder.png
- if (GetIconImage().IsEmpty())
- {
- if (!m_bIsFolder)
- {
- /* To reduce the average runtime of this code, this list should
- * be ordered with most frequently seen types first. Also bear
- * in mind the complexity of the code behind the check in the
- * case of IsWhatater() returns false.
- */
- if ( IsAudio() )
- {
- // audio
- SetIconImage("DefaultAudio.png");
- }
- else if ( IsVideo() )
- {
- // video
- SetIconImage("DefaultVideo.png");
- }
- else if ( IsPicture() )
- {
- // picture
- SetIconImage("DefaultPicture.png");
- }
- else if ( IsPlayList() )
- {
- SetIconImage("DefaultPlaylist.png");
- }
- else if ( IsPythonScript() )
- {
- SetIconImage("DefaultScript.png");
- }
- else
- {
- // default icon for unknown file type
- SetIconImage("DefaultFile.png");
- }
- }
- else
- {
- if ( IsPlayList() )
- {
- SetIconImage("DefaultPlaylist.png");
- }
- else if (IsParentFolder())
- {
- SetIconImage("DefaultFolderBack.png");
- }
- else
- {
- SetIconImage("DefaultFolder.png");
- }
- }
- }
- // Set the icon overlays (if applicable)
- if (!HasOverlay())
- {
- if (URIUtils::IsInRAR(m_strPath))
- SetOverlayImage(CGUIListItem::ICON_OVERLAY_RAR);
- else if (URIUtils::IsInZIP(m_strPath))
- SetOverlayImage(CGUIListItem::ICON_OVERLAY_ZIP);
- }
- }
- void CFileItem::RemoveExtension()
- {
- if (m_bIsFolder)
- return;
- CStdString strLabel = GetLabel();
- URIUtils::RemoveExtension(strLabel);
- SetLabel(strLabel);
- }
- void CFileItem::CleanString()
- {
- if (IsLiveTV())
- return;
- CStdString strLabel = GetLabel();
- CStdString strTitle, strTitleAndYear, strYear;
- CUtil::CleanString(strLabel, strTitle, strTitleAndYear, strYear, true );
- SetLabel(strTitleAndYear);
- }
- void CFileItem::SetLabel(const CStdString &strLabel)
- {
- if (strLabel=="..")
- {
- m_bIsParentFolder=true;
- m_bIsFolder=true;
- m_specialSort = SortSpecialOnTop;
- SetLabelPreformated(true);
- }
- CGUIListItem::SetLabel(strLabel);
- }
- void CFileItem::SetFileSizeLabel()
- {
- if( m_bIsFolder && m_dwSize == 0 )
- SetLabel2("");
- else
- SetLabel2(StringUtils::SizeToString(m_dwSize));
- }
- CURL CFileItem::GetAsUrl() const
- {
- return CURL(m_strPath);
- }
- bool CFileItem::CanQueue() const
- {
- return m_bCanQueue;
- }
- void CFileItem::SetCanQueue(bool bYesNo)
- {
- m_bCanQueue=bYesNo;
- }
- bool CFileItem::IsParentFolder() const
- {
- return m_bIsParentFolder;
- }
- const CStdString& CFileItem::GetMimeType(bool lookup /*= true*/) const
- {
- if( m_mimetype.IsEmpty() && lookup)
- {
- // discard const qualifyier
- CStdString& m_ref = (CStdString&)m_mimetype;
- if( m_bIsFolder )
- m_ref = "x-directory/normal";
- else if( m_strPath.Left(8).Equals("shout://")
- || m_strPath.Left(7).Equals("http://")
- || m_strPath.Left(8).Equals("https://"))
- {
- CCurlFile::GetMimeType(GetAsUrl(), m_ref);
- // try to get mime-type again but with an NSPlayer User-Agent
- // in order for server to provide correct mime-type. Allows us
- // to properly detect an MMS stream
- if (m_ref.Left(11).Equals("video/x-ms-"))
- CCurlFile::GetMimeType(GetAsUrl(), m_ref, "NSPlayer/11.00.6001.7000");
- // make sure there are no options set in mime-type
- // mime-type can look like "video/x-ms-asf ; charset=utf8"
- int i = m_ref.Find(';');
- if(i>=0)
- m_ref.Delete(i,m_ref.length()-i);
- m_ref.Trim();
- }
- else
- m_ref = CMime::GetMimeType(*this);
- // if it's still empty set to an unknown type
- if( m_ref.IsEmpty() )
- m_ref = "application/octet-stream";
- }
- // change protocol to mms for the following mome-type. Allows us to create proper FileMMS.
- if( m_mimetype.Left(32).Equals("application/vnd.ms.wms-hdr.asfv1") || m_mimetype.Left(24).Equals("application/x-mms-framed") )
- {
- CStdString& m_path = (CStdString&)m_strPath;
- m_path.Replace("http:", "mms:");
- }
- return m_mimetype;
- }
- bool CFileItem::IsSamePath(const CFileItem *item) const
- {
- if (!item)
- return false;
- if (item->GetPath() == m_strPath)
- {
- if (item->HasProperty("item_start") || HasProperty("item_start"))
- return (item->GetProperty("item_start") == GetProperty("item_start"));
- return true;
- }
- if (IsMusicDb() && HasMusicInfoTag())
- {
- CFileItem dbItem(m_musicInfoTag->GetURL(), false);
- dbItem.SetProperty("item_start", GetProperty("item_start"));
- return dbItem.IsSamePath(item);
- }
- if (IsVideoDb() && HasVideoInfoTag())
- {
- CFileItem dbItem(m_videoInfoTag->m_strFileNameAndPath, false);
- dbItem.SetProperty("item_start", GetProperty("item_start"));
- return dbItem.IsSamePath(item);
- }
- if (item->IsMusicDb() && item->HasMusicInfoTag())
- {
- CFileItem dbItem(item->m_musicInfoTag->GetURL(), false);
- dbItem.SetProperty("item_start", item->GetProperty("item_start"));
- return IsSamePath(&dbItem);
- }
- if (item->IsVideoDb() && item->HasVideoInfoTag())
- {
- CFileItem dbItem(item->m_videoInfoTag->m_strFileNameAndPath, false);
- dbItem.SetProperty("item_start", item->GetProperty("item_start"));
- return IsSamePath(&dbItem);
- }
- if (HasProperty("original_listitem_url"))
- return (GetProperty("original_listitem_url") == item->GetPath());
- return false;
- }
- bool CFileItem::IsAlbum() const
- {
- return m_bIsAlbum;
- }
- void CFileItem::UpdateInfo(const CFileItem &item, bool replaceLabels /*=true*/)
- {
- if (item.HasVideoInfoTag())
- { // copy info across (TODO: premiered info is normally stored in m_dateTime by the db)
- *GetVideoInfoTag() = *item.GetVideoInfoTag();
- SetOverlayImage(ICON_OVERLAY_UNWATCHED, GetVideoInfoTag()->m_playCount > 0);
- }
- if (item.HasMusicInfoTag())
- *GetMusicInfoTag() = *item.GetMusicInfoTag();
- if (item.HasPictureInfoTag())
- *GetPictureInfoTag() = *item.GetPictureInfoTag();
- if (replaceLabels && !item.GetLabel().IsEmpty())
- SetLabel(item.GetLabel());
- if (replaceLabels && !item.GetLabel2().IsEmpty())
- SetLabel2(item.GetLabel2());
- if (!item.GetThumbnailImage().IsEmpty())
- SetThumbnailImage(item.GetThumbnailImage());
- if (!item.GetIconImage().IsEmpty())
- SetIconImage(item.GetIconImage());
- AppendProperties(item);
- }
- /////////////////////////////////////////////////////////////////////////////////
- /////
- ///// CFileItemList
- /////
- //////////////////////////////////////////////////////////////////////////////////
- CFileItemList::CFileItemList()
- {
- m_fastLookup = false;
- m_bIsFolder = true;
- m_cacheToDisc = CACHE_IF_SLOW;
- m_sortMethod = SORT_METHOD_NONE;
- m_sortOrder = SortOrderNone;
- m_sortIgnoreFolders = false;
- m_replaceListing = false;
- }
- CFileItemList::CFileItemList(const CStdString& strPath) : CFileItem(strPath, true)
- {
- m_fastLookup = false;
- m_cacheToDisc = CACHE_IF_SLOW;
- m_sortMethod = SORT_METHOD_NONE;
- m_sortOrder = SortOrderNone;
- m_sortIgnoreFolders = false;
- m_replaceListing = false;
- }
- CFileItemList::~CFileItemList()
- {
- Clear();
- }
- CFileItemPtr CFileItemList::operator[] (int iItem)
- {
- return Get(iItem);
- }
- const CFileItemPtr CFileItemList::operator[] (int iItem) const
- {
- return Get(iItem);
- }
- CFileItemPtr CFileItemList::operator[] (const CStdString& strPath)
- {
- return Get(strPath);
- }
- const CFileItemPtr CFileItemList::operator[] (const CStdString& strPath) const
- {
- return Get(strPath);
- }
- void CFileItemList::SetFastLookup(bool fastLookup)
- {
- CSingleLock lock(m_lock);
- if (fastLookup && !m_fastLookup)
- { // generate the map
- m_map.clear();
- for (unsigned int i=0; i < m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- CStdString path(pItem->GetPath()); path.ToLower();
- m_map.insert(MAPFILEITEMSPAIR(path, pItem));
- }
- }
- if (!fastLookup && m_fastLookup)
- m_map.clear();
- m_fastLookup = fastLookup;
- }
- bool CFileItemList::Contains(const CStdString& fileName) const
- {
- CSingleLock lock(m_lock);
- // checks case insensitive
- CStdString checkPath(fileName); checkPath.ToLower();
- if (m_fastLookup)
- return m_map.find(checkPath) != m_map.end();
- // slow method...
- for (unsigned int i = 0; i < m_items.size(); i++)
- {
- const CFileItemPtr pItem = m_items[i];
- if (pItem->GetPath().Equals(checkPath))
- return true;
- }
- return false;
- }
- void CFileItemList::Clear()
- {
- CSingleLock lock(m_lock);
- ClearItems();
- m_sortMethod = SORT_METHOD_NONE;
- m_sortOrder = SortOrderNone;
- m_sortIgnoreFolders = false;
- m_cacheToDisc = CACHE_IF_SLOW;
- m_sortDetails.clear();
- m_replaceListing = false;
- m_content.Empty();
- }
- void CFileItemList::ClearItems()
- {
- CSingleLock lock(m_lock);
- // make sure we free the memory of the items (these are GUIControls which may have allocated resources)
- FreeMemory();
- for (unsigned int i = 0; i < m_items.size(); i++)
- {
- CFileItemPtr item = m_items[i];
- item->FreeMemory();
- }
- m_items.clear();
- m_map.clear();
- }
- void CFileItemList::Add(const CFileItemPtr &pItem)
- {
- CSingleLock lock(m_lock);
- m_items.push_back(pItem);
- if (m_fastLookup)
- {
- CStdString path(pItem->GetPath());
- path.ToLower();
- m_map.insert(MAPFILEITEMSPAIR(path, pItem));
- }
- }
- void CFileItemList::AddFront(const CFileItemPtr &pItem, int itemPosition)
- {
- CSingleLock lock(m_lock);
- if (itemPosition >= 0)
- {
- m_items.insert(m_items.begin()+itemPosition, pItem);
- }
- else
- {
- m_items.insert(m_items.begin()+(m_items.size()+itemPosition), pItem);
- }
- if (m_fastLookup)
- {
- CStdString path(pItem->GetPath()); path.ToLower();
- m_map.insert(MAPFILEITEMSPAIR(path, pItem));
- }
- }
- void CFileItemList::Remove(CFileItem* pItem)
- {
- CSingleLock lock(m_lock);
- for (IVECFILEITEMS it = m_items.begin(); it != m_items.end(); ++it)
- {
- if (pItem == it->get())
- {
- m_items.erase(it);
- if (m_fastLookup)
- {
- CStdString path(pItem->GetPath()); path.ToLower();
- m_map.erase(path);
- }
- break;
- }
- }
- }
- void CFileItemList::Remove(int iItem)
- {
- CSingleLock lock(m_lock);
- if (iItem >= 0 && iItem < (int)Size())
- {
- CFileItemPtr pItem = *(m_items.begin() + iItem);
- if (m_fastLookup)
- {
- CStdString path(pItem->GetPath()); path.ToLower();
- m_map.erase(path);
- }
- m_items.erase(m_items.begin() + iItem);
- }
- }
- void CFileItemList::Append(const CFileItemList& itemlist)
- {
- CSingleLock lock(m_lock);
- for (int i = 0; i < itemlist.Size(); ++i)
- Add(itemlist[i]);
- }
- void CFileItemList::Assign(const CFileItemList& itemlist, bool append)
- {
- CSingleLock lock(m_lock);
- if (!append)
- Clear();
- Append(itemlist);
- SetPath(itemlist.GetPath());
- SetLabel(itemlist.GetLabel());
- m_sortDetails = itemlist.m_sortDetails;
- m_replaceListing = itemlist.m_replaceListing;
- m_content = itemlist.m_content;
- m_mapProperties = itemlist.m_mapProperties;
- m_cacheToDisc = itemlist.m_cacheToDisc;
- }
- bool CFileItemList::Copy(const CFileItemList& items)
- {
- // assign all CFileItem parts
- *(CFileItem*)this = *(CFileItem*)&items;
- // assign the rest of the CFileItemList properties
- m_replaceListing = items.m_replaceListing;
- m_content = items.m_content;
- m_mapProperties = items.m_mapProperties;
- m_cacheToDisc = items.m_cacheToDisc;
- m_sortDetails = items.m_sortDetails;
- m_sortMethod = items.m_sortMethod;
- m_sortOrder = items.m_sortOrder;
- m_sortIgnoreFolders = items.m_sortIgnoreFolders;
- // make a copy of each item
- for (int i = 0; i < items.Size(); i++)
- {
- CFileItemPtr newItem(new CFileItem(*items[i]));
- Add(newItem);
- }
- return true;
- }
- CFileItemPtr CFileItemList::Get(int iItem)
- {
- CSingleLock lock(m_lock);
- if (iItem > -1 && iItem < (int)m_items.size())
- return m_items[iItem];
- return CFileItemPtr();
- }
- const CFileItemPtr CFileItemList::Get(int iItem) const
- {
- CSingleLock lock(m_lock);
- if (iItem > -1 && iItem < (int)m_items.size())
- return m_items[iItem];
- return CFileItemPtr();
- }
- CFileItemPtr CFileItemList::Get(const CStdString& strPath)
- {
- CSingleLock lock(m_lock);
- CStdString pathToCheck(strPath); pathToCheck.ToLower();
- if (m_fastLookup)
- {
- IMAPFILEITEMS it=m_map.find(pathToCheck);
- if (it != m_map.end())
- return it->second;
- return CFileItemPtr();
- }
- // slow method...
- for (unsigned int i = 0; i < m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- if (pItem->GetPath().Equals(pathToCheck))
- return pItem;
- }
- return CFileItemPtr();
- }
- const CFileItemPtr CFileItemList::Get(const CStdString& strPath) const
- {
- CSingleLock lock(m_lock);
-
- CStdString pathToCheck(strPath); pathToCheck.ToLower();
-
- if (m_fastLookup)
- {
- map<CStdString, CFileItemPtr>::const_iterator it=m_map.find(pathToCheck);
- if (it != m_map.end())
- return it->second;
- return CFileItemPtr();
- }
- // slow method...
- for (unsigned int i = 0; i < m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- if (pItem->GetPath().Equals(pathToCheck))
- return pItem;
- }
- return CFileItemPtr();
- }
- int CFileItemList::Size() const
- {
- CSingleLock lock(m_lock);
- return (int)m_items.size();
- }
- bool CFileItemList::IsEmpty() const
- {
- CSingleLock lock(m_lock);
- return (m_items.size() <= 0);
- }
- void CFileItemList::Reserve(int iCount)
- {
- CSingleLock lock(m_lock);
- m_items.reserve(iCount);
- }
- void CFileItemList::Sort(FILEITEMLISTCOMPARISONFUNC func)
- {
- CSingleLock lock(m_lock);
- std::stable_sort(m_items.begin(), m_items.end(), func);
- }
- void CFileItemList::FillSortFields(FILEITEMFILLFUNC func)
- {
- CSingleLock lock(m_lock);
- std::for_each(m_items.begin(), m_items.end(), func);
- }
- void CFileItemList::Sort(SORT_METHOD sortMethod, SortOrder sortOrder)
- {
- // Already sorted?
- if (sortMethod == m_sortMethod && m_sortOrder == sortOrder)
- return;
- SortBy sortBy = SortByNone;
- SortAttribute sortAttributes = SortAttributeNone;
- switch (sortMethod)
- {
- case SORT_METHOD_LABEL:
- case SORT_METHOD_LABEL_IGNORE_FOLDERS:
- case SORT_METHOD_LABEL_IGNORE_THE:
- sortBy = SortByLabel;
- break;
- case SORT_METHOD_DATE:
- sortBy = SortByDate;
- break;
- case SORT_METHOD_SIZE:
- sortBy = SortBySize;
- break;
- case SORT_METHOD_BITRATE:
- sortBy = SortByBitrate;
- break;
- case SORT_METHOD_DRIVE_TYPE:
- sortBy = SortByDriveType;
- break;
- case SORT_METHOD_TRACKNUM:
- sortBy = SortByTrackNumber;
- break;
- case SORT_METHOD_EPISODE:
- sortBy = SortByEpisodeNumber;
- break;
- case SORT_METHOD_DURATION:
- case SORT_METHOD_VIDEO_RUNTIME:
- sortBy = SortByTime;
- break;
- case SORT_METHOD_TITLE:
- case SORT_METHOD_TITLE_IGNORE_THE:
- case SORT_METHOD_VIDEO_TITLE:
- sortBy = SortByTitle;
- break;
- case SORT_METHOD_ARTIST:
- case SORT_METHOD_ARTIST_IGNORE_THE:
- sortBy = SortByArtist;
- break;
- case SORT_METHOD_ALBUM:
- case SORT_METHOD_ALBUM_IGNORE_THE:
- sortBy = SortByAlbum;
- break;
- case SORT_METHOD_GENRE:
- sortBy = SortByGenre;
- break;
- case SORT_METHOD_COUNTRY:
- sortBy = SortByCountry;
- break;
- case SORT_METHOD_DATEADDED:
- sortBy = SortByDateAdded;
- break;
- case SORT_METHOD_FILE:
- sortBy = SortByFile;
- break;
- case SORT_METHOD_SONG_RATING:
- case SORT_METHOD_VIDEO_RATING:
- sortBy = SortByRating;
- break;
- case SORT_METHOD_VIDEO_SORT_TITLE:
- case SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE:
- sortBy = SortBySortTitle;
- break;
- case SORT_METHOD_YEAR:
- sortBy = SortByYear;
- break;
- case SORT_METHOD_PRODUCTIONCODE:
- sortBy = SortByProductionCode;
- break;
- case SORT_METHOD_PROGRAM_COUNT:
- sortBy = SortByProgramCount;
- break;
- case SORT_METHOD_PLAYLIST_ORDER:
- sortBy = SortByPlaylistOrder;
- break;
- case SORT_METHOD_MPAA_RATING:
- sortBy = SortByMPAA;
- break;
- case SORT_METHOD_STUDIO:
- case SORT_METHOD_STUDIO_IGNORE_THE:
- sortBy = SortByStudio;
- break;
- case SORT_METHOD_FULLPATH:
- sortBy = SortByPath;
- break;
- case SORT_METHOD_LASTPLAYED:
- sortBy = SortByLastPlayed;
- break;
- case SORT_METHOD_PLAYCOUNT:
- sortBy = SortByPlaycount;
- break;
- case SORT_METHOD_LISTENERS:
- sortBy = SortByListeners;
- break;
- default:
- CLog::Log(LOGWARNING, "Unknown sort method %d", sortMethod);
- return;
- }
- if (sortMethod == SORT_METHOD_LABEL_IGNORE_THE ||
- sortMethod == SORT_METHOD_TITLE_IGNORE_THE ||
- sortMethod == SORT_METHOD_ARTIST_IGNORE_THE ||
- sortMethod == SORT_METHOD_ALBUM_IGNORE_THE ||
- sortMethod == SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE ||
- sortMethod == SORT_METHOD_STUDIO_IGNORE_THE)
- sortAttributes = (SortAttribute)((int)sortAttributes | SortAttributeIgnoreArticle);
- if (sortMethod == SORT_METHOD_FILE ||
- sortMethod == SORT_METHOD_VIDEO_SORT_TITLE ||
- sortMethod == SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE ||
- sortMethod == SORT_METHOD_LABEL_IGNORE_FOLDERS ||
- sortMethod == SORT_METHOD_DATEADDED ||
- sortMethod == SORT_METHOD_VIDEO_RATING ||
- sortMethod == SORT_METHOD_YEAR ||
- sortMethod == SORT_METHOD_PLAYLIST_ORDER ||
- sortMethod == SORT_METHOD_LASTPLAYED ||
- sortMethod == SORT_METHOD_PLAYCOUNT ||
- m_sortIgnoreFolders)
- sortAttributes = (SortAttribute)((int)sortAttributes | SortAttributeIgnoreFolders);
- if (sortBy == SortByNone)
- return;
- SortItems sortItems((size_t)Size());
- for (int index = 0; index < Size(); index++)
- {
- m_items[index]->ToSortable(sortItems[index]);
- sortItems[index][FieldId] = index;
- }
- // do the sorting
- SortUtils::Sort(sortBy, sortOrder, sortAttributes, sortItems);
- // apply the new order to the existing CFileItems
- VECFILEITEMS sortedFileItems;
- sortedFileItems.reserve(Size());
- for (SortItems::const_iterator it = sortItems.begin(); it != sortItems.end(); it++)
- {
- CFileItemPtr item = m_items[(int)it->at(FieldId).asInteger()];
- // Set the sort label in the CFileItem
- item->SetSortLabel(CStdStringW(it->at(FieldSort).asWideString()));
- sortedFileItems.push_back(item);
- }
- // replace the current list with the re-ordered one
- m_items.assign(sortedFileItems.begin(), sortedFileItems.end());
- m_sortMethod = sortMethod;
- m_sortOrder = sortOrder;
- }
- void CFileItemList::Randomize()
- {
- CSingleLock lock(m_lock);
- random_shuffle(m_items.begin(), m_items.end());
- }
- void CFileItemList::Archive(CArchive& ar)
- {
- CSingleLock lock(m_lock);
- if (ar.IsStoring())
- {
- CFileItem::Archive(ar);
- int i = 0;
- if (m_items.size() > 0 && m_items[0]->IsParentFolder())
- i = 1;
- ar << (int)(m_items.size() - i);
- ar << m_fastLookup;
- ar << (int)m_sortMethod;
- ar << (int)m_sortOrder;
- ar << m_sortIgnoreFolders;
- ar << (int)m_cacheToDisc;
- ar << (int)m_sortDetails.size();
- for (unsigned int j = 0; j < m_sortDetails.size(); ++j)
- {
- const SORT_METHOD_DETAILS &details = m_sortDetails[j];
- ar << (int)details.m_sortMethod;
- ar << details.m_buttonLabel;
- ar << details.m_labelMasks.m_strLabelFile;
- ar << details.m_labelMasks.m_strLabelFolder;
- ar << details.m_labelMasks.m_strLabel2File;
- ar << details.m_labelMasks.m_strLabel2Folder;
- }
- ar << m_content;
- for (; i < (int)m_items.size(); ++i)
- {
- CFileItemPtr pItem = m_items[i];
- ar << *pItem;
- }
- }
- else
- {
- CFileItemPtr pParent;
- if (!IsEmpty())
- {
- CFileItemPtr pItem=m_items[0];
- if (pItem->IsParentFolder())
- pParent.reset(new CFileItem(*pItem));
- }
- SetFastLookup(false);
- Clear();
- CFileItem::Archive(ar);
- int iSize = 0;
- ar >> iSize;
- if (iSize <= 0)
- return ;
- if (pParent)
- {
- m_items.reserve(iSize + 1);
- m_items.push_back(pParent);
- }
- else
- m_items.reserve(iSize);
- bool fastLookup=false;
- ar >> fastLookup;
- int tempint;
- ar >> (int&)tempint;
- m_sortMethod = SORT_METHOD(tempint);
- ar >> (int&)tempint;
- m_sortOrder = SortOrder(tempint);
- ar >> m_sortIgnoreFolders;
- ar >> (int&)tempint;
- m_cacheToDisc = CACHE_TYPE(tempint);
- unsigned int detailSize = 0;
- ar >> detailSize;
- for (unsigned int j = 0; j < detailSize; ++j)
- {
- SORT_METHOD_DETAILS details;
- ar >> (int&)tempint;
- details.m_sortMethod = SORT_METHOD(tempint);
- ar >> details.m_buttonLabel;
- ar >> details.m_labelMasks.m_strLabelFile;
- ar >> details.m_labelMasks.m_strLabelFolder;
- ar >> details.m_labelMasks.m_strLabel2File;
- ar >> details.m_labelMasks.m_strLabel2Folder;
- m_sortDetails.push_back(details);
- }
- ar >> m_content;
- for (int i = 0; i < iSize; ++i)
- {
- CFileItemPtr pItem(new CFileItem);
- ar >> *pItem;
- Add(pItem);
- }
- SetFastLookup(fastLookup);
- }
- }
- void CFileItemList::FillInDefaultIcons()
- {
- CSingleLock lock(m_lock);
- for (int i = 0; i < (int)m_items.size(); ++i)
- {
- CFileItemPtr pItem = m_items[i];
- pItem->FillInDefaultIcon();
- }
- }
- int CFileItemList::GetFolderCount() const
- {
- CSingleLock lock(m_lock);
- int nFolderCount = 0;
- for (int i = 0; i < (int)m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- if (pItem->m_bIsFolder)
- nFolderCount++;
- }
- return nFolderCount;
- }
- int CFileItemList::GetObjectCount() const
- {
- CSingleLock lock(m_lock);
- int numObjects = (int)m_items.size();
- if (numObjects && m_items[0]->IsParentFolder())
- numObjects--;
- return numObjects;
- }
- int CFileItemList::GetFileCount() const
- {
- CSingleLock lock(m_lock);
- int nFileCount = 0;
- for (int i = 0; i < (int)m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- if (!pItem->m_bIsFolder)
- nFileCount++;
- }
- return nFileCount;
- }
- int CFileItemList::GetSelectedCount() const
- {
- CSingleLock lock(m_lock);
- int count = 0;
- for (int i = 0; i < (int)m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- if (pItem->IsSelected())
- count++;
- }
- return count;
- }
- void CFileItemList::FilterCueItems()
- {
- CSingleLock lock(m_lock);
- // Handle .CUE sheet files...
- VECSONGS itemstoadd;
- CStdStringArray itemstodelete;
- for (int i = 0; i < (int)m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- if (!pItem->m_bIsFolder)
- { // see if it's a .CUE sheet
- if (pItem->IsCUESheet())
- {
- CCueDocument cuesheet;
- if (cuesheet.Parse(pItem->GetPath()))
- {
- VECSONGS newitems;
- cuesheet.GetSongs(newitems);
- std::vector<CStdString> MediaFileVec;
- cuesheet.GetMediaFiles(MediaFileVec);
- // queue the cue sheet and the underlying media file for deletion
- for(std::vector<CStdString>::iterator itMedia = MediaFileVec.begin(); itMedia != MediaFileVec.end(); itMedia++)
- {
- CStdString strMediaFile = *itMedia;
- CStdString fileFromCue = strMediaFile; // save the file from the cue we're matching against,
- // as we're going to search for others here...
- bool bFoundMediaFile = CFile::Exists(strMediaFile);
- // queue the cue sheet and the underlying media file for deletion
- if (!bFoundMediaFile)
- {
- // try file in same dir, not matching case...
- if (Contains(strMediaFile))
- {
- bFoundMediaFile = true;
- }
- else
- {
- // try removing the .cue extension...
- strMediaFile = pItem->GetPath();
- URIUtils::RemoveExtension(strMediaFile);
- CFileItem item(strMediaFile, false);
- if (item.IsAudio() && Contains(strMediaFile))
- {
- bFoundMediaFile = true;
- }
- else
- { // try replacing the extension with one of our allowed ones.
- CStdStringArray extensions;
- StringUtils::SplitString(g_settings.m_musicExtensions, "|", extensions);
- for (unsigned int i = 0; i < extensions.size(); i++)
- {
- strMediaFile = URIUtils::ReplaceExtension(pItem->GetPath(), extensions[i]);
- CFileItem item(strMediaFile, false);
- if (!item.IsCUESheet() && !item.IsPlayList() && Contains(strMediaFile))
- {
- bFoundMediaFile = true;
- break;
- }
- }
- }
- }
- }
- if (bFoundMediaFile)
- {
- itemstodelete.push_back(pItem->GetPath());
- itemstodelete.push_back(strMediaFile);
- // get the additional stuff (year, genre etc.) from the underlying media files tag.
- CMusicInfoTag tag;
- auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(strMediaFile));
- if (NULL != pLoader.get())
- {
- // get id3tag
- pLoader->Load(strMediaFile, tag);
- }
- // fill in any missing entries from underlying media file
- for (int j = 0; j < (int)newitems.size(); j++)
- {
- CSong song = newitems[j];
- // only for songs that actually match the current media file
- if (song.strFileName == fileFromCue)
- {
- // we might have a new media file from the above matching code
- song.strFileName = strMediaFile;
- if (tag.Loaded())
- {
- if (song.strAlbum.empty() && !tag.GetAlbum().empty()) song.strAlbum = tag.GetAlbum();
- if (song.albumArtist.empty() && !tag.GetAlbumArtist().empty()) song.albumArtist = tag.GetAlbumArtist();
- if (song.genre.empty() && !tag.GetGenre().empty()) song.genre = tag.GetGenre();
- if (song.artist.empty() && !tag.GetArtist().empty()) song.artist = tag.GetArtist();
- if (tag.GetDiscNumber()) song.iTrack |= (tag.GetDiscNumber() << 16); // see CMusicInfoTag::GetDiscNumber()
- SYSTEMTIME dateTime;
- tag.GetReleaseDate(dateTime);
- if (dateTime.wYear) song.iYear = dateTime.wYear;
- if (song.embeddedArt.empty() && !tag.GetCoverArtInfo().empty())
- song.embeddedArt = tag.GetCoverArtInfo();
- }
- if (!song.iDuration && tag.GetDuration() > 0)
- { // must be the last song
- song.iDuration = (tag.GetDuration() * 75 - song.iStartOffset + 37) / 75;
- }
- // add this item to the list
- itemstoadd.push_back(song);
- }
- }
- }
- else
- { // remove the .cue sheet from the directory
- itemstodelete.push_back(pItem->GetPath());
- }
- }
- }
- else
- { // remove the .cue sheet from the directory (can't parse it - no point listing it)
- itemstodelete.push_back(pItem->GetPath());
- }
- }
- }
- }
- // now delete the .CUE files and underlying media files.
- for (int i = 0; i < (int)itemstodelete.size(); i++)
- {
- for (int j = 0; j < (int)m_items.size(); j++)
- {
- CFileItemPtr pItem = m_items[j];
- if (stricmp(pItem->GetPath().c_str(), itemstodelete[i].c_str()) == 0)
- { // delete this item
- m_items.erase(m_items.begin() + j);
- break;
- }
- }
- }
- // and add the files from the .CUE sheet
- for (int i = 0; i < (int)itemstoadd.size(); i++)
- {
- // now create the file item, and add to the item list.
- CFileItemPtr pItem(new CFileItem(itemstoadd[i]));
- m_items.push_back(pItem);
- }
- }
- // Remove the extensions from the filenames
- void CFileItemList::RemoveExtensions()
- {
- CSingleLock lock(m_lock);
- for (int i = 0; i < Size(); ++i)
- m_items[i]->RemoveExtension();
- }
- void CFileItemList::Stack(bool stackFiles /* = true */)
- {
- CSingleLock lock(m_lock);
- // not allowed here
- if (IsVirtualDirectoryRoot() || IsLiveTV() || IsSourcesPath())
- return;
- SetProperty("isstacked", true);
- // items needs to be sorted for stuff below to work properly
- Sort(SORT_METHOD_LABEL, SortOrderAscending);
- StackFolders();
- if (stackFiles)
- StackFiles();
- }
- void CFileItemList::StackFolders()
- {
- // Precompile our REs
- VECCREGEXP folderRegExps;
- CRegExp folderRegExp(true);
- const CStdStringArray& strFolderRegExps = g_advancedSettings.m_folderStackRegExps;
- CStdStringArray::const_iterator strExpression = strFolderRegExps.begin();
- while (strExpression != strFolderRegExps.end())
- {
- if (!folderRegExp.RegComp(*strExpression))
- CLog::Log(LOGERROR, "%s: Invalid folder stack RegExp:'%s'", __FUNCTION__, strExpression->c_str());
- else
- folderRegExps.push_back(folderRegExp);
- strExpression++;
- }
- // stack folders
- for (int i = 0; i < Size(); i++)
- {
- CFileItemPtr item = Get(i);
- // combined the folder checks
- if (item->m_bIsFolder)
- {
- // only check known fast sources?
- // NOTES:
- // 1. rars and zips may be on slow sources? is this supposed to be allowed?
- if( !item->IsRemote()
- || item->IsSmb()
- || item->IsNfs()
- || item->IsAfp()
- || URIUtils::IsInRAR(item->GetPath())
- || URIUtils::IsInZIP(item->GetPath())
- || URIUtils::IsOnLAN(item->GetPath())
- )
- {
- // stack cd# folders if contains only a single video file
- bool bMatch(false);
- VECCREGEXP::iterator expr = folderRegExps.begin();
- while (!bMatch && expr != folderRegExps.end())
- {
- //CLog::Log(LOGDEBUG,"%s: Running expression %s on %s", __FUNCTION__, expr->GetPattern().c_str(), item->GetLabel().c_str());
- bMatch = (expr->RegFind(item->GetLabel().c_str()) != -1);
- if (bMatch)
- {
- CFileItemList items;
- CDirectory::GetDirectory(item->GetPath(),items,g_settings.m_videoExtensions);
- // optimized to only traverse listing once by checking for filecount
- // and recording last file item for later use
- int nFiles = 0;
- int index = -1;
- for (int j = 0; j < items.Size(); j++)
- {
- if (!items[j]->m_bIsFolder)
- {
- nFiles++;
- index = j;
- }
- if (nFiles > 1)
- break;
- }
- if (nFiles == 1)
- *item = *items[index];
- }
- expr++;
- }
- // check for dvd folders
- if (!bMatch)
- {
- CStdString path;
- CStdString dvdPath;
- URIUtils::AddFileToFolder(item->GetPath(), "VIDEO_TS.IFO", path);
- if (CFile::Exists(path))
- dvdPath = path;
- else
- {
- URIUtils::AddFileToFolder(item->GetPath(), "VIDEO_TS", dvdPath);
- URIUtils::AddFileToFolder(dvdPath, "VIDEO_TS.IFO", path);
- dvdPath.Empty();
- if (CFile::Exists(path))
- dvdPath = path;
- }
- #ifdef HAVE_LIBBLURAY
- if (dvdPath.IsEmpty())
- {
- URIUtils::AddFileToFolder(item->GetPath(), "index.bdmv", path);
- if (CFile::Exists(path))
- dvdPath = path;
- else
- {
- URIUtils::AddFileToFolder(item->GetPath(), "BDMV", dvdPath);
- URIUtils::AddFileToFolder(dvdPath, "index.bdmv", path);
- dvdPath.Empty();
- if (CFile::Exists(path))
- dvdPath = path;
- }
- }
- #endif
- if (!dvdPath.IsEmpty())
- {
- // NOTE: should this be done for the CD# folders too?
- item->m_bIsFolder = false;
- item->SetPath(dvdPath);
- item->SetLabel2("");
- item->SetLabelPreformated(true);
- m_sortMethod = SORT_METHOD_NONE; /* sorting is now broken */
- }
- }
- }
- }
- }
- }
- void CFileItemList::StackFiles()
- {
- // Precompile our REs
- VECCREGEXP stackRegExps;
- CRegExp tmpRegExp(true);
- const CStdStringArray& strStackRegExps = g_advancedSettings.m_videoStackRegExps;
- CStdStringArray::const_iterator strRegExp = strStackRegExps.begin();
- while (strRegExp != strStackRegExps.end())
- {
- if (tmpRegExp.RegComp(*strRegExp))
- {
- if (tmpRegExp.GetCaptureTotal() == 4)
- stackRegExps.push_back(tmpRegExp);
- else
- CLog::Log(LOGERROR, "Invalid video stack RE (%s). Must have 4 captures.", strRegExp->c_str());
- }
- strRegExp++;
- }
- // now stack the files, some of which may be from the previous stack iteration
- int i = 0;
- while (i < Size())
- {
- CFileItemPtr item1 = Get(i);
- // skip folders, nfo files, playlists
- if (item1->m_bIsFolder
- || item1->IsParentFolder()
- || item1->IsNFO()
- || item1->IsPlayList()
- )
- {
- // increment index
- i++;
- continue;
- }
- int64_t size = 0;
- size_t offset = 0;
- CStdString stackName;
- CStdString file1;
- CStdString filePath;
- vector<int> stack;
- VECCREGEXP::iterator expr = stackRegExps.begin();
- URIUtils::Split(item1->GetPath(), filePath, file1);
- if (URIUtils::ProtocolHasEncodedFilename(CURL(filePath).GetProtocol() ) )
- CURL::Decode(file1);
- int j;
- while (expr != stackRegExps.end())
- {
- if (expr->RegFind(file1, offset) != -1)
- {
- CStdString Title1 = expr->GetMatch(1),
- Volume1 = expr->GetMatch(2),
- Ignore1 = expr->GetMatch(3),
- Extension1 = expr->GetMatch(4);
- if (offset)
- Title1 = file1.substr(0, expr->GetSubStart(2));
- j = i + 1;
- while (j < Size())
- {
- CFileItemPtr item2 = Get(j);
- // skip folders, nfo files, playlists
- if (item2->m_bIsFolder
- || item2->IsParentFolder()
- || item2->IsNFO()
- || item2->IsPlayList()
- )
- {
- // increment index
- j++;
- continue;
- }
- CStdString file2, filePath2;
- URIUtils::Split(item2->GetPath(), filePath2, file2);
- if (URIUtils::ProtocolHasEncodedFilename(CURL(filePath2).GetProtocol() ) )
- CURL::Decode(file2);
- if (expr->RegFind(file2, offset) != -1)
- {
- CStdString Title2 = expr->GetMatch(1),
- Volume2 = expr->GetMatch(2),
- Ignore2 = expr->GetMatch(3),
- Extension2 = expr->GetMatch(4);
- if (offset)
- Title2 = file2.substr(0, expr->GetSubStart(2));
- if (Title1.Equals(Title2))
- {
- if (!Volume1.Equals(Volume2))
- {
- if (Ignore1.Equals(Ignore2) && Extension1.Equals(Extension2))
- {
- if (stack.size() == 0)
- {
- stackName = Title1 + Ignore1 + Extension1;
- stack.push_back(i);
- size += item1->m_dwSize;
- }
- stack.push_back(j);
- size += item2->m_dwSize;
- }
- else // Sequel
- {
- offset = 0;
- expr++;
- break;
- }
- }
- else if (!Ignore1.Equals(Ignore2)) // False positive, try again with offset
- {
- offset = expr->GetSubStart(3);
- break;
- }
- else // Extension mismatch
- {
- offset = 0;
- expr++;
- break;
- }
- }
- else // Title mismatch
- {
- offset = 0;
- expr++;
- break;
- }
- }
- else // No match 2, next expression
- {
- offset = 0;
- expr++;
- break;
- }
- j++;
- }
- if (j == Size())
- expr = stackRegExps.end();
- }
- else // No match 1
- {
- offset = 0;
- expr++;
- }
- if (stack.size() > 1)
- {
- // have a stack, remove the items and add the stacked item
- // dont actually stack a multipart rar set, just remove all items but the first
- CStdString stackPath;
- if (Get(stack[0])->IsRAR())
- stackPath = Get(stack[0])->GetPath();
- else
- {
- CStackDirectory dir;
- stackPath = dir.ConstructStackPath(*this, stack);
- }
- item1->SetPath(stackPath);
- // clean up list
- for (unsigned k = 1; k < stack.size(); k++)
- Remove(i+1);
- // item->m_bIsFolder = true; // don't treat stacked files as folders
- // the label may be in a different char set from the filename (eg over smb
- // the label is converted from utf8, but the filename is not)
- if (!g_guiSettings.GetBool("filelists.showextensions"))
- URIUtils::RemoveExtension(stackName);
- item1->SetLabel(stackName);
- item1->m_dwSize = size;
- break;
- }
- }
- i++;
- }
- }
- bool CFileItemList::Load(int windowID)
- {
- CFile file;
- if (file.Open(GetDiscFileCache(windowID)))
- {
- CLog::Log(LOGDEBUG,"Loading fileitems [%s]",GetPath().c_str());
- CArchive ar(&file, CArchive::load);
- ar >> *this;
- CLog::Log(LOGDEBUG," -- items: %i, directory: %s sort method: %i, ascending: %s",Size(),GetPath().c_str(), m_sortMethod, m_sortOrder ? "true" : "false");
- ar.Close();
- file.Close();
- return true;
- }
- return false;
- }
- bool CFileItemList::Save(int windowID)
- {
- int iSize = Size();
- if (iSize <= 0)
- return false;
- CLog::Log(LOGDEBUG,"Saving fileitems [%s]",GetPath().c_str());
- CFile file;
- if (file.OpenForWrite(GetDiscFileCache(windowID), true)) // overwrite always
- {
- CArchive ar(&file, CArchive::store);
- ar << *this;
- CLog::Log(LOGDEBUG," -- items: %i, sort method: %i, ascending: %s",iSize,m_sortMethod, m_sortOrder ? "true" : "false");
- ar.Close();
- file.Close();
- return true;
- }
- return false;
- }
- void CFileItemList::RemoveDiscCache(int windowID) const
- {
- CStdString cacheFile(GetDiscFileCache(windowID));
- if (CFile::Exists(cacheFile))
- {
- CLog::Log(LOGDEBUG,"Clearing cached fileitems [%s]",GetPath().c_str());
- CFile::Delete(cacheFile);
- }
- }
- CStdString CFileItemList::GetDiscFileCache(int windowID) const
- {
- CStdString strPath(GetPath());
- URIUtils::RemoveSlashAtEnd(strPath);
- Crc32 crc;
- crc.ComputeFromLowerCase(strPath);
- CStdString cacheFile;
- if (IsCDDA() || IsOnDVD())
- cacheFile.Format("special://temp/r-%08x.fi", (unsigned __int32)crc);
- else if (IsMusicDb())
- cacheFile.Format("special://temp/mdb-%08x.fi", (unsigned __int32)crc);
- else if (IsVideoDb())
- cacheFile.Format("special://temp/vdb-%08x.fi", (unsigned __int32)crc);
- else if (IsSmartPlayList())
- cacheFile.Format("special://temp/sp-%08x.fi", (unsigned __int32)crc);
- else if (windowID)
- cacheFile.Format("special://temp/%i-%08x.fi", windowID, (unsigned __int32)crc);
- else
- cacheFile.Format("special://temp/%08x.fi", (unsigned __int32)crc);
- return cacheFile;
- }
- bool CFileItemList::AlwaysCache() const
- {
- // some database folders are always cached
- if (IsMusicDb())
- return CMusicDatabaseDirectory::CanCache(GetPath());
- if (IsVideoDb())
- return CVideoDatabaseDirectory::CanCache(GetPath());
- return false;
- }
- CStdString CFileItem::GetUserMusicThumb(bool alwaysCheckRemote /* = false */) const
- {
- if (m_strPath.IsEmpty()
- || m_bIsShareOrDrive
- || IsInternetStream()
- || URIUtils::IsUPnP(m_strPath)
- || (URIUtils::IsFTP(m_strPath) && !g_advancedSettings.m_bFTPThumbs)
- || IsPlugin()
- || IsAddonsPath()
- || IsParentFolder()
- || IsMusicDb())
- return "";
- // we first check for <filename>.tbn or <foldername>.tbn
- CStdString fileThumb(GetTBNFile());
- if (CFile::Exists(fileThumb))
- return fileThumb;
- // if a folder, check for folder.jpg
- if (m_bIsFolder && !IsFileFolder() && (!IsRemote() || alwaysCheckRemote || g_guiSettings.GetBool("musicfiles.findremotethumbs")))
- {
- CStdStringArray thumbs;
- StringUtils::SplitString(g_advancedSettings.m_musicThumbs, "|", thumbs);
- for (unsigned int i = 0; i < thumbs.size(); ++i)
- {
- CStdString folderThumb(GetFolderThumb(thumbs[i]));
- if (CFile::Exists(folderThumb))
- {
- return folderThumb;
- }
- }
- }
- // No thumb found
- return "";
- }
- // Gets the .tbn filename from a file or folder name.
- // <filename>.ext -> <filename>.tbn
- // <foldername>/ -> <foldername>.tbn
- CStdString CFileItem::GetTBNFile() const
- {
- CStdString thumbFile;
- CStdString strFile = m_strPath;
- if (IsStack())
- {
- CStdString strPath, strReturn;
- URIUtils::GetParentPath(m_strPath,strPath);
- CFileItem item(CStackDirectory::GetFirstStackedFile(strFile),false);
- CStdString strTBNFile = item.GetTBNFile();
- URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile),strReturn);
- if (CFile::Exists(strReturn))
- return strReturn;
- URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(strFile)),strFile);
- }
- if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile))
- {
- CStdString strPath, strParent;
- URIUtils::GetDirectory(strFile,strPath);
- URIUtils::GetParentPath(strPath,strParent);
- URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath),strFile);
- }
- CURL url(strFile);
- strFile = url.GetFileName();
- if (m_bIsFolder && !IsFileFolder())
- URIUtils::RemoveSlashAtEnd(strFile);
- if (!strFile.IsEmpty())
- {
- if (m_bIsFolder && !IsFileFolder())
- thumbFile = strFile + ".tbn"; // folder, so just add ".tbn"
- else
- thumbFile = URIUtils::ReplaceExtension(strFile, ".tbn");
- url.SetFileName(thumbFile);
- thumbFile = url.Get();
- }
- return thumbFile;
- }
- CStdString CFileItem::GetUserVideoThumb() const
- {
- if (IsTuxBox())
- {
- if (!m_bIsFolder)
- return g_tuxbox.GetPicon(GetLabel());
- else return "";
- }
- if (m_strPath.IsEmpty()
- || m_bIsShareOrDrive
- || IsInternetStream()
- || URIUtils::IsUPnP(m_strPath)
- || (URIUtils::IsFTP(m_strPath) && !g_advancedSettings.m_bFTPThumbs)
- || IsPlugin()
- || IsAddonsPath()
- || IsParentFolder()
- || IsLiveTV()
- || IsDVD())
- return "";
- // 1. check <filename>.tbn or <foldername>.tbn
- CStdString fileThumb(GetTBNFile());
- if (CFile::Exists(fileThumb))
- return fileThumb;
- if (IsOpticalMediaFile())
- { // special case for optical media "folders" - check the parent folder (or parent of parent)
- // TODO: A better way to handle this would be to treat stacked folders as folders rather than files.
- CFileItem item(GetLocalMetadataPath(), true);
- CStdString thumb(item.GetUserVideoThumb());
- if (!thumb.IsEmpty())
- return thumb;
- }
- // 2. - check movie.tbn, as long as it's not a folder
- if (!m_bIsFolder)
- {
- CStdString strPath, movietbnFile;
- URIUtils::GetParentPath(m_strPath, strPath);
- URIUtils::AddFileToFolder(strPath, "movie.tbn", movietbnFile);
- if (CFile::Exists(movietbnFile))
- return movietbnFile;
- }
- // 3. check folder image in_m_dvdThumbs (folder.jpg)
- if (m_bIsFolder && !IsFileFolder())
- {
- CStdStringArray thumbs;
- StringUtils::SplitString(g_advancedSettings.m_dvdThumbs, "|", thumbs);
- for (unsigned int i = 0; i < thumbs.size(); ++i)
- {
- CStdString folderThumb(GetFolderThumb(thumbs[i]));
- if (CFile::Exists(folderThumb))
- {
- return folderThumb;
- }
- }
- }
- // No thumb found
- return "";
- }
- CStdString CFileItem::GetFolderThumb(const CStdString &folderJPG /* = "folder.jpg" */) const
- {
- CStdString folderThumb;
- CStdString strFolder = m_strPath;
- if (IsStack() ||
- URIUtils::IsInRAR(strFolder) ||
- URIUtils::IsInZIP(strFolder))
- {
- URIUtils::GetParentPath(m_strPath,strFolder);
- }
- if (IsMultiPath())
- strFolder = CMultiPathDirectory::GetFirstPath(m_strPath);
- URIUtils::AddFileToFolder(strFolder, folderJPG, folderThumb);
- return folderThumb;
- }
- CStdString CFileItem::GetMovieName(bool bUseFolderNames /* = false */) const
- {
- if (IsLabelPreformated())
- return GetLabel();
- CStdString strMovieName = GetBaseMoviePath(bUseFolderNames);
- if (URIUtils::IsStack(strMovieName))
- strMovieName = CStackDirectory::GetStackedTitlePath(strMovieName);
- URIUtils::RemoveSlashAtEnd(strMovieName);
- strMovieName = URIUtils::GetFileName(strMovieName);
- CURL::Decode(strMovieName);
- return strMovieName;
- }
- CStdString CFileItem::GetBaseMoviePath(bool bUseFolderNames) const
- {
- CStdString strMovieName = m_strPath;
- if (IsMultiPath())
- strMovieName = CMultiPathDirectory::GetFirstPath(m_strPath);
- if (IsOpticalMediaFile())
- return GetLocalMetadataPath();
- if ((!m_bIsFolder || URIUtils::IsInArchive(m_strPath)) && bUseFolderNames)
- {
- CStdString name2(strMovieName);
- URIUtils::GetParentPath(name2,strMovieName);
- if (URIUtils::IsInArchive(m_strPath))
- {
- CStdString strArchivePath;
- URIUtils::GetParentPath(strMovieName, strArchivePath);
- strMovieName = strArchivePath;
- }
- }
- return strMovieName;
- }
- #ifdef UNIT_TESTING
- bool CFileItem::testGetBaseMoviePath()
- {
- typedef struct
- {
- const char *file;
- bool use_folder;
- const char *base;
- } testfiles;
- const testfiles test_files[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\filename.avi" },
- { "c:\\dir\\filename.avi", true, "c:\\dir\\" },
- { "/dir/filename.avi", false, "/dir/filename.avi" },
- { "/dir/filename.avi", true, "/dir/" },
- { "smb://somepath/file.avi", false, "smb://somepath/file.avi" },
- { "smb://somepath/file.avi", true, "smb://somepath/" },
- { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", false, "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi" },
- { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", true, "/path/to/movie_name/" },
- { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01.avi" },
- { "/home/user/TV Shows/Dexter/S1/1x01.avi", true, "/home/user/TV Shows/Dexter/S1/" },
- { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", true, "g:\\multimedia\\movies\\" },
- { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", false, "/home/user/movies/movie_name/" },
- { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", true, "/home/user/movies/movie_name/" },
- { "/home/user/movies/movie_name/BDMV/index.bdmv", false, "/home/user/movies/movie_name/" },
- { "/home/user/movies/movie_name/BDMV/index.bdmv", true, "/home/user/movies/movie_name/" }};
- for (unsigned int i = 0; i < sizeof(test_files) / sizeof(testfiles); i++)
- {
- CFileItem item;
- item.SetPath(test_files[i].file);
- CStdString path = item.GetBaseMoviePath(test_files[i].use_folder);
- if (path != test_files[i].base)
- {
- CLog::Log(LOGFATAL, "%s failed ('%s' -> '%s' != '%s')", __FUNCTION__, test_files[i].file, path.c_str(), test_files[i].base);
- return false;
- }
- }
- return true;
- }
- #endif
- CStdString CFileItem::GetLocalFanart() const
- {
- if (IsVideoDb())
- {
- if (!HasVideoInfoTag())
- return ""; // nothing can be done
- CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder);
- return dbItem.GetLocalFanart();
- }
- CStdString strFile2;
- CStdString strFile = m_strPath;
- if (IsStack())
- {
- CStdString strPath;
- URIUtils::GetParentPath(m_strPath,strPath);
- CStackDirectory dir;
- CStdString strPath2;
- strPath2 = dir.GetStackedTitlePath(strFile);
- URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strPath2),strFile);
- CFileItem item(dir.GetFirstStackedFile(m_strPath),false);
- CStdString strTBNFile(URIUtils::ReplaceExtension(item.GetTBNFile(), "-fanart"));
- URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile),strFile2);
- }
- if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile))
- {
- CStdString strPath, strParent;
- URIUtils::GetDirectory(strFile,strPath);
- URIUtils::GetParentPath(strPath,strParent);
- URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath),strFile);
- }
- // no local fanart available for these
- if (IsInternetStream()
- || URIUtils::IsUPnP(strFile)
- || URIUtils::IsBluray(strFile)
- || IsLiveTV()
- || IsPlugin()
- || IsAddonsPath()
- || IsDVD()
- || (URIUtils::IsFTP(strFile) && !g_advancedSettings.m_bFTPThumbs)
- || m_strPath.IsEmpty())
- return "";
- CStdString strDir;
- URIUtils::GetDirectory(strFile, strDir);
- if (strDir.IsEmpty())
- return "";
- CFileItemList items;
- CDirectory::GetDirectory(strDir, items, g_settings.m_pictureExtensions, DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO);
- if (IsOpticalMediaFile())
- { // grab from the optical media parent folder as well - see GetUserVideoThumb
- CFileItemList moreItems;
- CDirectory::GetDirectory(GetLocalMetadataPath(), moreItems, g_settings.m_pictureExtensions, DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO);
- items.Append(moreItems);
- }
- CStdStringArray fanarts;
- StringUtils::SplitString(g_advancedSettings.m_fanartImages, "|", fanarts);
- strFile = URIUtils::ReplaceExtension(strFile, "-fanart");
- fanarts.insert(m_bIsFolder ? fanarts.end() : fanarts.begin(), URIUtils::GetFileName(strFile));
- if (!strFile2.IsEmpty())
- fanarts.insert(m_bIsFolder ? fanarts.end() : fanarts.begin(), URIUtils::GetFileName(strFile2));
- for (unsigned int i = 0; i < fanarts.size(); ++i)
- {
- for (int j = 0; j < items.Size(); j++)
- {
- CStdString strCandidate = URIUtils::GetFileName(items[j]->m_strPath);
- URIUtils::RemoveExtension(strCandidate);
- CStdString strFanart = fanarts[i];
- URIUtils::RemoveExtension(strFanart);
- if (strCandidate.CompareNoCase(strFanart) == 0)
- return items[j]->m_strPath;
- }
- }
- return "";
- }
- CStdString CFileItem::GetLocalMetadataPath() const
- {
- if (m_bIsFolder && !IsFileFolder())
- return m_strPath;
- CStdString parent(URIUtils::GetParentPath(m_strPath));
- CStdString parentFolder(parent);
- URIUtils::RemoveSlashAtEnd(parentFolder);
- parentFolder = URIUtils::GetFileName(parentFolder);
- if (parentFolder.CompareNoCase("VIDEO_TS") == 0 || parentFolder.CompareNoCase("BDMV") == 0)
- { // go back up another one
- parent = URIUtils::GetParentPath(parent);
- }
- return parent;
- }
- bool CFileItem::LoadMusicTag()
- {
- // not audio
- if (!IsAudio())
- return false;
- // already loaded?
- if (HasMusicInfoTag() && m_musicInfoTag->Loaded())
- return true;
- // check db
- CMusicDatabase musicDatabase;
- if (musicDatabase.Open())
- {
- CSong song;
- if (musicDatabase.GetSongByFileName(m_strPath, song))
- {
- GetMusicInfoTag()->SetSong(song);
- SetThumbnailImage(song.strThumb);
- return true;
- }
- musicDatabase.Close();
- }
- // load tag from file
- CLog::Log(LOGDEBUG, "%s: loading tag information for file: %s", __FUNCTION__, m_strPath.c_str());
- CMusicInfoTagLoaderFactory factory;
- auto_ptr<IMusicInfoTagLoader> pLoader (factory.CreateLoader(m_strPath));
- if (NULL != pLoader.get())
- {
- if (pLoader->Load(m_strPath, *GetMusicInfoTag()))
- return true;
- }
- // no tag - try some other things
- if (IsCDDA())
- {
- // we have the tracknumber...
- int iTrack = GetMusicInfoTag()->GetTrackNumber();
- if (iTrack >= 1)
- {
- CStdString strText = g_localizeStrings.Get(554); // "Track"
- if (strText.GetAt(strText.size() - 1) != ' ')
- strText += " ";
- CStdString strTrack;
- strTrack.Format(strText + "%i", iTrack);
- GetMusicInfoTag()->SetTitle(strTrack);
- GetMusicInfoTag()->SetLoaded(true);
- return true;
- }
- }
- else
- {
- CStdString fileName = URIUtils::GetFileName(m_strPath);
- URIUtils::RemoveExtension(fileName);
- for (unsigned int i = 0; i < g_advancedSettings.m_musicTagsFromFileFilters.size(); i++)
- {
- CLabelFormatter formatter(g_advancedSettings.m_musicTagsFromFileFilters[i], "");
- if (formatter.FillMusicTag(fileName, GetMusicInfoTag()))
- {
- GetMusicInfoTag()->SetLoaded(true);
- return true;
- }
- }
- }
- return false;
- }
- void CFileItemList::Swap(unsigned int item1, unsigned int item2)
- {
- if (item1 != item2 && item1 < m_items.size() && item2 < m_items.size())
- std::swap(m_items[item1], m_items[item2]);
- }
- bool CFileItemList::UpdateItem(const CFileItem *item)
- {
- if (!item) return false;
- CSingleLock lock(m_lock);
- for (unsigned int i = 0; i < m_items.size(); i++)
- {
- CFileItemPtr pItem = m_items[i];
- if (pItem->IsSamePath(item))
- {
- *pItem = *item;
- return true;
- }
- }
- return false;
- }
- void CFileItemList::AddSortMethod(SORT_METHOD sortMethod, int buttonLabel, const LABEL_MASKS &labelMasks)
- {
- SORT_METHOD_DETAILS sort;
- sort.m_sortMethod=sortMethod;
- sort.m_buttonLabel=buttonLabel;
- sort.m_labelMasks=labelMasks;
- m_sortDetails.push_back(sort);
- }
- void CFileItemList::SetReplaceListing(bool replace)
- {
- m_replaceListing = replace;
- }
- void CFileItemList::ClearSortState()
- {
- m_sortMethod = SORT_METHOD_NONE;
- m_sortOrder = SortOrderNone;
- }
- CVideoInfoTag* CFileItem::GetVideoInfoTag()
- {
- if (!m_videoInfoTag)
- m_videoInfoTag = new CVideoInfoTag;
- return m_videoInfoTag;
- }
- CPictureInfoTag* CFileItem::GetPictureInfoTag()
- {
- if (!m_pictureInfoTag)
- m_pictureInfoTag = new CPictureInfoTag;
- return m_pictureInfoTag;
- }
- MUSIC_INFO::CMusicInfoTag* CFileItem::GetMusicInfoTag()
- {
- if (!m_musicInfoTag)
- m_musicInfoTag = new MUSIC_INFO::CMusicInfoTag;
- return m_musicInfoTag;
- }
- CStdString CFileItem::FindTrailer() const
- {
- CStdString strFile2;
- CStdString strFile = m_strPath;
- if (IsStack())
- {
- CStdString strPath;
- URIUtils::GetParentPath(m_strPath,strPath);
- CStackDirectory dir;
- CStdString strPath2;
- strPath2 = dir.GetStackedTitlePath(strFile);
- URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strPath2),strFile);
- CFileItem item(dir.GetFirstStackedFile(m_strPath),false);
- CStdString strTBNFile(URIUtils::ReplaceExtension(item.GetTBNFile(), "-trailer"));
- URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile),strFile2);
- }
- if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile))
- {
- CStdString strPath, strParent;
- URIUtils::GetDirectory(strFile,strPath);
- URIUtils::GetParentPath(strPath,strParent);
- URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath),strFile);
- }
- // no local trailer available for these
- if (IsInternetStream()
- || URIUtils::IsUPnP(strFile)
- || URIUtils::IsBluray(strFile)
- || IsLiveTV()
- || IsPlugin()
- || IsDVD())
- return "";
- CStdString strDir;
- URIUtils::GetDirectory(strFile, strDir);
- CFileItemList items;
- CDirectory::GetDirectory(strDir, items, g_settings.m_videoExtensions, DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO);
- URIUtils::RemoveExtension(strFile);
- strFile += "-trailer";
- CStdString strFile3 = URIUtils::AddFileToFolder(strDir, "movie-trailer");
- // Precompile our REs
- VECCREGEXP matchRegExps;
- CRegExp tmpRegExp(true);
- const CStdStringArray& strMatchRegExps = g_advancedSettings.m_trailerMatchRegExps;
- CStdStringArray::const_iterator strRegExp = strMatchRegExps.begin();
- while (strRegExp != strMatchRegExps.end())
- {
- if (tmpRegExp.RegComp(*strRegExp))
- {
- matchRegExps.push_back(tmpRegExp);
- }
- strRegExp++;
- }
- CStdString strTrailer;
- for (int i = 0; i < items.Size(); i++)
- {
- CStdString strCandidate = items[i]->m_strPath;
- URIUtils::RemoveExtension(strCandidate);
- if (strCandidate.CompareNoCase(strFile) == 0 ||
- strCandidate.CompareNoCase(strFile2) == 0 ||
- strCandidate.CompareNoCase(strFile3) == 0)
- {
- strTrailer = items[i]->m_strPath;
- break;
- }
- else
- {
- VECCREGEXP::iterator expr = matchRegExps.begin();
- while (expr != matchRegExps.end())
- {
- if (expr->RegFind(strCandidate) != -1)
- {
- strTrailer = items[i]->m_strPath;
- i = items.Size();
- break;
- }
- expr++;
- }
- }
- }
- return strTrailer;
- }
- int CFileItem::GetVideoContentType() const
- {
- VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES;
- if (HasVideoInfoTag() && !GetVideoInfoTag()->m_strShowTitle.IsEmpty()) // tvshow
- type = VIDEODB_CONTENT_TVSHOWS;
- if (HasVideoInfoTag() && GetVideoInfoTag()->m_iSeason > -1 && !m_bIsFolder) // episode
- type = VIDEODB_CONTENT_EPISODES;
- if (HasVideoInfoTag() && !GetVideoInfoTag()->m_artist.empty())
- type = VIDEODB_CONTENT_MUSICVIDEOS;
- return type;
- }