#include "pictureCache.h" #include #include #include #include #include #include #include #include #include #include "plexSdOsd.h" #include "PVideo.h" #include "Directory.h" using Poco::URIStreamOpener; using Poco::StreamCopier; using Poco::Path; using Poco::Exception; using Poco::Net::HTTPStreamFactory; cPictureCache::cPictureCache() { m_cacheDir = cPlugin::CacheDirectory(PLUGIN_NAME_I18N); Poco::Path path(m_cacheDir); Poco::File f(path.toString()); f.createDirectories(); HTTPStreamFactory::registerFactory(); m_bAllInvalidated = false; } void cPictureCache::Action() { while(Running()) { while (m_qImagesToLoad.size() > 0) { CacheInfo info = m_qImagesToLoad.front(); m_qImagesToLoad.pop_front(); std::string transcodeUri = TranscodeUri(info.uri, info.width, info.height); std::string file = FileName(info.uri, info.width); if(!Cached(info.uri, info.width)) { auto stream = DownloadFile(transcodeUri); if(stream) { SaveFileToDisk(stream, file); LOCK_THREAD; if (!m_bAllInvalidated && info.onCached && info.calle && info.calle->IsVisible()) { info.onCached(info.calle); } } } cCondWait::SleepMs(5); } cCondWait::SleepMs(100); } } std::shared_ptr cPictureCache::DownloadFile(std::string uri) { try { std::shared_ptr pStream(URIStreamOpener::defaultOpener().open(uri)); return pStream; } catch (Poco::Exception &exc) { return NULL; } } void cPictureCache::SaveFileToDisk(std::shared_ptr file, std::string fileName) { try { Poco::Path p(fileName); Poco::File f(p.makeParent().toString()); f.createDirectories(); std::ofstream outFile; outFile.open(fileName); Poco::StreamCopier::copyStream(*file, outFile); outFile.close(); } catch (Poco::Exception &exc) { std::cout << "SaveFile Error: " << exc.displayText() << std::endl; } } std::string cPictureCache::FileName(std::string uri, int width) { Poco::URI u(uri); std::string file = Poco::format("%s_%d", u.getPathAndQuery(), width); Poco::Path path(m_cacheDir); path.append(file); return path.toString(); } std::string cPictureCache::TranscodeUri(std::string uri, int width, int height) { std::string escapedUri; Poco::URI::encode(uri, " !\"#$%&'()*+,/:;=?@[]", escapedUri); Poco::URI u(uri); int port = u.getPort(); std::string tUri = Poco::format("http://%s:%d/photo/:/transcode?width=%d&height=%d&url=%s", u.getHost(), port, width, height, escapedUri); return tUri; } bool cPictureCache::Cached(std::string uri, int width) { return Poco::File(FileName(uri, width)).exists(); } std::string cPictureCache::GetPath(std::string uri, int width, int height, bool& cached, std::function OnCached, cGridElement* calle) { m_bAllInvalidated = false; cached = Cached(uri, width); std::string file = FileName(uri, width); if(cached) { return file; } else { CacheInfo info(uri, width, height, OnCached, calle); m_qImagesToLoad.push_back(info); } return file; } void cPictureCache::Stop() { Cancel(); } void cPictureCache::Remove(cGridElement* element) { if(!element) return; if (auto video = dynamic_cast(element)) { Remove(video->ThumbUri()); Remove(video->ArtUri()); } } void cPictureCache::Remove(std::string uri) { LOCK_THREAD; for(std::deque::iterator it = m_qImagesToLoad.begin() ; it != m_qImagesToLoad.end(); ++it) { if(it->uri == uri) { m_qImagesToLoad.erase(it); return; } } } void cPictureCache::RemoveAll() { LOCK_THREAD; m_bAllInvalidated = true; m_qImagesToLoad.clear(); }