1 /* MP4Frame.h */ 2 3 /* Copyright (C) 2011-2020 Michael Lugmair (Lucio Carreras) 4 * 5 * This file is part of sayonara player 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef SAYONARA_ABSTRACT_MP4_FRAME_H 22 #define SAYONARA_ABSTRACT_MP4_FRAME_H 23 24 #include "Utils/Tagging/AbstractFrame.h" 25 #include "Utils/Algorithm.h" 26 27 #include <QString> 28 29 #include <taglib/tag.h> 30 #include <taglib/tstringlist.h> 31 #include <taglib/mp4tag.h> 32 #include <taglib/tpropertymap.h> 33 34 #include <algorithm> 35 #include <optional> 36 37 namespace MP4 38 { 39 template<typename Model_t> 40 class MP4Frame : 41 protected Tagging::AbstractFrame<TagLib::MP4::Tag> 42 { 43 protected: findKey(const TagLib::MP4::ItemMap & itemMap)44 TagLib::MP4::ItemMap::ConstIterator findKey(const TagLib::MP4::ItemMap& itemMap) const 45 { 46 return std::find_if(itemMap.begin(), itemMap.end(), [&](const auto& itemList) { 47 const auto convertedString = Tagging::convertString(itemList.first); 48 return (convertedString.compare(key(), Qt::CaseInsensitive) == 0); 49 }); 50 } 51 eraseAllFromTag(TagLib::MP4::Tag * tag,const QString & key)52 void eraseAllFromTag(TagLib::MP4::Tag* tag, const QString& key) 53 { 54 const auto taglibKey = Tagging::convertString(key); 55 while(tag->contains(taglibKey)) 56 { 57 tag->removeItem(taglibKey); 58 } 59 } 60 61 virtual std::optional<Model_t> mapItemToData(const TagLib::MP4::Item& item) const = 0; 62 virtual std::optional<TagLib::MP4::Item> mapDataToItem(const Model_t& model) = 0; 63 64 public: MP4Frame(TagLib::MP4::Tag * tag,const QString & identifier)65 MP4Frame(TagLib::MP4::Tag* tag, const QString& identifier) : 66 Tagging::AbstractFrame<TagLib::MP4::Tag>(tag, identifier) {} 67 68 virtual ~MP4Frame() = default; 69 read(Model_t & data)70 bool read(Model_t& data) const 71 { 72 if(!tag()) 73 { 74 return false; 75 } 76 77 const auto& itemMap = tag()->itemMap(); 78 const auto it = findKey(itemMap); 79 if(it != itemMap.end() && it->second.isValid()) 80 { 81 const auto optionalData = mapItemToData(it->second); 82 if(optionalData.has_value()) 83 { 84 data = optionalData.value(); 85 return true; 86 } 87 } 88 89 return false; 90 } 91 write(const Model_t & data)92 bool write(const Model_t& data) 93 { 94 if(!tag()) 95 { 96 return false; 97 } 98 99 eraseAllFromTag(tag(), key()); 100 101 const auto item = mapDataToItem(data); 102 if(item.has_value() && item.value().isValid()) 103 { 104 tag()->setItem(tagKey(), *item); 105 } 106 107 return item.has_value(); 108 } 109 isFrameAvailable()110 bool isFrameAvailable() const 111 { 112 if(!tag()) 113 { 114 return false; 115 } 116 117 const auto& itemMap = tag()->itemMap(); 118 return (findKey(itemMap) != itemMap.end()); 119 } 120 }; 121 } 122 123 #endif // SAYONARA_ABSTRACT_MP4_FRAME_H 124