File indexing completed on 2024-05-19 04:49:32
0001 /**************************************************************************************** 0002 * Copyright (c) 2010 Téo Mrnjavac <teo@kde.org> * 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 #include "TranscodingConfiguration.h" 0018 0019 #include "TranscodingProperty.h" 0020 #include "TranscodingFormat.h" 0021 #include "TranscodingController.h" 0022 #include "core/support/Components.h" 0023 0024 #include <KLocalizedString> 0025 0026 using namespace Transcoding; 0027 0028 QMap<Encoder, QString> Configuration::s_encoderNames; 0029 0030 Configuration::Configuration( Encoder encoder, TrackSelection trackSelection ) 0031 : m_encoder( encoder ) 0032 , m_trackSelection( trackSelection ) 0033 { 0034 } 0035 0036 void 0037 Configuration::addProperty( const QByteArray &name, const QVariant &value ) 0038 { 0039 m_values.insert( name, value ); 0040 } 0041 0042 QVariant 0043 Configuration::property( const QByteArray &name ) const 0044 { 0045 return m_values.value( name ); 0046 } 0047 0048 Configuration 0049 Configuration::fromConfigGroup( const KConfigGroup &serialized ) 0050 { 0051 QString encoderName = serialized.readEntry( "Encoder", QString() ); 0052 Encoder encoder = encoderNames().key( encoderName, INVALID ); 0053 TrackSelection trackSelection = TrackSelection( serialized.readEntry( "TrackSelection", int( TranscodeAll ) ) ); 0054 Configuration ret( encoder, trackSelection ); 0055 if( !ret.isValid() ) 0056 return ret; // return ret, so that its trackSelection value may be used 0057 0058 Controller *controller = Amarok::Components::transcodingController(); 0059 // reset controller to 0 if it doesn't contain encoder to prevent bogus format() call 0060 if( controller && !controller->allEncoders().contains( ret.encoder() ) ) 0061 controller = nullptr; 0062 Format *format = controller ? controller->format( ret.encoder() ) : nullptr; 0063 0064 PropertyList emptyList; 0065 foreach( const Property &property, format ? format->propertyList() : emptyList ) 0066 { 0067 Configuration invalid( INVALID ); 0068 QString key = QStringLiteral( "Parameter ").append( property.name() ); 0069 QVariant value = serialized.readEntry( key, QString() /* does not work with QVariant() */ ); 0070 0071 if( !value.isValid() ) 0072 return invalid; 0073 if( !value.canConvert( property.variantType() ) ) 0074 return invalid; 0075 switch( property.type() ) 0076 { 0077 case Property::TRADEOFF: 0078 if( value.toInt() < property.min() ) 0079 return invalid; 0080 if( value.toInt() > property.max() ) 0081 return invalid; 0082 break; 0083 } 0084 ret.m_values.insert( property.name(), value ); 0085 } 0086 return ret; 0087 } 0088 0089 void 0090 Configuration::saveToConfigGroup( KConfigGroup &group ) const 0091 { 0092 group.deleteGroup(); // remove all keys 0093 Q_ASSERT( encoderNames().contains( m_encoder ) ); 0094 QString encoderName = encoderNames().value( m_encoder ); 0095 group.writeEntry( QStringLiteral( "Encoder" ), encoderName ); 0096 group.writeEntry( QStringLiteral( "TrackSelection" ), int( m_trackSelection ) ); 0097 QMapIterator<QByteArray, QVariant> it( m_values ); 0098 while( it.hasNext() ) 0099 { 0100 it.next(); 0101 group.writeEntry( QStringLiteral( "Parameter " ).append( it.key() ), it.value() ); 0102 } 0103 } 0104 0105 QString 0106 Configuration::prettyName() const 0107 { 0108 if( !isValid() ) 0109 return i18n( "Invalid" ); 0110 if( isJustCopy() ) 0111 return i18n( "Just Copy" ); 0112 0113 Format *format = Amarok::Components::transcodingController()->format( m_encoder ); 0114 if( format->propertyList().isEmpty() ) 0115 return formatPrettyPrefix(); 0116 0117 // we take only the first property into account, assume it's the most significant 0118 const Property &property = format->propertyList().first(); 0119 QByteArray name = property.name(); 0120 Q_ASSERT( m_values.contains( name ) ); 0121 Q_ASSERT( m_values.value( name ).type() == property.variantType() ); 0122 QString propertyText; 0123 switch( property.type() ) 0124 { 0125 case Property::TRADEOFF: 0126 { 0127 const int currValue = m_values.value( name ).toInt(); 0128 const int min = property.min(); 0129 const int max = property.max(); 0130 Q_ASSERT( min <= currValue && currValue <= max ); 0131 if( property.valueLabels().size() == ( max - min + 1 ) ) 0132 propertyText = property.valueLabels().at( currValue - min ); 0133 else 0134 propertyText = i18nc( "%1 example: 'Compression level' %2 example: '5'", 0135 "%1 %2", property.prettyName(), currValue ); 0136 break; 0137 } 0138 } 0139 0140 return i18nc( "Displayed next to the \"Transcode:\" label. " 0141 "%1 example: 'All Tracks to MP3' %2 example: 'VBR 175kb/s'", 0142 "%1, %2", formatPrettyPrefix(), propertyText ); 0143 0144 } 0145 0146 const QMap<Encoder, QString>& 0147 Configuration::encoderNames() 0148 { 0149 if( !s_encoderNames.isEmpty() ) 0150 return s_encoderNames; 0151 0152 s_encoderNames.insert( INVALID, QStringLiteral( "INVALID" ) ); 0153 s_encoderNames.insert( JUST_COPY, QStringLiteral( "JUST_COPY" ) ); 0154 s_encoderNames.insert( AAC, QStringLiteral( "AAC" ) ); 0155 s_encoderNames.insert( ALAC, QStringLiteral( "ALAC" ) ); 0156 s_encoderNames.insert( FLAC, QStringLiteral( "FLAC" ) ); 0157 s_encoderNames.insert( MP3, QStringLiteral( "MP3" ) ); 0158 s_encoderNames.insert( OPUS, QStringLiteral( "OPUS" ) ); 0159 s_encoderNames.insert( VORBIS, QStringLiteral( "VORBIS" ) ); 0160 s_encoderNames.insert( WMA2, QStringLiteral( "WMA2" ) ); 0161 return s_encoderNames; 0162 } 0163 0164 bool 0165 Configuration::isJustCopy( const Meta::TrackPtr &srcTrack, 0166 const QStringList &playableFileTypes ) const 0167 { 0168 if( m_encoder == INVALID || m_encoder == JUST_COPY ) 0169 return true; 0170 0171 if( !srcTrack ) 0172 return false; 0173 0174 switch( m_trackSelection ) 0175 { 0176 case TranscodeUnlessSameType: 0177 { 0178 QString srcExt = srcTrack->type(); 0179 QString destExt = Amarok::Components::transcodingController()->format( m_encoder )->fileExtension(); 0180 if( destExt.compare( srcExt, Qt::CaseInsensitive ) == 0 ) //if source and destination file formats are the same 0181 return true; 0182 else 0183 return false; 0184 } 0185 case TranscodeOnlyIfNeeded: 0186 { 0187 QString srcExt = srcTrack->type(); 0188 //check if the file is already in a format supported by the target collection 0189 if( playableFileTypes.isEmpty() || playableFileTypes.contains( srcExt ) ) 0190 return true; // if isEmpty(), assume all formats compatible 0191 else 0192 return false; 0193 } 0194 case TranscodeAll: 0195 return false; 0196 } 0197 return false; // shouldn't really get here 0198 } 0199 0200 QString 0201 Configuration::formatPrettyPrefix() const 0202 { 0203 Format *format = Amarok::Components::transcodingController()->format( m_encoder ); 0204 0205 switch( m_trackSelection ) 0206 { 0207 case TranscodeAll: 0208 return i18nc( "Displayed next to the \"Transcode:\" label. " 0209 "%1 example: 'MP3'", 0210 "All Tracks to %1", format->prettyName() ); 0211 case TranscodeUnlessSameType: 0212 return i18nc( "Displayed next to the \"Transcode:\" label. " 0213 "%1 example: 'MP3'", 0214 "Non-%1 Tracks to %1", format->prettyName() ); 0215 case TranscodeOnlyIfNeeded: 0216 return i18nc( "Displayed next to the \"Transcode:\" label. " 0217 "%1 example: 'MP3'", 0218 "When Needed to %1", format->prettyName() ); 0219 } 0220 return format->prettyName(); 0221 } 0222 0223 void 0224 Configuration::setTrackSelection( TrackSelection trackSelection ) 0225 { 0226 m_trackSelection = trackSelection; 0227 } 0228 0229 bool 0230 Configuration::operator!=( const Configuration &other ) const 0231 { 0232 return m_encoder != other.m_encoder || 0233 m_trackSelection != other.m_trackSelection; 0234 }