~ubuntu-branches/ubuntu/natty/recorditnow/natty

« back to all changes in this revision

Viewing changes to src/plugins/recorder/recordmydesktop/recordmydesktoprecorder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2009-11-26 16:50:53 UTC
  • Revision ID: james.westby@ubuntu.com-20091126165053-yifjycveb8j7yt8r
Tags: upstream-0.4
Import upstream version 0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2009 by Kai Dombrowe <just89@gmx.de>                    *
 
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                         *
 
16
 *   Free Software Foundation, Inc.,                                       *
 
17
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
 
18
 ***************************************************************************/
 
19
 
 
20
 
 
21
// own
 
22
#include "recordmydesktoprecorder.h"
 
23
#include <recorditnow_recordmydesktop.h>
 
24
 
 
25
// KDE
 
26
#include <kplugininfo.h>
 
27
#include <kprocess.h>
 
28
#include <kglobal.h>
 
29
#include <kstandarddirs.h>
 
30
#include <kdebug.h>
 
31
 
 
32
// Qt
 
33
#include <QtGui/QWidget>
 
34
#include <QtCore/QDir>
 
35
 
 
36
// C
 
37
#include <sys/types.h>
 
38
#include <signal.h>
 
39
 
 
40
 
 
41
 
 
42
K_PLUGIN_FACTORY(myFactory, registerPlugin<RecordMyDesktopRecorder>();)
 
43
K_EXPORT_PLUGIN(myFactory("recordmydesktop_recorder"))
 
44
RecordMyDesktopRecorder::RecordMyDesktopRecorder(QObject *parent, const QVariantList &args)
 
45
    : AbstractRecorder(parent, args)
 
46
{
 
47
 
 
48
    m_recorder = 0;
 
49
    m_data.paused = false;
 
50
 
 
51
}
 
52
 
 
53
 
 
54
RecordMyDesktopRecorder::~RecordMyDesktopRecorder()
 
55
{
 
56
 
 
57
    clean();
 
58
 
 
59
}
 
60
 
 
61
 
 
62
void RecordMyDesktopRecorder::record(const AbstractRecorder::Data &d)
 
63
{
 
64
 
 
65
    const QString recordMyDesktop = KGlobal::dirs()->findExe("recordmydesktop");
 
66
    if (recordMyDesktop.isEmpty()) {
 
67
        emit error(i18n("Cannot find recordmydesktop!\n"
 
68
                        "Please install recordmydesktop or use another plugin."));
 
69
        return;
 
70
    }
 
71
 
 
72
    QStringList args;
 
73
 
 
74
    // default cfg
 
75
    if (!d.sound) {
 
76
        args << "--no-sound";
 
77
    }
 
78
    m_data.overwrite = d.overwrite;
 
79
    m_data.outputFile = d.outputFile;
 
80
    m_data.tmpFile = getTemporaryFile(d.workDir)+".ogv";
 
81
    args << "-o" << m_data.tmpFile;
 
82
 
 
83
    if (d.winId != -1) {
 
84
        args << "--windowid" << QString::number(d.winId);
 
85
    } else {
 
86
        if (d.geometry.x() > 0) {
 
87
            args << QString("-x") << QString::number(d.geometry.x());
 
88
        }
 
89
        if (d.geometry.y() > 0) {
 
90
            args << QString("-y") << QString::number(d.geometry.y());
 
91
        }
 
92
        args << QString("-width") << QString::number(d.geometry.width());
 
93
        args << QString("-height") << QString::number(d.geometry.height());
 
94
    }
 
95
    args << "--fps" << QString::number(d.fps);
 
96
    args << "--workdir" << d.workDir;
 
97
 
 
98
    // recordmydesktop cfg
 
99
    Settings::self()->readConfig(); // cfg changed?
 
100
 
 
101
    // image
 
102
    if (Settings::__no_cursor()) {
 
103
        args << "--no-cursor";
 
104
    }
 
105
    if (Settings::__no_shared()) {
 
106
        args << "--no-shared";
 
107
    }
 
108
    if (Settings::__full_shots()) {
 
109
        args << "--full-shots";
 
110
    }
 
111
    if (Settings::__subsampling()) {
 
112
        args << "--quick-subsampling";
 
113
    }
 
114
 
 
115
    // sound
 
116
    if (Settings::__channels() != -1) {
 
117
        args << "--channels" << QString::number(Settings::__channels());
 
118
    }
 
119
    if (Settings::__freq() != -1) {
 
120
        args << "--freq" << QString::number(Settings::__freq());
 
121
    }
 
122
    if (Settings::__buffer_size() != -1) {
 
123
        args << "--buffer-size" << QString::number(Settings::__buffer_size());
 
124
    }
 
125
    if (Settings::__ring_buffer_size() != -1) {
 
126
        args << "--ring-buffer-size" << QString::number(Settings::__ring_buffer_size());
 
127
    }
 
128
    if (Settings::__device() != "hw:0,0" && !Settings::__device().isEmpty()) {
 
129
        args << "--device" << Settings::__device();
 
130
    }
 
131
    if (!Settings::__use_jack().isEmpty()) {
 
132
        args << "--use-jack" << Settings::__use_jack();
 
133
    }
 
134
 
 
135
    // encoding
 
136
    if (Settings::__on_the_fly_encoding()) {
 
137
        args << "--on-the-fly-encoding";
 
138
    }
 
139
 
 
140
    args << "--v_quality" << QString::number(Settings::__v_quality());
 
141
    args << "--v_bitrate" << QString::number(Settings::__v_bitrate());
 
142
    args << "--s_quality" << QString::number(Settings::__s_quality());
 
143
 
 
144
    // misc
 
145
    if (Settings::__no_wm_check()) {
 
146
        args << "--no-wm-check";
 
147
    }
 
148
    if (Settings::__compress_cache()) {
 
149
        args << "--compress-cache";
 
150
    }
 
151
    if (Settings::followMouse()) {
 
152
        args << "--follow-mouse";
 
153
    }
 
154
    if (!Settings::frame()) {
 
155
        args << "--no-frame";
 
156
    }
 
157
 
 
158
    // create/start
 
159
    m_recorder = new KProcess(this);
 
160
    m_recorder->setOutputChannelMode(KProcess::MergedChannels);
 
161
 
 
162
    connect(m_recorder, SIGNAL(readyReadStandardOutput()), this, SLOT(newRecorderOutput()));
 
163
    connect(m_recorder, SIGNAL(finished(int)), this, SLOT(recorderFinished(int)));
 
164
 
 
165
    kDebug() << "starting:" << recordMyDesktop << "with:" << args;
 
166
 
 
167
    m_recorder->setProgram(recordMyDesktop, args);
 
168
 
 
169
    setState(Record);
 
170
    m_recorder->start();
 
171
 
 
172
}
 
173
 
 
174
 
 
175
void RecordMyDesktopRecorder::pause()
 
176
{
 
177
 
 
178
    if (!m_recorder) {
 
179
        return;
 
180
    }
 
181
 
 
182
    if (!m_data.paused) {
 
183
        emit status(i18n("Paused!"));
 
184
        kill(m_recorder->pid(), SIGSTOP);
 
185
        m_data.paused = true;
 
186
    } else {
 
187
        emit status(i18n("Capturing!"));
 
188
        kill(m_recorder->pid(), SIGCONT);
 
189
        m_data.paused = false;
 
190
    }
 
191
 
 
192
}
 
193
 
 
194
 
 
195
void RecordMyDesktopRecorder::stop()
 
196
{
 
197
 
 
198
    if (m_recorder) {
 
199
        kill(m_recorder->pid(), SIGINT);
 
200
        m_data.paused = false;
 
201
    }
 
202
 
 
203
}
 
204
 
 
205
 
 
206
void RecordMyDesktopRecorder::newRecorderOutput()
 
207
{
 
208
 
 
209
    if (!m_recorder) {
 
210
        return;
 
211
    }
 
212
 
 
213
    QString output = QString(m_recorder->readAllStandardOutput()).trimmed();
 
214
 
 
215
    if (output.isEmpty()) {
 
216
        return;
 
217
    }
 
218
 
 
219
    foreach (QString line, output.split('\n')) {
 
220
        kDebug() << "New Line:" << line;
 
221
        line = line.trimmed();
 
222
 
 
223
 
 
224
        if (line.startsWith("Cached")) {
 
225
            QString cached = line.remove(0, 7);
 
226
            QString rec = line.remove(0, line.indexOf("from ")+5);
 
227
 
 
228
            cached.remove(cached.indexOf(','), cached.length());
 
229
            rec.remove(rec.indexOf("that"), rec.length());
 
230
 
 
231
            emit status(i18n("Cached: %1", cached));
 
232
            emit status(i18n("Received: %1", rec));
 
233
        } else if (line.startsWith("Saved ")) {
 
234
            QString frames = line.remove("Saved ");
 
235
            frames.remove(frames.indexOf("frames"), frames.length());
 
236
            emit status(i18n("Frames: %1", frames));
 
237
        } else if (line.startsWith("Output file:")) {
 
238
            m_data.tmpFile = line.remove(0, 13);
 
239
        } else if (line.startsWith("[")) {
 
240
            for (int i = 0; i < line.length(); i++) {
 
241
                if (line[i] == '[') {
 
242
 
 
243
                    setState(Encode);
 
244
 
 
245
                    line.remove(0, i+1);
 
246
                    const int percent = line.mid(0, line.indexOf('%', 0)).toInt();
 
247
                    line.remove(0, line.indexOf("]"));
 
248
                    i = 0;
 
249
                    emit status(i18n("Encoding: %1",
 
250
                                     QString::number(percent > 100 ? 100 : percent)+'%'));
 
251
                }
 
252
            }
 
253
        }
 
254
        if (line == "Capturing!") {
 
255
            emit status(i18n("Capturing!"));
 
256
        } else if (line == "Shutting down..") {
 
257
            emit status(i18n("Shutting down.."));
 
258
        } else if (line == "Encoding started!") {
 
259
            emit status(i18n("Encoding started!"));
 
260
        } else if (line == "Done!!!") {
 
261
            emit status(i18n("Done!"));
 
262
        } else if (line.startsWith("Cannot open file")) {
 
263
            line = line.remove("Cannot open file ");
 
264
            line = line.remove(" for writting!");
 
265
            emit error(i18n("Cannot open file %1 for writting!", line));
 
266
        } else if (line.startsWith("Could not create temporary directory")) {
 
267
            emit error(i18n("Could not create temporary directory, check your config."));
 
268
        } else if (line.startsWith("recordMyDesktop is not compiled with Jack support!")) {
 
269
            emit error(i18n("recordMyDesktop is not compiled with Jack support."));
 
270
        } else if (line.startsWith("Error while opening/configuring soundcard")) {
 
271
            emit error(i18n("Error while opening/configuring soundcard."));
 
272
        } else if (line.startsWith("Window size specification out of bounds!")) {
 
273
            emit error(i18n("Window size specification out of bounds!"));
 
274
        }
 
275
    }
 
276
 
 
277
}
 
278
 
 
279
 
 
280
bool RecordMyDesktopRecorder::remove(const QString &file)
 
281
{
 
282
 
 
283
    QFile f(file);
 
284
    if (!f.remove()) {
 
285
        emit error(i18nc("%1 = file, %2 = error string", "recordmydesktop: Remove failed: %1.\n"
 
286
                         "Reason: %2", file, f.errorString()));
 
287
        return false;
 
288
    }
 
289
    return true;
 
290
 
 
291
}
 
292
 
 
293
 
 
294
bool RecordMyDesktopRecorder::move(const QString &from, const QString &to)
 
295
{
 
296
 
 
297
    QFile file;
 
298
    if (!file.rename(from, to)) {
 
299
        emit error(i18nc("%1 = source, %1 = destination, %3 = error string",
 
300
                         "Move failed: \"%1\" to \"%2\".\n"
 
301
                         "Reason: %3", from, to, file.errorString()));
 
302
        return false;
 
303
    }
 
304
    return true;
 
305
 
 
306
}
 
307
 
 
308
 
 
309
void RecordMyDesktopRecorder::clean()
 
310
{
 
311
 
 
312
    if (m_recorder) {
 
313
        m_recorder->disconnect(this);
 
314
        if (m_recorder->state() != KProcess::NotRunning) {
 
315
            m_recorder->terminate();
 
316
        }
 
317
        m_recorder->waitForFinished(-1);
 
318
        m_recorder->deleteLater();
 
319
        m_recorder = 0;
 
320
    }
 
321
 
 
322
}
 
323
 
 
324
 
 
325
void RecordMyDesktopRecorder::recorderFinished(const int &ret)
 
326
{
 
327
 
 
328
    const KProcess::ExitStatus status = m_recorder->exitStatus();
 
329
    kDebug() << "status:" << status << "ret:" << ret;
 
330
 
 
331
    if (status == KProcess::CrashExit || ret != 0) {
 
332
        clean();
 
333
        emit finished(Crash);
 
334
        return;
 
335
    }
 
336
 
 
337
    QFile outputFile(m_data.outputFile);
 
338
    if (outputFile.exists()) {
 
339
        if (m_data.overwrite) {
 
340
            if (!remove(m_data.outputFile)) {
 
341
                clean();
 
342
                return;
 
343
            }
 
344
        } else {
 
345
            m_data.outputFile = unique(m_data.outputFile);
 
346
            emit outputFileChanged(m_data.outputFile);
 
347
        }
 
348
    }
 
349
 
 
350
    if (!move(m_data.tmpFile, m_data.outputFile)) {
 
351
        clean();
 
352
        return;
 
353
    }
 
354
 
 
355
    clean();
 
356
 
 
357
    if (status == KProcess::CrashExit) {
 
358
        emit finished(Crash);
 
359
    } else {
 
360
        emit finished(Normal);
 
361
    }
 
362
 
 
363
}
 
364
 
 
365
 
 
366
#include "recordmydesktoprecorder.moc"