File indexing completed on 2024-04-21 04:48:15

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 &parameters)
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 }