File indexing completed on 2024-05-12 16:18:07
0001 /**************************************************************************************** 0002 * Copyright (c) 2010 Sergey Ivanov <123kash@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 0018 #include "ASFTagHelper.h" 0019 0020 #include "StringHelper.h" 0021 0022 #include <QBuffer> 0023 #include <QImage> 0024 0025 #include <asfattribute.h> 0026 0027 using namespace Meta::Tag; 0028 0029 ASFTagHelper::ASFTagHelper( TagLib::Tag *tag, TagLib::ASF::Tag *asfTag, Amarok::FileType fileType ) 0030 : TagHelper( tag, fileType ) 0031 , m_tag( asfTag ) 0032 { 0033 m_fieldMap.insert( Meta::valAlbumArtist, TagLib::String( "WM/AlbumArtist" ) ); 0034 m_fieldMap.insert( Meta::valBpm, TagLib::String( "WM/BeatsPerMinute" ) ); 0035 m_fieldMap.insert( Meta::valCompilation, TagLib::String( "Amarok/Compilation" ) ); //Not standard tag 0036 m_fieldMap.insert( Meta::valComposer, TagLib::String( "WM/Composer" ) ); 0037 m_fieldMap.insert( Meta::valDiscNr, TagLib::String( "WM/PartOfSet" ) ); 0038 m_fieldMap.insert( Meta::valHasCover, TagLib::String( "WM/Picture" ) ); 0039 m_fieldMap.insert( Meta::valPlaycount, TagLib::String( "FMPS/Playcount" ) ); 0040 m_fieldMap.insert( Meta::valRating, TagLib::String( "FMPS/Rating" ) ); 0041 m_fieldMap.insert( Meta::valScore, TagLib::String( "FMPS/Rating_Amarok_Score" ) ); 0042 m_fieldMap.insert( Meta::valLyrics, TagLib::String( "WM/Lyrics" ) ); 0043 0044 m_uidFieldMap.insert( UIDAFT, TagLib::String( "Amarok/AFTv1" ) ); 0045 } 0046 0047 Meta::FieldHash 0048 ASFTagHelper::tags() const 0049 { 0050 Meta::FieldHash data = TagHelper::tags(); 0051 0052 TagLib::ASF::AttributeListMap map = m_tag->attributeListMap(); 0053 for( TagLib::ASF::AttributeListMap::ConstIterator it = map.begin(); it != map.end(); ++it ) 0054 { 0055 if( !it->second.size() ) 0056 continue; 0057 0058 qint64 field; 0059 TagLib::ASF::Attribute value = it->second[0]; 0060 QString strValue = TStringToQString( value.toString() ); 0061 if( ( field = fieldName( it->first ) ) ) 0062 { 0063 if( field == Meta::valBpm || field == Meta::valPlaycount ) 0064 data.insert( field, value.toUInt() ); 0065 else if( field == Meta::valRating ) 0066 data.insert( field, qRound( strValue.toFloat() * 10.0 ) ); 0067 else if( field == Meta::valScore ) 0068 data.insert( field, strValue.toFloat() * 100.0 ); 0069 else if( field == Meta::valDiscNr ) 0070 data.insert( field, value.toUInt() ); 0071 else if( field == Meta::valCompilation ) 0072 data.insert( field, value.toBool() ); 0073 else if( field == Meta::valHasCover ) 0074 { 0075 for( TagLib::ASF::AttributeList::ConstIterator cover = it->second.begin(); cover != it->second.end(); ++cover ) 0076 { 0077 if( cover->type() != TagLib::ASF::Attribute::BytesType ) 0078 continue; 0079 0080 TagLib::ASF::Picture pict = cover->toPicture(); 0081 if( ( pict.type() == TagLib::ASF::Picture::FrontCover || 0082 pict.type() == TagLib::ASF::Picture::Other ) && 0083 pict.dataSize() > MIN_COVER_SIZE ) 0084 { 0085 data.insert( field, true ); 0086 break; 0087 } 0088 } 0089 } 0090 else 0091 data.insert( field, strValue ); 0092 } 0093 else if( it->first == uidFieldName( UIDAFT ) && isValidUID( strValue, UIDAFT ) ) 0094 data.insert( Meta::valUniqueId, strValue ); 0095 } 0096 0097 return data; 0098 } 0099 0100 bool 0101 ASFTagHelper::setTags( const Meta::FieldHash &changes ) 0102 { 0103 bool modified = TagHelper::setTags( changes ); 0104 0105 foreach( const qint64 key, changes.keys() ) 0106 { 0107 QVariant value = changes.value( key ); 0108 TagLib::String field = fieldName( key ); 0109 0110 if( !field.isNull() && !field.isEmpty() ) 0111 { 0112 if( key == Meta::valHasCover ) 0113 continue; 0114 // http://gitorious.org/~jefferai/xdg-specs/jefferais-xdg-specs/blobs/mediaspecs/specifications/FMPSpecs/specification.txt sais that mp4 tags should be saved as strings 0115 if( key == Meta::valHasCover ) 0116 continue; 0117 else if( key == Meta::valRating ) 0118 m_tag->setAttribute( field, TagLib::ASF::Attribute( Qt4QStringToTString( QString::number( value.toFloat() / 10.0 ) ) ) ); 0119 else if( key == Meta::valScore ) 0120 m_tag->setAttribute( field, TagLib::ASF::Attribute( Qt4QStringToTString( QString::number( value.toFloat() / 100.0 ) ) ) ); 0121 else if( key == Meta::valBpm || key == Meta::valDiscNr ) 0122 m_tag->setAttribute( field, TagLib::ASF::Attribute( value.toUInt() ) ); 0123 else if( key == Meta::valCompilation ) 0124 m_tag->setAttribute( field, TagLib::ASF::Attribute( value.toBool() ) ); 0125 else 0126 m_tag->setAttribute( field, TagLib::ASF::Attribute( Qt4QStringToTString( value.toString() ) ) ); 0127 0128 modified = true; 0129 } 0130 else if( key == Meta::valUniqueId ) 0131 { 0132 QPair < UIDType, QString > uidPair = splitUID( value.toString() ); 0133 if( uidPair.first == UIDInvalid ) 0134 continue; 0135 0136 m_tag->setAttribute( uidFieldName( uidPair.first ), 0137 TagLib::ASF::Attribute( Qt4QStringToTString( uidPair.second ) ) ); 0138 modified = true; 0139 } 0140 } 0141 0142 return modified; 0143 } 0144 0145 bool 0146 ASFTagHelper::hasEmbeddedCover() const 0147 { 0148 TagLib::ASF::AttributeListMap map = m_tag->attributeListMap(); 0149 TagLib::String name = fieldName( Meta::valHasCover ); 0150 for( TagLib::ASF::AttributeListMap::ConstIterator it = map.begin(); it != map.end(); ++it ) 0151 { 0152 if( it->first == name ) 0153 { 0154 TagLib::ASF::AttributeList coverList = it->second; 0155 for( TagLib::ASF::AttributeList::ConstIterator cover = coverList.begin(); cover != coverList.end(); ++cover ) 0156 { 0157 if( cover->type() != TagLib::ASF::Attribute::BytesType ) 0158 continue; 0159 0160 TagLib::ASF::Picture pict = cover->toPicture(); 0161 if( ( pict.type() == TagLib::ASF::Picture::FrontCover || 0162 pict.type() == TagLib::ASF::Picture::Other ) && 0163 pict.dataSize() > MIN_COVER_SIZE ) 0164 { 0165 return true; 0166 } 0167 } 0168 } 0169 } 0170 0171 return false; 0172 } 0173 0174 QImage 0175 ASFTagHelper::embeddedCover() const 0176 { 0177 TagLib::ASF::AttributeListMap map = m_tag->attributeListMap(); 0178 TagLib::String name = fieldName( Meta::valHasCover ); 0179 0180 TagLib::ASF::Picture cover, otherCover; 0181 bool hasCover = false, hasOtherCover = false; 0182 0183 for( TagLib::ASF::AttributeListMap::ConstIterator it = map.begin(); it != map.end(); ++it ) 0184 { 0185 if( it->first == name ) 0186 { 0187 TagLib::ASF::AttributeList coverList = it->second; 0188 for( TagLib::ASF::AttributeList::ConstIterator it = coverList.begin(); it != coverList.end(); ++it ) 0189 { 0190 if( it->type() != TagLib::ASF::Attribute::BytesType ) 0191 continue; 0192 0193 TagLib::ASF::Picture pict = it->toPicture(); 0194 0195 if( pict.dataSize() < MIN_COVER_SIZE ) 0196 continue; 0197 0198 if( pict.type() == TagLib::ASF::Picture::FrontCover ) 0199 { 0200 cover = pict; 0201 hasCover = true; 0202 } 0203 else if( pict.type() == TagLib::ASF::Picture::Other ) 0204 { 0205 otherCover = pict; 0206 hasOtherCover = true; 0207 } 0208 } 0209 } 0210 } 0211 0212 if( !hasCover && hasOtherCover ) 0213 { 0214 cover = otherCover; 0215 hasCover = true; 0216 } 0217 0218 if( !hasCover ) 0219 return QImage(); 0220 0221 return QImage::fromData( ( uchar * ) cover.picture().data(), cover.picture().size() ); 0222 } 0223 0224 bool 0225 ASFTagHelper::setEmbeddedCover( const QImage &cover ) 0226 { 0227 QByteArray bytes; 0228 QBuffer buffer( &bytes ); 0229 0230 buffer.open( QIODevice::WriteOnly ); 0231 0232 if( !cover.save( &buffer, "JPEG" ) ) 0233 { 0234 buffer.close(); 0235 return false; 0236 } 0237 0238 buffer.close(); 0239 0240 TagLib::String name = fieldName( Meta::valHasCover ); 0241 0242 // remove all covers 0243 m_tag->removeItem( name ); 0244 0245 // add new cover 0246 TagLib::ASF::Picture picture; 0247 picture.setPicture( TagLib::ByteVector( bytes.data(), bytes.count() ) ); 0248 picture.setType( TagLib::ASF::Picture::FrontCover ); 0249 picture.setMimeType( "image/jpeg" ); 0250 m_tag->addAttribute( name, TagLib::ASF::Attribute( picture.render() ) ); 0251 0252 return true; 0253 }