1 /* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2021 Ricardo Villalba <ricardo@smplayer.info>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "myprocess.h"
20 #include <QDir>
21 #include <QDebug>
22
23 #ifdef Q_OS_WIN
24
25 #if QT_VERSION < 0x040300
26 #define USE_TEMP_FILE 1
27 #else
28 #define USE_TEMP_FILE 0
29 #endif
30
31 #else
32 #define USE_TEMP_FILE 0
33 #endif
34
35
MyProcess(QObject * parent)36 MyProcess::MyProcess(QObject * parent) : QProcess(parent)
37 {
38 clearArguments();
39 setProcessChannelMode( QProcess::MergedChannels );
40
41 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
42 #ifndef Q_OS_WIN
43 QString bin_path = QDir::homePath() + "/bin";
44 qDebug() << "MyProcess::MyProcess: bin_path:" << bin_path;
45 qDebug() << "MyProcess::MyProcess: PATH:" << env.value("PATH");
46 QStringList paths = env.value("PATH").split(":");
47 qDebug() << "MyProcess::MyProcess: paths:" << paths;
48 if (!paths.contains(bin_path)) {
49 QString new_path = bin_path +":" + env.value("PATH");
50 env.insert("PATH", new_path);
51 qDebug() << "MyProcess::MyProcess: PATH:" << env.value("PATH");
52 }
53 #endif
54 setProcessEnvironment(env);
55
56 #if USE_TEMP_FILE
57 temp_file.open(); // Create temporary file
58 QString filename = temp_file.fileName();
59 setStandardOutputFile( filename );
60 qDebug("MyProcess::MyProcess: temporary file: %s", filename.toUtf8().data());
61 temp_file.close();
62
63 //connect(&temp_file, SIGNAL(readyRead()), this, SLOT(readTmpFile()) );
64 connect(&timer, SIGNAL(timeout()), this, SLOT(readTmpFile()) );
65 #else
66 connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOut()) );
67 #endif
68
69 connect(this, SIGNAL(finished(int, QProcess::ExitStatus)),
70 this, SLOT(procFinished()) );
71
72 // Test splitArguments
73 //QStringList l = MyProcess::splitArguments("-opt 1 hello \"56 67\" wssx -ios");
74 }
75
clearArguments()76 void MyProcess::clearArguments() {
77 program = "";
78 arg.clear();
79 }
80
isRunning()81 bool MyProcess::isRunning() {
82 return (state() == QProcess::Running);
83 }
84
addArgument(const QString & a)85 void MyProcess::addArgument(const QString & a) {
86 if (program.isEmpty()) {
87 program = a;
88 } else {
89 arg.append(a);
90 }
91 }
92
arguments()93 QStringList MyProcess::arguments() {
94 QStringList l = arg;
95 l.prepend(program);
96 return l;
97 }
98
start()99 void MyProcess::start() {
100 qDebug() << "MyProcess::start: environment path:" << processEnvironment().value("PATH");
101 qDebug() << "MyProcess::start: current directory:" << QDir::currentPath();
102
103 remaining_output.clear();
104
105 QString bin = program;
106 /*
107 QFileInfo fi(program);
108 if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
109 bin = fi.absoluteFilePath();
110 }
111 qDebug() << "MyProcess::start: executable:" << bin;
112 */
113
114 QProcess::start(bin, arg);
115
116 #if USE_TEMP_FILE
117 //bool r = temp_file.open(QIODevice::ReadOnly);
118 bool r = temp_file.open();
119 timer.start(50);
120 qDebug("MyProcess::start: r: %d", r);
121 #endif
122 }
123
readStdOut()124 void MyProcess::readStdOut() {
125 genericRead( readAllStandardOutput() );
126 }
127
128
readTmpFile()129 void MyProcess::readTmpFile() {
130 genericRead( temp_file.readAll() );
131 }
132
genericRead(QByteArray buffer)133 void MyProcess::genericRead(QByteArray buffer) {
134 QByteArray ba = remaining_output + buffer;
135 int start = 0;
136 int from_pos = 0;
137 int pos = canReadLine(ba, from_pos);
138
139 //qDebug("MyProcess::read: pos: %d", pos);
140 while ( pos > -1 ) {
141 // Readline
142 //QByteArray line = ba.left(pos);
143 QByteArray line = ba.mid(start, pos-start);
144 //ba = ba.mid(pos+1);
145 from_pos = pos + 1;
146 #if defined(Q_OS_WIN) || defined(Q_OS_OS2)
147 if ((from_pos < ba.size()) && (ba.at(from_pos)=='\n')) from_pos++;
148 #endif
149 start = from_pos;
150
151 emit lineAvailable(line);
152
153 pos = canReadLine(ba, from_pos);
154 }
155
156 remaining_output = ba.mid(from_pos);
157 }
158
canReadLine(const QByteArray & ba,int from)159 int MyProcess::canReadLine(const QByteArray & ba, int from) {
160 int pos1 = ba.indexOf('\n', from);
161 int pos2 = ba.indexOf('\r', from);
162
163 //qDebug("MyProcess::canReadLine: pos2: %d", pos2);
164
165 if ( (pos1 == -1) && (pos2 == -1) ) return -1;
166
167 int pos = pos1;
168 if ( (pos1 != -1) && (pos2 != -1) ) {
169 /*
170 if (pos2 == (pos1+1)) pos = pos2; // \r\n
171 else
172 */
173 if (pos1 < pos2) pos = pos1; else pos = pos2;
174 } else {
175 if (pos1 == -1) pos = pos2;
176 else
177 if (pos2 == -1) pos = pos1;
178 }
179
180 return pos;
181 }
182
183 /*!
184 Do some clean up, and be sure that all output has been read.
185 */
procFinished()186 void MyProcess::procFinished() {
187 qDebug("MyProcess::procFinished");
188
189 #if !USE_TEMP_FILE
190 qDebug() << "MyProcess::procFinished: Bytes available: " << bytesAvailable();
191 if ( bytesAvailable() > 0 ) readStdOut();
192 #else
193 timer.stop();
194
195 qDebug() << "MyProcess::procFinished: Bytes available: " << temp_file.bytesAvailable();
196 if ( temp_file.bytesAvailable() > 0 ) readTmpFile();
197 qDebug() << "MyProcess::procFinished: Bytes available:" << temp_file.bytesAvailable();
198
199 temp_file.close();
200 #endif
201 }
202
splitArguments(const QString & args)203 QStringList MyProcess::splitArguments(const QString & args) {
204 qDebug("MyProcess::splitArguments: '%s'", args.toUtf8().constData());
205
206 QStringList l;
207
208 bool opened_quote = false;
209 int init_pos = 0;
210 for (int n = 0; n < args.length(); n++) {
211 if ((args[n] == QChar(' ')) && (!opened_quote)) {
212 l.append(args.mid(init_pos, n - init_pos));
213 init_pos = n+1;
214 }
215 else
216 if (args[n] == QChar('\"')) opened_quote = !opened_quote;
217
218 if (n == args.length()-1) {
219 l.append(args.mid(init_pos, (n - init_pos)+1));
220 }
221 }
222
223 for (int n = 0; n < l.count(); n++) {
224 qDebug("MyProcess::splitArguments: arg: %d '%s'", n, l[n].toUtf8().constData());
225 }
226
227 return l;
228 }
229
230 #include "moc_myprocess.cpp"
231