Support building .deb package for Debian
[skype-call-recorder.git] / recorder.cpp
blobe6394515616699a267b0cbd8d00c8b832e2c6603
1 /*
2 Skype Call Recorder
3 Copyright (C) 2008 jlh (jlh at gmx dot ch)
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2 of the License, version 3 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 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 St, Fifth Floor, Boston, MA 02110-1301 USA
19 The GNU General Public License version 2 is included with the source of
20 this program under the file name COPYING. You can also get a copy on
21 http://www.fsf.org/
24 #include <QMessageBox>
25 #include <QDir>
26 #include <QProcess>
27 #include <QTimer>
28 #include <QDesktopServices>
29 #include <QUrl>
30 #include <iostream>
31 #include <cstdlib>
33 #include "recorder.h"
34 #include "common.h"
35 #include "gui.h"
36 #include "trayicon.h"
37 #include "preferences.h"
38 #include "skype.h"
39 #include "call.h"
41 Recorder::Recorder(int &argc, char **argv) :
42 QApplication(argc, argv)
44 recorderInstance = this;
46 debug("Initializing application");
48 // check for already running instance
49 if (!lockFile.lock(QDir::homePath() + "/.skypecallrecorder.lock")) {
50 debug("Other instance is running");
51 QTimer::singleShot(0, this, SLOT(quit()));
52 return;
55 loadPreferences();
57 setupGUI();
58 setupSkype();
59 setupCallHandler();
62 Recorder::~Recorder() {
63 delete preferencesDialog;
66 void Recorder::setupGUI() {
67 setWindowIcon(QIcon(":/icon.png"));
68 setQuitOnLastWindowClosed(false);
70 trayIcon = new TrayIcon(this);
71 connect(trayIcon, SIGNAL(requestQuit()), this, SLOT(quitConfirmation()));
72 connect(trayIcon, SIGNAL(requestAbout()), this, SLOT(about()));
73 connect(trayIcon, SIGNAL(requestWebsite()), this, SLOT(openWebsite()));
74 connect(trayIcon, SIGNAL(requestOpenPreferences()), this, SLOT(openPreferences()));
75 connect(trayIcon, SIGNAL(requestBrowseCalls()), this, SLOT(browseCalls()));
77 debug("GUI initialized");
79 if (!preferences.get(Pref::SuppressFirstRunInformation).toBool())
80 new FirstRunDialog();
83 void Recorder::setupSkype() {
84 skype = new Skype(this);
85 connect(skype, SIGNAL(notify(const QString &)), this, SLOT(skypeNotify(const QString &)));
86 connect(skype, SIGNAL(connected(bool)), this, SLOT(skypeConnected(bool)));
87 connect(skype, SIGNAL(connectionFailed(const QString &)), this, SLOT(skypeConnectionFailed(const QString &)));
89 connect(skype, SIGNAL(connected(bool)), trayIcon, SLOT(setColor(bool)));
92 void Recorder::setupCallHandler() {
93 callHandler = new CallHandler(this, skype);
95 connect(trayIcon, SIGNAL(startRecording(int)), callHandler, SLOT(startRecording(int)));
96 connect(trayIcon, SIGNAL(stopRecording(int)), callHandler, SLOT(stopRecording(int)));
97 connect(trayIcon, SIGNAL(stopRecordingAndDelete(int)), callHandler, SLOT(stopRecordingAndDelete(int)));
99 connect(callHandler, SIGNAL(startedCall(int, const QString &)), trayIcon, SLOT(startedCall(int, const QString &)));
100 connect(callHandler, SIGNAL(stoppedCall(int)), trayIcon, SLOT(stoppedCall(int)));
101 connect(callHandler, SIGNAL(startedRecording(int)), trayIcon, SLOT(startedRecording(int)));
102 connect(callHandler, SIGNAL(stoppedRecording(int)), trayIcon, SLOT(stoppedRecording(int)));
105 QString Recorder::getConfigFile() const {
106 return QDir::homePath() + "/.skypecallrecorder.rc";
109 void Recorder::loadPreferences() {
110 preferences.load(getConfigFile());
111 int c = preferences.count();
113 // since Pref::PreferencesVersion did not exist from the first version
114 // on, some people might not have it; but we cannot just let it receive
115 // the default value, as those old settings must be updated. If it is
116 // missing but Pref::OutputPath exists (which has always been around),
117 // then set Pref::PreferencesVersion to 1
118 if (!preferences.exists(Pref::PreferencesVersion) && preferences.exists(Pref::OutputPath))
119 preferences.get(Pref::PreferencesVersion).set(1);
121 #define X(n, v) preferences.get(n).setIfNotSet(v);
122 // default preferences
123 X(Pref::AutoRecordDefault, "ask"); // "yes", "ask", "no"
124 X(Pref::AutoRecordAsk, ""); // comma separated skypenames to always ask for
125 X(Pref::AutoRecordYes, ""); // comma separated skypenames to always record
126 X(Pref::AutoRecordNo, ""); // comma separated skypenames to never record
127 X(Pref::OutputPath, "~/Skype Calls");
128 X(Pref::OutputPattern, "Calls with &s/Call with &s, %a %b %d %Y, %H:%M:%S");
129 X(Pref::OutputFormat, "mp3"); // "mp3", "vorbis" or "wav"
130 X(Pref::OutputFormatMp3Bitrate, 64);
131 X(Pref::OutputFormatVorbisQuality, 3);
132 X(Pref::OutputStereo, true);
133 X(Pref::OutputStereoMix, 0); // 0 .. 100
134 X(Pref::OutputSaveTags, true);
135 X(Pref::SuppressLegalInformation, false);
136 X(Pref::SuppressFirstRunInformation, false);
137 X(Pref::PreferencesVersion, 2);
138 X(Pref::NotifyRecordingStart, true)
139 X(Pref::GuiWindowed, false)
140 X(Pref::DebugWriteSyncFile, false)
141 #undef X
143 c = preferences.count() - c;
145 if (c)
146 debug(QString("Loading %1 built-in default preference(s)").arg(c));
148 sanatizePreferences();
151 void Recorder::savePreferences() {
152 preferences.save(getConfigFile());
153 // TODO: when failure?
156 void Recorder::sanatizePreferences() {
157 // this converts old preferences to new preferences
159 int v = preferences.get(Pref::PreferencesVersion).toInt();
160 bool didSomething = false;
162 switch (v) {
163 case 1:
164 didSomething |= convertSettingsToV2();
167 didSomething |= sanatizePreferencesGeneric();
169 if (didSomething)
170 savePreferences();
173 bool Recorder::convertSettingsToV2() {
174 debug("Converting settings from v1 to v2");
176 QString s = preferences.get("output.channelmode").toString();
177 preferences.remove("output.channelmode");
179 if (s == "stereo") {
180 preferences.get(Pref::OutputStereo).set(true);
181 preferences.get(Pref::OutputStereoMix).set(0);
182 } else if (s == "oerets") {
183 preferences.get(Pref::OutputStereo).set(true);
184 preferences.get(Pref::OutputStereoMix).set(100);
185 } else if (s == "mono") {
186 preferences.get(Pref::OutputStereo).set(false);
187 preferences.get(Pref::OutputStereoMix).set(0);
190 preferences.get(Pref::PreferencesVersion).set(2);
192 return true;
195 bool Recorder::sanatizePreferencesGeneric() {
196 QString s;
197 int i;
198 bool didSomething = false;
200 s = preferences.get(Pref::AutoRecordDefault).toString();
201 if (s != "ask" && s != "yes" && s != "no") {
202 preferences.get(Pref::AutoRecordDefault).set("ask");
203 didSomething = true;
206 s = preferences.get(Pref::OutputFormat).toString();
207 if (s != "mp3" && s != "vorbis" && s != "wav") {
208 preferences.get(Pref::OutputFormat).set("mp3");
209 didSomething = true;
212 i = preferences.get(Pref::OutputFormatMp3Bitrate).toInt();
213 if (i < 8 || (i < 64 && i % 8 != 0) || (i < 160 && i % 16 != 0) || i > 160) {
214 preferences.get(Pref::OutputFormatMp3Bitrate).set(64);
215 didSomething = true;
218 i = preferences.get(Pref::OutputFormatVorbisQuality).toInt();
219 if (i < -1 || i > 10) {
220 preferences.get(Pref::OutputFormatVorbisQuality).set(3);
221 didSomething = true;
224 i = preferences.get(Pref::OutputStereoMix).toInt();
225 if (i < 0 || i > 100) {
226 preferences.get(Pref::OutputStereoMix).set(0);
227 didSomething = true;
230 s = preferences.get(Pref::OutputPath).toString();
231 if (s.trimmed().isEmpty()) {
232 preferences.get(Pref::OutputPath).set("~/Skype Calls");
233 didSomething = true;
236 s = preferences.get(Pref::OutputPattern).toString();
237 if (s.trimmed().isEmpty()) {
238 preferences.get(Pref::OutputPattern).set("Calls with &s/Call with &s, %a %b %d %Y, %H:%M:%S");
239 didSomething = true;
242 if (didSomething)
243 debug("At least one preference has been reset to its default value, because it contained bogus data.");
245 return didSomething;
248 void Recorder::about() {
249 if (!aboutDialog)
250 aboutDialog = new AboutDialog;
252 aboutDialog->raise();
253 aboutDialog->activateWindow();
256 void Recorder::openWebsite() {
257 bool ret = QDesktopServices::openUrl(QUrl::fromEncoded(websiteURL));
259 if (!ret)
260 QMessageBox::information(NULL, PROGRAM_NAME,
261 QString("Failed to open URL %1").arg(websiteURL));
264 void Recorder::openPreferences() {
265 debug("Show preferences dialog");
267 if (!preferencesDialog) {
268 preferencesDialog = new PreferencesDialog();
269 connect(preferencesDialog, SIGNAL(finished(int)), this, SLOT(savePreferences()));
272 preferencesDialog->raise();
273 preferencesDialog->activateWindow();
276 void Recorder::closePerCallerDialog() {
277 debug("Hide per-caller dialog");
278 if (preferencesDialog)
279 preferencesDialog->closePerCallerDialog();
282 void Recorder::browseCalls() {
283 QString path = getOutputPath();
284 QDir().mkpath(path);
285 QUrl url = QUrl(QString("file://") + path);
286 bool ret = QDesktopServices::openUrl(url);
288 if (!ret)
289 QMessageBox::information(NULL, PROGRAM_NAME,
290 QString("Failed to open URL %1").arg(QString(url.toEncoded())));
293 void Recorder::quitConfirmation() {
294 debug("Request to quit");
295 savePreferences();
296 quit();
299 void Recorder::skypeNotify(const QString &s) {
300 QStringList args = s.split(' ');
301 QString cmd = args.takeFirst();
302 if (cmd == "CALL")
303 callHandler->callCmd(args);
306 void Recorder::skypeConnected(bool conn) {
307 if (conn)
308 debug("skype connection established");
309 else
310 debug("skype not connected");
313 void Recorder::skypeConnectionFailed(const QString &reason) {
314 debug("skype connection failed, reason: " + reason);
316 QMessageBox::critical(NULL, PROGRAM_NAME " - Error",
317 QString("The connection to Skype failed! %1 cannot operate without this "
318 "connection, please make sure you haven't blocked access from within Skype.\n\n"
319 "Internal reason for failure: %2").arg(PROGRAM_NAME, reason));
322 void Recorder::debugMessage(const QString &s) {
323 std::cout << s.toLocal8Bit().constData() << "\n";
326 int main(int argc, char **argv) {
327 Recorder recorder(argc, argv);
329 return recorder.exec();