static void ParseItem(CFileItem* item, TiXmlElement* root, const std::string& path) { SResources resources; ParseItem(item, resources, root, path); const char* prio[] = { "media:content", "voddler:trailer", "rss:enclosure", "svtplay:broadcasts", "svtplay:xmllink", "rss:link", "rss:guid", NULL }; std::string mime; if (FindMime(resources, "video/")) mime = "video/"; else if(FindMime(resources, "audio/")) mime = "audio/"; else if(FindMime(resources, "application/rss")) mime = "application/rss"; else if(FindMime(resources, "image/")) mime = "image/"; int maxrate = CSettings::Get().GetInt(CSettings::SETTING_NETWORK_BANDWIDTH); if(maxrate == 0) maxrate = INT_MAX; SResources::iterator best = resources.end(); for(const char** type = prio; *type && best == resources.end(); type++) { for(SResources::iterator it = resources.begin(); it != resources.end(); it++) { if(!StringUtils::StartsWith(it->mime, mime)) continue; if(it->tag == *type) { if(best == resources.end()) { best = it; continue; } if(it->bitrate == best->bitrate) { if(it->width*it->height > best->width*best->height) best = it; continue; } if(it->bitrate > maxrate) { if(it->bitrate < best->bitrate) best = it; continue; } if(it->bitrate > best->bitrate) { best = it; continue; } } } } if(best != resources.end()) { item->SetMimeType(best->mime); item->SetPath(best->path); item->m_dwSize = best->size; if(best->duration) item->SetProperty("duration", StringUtils::SecondsToTimeString(best->duration)); /* handling of mimetypes fo directories are sub optimal at best */ if(best->mime == "application/rss+xml" && StringUtils::StartsWithNoCase(item->GetPath(), "http://")) item->SetPath("rss://" + item->GetPath().substr(7)); if(StringUtils::StartsWithNoCase(item->GetPath(), "rss://")) item->m_bIsFolder = true; else item->m_bIsFolder = false; } if(!item->m_strTitle.empty()) item->SetLabel(item->m_strTitle); if(item->HasVideoInfoTag()) { CVideoInfoTag* vtag = item->GetVideoInfoTag(); if(item->HasProperty("duration") && !vtag->GetDuration()) vtag->m_duration = StringUtils::TimeStringToSeconds(item->GetProperty("duration").asString()); if(item->HasProperty("description") && vtag->m_strPlot.empty()) vtag->m_strPlot = item->GetProperty("description").asString(); if(vtag->m_strPlotOutline.empty() && !vtag->m_strPlot.empty()) { size_t pos = vtag->m_strPlot.find('\n'); if(pos != std::string::npos) vtag->m_strPlotOutline = vtag->m_strPlot.substr(0, pos); else vtag->m_strPlotOutline = vtag->m_strPlot; } if(!vtag->GetDuration()) item->SetLabel2(StringUtils::SecondsToTimeString(vtag->GetDuration())); } }
bool CThumbExtractor::DoWork() { if (m_item.IsLiveTV() // Due to a pvr addon api design flaw (no support for multiple concurrent streams // per addon instance), pvr recording thumbnail extraction does not work (reliably). || URIUtils::IsPVRRecording(m_item.GetDynPath()) || URIUtils::IsUPnP(m_item.GetPath()) || URIUtils::IsBluray(m_item.GetPath()) || m_item.IsBDFile() || m_item.IsDVD() || m_item.IsDiscImage() || m_item.IsDVDFile(false, true) || m_item.IsInternetStream() || m_item.IsDiscStub() || m_item.IsPlayList()) return false; // For HTTP/FTP we only allow extraction when on a LAN if (URIUtils::IsRemote(m_item.GetPath()) && !URIUtils::IsOnLAN(m_item.GetPath()) && (URIUtils::IsFTP(m_item.GetPath()) || URIUtils::IsHTTP(m_item.GetPath()))) return false; bool result=false; if (m_thumb) { CLog::Log(LOGDEBUG,"%s - trying to extract thumb from video file %s", __FUNCTION__, CURL::GetRedacted(m_item.GetPath()).c_str()); // construct the thumb cache file CTextureDetails details; details.file = CTextureCache::GetCacheFile(m_target) + ".jpg"; result = CDVDFileInfo::ExtractThumb(m_item, details, m_fillStreamDetails ? &m_item.GetVideoInfoTag()->m_streamDetails : nullptr, m_pos); if(result) { CTextureCache::GetInstance().AddCachedTexture(m_target, details); m_item.SetProperty("HasAutoThumb", true); m_item.SetProperty("AutoThumbImage", m_target); m_item.SetArt("thumb", m_target); CVideoInfoTag* info = m_item.GetVideoInfoTag(); if (info->m_iDbId > 0 && !info->m_type.empty()) { CVideoDatabase db; if (db.Open()) { db.SetArtForItem(info->m_iDbId, info->m_type, "thumb", m_item.GetArt("thumb")); db.Close(); } } } } else if (!m_item.IsPlugin() && (!m_item.HasVideoInfoTag() || !m_item.GetVideoInfoTag()->HasStreamDetails())) { // No tag or no details set, so extract them CLog::Log(LOGDEBUG,"%s - trying to extract filestream details from video file %s", __FUNCTION__, CURL::GetRedacted(m_item.GetPath()).c_str()); result = CDVDFileInfo::GetFileStreamDetails(&m_item); } if (result) { CVideoInfoTag* info = m_item.GetVideoInfoTag(); CVideoDatabase db; if (db.Open()) { if (URIUtils::IsStack(m_listpath)) { // Don't know the total time of the stack, so set duration to zero to avoid confusion info->m_streamDetails.SetVideoDuration(0, 0); // Restore original stack path m_item.SetPath(m_listpath); } if (info->m_iFileId < 0) db.SetStreamDetailsForFile(info->m_streamDetails, !info->m_strFileNameAndPath.empty() ? info->m_strFileNameAndPath : m_item.GetPath()); else db.SetStreamDetailsForFileId(info->m_streamDetails, info->m_iFileId); // overwrite the runtime value if the one from streamdetails is available if (info->m_iDbId > 0 && info->GetStaticDuration() != info->GetDuration()) { info->SetDuration(info->GetDuration()); // store the updated information in the database db.SetDetailsForItem(info->m_iDbId, info->m_type, *info, m_item.GetArt()); } db.Close(); } return true; } return false; }
static void ParseItem(CFileItem* item, TiXmlElement* root, const CStdString& path) { SResources resources; ParseItem(item, resources, root, path); const char* prio[] = { "media:content", "voddler:trailer", "rss:enclosure", "svtplay:broadcasts", "svtplay:xmllink", "rss:link", "rss:guid", NULL }; CStdString mime; if (FindMime(resources, "video/")) mime = "video/"; else if(FindMime(resources, "audio/")) mime = "audio/"; else if(FindMime(resources, "application/rss")) mime = "application/rss"; else if(FindMime(resources, "image/")) mime = "image/"; int maxrate = g_guiSettings.GetInt("network.bandwidth"); if(maxrate == 0) maxrate = INT_MAX; SResources::iterator best = resources.end(); for(const char** type = prio; *type && best == resources.end(); type++) { for(SResources::iterator it = resources.begin(); it != resources.end(); it++) { if(it->mime.Left(mime.length()) != mime) continue; if(it->tag == *type) { if(best == resources.end()) { best = it; continue; } if(it->bitrate == best->bitrate) { if(it->width*it->height > best->width*best->height) best = it; continue; } if(it->bitrate > maxrate) { if(it->bitrate < best->bitrate) best = it; continue; } if(it->bitrate > best->bitrate) { best = it; continue; } } } } if(best != resources.end()) { item->SetMimeType(best->mime); item->SetPath(best->path); item->m_dwSize = best->size; if(best->duration) item->SetProperty("duration", StringUtils::SecondsToTimeString(best->duration)); /* handling of mimetypes fo directories are sub optimal at best */ if(best->mime == "application/rss+xml" && item->GetPath().Left(7).Equals("http://")) item->SetPath("rss://" + item->GetPath().Mid(7)); if(item->GetPath().Left(6).Equals("rss://")) item->m_bIsFolder = true; else item->m_bIsFolder = false; } if(!item->m_strTitle.IsEmpty()) item->SetLabel(item->m_strTitle); if(item->HasVideoInfoTag()) { CVideoInfoTag* vtag = item->GetVideoInfoTag(); if(item->HasProperty("duration") && !vtag->GetDuration()) vtag->m_duration = StringUtils::TimeStringToSeconds(item->GetProperty("duration").asString()); if(item->HasProperty("description") && vtag->m_strPlot.IsEmpty()) vtag->m_strPlot = item->GetProperty("description").asString(); if(vtag->m_strPlotOutline.IsEmpty() && !vtag->m_strPlot.IsEmpty()) { int pos = vtag->m_strPlot.Find('\n'); if(pos >= 0) vtag->m_strPlotOutline = vtag->m_strPlot.Left(pos); else vtag->m_strPlotOutline = vtag->m_strPlot; } if(!vtag->GetDuration()) item->SetLabel2(StringUtils::SecondsToTimeString(vtag->GetDuration())); } }
bool CThumbExtractor::DoWork() { if (m_item.IsLiveTV() || URIUtils::IsUPnP(m_item.GetPath()) || m_item.IsDAAP() || m_item.IsDVD() || m_item.IsDiscImage() || m_item.IsDVDFile(false, true) || m_item.IsInternetStream() || m_item.IsDiscStub() || m_item.IsPlayList()) return false; if (URIUtils::IsRemote(m_item.GetPath()) && !URIUtils::IsOnLAN(m_item.GetPath())) { // A quasi internet filesystem like webdav is generally fast enough for extracting stuff if (!URIUtils::IsDAV(m_item.GetPath())) return false; } bool result=false; if (m_thumb) { CLog::Log(LOGDEBUG,"%s - trying to extract thumb from video file %s", __FUNCTION__, CURL::GetRedacted(m_item.GetPath()).c_str()); // construct the thumb cache file CTextureDetails details; details.file = CTextureCache::GetCacheFile(m_target) + ".jpg"; result = CDVDFileInfo::ExtractThumb(m_item.GetPath(), details, &m_item.GetVideoInfoTag()->m_streamDetails); if(result) { CTextureCache::Get().AddCachedTexture(m_target, details); m_item.SetProperty("HasAutoThumb", true); m_item.SetProperty("AutoThumbImage", m_target); m_item.SetArt("thumb", m_target); CVideoInfoTag* info = m_item.GetVideoInfoTag(); if (info->m_iDbId > 0 && !info->m_type.empty()) { CVideoDatabase db; if (db.Open()) { db.SetArtForItem(info->m_iDbId, info->m_type, "thumb", m_item.GetArt("thumb")); db.Close(); } } } } else if (!m_item.HasVideoInfoTag() || !m_item.GetVideoInfoTag()->HasStreamDetails()) { // No tag or no details set, so extract them CLog::Log(LOGDEBUG,"%s - trying to extract filestream details from video file %s", __FUNCTION__, CURL::GetRedacted(m_item.GetPath()).c_str()); result = CDVDFileInfo::GetFileStreamDetails(&m_item); } if (result) { CVideoInfoTag* info = m_item.GetVideoInfoTag(); CVideoDatabase db; if (db.Open()) { if (URIUtils::IsStack(m_listpath)) { // Don't know the total time of the stack, so set duration to zero to avoid confusion info->m_streamDetails.SetVideoDuration(0, 0); // Restore original stack path m_item.SetPath(m_listpath); } if (info->m_iFileId < 0) db.SetStreamDetailsForFile(info->m_streamDetails, !info->m_strFileNameAndPath.empty() ? info->m_strFileNameAndPath : static_cast<const std::string&>(m_item.GetPath())); else db.SetStreamDetailsForFileId(info->m_streamDetails, info->m_iFileId); // overwrite the runtime value if the one from streamdetails is available if (info->m_iDbId > 0 && info->m_duration != info->GetDuration()) { info->m_duration = info->GetDuration(); // store the updated information in the database db.SetDetailsForItem(info->m_iDbId, info->m_type, *info, m_item.GetArt()); } db.Close(); } return true; } return false; }