File indexing completed on 2024-04-28 16:06:18
0001 /* AUDEX CDDA EXTRACTOR 0002 * SPDX-FileCopyrightText: Copyright (C) 2007 Marco Nelles 0003 * <https://userbase.kde.org/Audex> 0004 * 0005 * SPDX-License-Identifier: GPL-3.0-or-later 0006 */ 0007 0008 #include "encoderassistant.h" 0009 0010 long makeVersionNumber(int major, int minor, int patch) 0011 { 0012 long versionNumber = ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF); 0013 return versionNumber; 0014 } 0015 0016 const QString EncoderAssistant::name(const EncoderAssistant::Encoder encoder) 0017 { 0018 switch (encoder) { 0019 case EncoderAssistant::LAME: 0020 return ENCODER_LAME_NAME; 0021 case EncoderAssistant::OGGENC: 0022 return ENCODER_OGGENC_NAME; 0023 case EncoderAssistant::OPUSENC: 0024 return ENCODER_OPUSENC_NAME; 0025 case EncoderAssistant::FLAC: 0026 return ENCODER_FLAC_NAME; 0027 case EncoderAssistant::FAAC: 0028 return ENCODER_FAAC_NAME; 0029 case EncoderAssistant::WAVE: 0030 return ENCODER_WAVE_NAME; 0031 case EncoderAssistant::CUSTOM: 0032 return ENCODER_CUSTOM_NAME; 0033 default: 0034 return ""; 0035 } 0036 0037 return ""; 0038 } 0039 0040 const QString EncoderAssistant::encoderName(const Encoder encoder) 0041 { 0042 switch (encoder) { 0043 case EncoderAssistant::LAME: 0044 return ENCODER_LAME_ENCODER_NAME; 0045 case EncoderAssistant::OGGENC: 0046 return ENCODER_OGGENC_ENCODER_NAME; 0047 case EncoderAssistant::OPUSENC: 0048 return ENCODER_OPUSENC_ENCODER_NAME; 0049 case EncoderAssistant::FLAC: 0050 return ENCODER_FLAC_ENCODER_NAME; 0051 case EncoderAssistant::FAAC: 0052 return ENCODER_FAAC_ENCODER_NAME; 0053 case EncoderAssistant::WAVE: 0054 return ENCODER_WAVE_ENCODER_NAME; 0055 case EncoderAssistant::CUSTOM: 0056 return ENCODER_CUSTOM_ENCODER_NAME; 0057 default: 0058 return ""; 0059 } 0060 0061 return ""; 0062 } 0063 0064 const QString EncoderAssistant::icon(const EncoderAssistant::Encoder encoder) 0065 { 0066 switch (encoder) { 0067 case EncoderAssistant::LAME: 0068 return ENCODER_LAME_ICON; 0069 case EncoderAssistant::OGGENC: 0070 return ENCODER_OGGENC_ICON; 0071 case EncoderAssistant::OPUSENC: 0072 return ENCODER_OPUSENC_ICON; 0073 case EncoderAssistant::FLAC: 0074 return ENCODER_FLAC_ICON; 0075 case EncoderAssistant::FAAC: 0076 return ENCODER_FAAC_ICON; 0077 case EncoderAssistant::WAVE: 0078 return ENCODER_WAVE_ICON; 0079 case EncoderAssistant::CUSTOM: 0080 return ENCODER_CUSTOM_ICON; 0081 default: 0082 return ""; 0083 } 0084 0085 return ""; 0086 } 0087 0088 bool EncoderAssistant::available(const EncoderAssistant::Encoder encoder) 0089 { 0090 switch (encoder) { 0091 case EncoderAssistant::LAME: 0092 return (KProcess::execute(ENCODER_LAME_BIN, QStringList() << ENCODER_LAME_VERSION_PARA) == 0); 0093 case EncoderAssistant::OGGENC: 0094 return (KProcess::execute(ENCODER_OGGENC_BIN, QStringList() << ENCODER_OGGENC_VERSION_PARA) == 0); 0095 case EncoderAssistant::OPUSENC: 0096 return (KProcess::execute(ENCODER_OPUSENC_BIN, QStringList() << ENCODER_OPUSENC_VERSION_PARA) == 0); 0097 case EncoderAssistant::FLAC: 0098 return (KProcess::execute(ENCODER_FLAC_BIN, QStringList() << ENCODER_FLAC_VERSION_PARA) == 0); 0099 case EncoderAssistant::FAAC: 0100 return (KProcess::execute(ENCODER_FAAC_BIN, QStringList() << ENCODER_FAAC_VERSION_PARA) == 1); 0101 case EncoderAssistant::WAVE: 0102 return (KProcess::execute(ENCODER_WAVE_BIN, QStringList() << ENCODER_WAVE_VERSION_PARA) == 0); 0103 case EncoderAssistant::CUSTOM: 0104 return true; 0105 default: 0106 return false; 0107 } 0108 0109 return false; 0110 } 0111 0112 bool EncoderAssistant::canEmbedCover(const Encoder encoder, int *maxCoverSize) 0113 { 0114 switch (encoder) { 0115 case EncoderAssistant::LAME: 0116 if (maxCoverSize) 0117 *maxCoverSize = ENCODER_LAME_MAX_EMBED_COVER_SIZE; 0118 return true; 0119 case EncoderAssistant::OPUSENC: 0120 case EncoderAssistant::FLAC: 0121 case EncoderAssistant::FAAC: 0122 return true; 0123 case EncoderAssistant::OGGENC: 0124 case EncoderAssistant::WAVE: 0125 case EncoderAssistant::CUSTOM: 0126 default: 0127 break; 0128 } 0129 0130 if (maxCoverSize) 0131 *maxCoverSize = 0; 0132 0133 return false; 0134 } 0135 0136 const QString EncoderAssistant::version(const EncoderAssistant::Encoder encoder) 0137 { 0138 KProcess process; 0139 process.setOutputChannelMode(KProcess::SeparateChannels); 0140 process.setReadChannel(KProcess::StandardError); 0141 switch (encoder) { 0142 case EncoderAssistant::LAME: 0143 process.setShellCommand(QString(ENCODER_LAME_BIN) + ' ' + QString(ENCODER_LAME_VERSION_PARA)); 0144 break; 0145 case EncoderAssistant::OGGENC: 0146 process.setShellCommand(QString(ENCODER_OGGENC_BIN) + ' ' + QString(ENCODER_OGGENC_VERSION_PARA)); 0147 break; 0148 case EncoderAssistant::OPUSENC: 0149 process.setShellCommand(QString(ENCODER_OPUSENC_BIN) + ' ' + QString(ENCODER_OPUSENC_VERSION_PARA)); 0150 break; 0151 case EncoderAssistant::FLAC: 0152 process.setShellCommand(QString(ENCODER_FLAC_BIN) + ' ' + QString(ENCODER_FLAC_VERSION_PARA)); 0153 break; 0154 case EncoderAssistant::FAAC: 0155 process.setShellCommand(QString(ENCODER_FAAC_BIN) + ' ' + QString(ENCODER_FAAC_VERSION_PARA)); 0156 break; 0157 case EncoderAssistant::WAVE: 0158 return ""; 0159 case EncoderAssistant::CUSTOM: 0160 return ""; 0161 default: 0162 return ""; 0163 } 0164 process.start(); 0165 if (!process.waitForFinished()) 0166 return ""; 0167 QByteArray rawoutput = process.readAllStandardError(); 0168 if (rawoutput.size() == 0) 0169 rawoutput = process.readAllStandardOutput(); 0170 QString output(rawoutput); 0171 QStringList list = output.trimmed().split('\n'); 0172 if (list.count() == 0) 0173 return ""; 0174 QStringList words = list[0].split(' '); 0175 if (words.count() == 0) 0176 return ""; 0177 0178 switch (encoder) { 0179 case EncoderAssistant::LAME: 0180 if ((words.contains("version")) && (words.indexOf("version") + 1 < words.count())) 0181 return words[words.indexOf("version") + 1]; 0182 if (words.count() < 2) 0183 return ""; 0184 return words[words.count() - 2]; 0185 0186 case EncoderAssistant::OPUSENC: 0187 return words[2]; 0188 0189 case EncoderAssistant::OGGENC: 0190 0191 case EncoderAssistant::FLAC: 0192 return words.last(); 0193 0194 case EncoderAssistant::FAAC: 0195 if (list.count() < 2) 0196 return ""; 0197 words = list[1].split(' '); 0198 if (words.count() < 2) 0199 return ""; 0200 if ((words.contains("FAAC")) && (words.indexOf("FAAC") + 1 < words.count())) 0201 return words[words.indexOf("FAAC") + 1]; 0202 return words[1]; 0203 0204 case EncoderAssistant::WAVE: 0205 0206 case EncoderAssistant::CUSTOM: 0207 0208 default:; 0209 } 0210 0211 return ""; 0212 } 0213 0214 long EncoderAssistant::versionNumber(const EncoderAssistant::Encoder encoder) 0215 { 0216 QString v = version(encoder); 0217 long versionNumber = 0; 0218 0219 switch (encoder) { 0220 case EncoderAssistant::LAME: 0221 0222 case EncoderAssistant::OGGENC: 0223 0224 case EncoderAssistant::OPUSENC: 0225 0226 case EncoderAssistant::FLAC: 0227 0228 case EncoderAssistant::FAAC: { 0229 // At present all encoders seem to use 2 or 3 version number items 0230 // separated by . so we use the same code for all 0231 // convert to a number for easy version comparison. 0232 // Each of the 3 version components must be < 255 0233 QStringList version = v.split('.'); 0234 int major = 0; 0235 int minor = 0; 0236 int patch = 0; 0237 0238 if (version.count() > 0) { 0239 major = version[0].toUInt(); 0240 versionNumber = (major & 0xFF) << 16; 0241 } 0242 if (version.count() > 1) { 0243 minor = version[1].toUInt(); 0244 versionNumber = versionNumber | (minor & 0xFF) << 8; 0245 } 0246 if (version.count() > 2) { 0247 patch = version[2].toUInt(); 0248 versionNumber = versionNumber | (patch & 0xFF); 0249 } 0250 } break; 0251 0252 case EncoderAssistant::WAVE: 0253 0254 case EncoderAssistant::CUSTOM: 0255 0256 default:; 0257 } 0258 return versionNumber; 0259 } 0260 0261 const QString EncoderAssistant::scheme(const EncoderAssistant::Encoder encoder, const Parameters ¶meters) 0262 { 0263 switch (encoder) { 0264 case EncoderAssistant::LAME: { 0265 int preset = parameters.value(ENCODER_LAME_PRESET_KEY, ENCODER_LAME_PRESET).toInt(); 0266 bool cbr = parameters.value(ENCODER_LAME_CBR_KEY).toBool(); 0267 int bitrate = parameters.value(ENCODER_LAME_BITRATE_KEY, ENCODER_LAME_BITRATE).toInt(); 0268 bool embed_cover = parameters.value(ENCODER_LAME_EMBED_COVER_KEY).toBool(); 0269 QString cmd = ENCODER_LAME_BIN; 0270 switch (preset) { 0271 case ENCODER_LAME_PRESET_MEDIUM: 0272 cmd += " --preset medium"; 0273 break; 0274 case ENCODER_LAME_PRESET_STANDARD: 0275 cmd += " --preset standard"; 0276 break; 0277 case ENCODER_LAME_PRESET_EXTREME: 0278 cmd += " --preset extreme"; 0279 break; 0280 case ENCODER_LAME_PRESET_INSANE: 0281 cmd += " --preset insane"; 0282 break; 0283 case ENCODER_LAME_PRESET_CUSTOM: 0284 cmd += QString(" --preset") + (cbr ? QString(" cbr") : QString()) + QString(" %1").arg(bitrate); 0285 break; 0286 default: 0287 cmd += " --preset standard"; 0288 } 0289 QString v = EncoderAssistant::version(EncoderAssistant::LAME); 0290 if ((v.startsWith(QLatin1String("3.95"))) || (v.startsWith(QLatin1String("3.96"))) || (v.startsWith(QLatin1String("3.97")))) 0291 cmd += QString(" --vbr-new"); 0292 0293 if (embed_cover) 0294 cmd += QString::fromUtf8(" --ti \"${" VAR_COVER_FILE "}\""); 0295 0296 cmd += QString::fromUtf8(" --add-id3v2 --id3v2-only --ignore-tag-errors --tt \"$" VAR_TRACK_TITLE "\" --ta \"$" VAR_TRACK_ARTIST 0297 "\" --tl \"$" VAR_ALBUM_TITLE "\" --ty \"$" VAR_DATE "\" --tn \"$" VAR_TRACK_NO "/$" VAR_NO_OF_TRACKS "\" --tc \"$" VAR_AUDEX 0298 " / Encoder $" VAR_ENCODER 0299 "\" " 0300 "--tg \"$" VAR_GENRE "\" --tv TPOS=$" VAR_CD_NO " $" VAR_INPUT_FILE " \"$" VAR_OUTPUT_FILE "\""); 0301 0302 return cmd; 0303 } 0304 0305 case EncoderAssistant::OGGENC: { 0306 qreal quality = parameters.value(ENCODER_OGGENC_QUALITY_KEY, ENCODER_OGGENC_QUALITY).toReal(); 0307 bool min_bitrate = parameters.value(ENCODER_OGGENC_MINBITRATE_KEY).toBool(); 0308 int min_bitrate_value = parameters.value(ENCODER_OGGENC_MINBITRATE_VALUE_KEY, ENCODER_OGGENC_MINBITRATE_VALUE).toInt(); 0309 bool max_bitrate = parameters.value(ENCODER_OGGENC_MAXBITRATE_KEY).toBool(); 0310 int max_bitrate_value = parameters.value(ENCODER_OGGENC_MAXBITRATE_VALUE_KEY, ENCODER_OGGENC_MAXBITRATE_VALUE).toInt(); 0311 QString cmd = ENCODER_OGGENC_BIN; 0312 cmd += QString(" -q %1").arg(quality, 0, 'f', 2); 0313 0314 if (min_bitrate) 0315 cmd += QString(" -m %1").arg(min_bitrate_value); 0316 0317 if (max_bitrate) 0318 cmd += QString(" -M %1").arg(max_bitrate_value); 0319 0320 cmd += QString::fromUtf8(" -c \"Artist=$" VAR_TRACK_ARTIST "\" -c \"Title=$" VAR_TRACK_TITLE "\" -c \"Album=$" VAR_ALBUM_TITLE "\" -c \"Date=$" VAR_DATE 0321 "\" -c \"Tracknumber=$" VAR_TRACK_NO "\" -c \"Genre=$" VAR_GENRE "\" -c Discnumber=$" VAR_CD_NO " -o \"$" VAR_OUTPUT_FILE 0322 "\" $" VAR_INPUT_FILE); 0323 0324 return cmd; 0325 } 0326 0327 case EncoderAssistant::OPUSENC: { 0328 qreal bitrate = parameters.value(ENCODER_OPUSENC_BITRATE_KEY, ENCODER_OPUSENC_BITRATE).toReal(); 0329 bool embed_cover = parameters.value(ENCODER_OPUSENC_EMBED_COVER_KEY).toBool(); 0330 QString cmd = ENCODER_OPUSENC_BIN; 0331 cmd += QString(" --bitrate %1").arg(bitrate, 0, 'f', 2); 0332 0333 if (embed_cover) 0334 cmd += QString::fromUtf8(" --picture \"3||||${" VAR_COVER_FILE "}\""); 0335 0336 cmd += QString::fromUtf8(" --artist \"$" VAR_TRACK_ARTIST "\" --title \"$" VAR_TRACK_TITLE "\" --album \"$" VAR_ALBUM_TITLE "\" --date \"$" VAR_DATE 0337 "\" --tracknumber \"$" VAR_TRACK_NO "\" --genre \"$" VAR_GENRE 0338 "\"" 0339 " $" VAR_INPUT_FILE " \"$" VAR_OUTPUT_FILE "\""); 0340 0341 return cmd; 0342 } 0343 0344 case EncoderAssistant::FLAC: { 0345 int compression = parameters.value(ENCODER_FLAC_COMPRESSION_KEY, ENCODER_FLAC_COMPRESSION).toInt(); 0346 bool embed_cover = parameters.value(ENCODER_FLAC_EMBED_COVER_KEY).toBool(); 0347 QString cmd = ENCODER_FLAC_BIN; 0348 0349 if (embed_cover) { 0350 long versionNumber = EncoderAssistant::versionNumber(EncoderAssistant::FLAC); 0351 if (versionNumber >= makeVersionNumber(1, 1, 3)) 0352 cmd += QString::fromUtf8(" --picture=\"\\|\\|\\|\\|$" VAR_COVER_FILE "\""); 0353 } 0354 0355 cmd += QString(" -%1").arg(compression); 0356 cmd += QString::fromUtf8(" -T Artist=\"$" VAR_TRACK_ARTIST "\" -T Title=\"$" VAR_TRACK_TITLE "\" -T Album=\"$" VAR_ALBUM_TITLE "\" -T Date=\"$" VAR_DATE 0357 "\" -T Tracknumber=\"$" VAR_TRACK_NO "\" -T Genre=\"$" VAR_GENRE "\" -o \"$" VAR_OUTPUT_FILE "\" $" VAR_INPUT_FILE); 0358 return cmd; 0359 } 0360 0361 case EncoderAssistant::FAAC: { 0362 int quality = parameters.value(ENCODER_FAAC_QUALITY_KEY, ENCODER_FAAC_QUALITY).toInt(); 0363 bool embed_cover = parameters.value(ENCODER_FAAC_EMBED_COVER_KEY).toBool(); 0364 QString cmd = ENCODER_FAAC_BIN; 0365 cmd += QString(" -q %1").arg(quality); 0366 0367 if (embed_cover) 0368 cmd += QString::fromUtf8(" --cover-art \"${" VAR_COVER_FILE "}\""); 0369 0370 cmd += QString::fromUtf8(" --title \"$" VAR_TRACK_TITLE "\" --artist \"$" VAR_TRACK_ARTIST "\" --album \"$" VAR_ALBUM_TITLE "\" --year \"$" VAR_DATE 0371 "\" --track $" VAR_TRACK_NO " --disc $" VAR_CD_NO " --genre \"$" VAR_GENRE "\" -o \"$" VAR_OUTPUT_FILE "\" $" VAR_INPUT_FILE); 0372 0373 return cmd; 0374 } 0375 0376 case EncoderAssistant::WAVE: { 0377 return QString(ENCODER_WAVE_BIN) + " $" VAR_INPUT_FILE " \"$" VAR_OUTPUT_FILE "\""; 0378 } 0379 0380 case EncoderAssistant::CUSTOM: { 0381 return parameters.value(ENCODER_CUSTOM_COMMAND_SCHEME_KEY, ENCODER_CUSTOM_COMMAND_SCHEME).toString(); 0382 } 0383 0384 default:; 0385 } 0386 0387 return ""; 0388 } 0389 0390 Parameters EncoderAssistant::stdParameters(const Encoder encoder) 0391 { 0392 Parameters parameters; 0393 0394 switch (encoder) { 0395 case EncoderAssistant::LAME: 0396 0397 parameters.setValue(ENCODER_LAME_PRESET_KEY, ENCODER_LAME_PRESET); 0398 parameters.setValue(ENCODER_LAME_BITRATE_KEY, ENCODER_LAME_BITRATE); 0399 parameters.setValue(ENCODER_LAME_EMBED_COVER_KEY, ENCODER_LAME_EMBED_COVER); 0400 0401 break; 0402 0403 case EncoderAssistant::OGGENC: 0404 0405 parameters.setValue(ENCODER_OGGENC_QUALITY_KEY, ENCODER_OGGENC_QUALITY); 0406 parameters.setValue(ENCODER_OGGENC_MINBITRATE_KEY, ENCODER_OGGENC_MINBITRATE); 0407 parameters.setValue(ENCODER_OGGENC_MINBITRATE_VALUE_KEY, ENCODER_OGGENC_MINBITRATE_VALUE); 0408 parameters.setValue(ENCODER_OGGENC_MAXBITRATE_KEY, ENCODER_OGGENC_MAXBITRATE); 0409 parameters.setValue(ENCODER_OGGENC_MAXBITRATE_VALUE_KEY, ENCODER_OGGENC_MAXBITRATE_VALUE); 0410 0411 break; 0412 0413 case EncoderAssistant::OPUSENC: 0414 0415 parameters.setValue(ENCODER_OPUSENC_BITRATE_KEY, ENCODER_OPUSENC_BITRATE); 0416 parameters.setValue(ENCODER_OPUSENC_EMBED_COVER_KEY, ENCODER_OPUSENC_EMBED_COVER); 0417 break; 0418 0419 case EncoderAssistant::FLAC: 0420 0421 parameters.setValue(ENCODER_FLAC_COMPRESSION_KEY, ENCODER_FLAC_COMPRESSION); 0422 parameters.setValue(ENCODER_FLAC_EMBED_COVER_KEY, ENCODER_FLAC_EMBED_COVER); 0423 0424 break; 0425 0426 case EncoderAssistant::FAAC: 0427 0428 parameters.setValue(ENCODER_FAAC_QUALITY_KEY, ENCODER_FAAC_QUALITY); 0429 parameters.setValue(ENCODER_FAAC_EMBED_COVER_KEY, ENCODER_FAAC_EMBED_COVER); 0430 break; 0431 0432 case EncoderAssistant::WAVE: 0433 0434 case EncoderAssistant::CUSTOM: 0435 0436 default:; 0437 } 0438 0439 return parameters; 0440 } 0441 0442 const QMap<int, QString> EncoderAssistant::encoderList() 0443 { 0444 QMap<int, QString> encoders; 0445 0446 encoders[(int)EncoderAssistant::LAME] = ENCODER_LAME_NAME; 0447 encoders[(int)EncoderAssistant::OGGENC] = ENCODER_OGGENC_NAME; 0448 encoders[(int)EncoderAssistant::FLAC] = ENCODER_FLAC_NAME; 0449 encoders[(int)EncoderAssistant::FAAC] = ENCODER_FAAC_NAME; 0450 encoders[(int)EncoderAssistant::WAVE] = ENCODER_WAVE_NAME; 0451 encoders[(int)EncoderAssistant::CUSTOM] = ENCODER_CUSTOM_NAME; 0452 encoders[(int)EncoderAssistant::OPUSENC] = ENCODER_OGGENC_NAME; 0453 0454 return encoders; 0455 } 0456 0457 const QMap<int, QString> EncoderAssistant::availableEncoderNameList() 0458 { 0459 QMap<int, QString> encoders; 0460 0461 if (EncoderAssistant::available(EncoderAssistant::LAME)) 0462 encoders[(int)EncoderAssistant::LAME] = ENCODER_LAME_NAME; 0463 if (EncoderAssistant::available(EncoderAssistant::OGGENC)) 0464 encoders[(int)EncoderAssistant::OGGENC] = ENCODER_OGGENC_NAME; 0465 if (EncoderAssistant::available(EncoderAssistant::OPUSENC)) 0466 encoders[(int)EncoderAssistant::OPUSENC] = ENCODER_OPUSENC_NAME; 0467 if (EncoderAssistant::available(EncoderAssistant::FLAC)) 0468 encoders[(int)EncoderAssistant::FLAC] = ENCODER_FLAC_NAME; 0469 if (EncoderAssistant::available(EncoderAssistant::FAAC)) 0470 encoders[(int)EncoderAssistant::FAAC] = ENCODER_FAAC_NAME; 0471 if (EncoderAssistant::available(EncoderAssistant::WAVE)) 0472 encoders[(int)EncoderAssistant::WAVE] = ENCODER_WAVE_NAME; 0473 if (EncoderAssistant::available(EncoderAssistant::CUSTOM)) 0474 encoders[(int)EncoderAssistant::CUSTOM] = ENCODER_CUSTOM_NAME; 0475 0476 return encoders; 0477 } 0478 0479 const QMap<int, QString> EncoderAssistant::availableEncoderNameListWithVersions() 0480 { 0481 QMap<int, QString> encoders; 0482 0483 if (EncoderAssistant::available(EncoderAssistant::LAME)) 0484 encoders[(int)EncoderAssistant::LAME] = ENCODER_LAME_NAME + ' ' + version(LAME); 0485 if (EncoderAssistant::available(EncoderAssistant::OGGENC)) 0486 encoders[(int)EncoderAssistant::OGGENC] = ENCODER_OGGENC_NAME + ' ' + version(OGGENC); 0487 if (EncoderAssistant::available(EncoderAssistant::OPUSENC)) 0488 encoders[(int)EncoderAssistant::OPUSENC] = ENCODER_OPUSENC_NAME + ' ' + version(OPUSENC); 0489 if (EncoderAssistant::available(EncoderAssistant::FLAC)) 0490 encoders[(int)EncoderAssistant::FLAC] = ENCODER_FLAC_NAME + ' ' + version(FLAC); 0491 if (EncoderAssistant::available(EncoderAssistant::FAAC)) 0492 encoders[(int)EncoderAssistant::FAAC] = ENCODER_FAAC_NAME + ' ' + version(FAAC); 0493 if (EncoderAssistant::available(EncoderAssistant::WAVE)) 0494 encoders[(int)EncoderAssistant::WAVE] = ENCODER_WAVE_NAME + ' ' + version(WAVE); 0495 if (EncoderAssistant::available(EncoderAssistant::CUSTOM)) 0496 encoders[(int)EncoderAssistant::CUSTOM] = ENCODER_CUSTOM_NAME + ' ' + version(CUSTOM); 0497 0498 return encoders; 0499 }