3 Copyright 2008 - 2009 by 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>
38 #include "preferences.h"
42 Recorder::Recorder(int &argc
, char **argv
) :
43 QApplication(argc
, argv
)
45 recorderInstance
= this;
47 debug("Initializing application");
49 // check for already running instance
50 if (!lockFile
.lock(QDir::homePath() + "/.skypecallrecorder.lock")) {
51 debug("Other instance is running");
52 QTimer::singleShot(0, this, SLOT(quit()));
63 Recorder::~Recorder() {
64 // the Recorder object must still exist while the child objects are
65 // being destroyed, because debug() must still be available. Qt would
66 // do it automatically but only after Recorder ceased to exist, in the
69 delete preferencesDialog
;
75 void Recorder::setupGUI() {
76 setWindowIcon(QIcon(":/icon.png"));
77 setQuitOnLastWindowClosed(false);
79 trayIcon
= new TrayIcon(this);
80 connect(trayIcon
, SIGNAL(requestQuit()), this, SLOT(quitConfirmation()));
81 connect(trayIcon
, SIGNAL(requestAbout()), this, SLOT(about()));
82 connect(trayIcon
, SIGNAL(requestWebsite()), this, SLOT(openWebsite()));
83 connect(trayIcon
, SIGNAL(requestOpenPreferences()), this, SLOT(openPreferences()));
84 connect(trayIcon
, SIGNAL(requestBrowseCalls()), this, SLOT(browseCalls()));
86 debug("GUI initialized");
88 if (!preferences
.get(Pref::SuppressFirstRunInformation
).toBool())
92 void Recorder::setupSkype() {
93 skype
= new Skype(this);
94 connect(skype
, SIGNAL(notify(const QString
&)), this, SLOT(skypeNotify(const QString
&)));
95 connect(skype
, SIGNAL(connected(bool)), this, SLOT(skypeConnected(bool)));
96 connect(skype
, SIGNAL(connectionFailed(const QString
&)), this, SLOT(skypeConnectionFailed(const QString
&)));
98 connect(skype
, SIGNAL(connected(bool)), trayIcon
, SLOT(setColor(bool)));
101 void Recorder::setupCallHandler() {
102 callHandler
= new CallHandler(this, skype
);
104 connect(trayIcon
, SIGNAL(startRecording(int)), callHandler
, SLOT(startRecording(int)));
105 connect(trayIcon
, SIGNAL(stopRecording(int)), callHandler
, SLOT(stopRecording(int)));
106 connect(trayIcon
, SIGNAL(stopRecordingAndDelete(int)), callHandler
, SLOT(stopRecordingAndDelete(int)));
108 connect(callHandler
, SIGNAL(startedCall(int, const QString
&)), trayIcon
, SLOT(startedCall(int, const QString
&)));
109 connect(callHandler
, SIGNAL(stoppedCall(int)), trayIcon
, SLOT(stoppedCall(int)));
110 connect(callHandler
, SIGNAL(startedRecording(int)), trayIcon
, SLOT(startedRecording(int)));
111 connect(callHandler
, SIGNAL(stoppedRecording(int)), trayIcon
, SLOT(stoppedRecording(int)));
114 QString
Recorder::getConfigFile() const {
115 return QDir::homePath() + "/.skypecallrecorder.rc";
118 void Recorder::loadPreferences() {
119 preferences
.load(getConfigFile());
120 int c
= preferences
.count();
122 // since Pref::PreferencesVersion did not exist from the first version
123 // on, some people might not have it; but we cannot just let it receive
124 // the default value, as those old settings must be updated. If it is
125 // missing but Pref::OutputPath exists (which has always been around),
126 // then set Pref::PreferencesVersion to 1
127 if (!preferences
.exists(Pref::PreferencesVersion
) && preferences
.exists(Pref::OutputPath
))
128 preferences
.get(Pref::PreferencesVersion
).set(1);
130 #define X(n, v) preferences.get(n).setIfNotSet(v);
131 // default preferences
132 X(Pref::AutoRecordDefault
, "ask"); // "yes", "ask", "no"
133 X(Pref::AutoRecordAsk
, ""); // comma separated skypenames to always ask for
134 X(Pref::AutoRecordYes
, ""); // comma separated skypenames to always record
135 X(Pref::AutoRecordNo
, ""); // comma separated skypenames to never record
136 X(Pref::OutputPath
, "~/Skype Calls");
137 X(Pref::OutputPattern
, "Calls with &s/Call with &s, %a %b %d %Y, %H:%M:%S");
138 X(Pref::OutputFormat
, "mp3"); // "mp3", "vorbis" or "wav"
139 X(Pref::OutputFormatMp3Bitrate
, 64);
140 X(Pref::OutputFormatVorbisQuality
, 3);
141 X(Pref::OutputStereo
, true);
142 X(Pref::OutputStereoMix
, 0); // 0 .. 100
143 X(Pref::OutputSaveTags
, true);
144 X(Pref::SuppressLegalInformation
, false);
145 X(Pref::SuppressFirstRunInformation
, false);
146 X(Pref::PreferencesVersion
, 2);
147 X(Pref::NotifyRecordingStart
, true)
148 X(Pref::GuiWindowed
, false)
149 X(Pref::DebugWriteSyncFile
, false)
152 c
= preferences
.count() - c
;
155 debug(QString("Loading %1 built-in default preference(s)").arg(c
));
157 sanatizePreferences();
160 void Recorder::savePreferences() {
161 preferences
.save(getConfigFile());
162 // TODO: when failure?
165 void Recorder::sanatizePreferences() {
166 // this converts old preferences to new preferences
168 int v
= preferences
.get(Pref::PreferencesVersion
).toInt();
169 bool didSomething
= false;
173 didSomething
|= convertSettingsToV2();
176 didSomething
|= sanatizePreferencesGeneric();
182 bool Recorder::convertSettingsToV2() {
183 debug("Converting settings from v1 to v2");
185 QString s
= preferences
.get("output.channelmode").toString();
186 preferences
.remove("output.channelmode");
189 preferences
.get(Pref::OutputStereo
).set(true);
190 preferences
.get(Pref::OutputStereoMix
).set(0);
191 } else if (s
== "oerets") {
192 preferences
.get(Pref::OutputStereo
).set(true);
193 preferences
.get(Pref::OutputStereoMix
).set(100);
194 } else if (s
== "mono") {
195 preferences
.get(Pref::OutputStereo
).set(false);
196 preferences
.get(Pref::OutputStereoMix
).set(0);
199 preferences
.get(Pref::PreferencesVersion
).set(2);
204 bool Recorder::sanatizePreferencesGeneric() {
207 bool didSomething
= false;
209 s
= preferences
.get(Pref::AutoRecordDefault
).toString();
210 if (s
!= "ask" && s
!= "yes" && s
!= "no") {
211 preferences
.get(Pref::AutoRecordDefault
).set("ask");
215 s
= preferences
.get(Pref::OutputFormat
).toString();
216 if (s
!= "mp3" && s
!= "vorbis" && s
!= "wav") {
217 preferences
.get(Pref::OutputFormat
).set("mp3");
221 i
= preferences
.get(Pref::OutputFormatMp3Bitrate
).toInt();
222 if (i
< 8 || (i
< 64 && i
% 8 != 0) || (i
< 160 && i
% 16 != 0) || i
> 160) {
223 preferences
.get(Pref::OutputFormatMp3Bitrate
).set(64);
227 i
= preferences
.get(Pref::OutputFormatVorbisQuality
).toInt();
228 if (i
< -1 || i
> 10) {
229 preferences
.get(Pref::OutputFormatVorbisQuality
).set(3);
233 i
= preferences
.get(Pref::OutputStereoMix
).toInt();
234 if (i
< 0 || i
> 100) {
235 preferences
.get(Pref::OutputStereoMix
).set(0);
239 s
= preferences
.get(Pref::OutputPath
).toString();
240 if (s
.trimmed().isEmpty()) {
241 preferences
.get(Pref::OutputPath
).set("~/Skype Calls");
245 s
= preferences
.get(Pref::OutputPattern
).toString();
246 if (s
.trimmed().isEmpty()) {
247 preferences
.get(Pref::OutputPattern
).set("Calls with &s/Call with &s, %a %b %d %Y, %H:%M:%S");
252 debug("At least one preference has been reset to its default value, because it contained bogus data.");
257 void Recorder::about() {
259 aboutDialog
= new AboutDialog
;
261 aboutDialog
->raise();
262 aboutDialog
->activateWindow();
265 void Recorder::openWebsite() {
266 bool ret
= QDesktopServices::openUrl(QUrl::fromEncoded(websiteURL
));
269 QMessageBox::information(NULL
, PROGRAM_NAME
,
270 QString("Failed to open URL %1").arg(websiteURL
));
273 void Recorder::openPreferences() {
274 debug("Show preferences dialog");
276 if (!preferencesDialog
) {
277 preferencesDialog
= new PreferencesDialog();
278 connect(preferencesDialog
, SIGNAL(finished(int)), this, SLOT(savePreferences()));
281 preferencesDialog
->raise();
282 preferencesDialog
->activateWindow();
285 void Recorder::closePerCallerDialog() {
286 debug("Hide per-caller dialog");
287 if (preferencesDialog
)
288 preferencesDialog
->closePerCallerDialog();
291 void Recorder::browseCalls() {
292 QString path
= getOutputPath();
294 QUrl url
= QUrl(QString("file://") + path
);
295 bool ret
= QDesktopServices::openUrl(url
);
298 QMessageBox::information(NULL
, PROGRAM_NAME
,
299 QString("Failed to open URL %1").arg(QString(url
.toEncoded())));
302 void Recorder::quitConfirmation() {
303 debug("Request to quit");
308 void Recorder::skypeNotify(const QString
&s
) {
309 QStringList args
= s
.split(' ');
310 QString cmd
= args
.takeFirst();
312 callHandler
->callCmd(args
);
315 void Recorder::skypeConnected(bool conn
) {
317 debug("skype connection established");
319 debug("skype not connected");
322 void Recorder::skypeConnectionFailed(const QString
&reason
) {
323 debug("skype connection failed, reason: " + reason
);
325 QMessageBox::critical(NULL
, PROGRAM_NAME
" - Error",
326 QString("The connection to Skype failed! %1 cannot operate without this "
327 "connection, please make sure you haven't blocked access from within Skype.\n\n"
328 "Internal reason for failure: %2").arg(PROGRAM_NAME
, reason
));
331 void Recorder::debugMessage(const QString
&s
) {
332 std::cout
<< QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ").toLocal8Bit().constData()
333 << s
.toLocal8Bit().constData() << "\n";
336 int main(int argc
, char **argv
) {
337 Recorder
recorder(argc
, argv
);
339 return recorder
.exec();