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
24 #include <QMessageBox>
28 #include <QDesktopServices>
37 #include "preferences.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()));
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())
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)
143 c
= preferences
.count() - 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;
164 didSomething
|= convertSettingsToV2();
167 didSomething
|= sanatizePreferencesGeneric();
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");
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);
195 bool Recorder::sanatizePreferencesGeneric() {
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");
206 s
= preferences
.get(Pref::OutputFormat
).toString();
207 if (s
!= "mp3" && s
!= "vorbis" && s
!= "wav") {
208 preferences
.get(Pref::OutputFormat
).set("mp3");
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);
218 i
= preferences
.get(Pref::OutputFormatVorbisQuality
).toInt();
219 if (i
< -1 || i
> 10) {
220 preferences
.get(Pref::OutputFormatVorbisQuality
).set(3);
224 i
= preferences
.get(Pref::OutputStereoMix
).toInt();
225 if (i
< 0 || i
> 100) {
226 preferences
.get(Pref::OutputStereoMix
).set(0);
230 s
= preferences
.get(Pref::OutputPath
).toString();
231 if (s
.trimmed().isEmpty()) {
232 preferences
.get(Pref::OutputPath
).set("~/Skype Calls");
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");
243 debug("At least one preference has been reset to its default value, because it contained bogus data.");
248 void Recorder::about() {
250 aboutDialog
= new AboutDialog
;
252 aboutDialog
->raise();
253 aboutDialog
->activateWindow();
256 void Recorder::openWebsite() {
257 bool ret
= QDesktopServices::openUrl(QUrl::fromEncoded(websiteURL
));
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();
285 QUrl url
= QUrl(QString("file://") + path
);
286 bool ret
= QDesktopServices::openUrl(url
);
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");
299 void Recorder::skypeNotify(const QString
&s
) {
300 QStringList args
= s
.split(' ');
301 QString cmd
= args
.takeFirst();
303 callHandler
->callCmd(args
);
306 void Recorder::skypeConnected(bool conn
) {
308 debug("skype connection established");
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();