OSDN Git Service

Build fix for latest changes in MUtilities library.
[x264-launcher/x264-launcher.git] / src / source_abstract.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
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.
9 //
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.
14 //
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.
18 //
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "source_abstract.h"
23
24 //Internal
25 #include "global.h"
26 #include "model_sysinfo.h"
27 #include "model_options.h"
28 #include "model_preferences.h"
29
30 //MUtils
31 #include <MUtils/Global.h>
32 #include <MUtils/OSSupport.h>
33 #include <MUtils/Exception.h>
34
35 //Qt
36 #include <QProcess>
37 #include <QTextCodec>
38 #include <QDir>
39 #include <QPair>
40
41 // ------------------------------------------------------------
42 // Constructor & Destructor
43 // ------------------------------------------------------------
44
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)
46 :
47         AbstractTool(jobObject, options, sysinfo, preferences, jobStatus, abort, pause, semaphorePause),
48         m_sourceFile(sourceFile)
49 {
50         /*Nothing to do here*/
51 }
52
53 AbstractSource::~AbstractSource(void)
54 {
55         /*Nothing to do here*/
56 }
57
58 // ------------------------------------------------------------
59 // Check Source Properties
60 // ------------------------------------------------------------
61
62 bool AbstractSource::checkSourceProperties(ClipInfo &clipInfo)
63 {
64         QStringList cmdLine;
65         QList<QRegExp*> patterns;
66         QProcess process;
67
68         checkSourceProperties_init(patterns, cmdLine);
69
70         log("Creating process:");
71         if(!startProcess(process, getBinaryPath(), cmdLine, true, &getExtraPaths(), &getExtraEnv()))
72         {
73                 return false;;
74         }
75         
76         QTextCodec *localCodec = QTextCodec::codecForName("System");
77
78         bool bTimeout = false;
79         bool bAborted = false;
80         
81         clipInfo.reset();
82                 
83         unsigned int waitCounter = 0;
84
85         while(process.state() != QProcess::NotRunning)
86         {
87                 if(*m_abort)
88                 {
89                         process.kill();
90                         bAborted = true;
91                         break;
92                 }
93                 if(!process.waitForReadyRead(m_processTimeoutInterval))
94                 {
95                         if(process.state() == QProcess::Running)
96                         {
97                                 if(++waitCounter > m_processTimeoutMaxCounter)
98                                 {
99                                         if(m_preferences->getAbortOnTimeout())
100                                         {
101                                                 process.kill();
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!");
105                                                 bTimeout = true;
106                                                 break;
107                                         }
108                                 }
109                                 else if(waitCounter == m_processTimeoutWarning)
110                                 {
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)));
113                                 }
114                         }
115                         continue;
116                 }
117                 
118                 waitCounter = 0;
119                 PROCESS_PENDING_LINES(process, checkSourceProperties_parseLine, patterns, clipInfo);
120         }
121
122         if(!(bTimeout || bAborted))
123         {
124                 PROCESS_PENDING_LINES(process, checkSourceProperties_parseLine, patterns, clipInfo);
125         }
126
127         process.waitForFinished();
128         if(process.state() != QProcess::NotRunning)
129         {
130                 process.kill();
131                 process.waitForFinished(-1);
132         }
133
134         while(!patterns.isEmpty())
135         {
136                 QRegExp *pattern = patterns.takeFirst();
137                 MUTILS_DELETE(pattern);
138         }
139
140         if(bTimeout || bAborted || process.exitCode() != EXIT_SUCCESS)
141         {
142                 if(!(bTimeout || bAborted))
143                 {
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))
147                         {
148                                 log(tr("\nIMPORTANT: The Avs2YUV process terminated abnormally. This means Avisynth or one of your Avisynth-Plugin's just crashed."));
149                                 log(tr("IMPORTANT: Please fix your Avisynth script and try again! If you use Avisynth-MT, try using a *stable* Avisynth instead!"));
150                         }
151                 }
152                 return false;
153         }
154
155         if(clipInfo.getFrameCount() < 1)
156         {
157                 log(tr("\nFAILED TO DETERMINE CLIP PROPERTIES !!!"));
158                 return false;
159         }
160         
161         log("");
162
163         const QPair<quint32, quint32> frameSize = clipInfo.getFrameSize();
164         if((frameSize.first > 0) && (frameSize.second > 0))
165         {
166                 log(tr("Resolution: %1 x %2").arg(QString::number(frameSize.first), QString::number(frameSize.second)));
167         }
168
169         const QPair<quint32, quint32> frameRate = clipInfo.getFrameRate();
170         if((frameRate.first > 0) && (frameRate.second > 0))
171         {
172                 log(tr("Frame Rate: %1/%2").arg(QString::number(frameRate.first), QString::number(frameRate.second)));
173         }
174         else if(frameRate.first > 0)
175         {
176                 log(tr("Frame Rate: %1").arg(QString::number(frameRate.first)));
177         }
178
179         log(tr("No. Frames: %1").arg(QString::number(clipInfo.getFrameCount())));
180         return true;
181 }
182
183 // ------------------------------------------------------------
184 // Source Processing
185 // ------------------------------------------------------------
186
187 bool AbstractSource::createProcess(QProcess &processEncode, QProcess&processInput)
188 {
189         processInput.setStandardOutputProcess(&processEncode);
190         
191         QStringList cmdLine_Input;
192         buildCommandLine(cmdLine_Input);
193
194         log("Creating input process:");
195         if(!startProcess(processInput, getBinaryPath(), cmdLine_Input, false, &getExtraPaths(), &getExtraEnv()))
196         {
197                 return false;
198         }
199
200         return true;
201 }
202
203 // ------------------------------------------------------------
204 // Source Info
205 // ------------------------------------------------------------
206
207 const AbstractSourceInfo& AbstractSource::getSourceInfo(void)
208 {
209         MUTILS_THROW("[getSourceInfo] This function must be overwritten in sub-classes!");
210 }
211
212 // ------------------------------------------------------------
213 // Auxiliary FUnctions
214 // ------------------------------------------------------------
215
216 QHash<QString, QString> AbstractSource::getExtraEnv(void) const
217 {
218         QHash<QString, QString> extraEnv;
219
220         const QString profilePath = MUtils::OS::known_folder(MUtils::OS::FOLDER_PROFILE_USER);
221         if (!profilePath.isEmpty())
222         {
223                 extraEnv.insert("USERPROFILE", QDir::toNativeSeparators(profilePath));
224         }
225
226         const QString appDataPath = MUtils::OS::known_folder(MUtils::OS::FOLDER_APPDATA_ROAM);
227         if (!appDataPath.isEmpty())
228         {
229                 extraEnv.insert("APPDATA", QDir::toNativeSeparators(appDataPath));
230         }
231
232         return extraEnv;
233 }