diff --git a/tools/cli-video/appl/main-tool-client-video.cpp b/tools/cli-video/appl/main-tool-client-video.cpp index b90bf9c..c8620e1 100644 --- a/tools/cli-video/appl/main-tool-client-video.cpp +++ b/tools/cli-video/appl/main-tool-client-video.cpp @@ -192,6 +192,7 @@ bool pushVideoFile(zeus::service::ProxyVideo& _srv, std::string _path, std::map< // send all meta data: zeus::FutureGroup group; for (auto &itKey : _basicKey) { + APPL_WARNING("Set metaData: " << itKey.first << " : " << itKey.second); group.add(media.setMetadata(itKey.first, itKey.second)); } group.wait(); @@ -207,31 +208,29 @@ void installVideoPath(zeus::service::ProxyVideo& _srv, std::string _path, std::m APPL_INFO("Add Sub path: '" << itPath << "'"); std::string lastPathName = etk::split(itPath, '/').back(); if (basicKeyTmp.size() == 0) { - APPL_INFO("find '" << lastPathName << "' " << basicKeyTmp.size()); - if (lastPathName == "films") { + APPL_INFO("find A '" << lastPathName << "' " << basicKeyTmp.size()); + if (lastPathName == "film") { basicKeyTmp.insert(std::pair<std::string,std::string>("type", "film")); basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "picture")); - } else if (lastPathName == "films-annimation") { + } else if (lastPathName == "film-annimation") { basicKeyTmp.insert(std::pair<std::string,std::string>("type", "film")); basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "draw")); + } else if (lastPathName == "film-short") { // short films + basicKeyTmp.insert(std::pair<std::string,std::string>("type", "film")); + basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "short")); } else if (lastPathName == "tv-show") { basicKeyTmp.insert(std::pair<std::string,std::string>("type", "tv-show")); basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "picture")); - } else if (lastPathName == "anim") { + } else if (lastPathName == "tv-show-annimation") { basicKeyTmp.insert(std::pair<std::string,std::string>("type", "tv-show")); basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "draw")); - } else if (lastPathName == "courses") { // short films - basicKeyTmp.insert(std::pair<std::string,std::string>("type", "courses")); - basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "picture")); // TODO : Check "draw" } else if (lastPathName == "theater") { basicKeyTmp.insert(std::pair<std::string,std::string>("type", "theater")); - basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "picture")); - } else if (lastPathName == "one-man-show") { - basicKeyTmp.insert(std::pair<std::string,std::string>("type", "one-man show")); - basicKeyTmp.insert(std::pair<std::string,std::string>("production-methode", "picture")); + } else if (lastPathName == "one-man") { + basicKeyTmp.insert(std::pair<std::string,std::string>("type", "one-man")); } } else { - APPL_INFO("find '" << lastPathName << "' " << basicKeyTmp.size()); + APPL_INFO("find B '" << lastPathName << "' " << basicKeyTmp.size()); if (lastPathName == "saison_01") { basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "1")); } else if (lastPathName == "saison_02") { @@ -272,6 +271,24 @@ void installVideoPath(zeus::service::ProxyVideo& _srv, std::string _path, std::m basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "19")); } else if (lastPathName == "saison_20") { basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "20")); + } else if (lastPathName == "saison_21") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "21")); + } else if (lastPathName == "saison_22") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "22")); + } else if (lastPathName == "saison_23") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "23")); + } else if (lastPathName == "saison_24") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "24")); + } else if (lastPathName == "saison_25") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "25")); + } else if (lastPathName == "saison_26") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "26")); + } else if (lastPathName == "saison_27") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "27")); + } else if (lastPathName == "saison_28") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "28")); + } else if (lastPathName == "saison_29") { + basicKeyTmp.insert(std::pair<std::string,std::string>("saison", "29")); } else { basicKeyTmp.insert(std::pair<std::string,std::string>("series-name", lastPathName)); } @@ -462,7 +479,9 @@ int main(int _argc, const char *_argv[]) { APPL_PRINT("== push path: "); APPL_PRINT("============================================"); // Send a full path: - // installVideoPath(remoteServiceVideo, "testVideo"); + for (auto &it: args) { + installVideoPath(remoteServiceVideo, it); + } APPL_PRINT("============================================"); APPL_PRINT("== DONE =="); APPL_PRINT("============================================"); diff --git a/tools/player-video/appl/widget/ListViewer.cpp b/tools/player-video/appl/widget/ListViewer.cpp index 1adbe25..af71b75 100644 --- a/tools/player-video/appl/widget/ListViewer.cpp +++ b/tools/player-video/appl/widget/ListViewer.cpp @@ -59,7 +59,7 @@ void appl::widget::ListViewer::searchElements(std::string _filter) { } else if (_filter == "one-man") { searchElementsInternal("'type' == 'one-man'"); } else if (_filter == "courses") { - searchElementsInternal("'type' == 'courses'"); + searchElementsInternal("'type' == 'film' AND 'production-methode' == 'short'"); } else { searchElementsInternal("*"); } diff --git a/tools/service-video/appl/main-service-video.cpp b/tools/service-video/appl/main-service-video.cpp index 1b304d8..de526fd 100644 --- a/tools/service-video/appl/main-service-video.cpp +++ b/tools/service-video/appl/main-service-video.cpp @@ -86,6 +86,21 @@ static std::vector<std::string> splitAction(const std::string& _in) { return out; } +static void metadataChange(zeus::MediaImpl* _element, const std::string& _key) { + g_needToStore = true; + // meta_data have chage ==> we need to upfdate the path of the file where the data is stored ... + if (_element == nullptr) { + return; + } + _element->forceUpdateDecoratedName(); + std::string current = _element->getFileName(); + std::string next = _element->getDecoratedName() + "_" + _element->getSha512(); + if (next == current) { + return; + } + _element->move(next); +} + namespace appl { class VideoService : public zeus::service::Video { private: @@ -156,7 +171,7 @@ namespace appl { if (it == nullptr) { continue; } - if (it->getFileName() == sha512StringRemote) { + if (it->getSha512() == sha512StringRemote) { APPL_INFO("File already registered at ");// << it.m_creationData); // simply send the Id of the file // TODO : Check right of this file ... @@ -173,10 +188,20 @@ namespace appl { APPL_ERROR("try to store an empty file"); throw std::runtime_error("file size == 0"); } - etk::FSNodeMove(tmpFileName, g_basePath + sha512String + "." + zeus::getExtention(futType.get())); - ememory::SharedPtr<zeus::MediaImpl> property = ememory::makeShared<zeus::MediaImpl>(id, sha512String + "." + zeus::getExtention(futType.get())); - //property->setName(futName.get()); - m_listFile.push_back(property); + if (zeus::getExtention(futType.get()) == "") { + etk::FSNodeMove(tmpFileName, g_basePath + sha512String + "." + zeus::getExtention(futType.get())); + ememory::SharedPtr<zeus::MediaImpl> property = ememory::makeShared<zeus::MediaImpl>(id, sha512String + "." + zeus::getExtention(futType.get()), g_basePath); + property->setMetadata("sha512", sha512String); + property->setMetadata("mime-type", futType.get()); + property->setCallbackMetadataChange(&metadataChange); + m_listFile.push_back(property); + } else { + etk::FSNodeMove(tmpFileName, g_basePath + sha512String); + ememory::SharedPtr<zeus::MediaImpl> property = ememory::makeShared<zeus::MediaImpl>(id, sha512String, g_basePath); + property->setMetadata("sha512", sha512String); + property->setCallbackMetadataChange(&metadataChange); + m_listFile.push_back(property); + } g_needToStore = true; APPL_DEBUG(" filename : " << sha512String); return id; @@ -379,6 +404,7 @@ static void load_db() { if (property->getFileName() == "") { APPL_ERROR("Can not access on the file : ... No name "); } else { + property->setCallbackMetadataChange(&metadataChange); m_listFile.push_back(property); } } diff --git a/tools/service-video/appl/zeus-service-video.srv.zeus.idl b/tools/service-video/appl/zeus-service-video.srv.zeus.idl index 5f341de..9984f17 100644 --- a/tools/service-video/appl/zeus-service-video.srv.zeus.idl +++ b/tools/service-video/appl/zeus-service-video.srv.zeus.idl @@ -48,3 +48,16 @@ vector:uint32 getSQL(string) #param:sqlLikeRequest:A string containing the request on the data #return:All The possible values of a key vector:string getMetadataValuesWhere(string, string) +/* +#brief:Get a media cover +#param:mediaId:Id of the media +#param:maxSize:max size of the image requested (can return a smaller image) +#return:A simple file that might contain a jpg or png file +obj:zeus-File getCover(uint32, uint32) + +#brief:Get a media cover +#param:sqlLikeRequest:sql request mode to filter the cover +#param:maxSize:max size of the image requested (can return a smaller image) +#return:A simple file that might contain a jpg or png file +obj:zeus-File getGroupCover(string, uint32) +*/ diff --git a/zeus/mineType.cpp b/zeus/mineType.cpp index 039d522..b10d0a1 100644 --- a/zeus/mineType.cpp +++ b/zeus/mineType.cpp @@ -158,8 +158,10 @@ std::string zeus::getMineType(std::string _extention) { return it.second; } } - ZEUS_ERROR(" estention to mine type error : '" << _extention << "' ==> unknow"); - return ""; + if (_extention == "") { + return ""; + } + return "unknow/" + _extention; } std::string zeus::getExtention(std::string _mineType) { @@ -169,6 +171,9 @@ std::string zeus::getExtention(std::string _mineType) { return it.first; } } - ZEUS_ERROR(" mine type to estention error : '" << _mineType << "' ==> unknow"); + // special internal case to support all type of extention ... + if (etk::start_with(_mineType, "unknow/") == true) { + return &_mineType[7]; + } return ""; } diff --git a/zeus/zeus-Media.impl.cpp b/zeus/zeus-Media.impl.cpp index 8aad094..f6ab40d 100644 --- a/zeus/zeus-Media.impl.cpp +++ b/zeus/zeus-Media.impl.cpp @@ -19,9 +19,6 @@ ejson::Object zeus::MediaImpl::getJson() { ejson::Object out; out.add("id", ejson::Number(m_id)); out.add("file-name", ejson::String(m_fileName)); - out.add("name", ejson::String(m_name)); - out.add("mine-type", ejson::String(m_mineType)); - out.add("add-date", ejson::Number(m_creationData.count())); if (m_metadata.size() != 0) { ejson::Object listMetadata; out.add("meta", listMetadata); @@ -37,10 +34,6 @@ zeus::MediaImpl::MediaImpl(const std::string& _basePath, ejson::Object _property m_id = _property["id"].toNumber().getU64(); ZEUS_INFO("get ID : " << m_id); m_fileName = _property["file-name"].toString().get(); - m_name = _property["name"].toString().get(); - m_mineType = _property["mine-type"].toString().get(); - m_creationData = echrono::Time(_property["add-date"].toNumber().getU64()*1000); - ejson::Object tmpObj = _property["meta"].toObject(); if (tmpObj.exist() == true) { for (auto itValue = tmpObj.begin(); @@ -55,8 +48,9 @@ uint64_t zeus::MediaImpl::getUniqueId() { return m_id; } -zeus::MediaImpl::MediaImpl(uint64_t _id, const std::string& _fileNameReal): +zeus::MediaImpl::MediaImpl(uint64_t _id, const std::string& _fileNameReal, const std::string& _basePath): m_id(_id), + m_basePath(_basePath), m_fileName(_fileNameReal) { std::string extention; if ( m_fileName.rfind('.') != std::string::npos @@ -64,8 +58,10 @@ zeus::MediaImpl::MediaImpl(uint64_t _id, const std::string& _fileNameReal): extention = etk::tolower(std::string(m_fileName.begin()+m_fileName.rfind('.')+1, m_fileName.end())); m_fileName = std::string(m_fileName.begin(), m_fileName.begin()+m_fileName.rfind('.')); } - m_mineType = zeus::getMineType(extention); - m_creationData = echrono::Time::now(); + if (extention != "") { + setMetadata("mime-type", zeus::getMineType(extention)); + //m_creationData = echrono::Time::now(); + } } zeus::MediaImpl::~MediaImpl() { @@ -73,11 +69,56 @@ zeus::MediaImpl::~MediaImpl() { } std::string zeus::MediaImpl::getMineType() { - return m_mineType; + return getMetadata("mime-type"); +} + + +std::string zeus::MediaImpl::getSha512() { + try { + return getMetadata("sha512"); + } catch (std::invalid_argument _eee) { + // Nothing to do ... + } + std::string sha512; + auto it = m_metadata.find("mime-type"); + if (it != m_metadata.end()) { + sha512 = algue::stringConvert(algue::sha512::encodeFromFile(m_basePath + m_fileName + "." + zeus::getExtention(it->second))); + } else { + sha512 = algue::stringConvert(algue::sha512::encodeFromFile(m_basePath + m_fileName)); + } + setMetadata("sha512", sha512); + return sha512; +} + + +void zeus::MediaImpl::forceUpdateDecoratedName() { + // force the new calculation .. + std::string value = getDecoratedNameFrom(m_metadata); + setMetadata("decorated-name", value); +} + +std::string zeus::MediaImpl::getDecoratedName() { + try { + std::string out = getMetadata("decorated-name"); + if (out != "") { + return out; + } + } catch (std::invalid_argument _eee) { + // Nothing to do ... + } + // Store the metadat to not calculated it all the time ... + std::string value = getDecoratedNameFrom(m_metadata); + setMetadata("decorated-name", value); + return value; } ememory::SharedPtr<zeus::File> zeus::MediaImpl::getFile() { - return zeus::File::create(m_basePath + m_fileName + "." + zeus::getExtention(m_mineType), "", m_mineType); + auto it = m_metadata.find("mime-type"); + if (it != m_metadata.end()) { + return zeus::File::create(m_basePath + m_fileName + "." + zeus::getExtention(it->second), "", it->second); + } + // no mimetype specify ... ==> theoric impossible case ... + return zeus::File::create(m_basePath + m_fileName, "", ""); } std::vector<std::string> zeus::MediaImpl::getMetadataKeys() { @@ -100,15 +141,216 @@ void zeus::MediaImpl::setMetadata(std::string _key, std::string _value) { ZEUS_INFO("metadataSetKey: '" << _key << "' value='" << _value << "'"); auto it = m_metadata.find(_key); if (it != m_metadata.end()) { - it->second = _value; + if (_value == "") { + m_metadata.erase(it); + } else if (it->second == _value) { + return; + } else { + it->second = _value; + } } else { m_metadata.insert(std::make_pair(_key, _value)); } + // hook to remove some case that does not call the callback ==> can change many times ... + if ( _key == "sha512" + || _key == "mime-type" + || _key == "decorated-name") { + return; + } + if (m_callback != nullptr) { + m_callback(this, _key); + } } bool zeus::MediaImpl::erase() { - return etk::FSNodeRemove(m_basePath + m_fileName + "." + zeus::getExtention(m_mineType)); + auto it = m_metadata.find("mime-type"); + if (it != m_metadata.end()) { + return etk::FSNodeRemove(m_basePath + m_fileName + "." + zeus::getExtention(it->second)); + } + return etk::FSNodeRemove(m_basePath + m_fileName); +} + +bool zeus::MediaImpl::move(const std::string& _newOffsetFile) { + ZEUS_INFO("move file : '" << m_basePath + m_fileName << "' ==> " << m_basePath + _newOffsetFile << "'"); + if (_newOffsetFile == m_fileName) { + // nothing to do ... + return true; + } + auto it = m_metadata.find("mime-type"); + if (it != m_metadata.end()) { + bool ret = etk::FSNodeMove(m_basePath + m_fileName + "." + zeus::getExtention(it->second), m_basePath + _newOffsetFile + "." + zeus::getExtention(it->second)); + if (ret == true) { + m_fileName = _newOffsetFile; + } + return ret; + } + bool ret = etk::FSNodeMove(m_basePath + m_fileName, m_basePath + _newOffsetFile); + if (ret == true) { + m_fileName = _newOffsetFile; + } + return ret; } + +std::string zeus::MediaImpl::getMetadataFrom(const std::map<std::string, std::string>& _metadata, std::string _key) { + auto it = _metadata.find(_key); + if (it != _metadata.end()) { + return it->second; + } + return ""; +} + +std::string zeus::MediaImpl::getDecoratedNameFrom(const std::map<std::string, std::string>& _metadata) { + std::string basePath; + std::string type = getMetadataFrom(_metadata, "type"); + std::string title = getMetadataFrom(_metadata, "title"); + /* + ZEUS_INFO("---- : " << type << " " << title << " "); + for (auto &it: _metadata) { + ZEUS_INFO(" " << it.first << " " << it.second); + } + */ + std::string out; + if (type == "film") { + std::string productionMethode = getMetadataFrom(_metadata, "production-methode"); + std::string serie = getMetadataFrom(_metadata, "series-name"); + std::string episode = getMetadataFrom(_metadata, "episode"); + if (productionMethode == "picture") { + // real film with real human + basePath += "film/"; + } else if (productionMethode == "draw") { + // annimation films + basePath += "film-annimation/"; + } else if (productionMethode == "short") { + // annimation films + basePath += "film-short/"; + } else { + basePath += "film-other/"; + } + if (serie != "") { + out += serie + "-"; + } + if (episode != "") { + out += "e" + episode + "-"; + } + } else if (type == "tv-show") { + std::string productionMethode = getMetadataFrom(_metadata, "production-methode"); + std::string serie = getMetadataFrom(_metadata, "series-name"); + std::string saison = getMetadataFrom(_metadata, "saison"); + std::string episode = getMetadataFrom(_metadata, "episode"); + if (productionMethode == "picture") { + // real film with real human + basePath += "tv-show/"; + } else if (productionMethode == "draw") { + // annimation films + basePath += "tv-show-annimation/"; + } else { + basePath += "tv-show-other/"; + } + if (serie != "") { + basePath += serie + "/"; + out += serie + "-"; + } + if (saison != "") { + basePath += "saison_" + saison + "/"; + if (saison.size() < 2) { + out += "s0" + saison + "-"; + } else { + out += "s" + saison + "-"; + } + } + if (episode != "") { + if (episode.size() < 2) { + out += "e0" + episode + "-"; + } else { + out += "e" + episode + "-"; + } + } + } else if (type == "theater") { + std::string serie = getMetadataFrom(_metadata, "series-name"); + std::string episode = getMetadataFrom(_metadata, "episode"); + basePath += type + "/"; + if (serie != "") { + basePath += serie + "/"; + out += serie + "-"; + } + if (episode != "") { + if (episode.size() < 2) { + out += "e0" + episode + "-"; + } else { + out += "e" + episode + "-"; + } + } + } else if (type == "one-man") { + std::string author = getMetadataFrom(_metadata, "author"); + std::string episode = getMetadataFrom(_metadata, "episode"); + basePath += type + "/"; + if (author != "") { + basePath += author + "/"; + out += author + "-"; + } + if (episode != "") { + if (episode.size() < 2) { + out += "e0" + episode + "-"; + } else { + out += "e" + episode + "-"; + } + } + } else if ( type == "sound-track" + || type == "album") { + // soundtrack: Original sound track from films + // album: general audio track + std::string author = getMetadataFrom(_metadata, "author"); + std::string album = getMetadataFrom(_metadata, "album"); + std::string episode = getMetadataFrom(_metadata, "episode"); + basePath += type + "/"; + if (author != "") { + basePath += author + "/"; + out += author + "-"; + } + if (album != "") { + basePath += album + "/"; + out += album + "-"; + } + if (episode != "") { + if (episode.size() < 2) { + out += "e0" + episode + "-"; + } else { + out += "e" + episode + "-"; + } + } + } else if (type == "file") { + // generic file that is provided to the generic cloud system ==> simple sharing of files + std::string path = getMetadataFrom(_metadata, "path"); + basePath += type + "/"; + if (path != "") { + basePath += path + "/"; + } + } else { + std::string author = getMetadataFrom(_metadata, "author"); + std::string group = getMetadataFrom(_metadata, "group"); + std::string episode = getMetadataFrom(_metadata, "episode"); + std::string serie = getMetadataFrom(_metadata, "series-name"); + basePath += "unknow/"; + if (author != "") { + out += author + "-"; + } + if (group != "") { + out += group + "-"; + } + if (serie != "") { + out += serie + "-"; + } + if (episode != "") { + out += "e" + episode + "-"; + } + } + out += title; + std::string mimeType = getMetadataFrom(_metadata, "mime-type"); + if (mimeType != "") { + return basePath + out + "." + zeus::getExtention(mimeType); + } + return basePath + out; +} \ No newline at end of file diff --git a/zeus/zeus-Media.impl.hpp b/zeus/zeus-Media.impl.hpp index 6639344..23a4826 100644 --- a/zeus/zeus-Media.impl.hpp +++ b/zeus/zeus-Media.impl.hpp @@ -15,11 +15,13 @@ namespace zeus { private: uint64_t m_id; //!< use local reference ID to have faster access on the file ... std::string m_basePath; //!< basic global path - std::string m_fileName; // Sha 512 - std::string m_name; - std::string m_mineType; - echrono::Time m_creationData; + std::string m_fileName; //!< Name of the file std::map<std::string, std::string> m_metadata; //!< all extra property + std::function<void(zeus::MediaImpl*, const std::string& )> m_callback; + public: + void setCallbackMetadataChange(std::function<void(zeus::MediaImpl*, const std::string& )> _callback) { + m_callback = _callback; + } public: /** * @brief Generic json constructor @@ -28,7 +30,7 @@ namespace zeus { /** * @brief Generic file constructor */ - MediaImpl(uint64_t _id, const std::string& _fileNameReal); + MediaImpl(uint64_t _id, const std::string& _fileNameReal, const std::string& _basePath=""); /** * @brief Generic destructor */ @@ -39,6 +41,8 @@ namespace zeus { std::vector<std::string> getMetadataKeys() override; std::string getMetadata(std::string _key) override; void setMetadata(std::string _key, std::string _value) override; + std::string getSha512() override; + std::string getDecoratedName() override; /** * @brief Export json property * @return A json Object with data @@ -48,9 +52,15 @@ namespace zeus { return m_fileName; } bool erase(); + bool move(const std::string& _newOffsetFile); const std::map<std::string, std::string>& getMetadataDirect() { return m_metadata; } + void forceUpdateDecoratedName(); + public: + // local tools: + static std::string getMetadataFrom(const std::map<std::string, std::string>& _metadata, std::string _key); + static std::string getDecoratedNameFrom(const std::map<std::string, std::string>& _metadata); }; } diff --git a/zeus/zeus-Media.obj.zeus.idl b/zeus/zeus-Media.obj.zeus.idl index 18d8a4b..ec860f1 100644 --- a/zeus/zeus-Media.obj.zeus.idl +++ b/zeus/zeus-Media.obj.zeus.idl @@ -57,3 +57,11 @@ json getMetadataJson() #param:description: a json description of the metadata void setMetadataJson(json) */ + +#brief:Get sha 512 of the file +#return:get the sha512 of the stored file +string getSha512() + +#brief:Get decorated name of the file +#return:decorated name: Name of the file decorated like StarWars-e04-A new Hope(1978).mkv +string getDecoratedName()