File indexing completed on 2024-04-28 12:37:48
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 "encoderwrapper.h" 0009 0010 #include <QDebug> 0011 0012 EncoderWrapper::EncoderWrapper(QObject *parent, const QString &commandScheme, const QString &encoderName, const bool deleteFractionFiles) 0013 : QObject(parent) 0014 { 0015 command_scheme = commandScheme; 0016 encoder_name = encoderName; 0017 delete_fraction_files = deleteFractionFiles; 0018 0019 connect(&proc, SIGNAL(readyReadStandardError()), this, SLOT(parseOutput())); 0020 connect(&proc, SIGNAL(readyReadStandardOutput()), this, SLOT(parseOutput())); 0021 connect(&proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus))); 0022 connect(&proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError))); 0023 0024 proc.setOutputChannelMode(KProcess::SeparateChannels); 0025 proc.setReadChannel(KProcess::StandardError); 0026 0027 termination = false; 0028 processing = 0; 0029 0030 not_found_counter = 0; 0031 } 0032 0033 EncoderWrapper::~EncoderWrapper() 0034 { 0035 } 0036 0037 bool EncoderWrapper::encode(int n, 0038 int cdno, 0039 int trackoffset, 0040 int nooftracks, 0041 const QString &artist, 0042 const QString &album, 0043 const QString &tartist, 0044 const QString &ttitle, 0045 const QString &genre, 0046 const QString &date, 0047 const QString &suffix, 0048 const QString &isrc, 0049 const QImage &cover, 0050 const QString &tmppath, 0051 const QString &input, 0052 const QString &output) 0053 { 0054 if (!processing) 0055 processing = 1; 0056 else 0057 return false; 0058 termination = false; 0059 0060 if (command_scheme.isEmpty()) { 0061 Q_EMIT error(i18n("Command scheme is empty.")); 0062 return false; 0063 } 0064 0065 SchemeParser schemeparser; 0066 QString command = schemeparser.parsePerTrackCommandScheme(command_scheme, 0067 input, 0068 output, 0069 n, 0070 cdno, 0071 trackoffset, 0072 nooftracks, 0073 artist, 0074 album, 0075 tartist, 0076 ttitle, 0077 date, 0078 genre, 0079 isrc, 0080 suffix, 0081 cover, 0082 tmppath, 0083 encoder_name); 0084 0085 qDebug() << "executing command " << command; 0086 proc.setShellCommand(command); 0087 proc.start(); 0088 proc.waitForStarted(); 0089 0090 processing_filename = output; 0091 0092 Q_EMIT info(i18n("Encoding track %1...", n)); 0093 0094 return true; 0095 } 0096 0097 void EncoderWrapper::cancel() 0098 { 0099 if (!processing) 0100 return; 0101 0102 // we need to suppress normal error messages, because with a cancel the user known what he does 0103 termination = true; 0104 proc.terminate(); 0105 0106 if (delete_fraction_files) { 0107 QFile file(processing_filename); 0108 if (file.exists()) { 0109 file.remove(); 0110 Q_EMIT warning(i18n("Deleted partial file \"%1\".", processing_filename.mid(processing_filename.lastIndexOf("/") + 1))); 0111 qDebug() << "deleted partial file" << processing_filename; 0112 } 0113 } 0114 0115 Q_EMIT error(i18n("User canceled encoding.")); 0116 qDebug() << "Interrupt encoding."; 0117 } 0118 0119 bool EncoderWrapper::isProcessing() 0120 { 0121 return (processing > 0); 0122 } 0123 0124 const QStringList &EncoderWrapper::log() 0125 { 0126 return p_log; 0127 } 0128 0129 void EncoderWrapper::parseOutput() 0130 { 0131 QByteArray rawoutput = proc.readAllStandardError(); 0132 if (rawoutput.size() == 0) 0133 rawoutput = proc.readAllStandardOutput(); 0134 bool found = false; 0135 if (rawoutput.size() > 0) { 0136 QString output(rawoutput); 0137 QStringList list = output.trimmed().split('\n'); 0138 p_log << list; 0139 for (int i = 0; i < list.count(); ++i) { 0140 if (list.at(i).contains('%')) { 0141 QString line = list.at(i); 0142 static const QRegularExpression regex("\\d+[,.]?\\d*\\%"); 0143 int startPos = line.indexOf(regex); 0144 if (startPos == -1) 0145 continue; 0146 QString p = line.mid(startPos); 0147 p = p.left(p.indexOf('%')); 0148 bool conversionSuccessful = false; 0149 double percent = p.toDouble(&conversionSuccessful); 0150 if ((conversionSuccessful) && (percent >= 0) && (percent <= 100)) { 0151 Q_EMIT progress((int)percent); 0152 found = true; 0153 not_found_counter = 0; 0154 } 0155 } 0156 } 0157 } 0158 if (!found) { 0159 if (not_found_counter > 5) 0160 Q_EMIT progress(-1); 0161 else 0162 ++not_found_counter; 0163 } 0164 } 0165 0166 void EncoderWrapper::processFinished(int exitCode, QProcess::ExitStatus exitStatus) 0167 { 0168 processing = 0; 0169 if (termination) { 0170 Q_EMIT finished(); 0171 return; 0172 } 0173 if ((exitStatus == QProcess::NormalExit) && (exitCode == 0)) { 0174 Q_EMIT info(i18n("Encoding OK (\"%1\").", processing_filename)); 0175 } else { 0176 Q_EMIT error(i18n("An error occurred while encoding file \"%1\".", processing_filename), i18n("Please check your profile.")); 0177 } 0178 Q_EMIT finished(); 0179 qDebug() << "encoding finished."; 0180 } 0181 0182 void EncoderWrapper::processError(QProcess::ProcessError err) 0183 { 0184 if (termination) 0185 return; 0186 switch (err) { 0187 case QProcess::FailedToStart: 0188 Q_EMIT error(i18n("%1 failed to start.", encoder), i18n("Either it is missing, or you may have insufficient permissions to invoke the program.")); 0189 break; 0190 case QProcess::Crashed: 0191 Q_EMIT error(i18n("%1 crashed some time after starting successfully.", encoder), i18n("Please check your profile.")); 0192 break; 0193 case QProcess::Timedout: 0194 Q_EMIT error(i18n("%1 timed out. This should not happen.", encoder), i18n("Please check your profile.")); 0195 break; 0196 case QProcess::WriteError: 0197 Q_EMIT error(i18n("An error occurred when attempting to write to %1.", encoder), 0198 i18n("For example, the process may not be running, or it may have closed its input channel.")); 0199 break; 0200 case QProcess::ReadError: 0201 Q_EMIT error(i18n("An error occurred when attempting to read from %1.", encoder), i18n("For example, the process may not be running.")); 0202 break; 0203 case QProcess::UnknownError: 0204 Q_EMIT error(i18n("An unknown error occurred to %1. This should not happen.", encoder), i18n("Please check your profile.")); 0205 break; 0206 } 0207 Q_EMIT finished(); 0208 qDebug() << "encoding finished."; 0209 }