Added CFileItem::FillInMimeType() and make GetMimeType() respect const qualifiers.
authorGarrett Brown <garbearucla@gmail.com>
Sat, 15 Jun 2013 01:17:48 +0000 (18:17 -0700)
committerGarrett Brown <garbearucla@gmail.com>
Sat, 15 Jun 2013 01:49:43 +0000 (18:49 -0700)
Before, the MIME type would only be resolved if GetMimeType(true) was called, which is potentially blocking. Now MIME types will be resolved from the file's extension without possibly blocking the thread. See doxy of CFileItem::FillInMimeType() for more info.

xbmc/Application.cpp
xbmc/FileItem.cpp
xbmc/FileItem.h
xbmc/TextureCacheJob.cpp
xbmc/filesystem/PluginDirectory.cpp
xbmc/guilib/GUIMultiImage.cpp
xbmc/network/upnp/UPnPInternal.cpp
xbmc/pictures/GUIWindowSlideShow.cpp
xbmc/playlists/PlayListFactory.cpp

index 39182fc..bd482e7 100644 (file)
@@ -3628,6 +3628,10 @@ PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
 
 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
 {
+  // Ensure the MIME type has been retrieved for http:// and shout:// streams
+  if (item.GetMimeType().empty())
+    const_cast<CFileItem&>(item).FillInMimeType();
+
   if (!bRestart)
   {
     SaveCurrentFileSettings();
index d500678..b22f6d6 100644 (file)
@@ -112,6 +112,7 @@ CFileItem::CFileItem(const CMusicInfoTag& music)
   m_bIsFolder = URIUtils::HasSlashAtEnd(m_strPath);
   *GetMusicInfoTag() = music;
   FillInDefaultIcon();
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CVideoInfoTag& movie)
@@ -149,6 +150,8 @@ CFileItem::CFileItem(const CEpgInfoTag& tag)
 
   if (!tag.Icon().IsEmpty())
     SetIconImage(tag.Icon());
+
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CPVRChannel& channel)
@@ -198,6 +201,8 @@ CFileItem::CFileItem(const CPVRChannel& channel)
   SetProperty("channelid", channel.ChannelID());
   SetProperty("path", channel.Path());
   SetArt("thumb", channel.IconPath());
+
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CPVRRecording& record)
@@ -217,6 +222,8 @@ CFileItem::CFileItem(const CPVRRecording& record)
   *GetPVRRecordingInfoTag() = record;
   SetLabel(record.m_strTitle);
   m_strLabel2 = record.m_strPlot;
+
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CPVRTimerInfoTag& timer)
@@ -240,6 +247,8 @@ CFileItem::CFileItem(const CPVRTimerInfoTag& timer)
 
   if (!timer.ChannelIcon().IsEmpty())
     SetIconImage(timer.ChannelIcon());
+
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CArtist& artist)
@@ -257,6 +266,7 @@ CFileItem::CFileItem(const CArtist& artist)
   m_bIsFolder = true;
   URIUtils::AddSlashAtEnd(m_strPath);
   GetMusicInfoTag()->SetArtist(artist.strArtist);
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CGenre& genre)
@@ -274,6 +284,7 @@ CFileItem::CFileItem(const CGenre& genre)
   m_bIsFolder = true;
   URIUtils::AddSlashAtEnd(m_strPath);
   GetMusicInfoTag()->SetGenre(genre.strGenre);
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CFileItem& item): CGUIListItem()
@@ -301,6 +312,8 @@ CFileItem::CFileItem(const CGUIListItem& item)
   // not particularly pretty, but it gets around the issue of Reset() defaulting
   // parameters in the CGUIListItem base class.
   *((CGUIListItem *)this) = item;
+
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(void)
@@ -344,6 +357,7 @@ CFileItem::CFileItem(const CStdString& strPath, bool bIsFolder)
   // tuxbox urls cannot have a / at end
   if (m_bIsFolder && !m_strPath.IsEmpty() && !IsFileFolder() && !URIUtils::IsTuxBox(m_strPath))
     URIUtils::AddSlashAtEnd(m_strPath);
+  FillInMimeType(false);
 }
 
 CFileItem::CFileItem(const CMediaSource& share)
@@ -374,6 +388,7 @@ CFileItem::CFileItem(const CMediaSource& share)
   SetLabelPreformated(true);
   if (IsDVD())
     GetVideoInfoTag()->m_strFileNameAndPath = share.strDiskUniqueId; // share.strDiskUniqueId contains disc unique id
+  FillInMimeType(false);
 }
 
 CFileItem::~CFileItem(void)
@@ -670,7 +685,7 @@ void CFileItem::Serialize(CVariant& value) const
   value["size"] = (int) m_dwSize / 1000;
   value["DVDLabel"] = m_strDVDLabel;
   value["title"] = m_strTitle;
-  value["mimetype"] = GetMimeType();
+  value["mimetype"] = m_mimetype;
   value["extrainfo"] = m_extrainfo;
 
   if (m_musicInfoTag)
@@ -1010,7 +1025,7 @@ bool CFileItem::IsCBR() const
 bool CFileItem::IsRSS() const
 {
   return m_strPath.Left(6).Equals("rss://") || URIUtils::HasExtension(m_strPath, ".rss")
-      || GetMimeType() == "application/rss+xml";
+      || m_mimetype == "application/rss+xml";
 }
 
 bool CFileItem::IsAndroidApp() const
@@ -1336,51 +1351,48 @@ bool CFileItem::IsParentFolder() const
   return m_bIsParentFolder;
 }
 
-const CStdString& CFileItem::GetMimeType(bool lookup /*= true*/) const
+void CFileItem::FillInMimeType(bool lookup /*= true*/)
 {
-  if( m_mimetype.IsEmpty() && lookup)
+  if (m_mimetype.IsEmpty())
   {
-    CStdString& m_ref = const_cast<CStdString&>(m_mimetype);
-
     if( m_bIsFolder )
-      m_ref = "x-directory/normal";
+      m_mimetype = "x-directory/normal";
     else if( m_pvrChannelInfoTag )
-      m_ref = m_pvrChannelInfoTag->InputFormat();
+      m_mimetype = m_pvrChannelInfoTag->InputFormat();
     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);
+      // If lookup is false, bail out early to leave mime type empty
+      if (!lookup)
+        return;
+
+      CCurlFile::GetMimeType(GetAsUrl(), m_mimetype);
 
       // 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");
+      if (m_mimetype.Left(11).Equals("video/x-ms-"))
+        CCurlFile::GetMimeType(GetAsUrl(), m_mimetype, "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(';');
+      int i = m_mimetype.Find(';');
       if(i>=0)
-        m_ref.Delete(i,m_ref.length()-i);
-      m_ref.Trim();
+        m_mimetype.Delete(i, m_mimetype.length() - i);
+      m_mimetype.Trim();
     }
     else
-      m_ref = CMime::GetMimeType(*this);
+      m_mimetype = CMime::GetMimeType(*this);
 
     // if it's still empty set to an unknown type
-    if( m_ref.IsEmpty() )
-      m_ref = "application/octet-stream";
+    if (m_mimetype.IsEmpty())
+      m_mimetype = "application/octet-stream";
   }
 
-  // change protocol to mms for the following mome-type.  Allows us to create proper FileMMS.
+  // change protocol to mms for the following mime-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 = const_cast<CStdString&>(m_strPath);
-    m_path.Replace("http:", "mms:");
-  }
-
-  return m_mimetype;
+    m_strPath.Replace("http:", "mms:");
 }
 
 bool CFileItem::IsSamePath(const CFileItem *item) const
@@ -1478,6 +1490,7 @@ void CFileItem::SetFromVideoInfoTag(const CVideoInfoTag &video)
   if (video.m_iSeason == 0)
     SetProperty("isspecial", "true");
   FillInDefaultIcon();
+  FillInMimeType(false);
 }
 
 void CFileItem::SetFromAlbum(const CAlbum &album)
@@ -1489,6 +1502,7 @@ void CFileItem::SetFromAlbum(const CAlbum &album)
   GetMusicInfoTag()->SetAlbum(album);
   m_bIsAlbum = true;
   CMusicDatabase::SetPropertiesFromAlbum(*this,album);
+  FillInMimeType(false);
 }
 
 void CFileItem::SetFromSong(const CSong &song)
@@ -1504,6 +1518,7 @@ void CFileItem::SetFromSong(const CSong &song)
   m_lEndOffset = song.iEndOffset;
   if (!song.strThumb.empty())
     SetArt("thumb", song.strThumb);
+  FillInMimeType(false);
 }
 
 /////////////////////////////////////////////////////////////////////////////////
index 7f8501b..705d1d3 100644 (file)
@@ -360,12 +360,19 @@ public:
 
   virtual bool LoadMusicTag();
 
-  /* returns the content type of this item if known. will lookup for http streams */
-  const CStdString& GetMimeType(bool lookup = true) const;
+  /* Returns the content type of this item if known */
+  const CStdString& GetMimeType() const { return m_mimetype; }
 
   /* sets the mime-type if known beforehand */
   void SetMimeType(const CStdString& mimetype) { m_mimetype = mimetype; } ;
 
+  /*! \brief Resolve the MIME type based on file extension or a web lookup
+   If m_mimetype is already set (non-empty), this function has no effect. For
+   http:// and shout:// streams, this will query the stream (blocking operation).
+   Set lookup=false to skip any internet lookups and always return immediately.
+   */
+  void FillInMimeType(bool lookup = true);
+
   /* general extra info about the contents of the item, not for display */
   void SetExtraInfo(const CStdString& info) { m_extrainfo = info; };
   const CStdString& GetExtraInfo() const { return m_extrainfo; };
index 787d1e4..47107ec 100644 (file)
@@ -173,6 +173,7 @@ CBaseTexture *CTextureCacheJob::LoadImage(const CStdString &image, unsigned int
 
   // Validate file URL to see if it is an image
   CFileItem file(image, false);
+  file.FillInMimeType();
   if (!(file.IsPicture() && !(file.IsZIP() || file.IsRAR() || file.IsCBR() || file.IsCBZ() ))
       && !file.GetMimeType().Left(6).Equals("image/") && !file.GetMimeType().Equals("application/octet-stream")) // ignore non-pictures
     return NULL;
index d3acb91..0442df0 100644 (file)
@@ -160,7 +160,7 @@ bool CPluginDirectory::GetPluginResult(const CStdString& strPath, CFileItem &res
     if (!resultItem.HasProperty("original_listitem_url"))
       resultItem.SetProperty("original_listitem_url", resultItem.GetPath());
     resultItem.SetPath(newDir->m_fileResult->GetPath());
-    resultItem.SetMimeType(newDir->m_fileResult->GetMimeType(false));
+    resultItem.SetMimeType(newDir->m_fileResult->GetMimeType());
     resultItem.UpdateInfo(*newDir->m_fileResult);
     if (newDir->m_fileResult->HasVideoInfoTag() && newDir->m_fileResult->GetVideoInfoTag()->m_resumePoint.IsSet())
       resultItem.m_lStartOffset = STARTOFFSET_RESUME; // resume point set in the resume item, so force resume
index 43e869f..d1452ca 100644 (file)
@@ -298,6 +298,7 @@ bool CGUIMultiImage::CMultiImageJob::DoWork()
 {
   // check to see if we have a single image or a folder of images
   CFileItem item(m_path, false);
+  item.FillInMimeType();
   if (item.IsPicture() || item.GetMimeType().Left(6).Equals("image/"))
   {
     m_files.push_back(m_path);
index 98ade1b..02d7876 100644 (file)
@@ -815,7 +815,7 @@ bool GetResource(const PLT_MediaObject* entry, CFileItem& item)
 
   // store original path so we remember it
   item.SetProperty("original_listitem_url",  item.GetPath());
-  item.SetProperty("original_listitem_mime", item.GetMimeType(false));
+  item.SetProperty("original_listitem_mime", item.GetMimeType());
 
   // look for a resource with "xbmc-get" protocol
   // if we can't find one, try to find a valid resource
index bd638c5..1e7797c 100644 (file)
@@ -294,7 +294,7 @@ void CGUIWindowSlideShow::Add(const CFileItem *picture)
   if (!item->HasVideoInfoTag() && !item->HasPictureInfoTag())
   {
     // item without tag; get mimetype then we can tell whether it's video item
-    item->GetMimeType();
+    item->FillInMimeType();
 
     if (!item->IsVideo())
       // then it is a picture and force tag generation
index 0a22044..b5ef410 100644 (file)
@@ -39,6 +39,10 @@ CPlayList* CPlayListFactory::Create(const CFileItem& item)
 {
   if( item.IsInternetStream() )
   {
+    // Ensure the MIME type has been retrieved for http:// and shout:// streams
+    if (item.GetMimeType().empty())
+      const_cast<CFileItem&>(item).FillInMimeType();
+
     CStdString strMimeType = item.GetMimeType();
     strMimeType.MakeLower();