1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2020 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
22 #include "source_abstract.h"
26 #include "model_sysinfo.h"
27 #include "model_options.h"
28 #include "model_preferences.h"
31 #include <MUtils/Global.h>
32 #include <MUtils/OSSupport.h>
33 #include <MUtils/Exception.h>
41 // ------------------------------------------------------------
42 // Constructor & Destructor
43 // ------------------------------------------------------------
45 AbstractSource::AbstractSource(JobObject
*jobObject
, const OptionsModel
*options
, const SysinfoModel
*const sysinfo
, const PreferencesModel
*const preferences
, JobStatus
&jobStatus
, volatile bool *abort
, volatile bool *pause
, QSemaphore
*semaphorePause
, const QString
&sourceFile
)
47 AbstractTool(jobObject
, options
, sysinfo
, preferences
, jobStatus
, abort
, pause
, semaphorePause
),
48 m_sourceFile(sourceFile
)
50 /*Nothing to do here*/
53 AbstractSource::~AbstractSource(void)
55 /*Nothing to do here*/
58 // ------------------------------------------------------------
59 // Check Source Properties
60 // ------------------------------------------------------------
62 bool AbstractSource::checkSourceProperties(ClipInfo
&clipInfo
)
65 QList
<QRegExp
*> patterns
;
68 checkSourceProperties_init(patterns
, cmdLine
);
70 log("Creating process:");
71 if(!startProcess(process
, getBinaryPath(), cmdLine
, true, &getExtraPaths(), &getExtraEnv()))
76 QTextCodec
*localCodec
= QTextCodec::codecForName("System");
78 bool bTimeout
= false;
79 bool bAborted
= false;
83 unsigned int waitCounter
= 0;
85 while(process
.state() != QProcess::NotRunning
)
93 if(!process
.waitForReadyRead(m_processTimeoutInterval
))
95 if(process
.state() == QProcess::Running
)
97 if(++waitCounter
> m_processTimeoutMaxCounter
)
99 if(m_preferences
->getAbortOnTimeout())
102 qWarning("Source process timed out <-- killing!");
103 log("\nPROCESS TIMEOUT !!!");
104 log("\nInput process has encountered a deadlock or your script takes EXTREMELY long to initialize!");
109 else if(waitCounter
== m_processTimeoutWarning
)
111 unsigned int timeOut
= (waitCounter
* m_processTimeoutInterval
) / 1000U;
112 log(tr("Warning: Input process did not respond for %1 seconds, potential deadlock...").arg(QString::number(timeOut
)));
119 PROCESS_PENDING_LINES(process
, checkSourceProperties_parseLine
, patterns
, clipInfo
);
122 if(!(bTimeout
|| bAborted
))
124 PROCESS_PENDING_LINES(process
, checkSourceProperties_parseLine
, patterns
, clipInfo
);
127 process
.waitForFinished();
128 if(process
.state() != QProcess::NotRunning
)
131 process
.waitForFinished(-1);
134 while(!patterns
.isEmpty())
136 QRegExp
*pattern
= patterns
.takeFirst();
137 MUTILS_DELETE(pattern
);
140 if(bTimeout
|| bAborted
|| process
.exitCode() != EXIT_SUCCESS
)
142 if(!(bTimeout
|| bAborted
))
144 const int exitCode
= process
.exitCode();
145 log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(exitCode
)));
146 if((exitCode
< 0) || (exitCode
>= 32))
148 log(tr("\nIMPORTANT: The input process terminated abnormally. This means Avisynth/VapourSynth or one of its plugins crashed!"));
154 if(clipInfo
.getFrameCount() < 1)
156 log(tr("\nFAILED TO DETERMINE CLIP PROPERTIES !!!"));
162 const QPair
<quint32
, quint32
> frameSize
= clipInfo
.getFrameSize();
163 if((frameSize
.first
> 0) && (frameSize
.second
> 0))
165 log(tr("Resolution: %1 x %2").arg(QString::number(frameSize
.first
), QString::number(frameSize
.second
)));
168 const QPair
<quint32
, quint32
> frameRate
= clipInfo
.getFrameRate();
169 if((frameRate
.first
> 0) && (frameRate
.second
> 0))
171 log(tr("Frame Rate: %1/%2").arg(QString::number(frameRate
.first
), QString::number(frameRate
.second
)));
173 else if(frameRate
.first
> 0)
175 log(tr("Frame Rate: %1").arg(QString::number(frameRate
.first
)));
178 log(tr("No. Frames: %1").arg(QString::number(clipInfo
.getFrameCount())));
182 // ------------------------------------------------------------
184 // ------------------------------------------------------------
186 bool AbstractSource::createProcess(QProcess
&processEncode
, QProcess
&processInput
)
188 processInput
.setStandardOutputProcess(&processEncode
);
190 QStringList cmdLine_Input
;
191 buildCommandLine(cmdLine_Input
);
193 log("Creating input process:");
194 if(!startProcess(processInput
, getBinaryPath(), cmdLine_Input
, false, &getExtraPaths(), &getExtraEnv()))
202 // ------------------------------------------------------------
204 // ------------------------------------------------------------
206 const AbstractSourceInfo
& AbstractSource::getSourceInfo(void)
208 MUTILS_THROW("[getSourceInfo] This function must be overwritten in sub-classes!");
211 // ------------------------------------------------------------
212 // Auxiliary FUnctions
213 // ------------------------------------------------------------
215 QHash
<QString
, QString
> AbstractSource::getExtraEnv(void) const
217 QHash
<QString
, QString
> extraEnv
;
219 const QString profilePath
= MUtils::OS::known_folder(MUtils::OS::FOLDER_PROFILE_USER
);
220 if (!profilePath
.isEmpty())
222 extraEnv
.insert("USERPROFILE", QDir::toNativeSeparators(profilePath
));
225 const QString appDataPath
= MUtils::OS::known_folder(MUtils::OS::FOLDER_APPDATA_ROAM
);
226 if (!appDataPath
.isEmpty())
228 extraEnv
.insert("APPDATA", QDir::toNativeSeparators(appDataPath
));