3 #include "apitracecall.h"
8 #include <qjson/parser.h>
10 Retracer::Retracer(QObject *parent)
12 m_benchmarking(false),
13 m_doubleBuffered(true),
14 m_captureState(false),
18 QString format = QLatin1String("%1;");
20 QString format = QLatin1String("%1:");
22 QString buildPath = format.arg(APITRACE_BINARY_DIR);
23 m_processEnvironment = QProcessEnvironment::systemEnvironment();
24 m_processEnvironment.insert("PATH", buildPath +
25 m_processEnvironment.value("PATH"));
28 m_processEnvironment.value("PATH").toLatin1());
31 QString Retracer::fileName() const
36 void Retracer::setFileName(const QString &name)
41 void Retracer::setAPI(trace::API api)
46 bool Retracer::isBenchmarking() const
48 return m_benchmarking;
51 void Retracer::setBenchmarking(bool bench)
53 m_benchmarking = bench;
56 bool Retracer::isDoubleBuffered() const
58 return m_doubleBuffered;
61 void Retracer::setDoubleBuffered(bool db)
63 m_doubleBuffered = db;
66 void Retracer::setCaptureAtCallNumber(qlonglong num)
71 qlonglong Retracer::captureAtCallNumber() const
76 bool Retracer::captureState() const
78 return m_captureState;
81 void Retracer::setCaptureState(bool enable)
83 m_captureState = enable;
89 RetraceProcess *retrace = new RetraceProcess();
90 retrace->process()->setProcessEnvironment(m_processEnvironment);
92 retrace->setFileName(m_fileName);
93 retrace->setAPI(m_api);
94 retrace->setBenchmarking(m_benchmarking);
95 retrace->setDoubleBuffered(m_doubleBuffered);
96 retrace->setCaptureState(m_captureState);
97 retrace->setCaptureAtCallNumber(m_captureCall);
99 connect(retrace, SIGNAL(finished(const QString&)),
100 this, SLOT(cleanup()));
101 connect(retrace, SIGNAL(error(const QString&)),
102 this, SLOT(cleanup()));
103 connect(retrace, SIGNAL(finished(const QString&)),
104 this, SIGNAL(finished(const QString&)));
105 connect(retrace, SIGNAL(error(const QString&)),
106 this, SIGNAL(error(const QString&)));
107 connect(retrace, SIGNAL(foundState(ApiTraceState*)),
108 this, SIGNAL(foundState(ApiTraceState*)));
109 connect(retrace, SIGNAL(retraceErrors(const QList<ApiTraceError>&)),
110 this, SIGNAL(retraceErrors(const QList<ApiTraceError>&)));
116 /* means we need to kill the process */
117 if (retrace->process()->state() != QProcess::NotRunning) {
118 retrace->terminate();
125 void RetraceProcess::start()
128 QStringList arguments;
130 if (m_api == trace::API_GL) {
131 prog = QLatin1String("glretrace");
132 } else if (m_api == trace::API_EGL) {
133 prog = QLatin1String("eglretrace");
139 if (m_doubleBuffered) {
140 arguments << QLatin1String("-db");
142 arguments << QLatin1String("-sb");
145 if (m_captureState) {
146 arguments << QLatin1String("-D");
147 arguments << QString::number(m_captureCall);
149 if (m_benchmarking) {
150 arguments << QLatin1String("-b");
154 arguments << m_fileName;
156 m_process->start(prog, arguments);
160 void RetraceProcess::replayFinished(int exitCode, QProcess::ExitStatus exitStatus)
162 QByteArray output = m_process->readAllStandardOutput();
164 QString errStr = m_process->readAllStandardError();
167 qDebug()<<"Process finished = ";
168 qDebug()<<"\terr = "<<errStr;
169 qDebug()<<"\tout = "<<output;
172 if (exitStatus != QProcess::NormalExit) {
173 msg = QLatin1String("Process crashed");
174 } else if (exitCode != 0) {
175 msg = QLatin1String("Process exited with non zero exit code");
177 if (m_captureState) {
179 QVariantMap parsedJson = m_jsonParser->parse(output, &ok).toMap();
180 ApiTraceState *state = new ApiTraceState(parsedJson);
181 emit foundState(state);
182 msg = tr("State fetched.");
184 msg = QString::fromUtf8(output);
188 QStringList errorLines = errStr.split('\n');
189 QList<ApiTraceError> errors;
190 QRegExp regexp("(^\\d+): +(\\b\\w+\\b): (.+$)");
191 foreach(QString line, errorLines) {
192 if (regexp.indexIn(line) != -1) {
194 error.callIndex = regexp.cap(1).toInt();
195 error.type = regexp.cap(2);
196 error.message = regexp.cap(3);
197 errors.append(error);
200 if (!errors.isEmpty()) {
201 emit retraceErrors(errors);
206 void RetraceProcess::replayError(QProcess::ProcessError err)
209 * XXX: this function is likely unnecessary and should be eliminated given
210 * that replayFinished is always called, even on errors.
214 qDebug()<<"Process error = "<<err;
215 qDebug()<<"\terr = "<<m_process->readAllStandardError();
216 qDebug()<<"\tout = "<<m_process->readAllStandardOutput();
220 tr("Couldn't execute the replay file '%1'").arg(m_fileName));
223 Q_DECLARE_METATYPE(QList<ApiTraceError>);
224 RetraceProcess::RetraceProcess(QObject *parent)
227 m_process = new QProcess(this);
228 m_jsonParser = new QJson::Parser();
230 qRegisterMetaType<QList<ApiTraceError> >();
232 connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
233 this, SLOT(replayFinished(int, QProcess::ExitStatus)));
234 connect(m_process, SIGNAL(error(QProcess::ProcessError)),
235 this, SLOT(replayError(QProcess::ProcessError)));
238 QProcess * RetraceProcess::process() const
243 QString RetraceProcess::fileName() const
248 void RetraceProcess::setFileName(const QString &name)
253 void RetraceProcess::setAPI(trace::API api)
258 bool RetraceProcess::isBenchmarking() const
260 return m_benchmarking;
263 void RetraceProcess::setBenchmarking(bool bench)
265 m_benchmarking = bench;
268 bool RetraceProcess::isDoubleBuffered() const
270 return m_doubleBuffered;
273 void RetraceProcess::setDoubleBuffered(bool db)
275 m_doubleBuffered = db;
278 void RetraceProcess::setCaptureAtCallNumber(qlonglong num)
283 qlonglong RetraceProcess::captureAtCallNumber() const
285 return m_captureCall;
288 bool RetraceProcess::captureState() const
290 return m_captureState;
293 void RetraceProcess::setCaptureState(bool enable)
295 m_captureState = enable;
298 void RetraceProcess::terminate()
301 m_process->terminate();
302 emit finished(tr("Process terminated."));
306 void Retracer::cleanup()
311 RetraceProcess::~RetraceProcess()
316 #include "retracer.moc"