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 // the Recorder object must still exist while the child objects are
64 // being destroyed, because debug() must still be available. Qt would
65 // do it automatically but only after Recorder ceased to exist, in the
68 delete preferencesDialog
;
74 void Recorder::setupGUI() {
75 setWindowIcon(QIcon(":/icon.png"));
76 setQuitOnLastWindowClosed(false);
78 trayIcon
= new TrayIcon(this);
79 connect(trayIcon
, SIGNAL(requestQuit()), this, SLOT(quitConfirmation()));
80 connect(trayIcon
, SIGNAL(requestAbout()), this, SLOT(about()));
81 connect(trayIcon
, SIGNAL(requestWebsite()), this, SLOT(openWebsite()));
82 connect(trayIcon
, SIGNAL(requestOpenPreferences()), this, SLOT(openPreferences()));
83 connect(trayIcon
, SIGNAL(requestBrowseCalls()), this, SLOT(browseCalls()));
85 debug("GUI initialized");
87 if (!preferences
.get(Pref::SuppressFirstRunInformation
).toBool())
91 void Recorder::setupSkype() {
92 skype
= new Skype(this);
93 connect(skype
, SIGNAL(notify(const QString
&)), this, SLOT(skypeNotify(const QString
&)));
94 connect(skype
, SIGNAL(connected(bool)), this, SLOT(skypeConnected(bool)));
95 connect(skype
, SIGNAL(connectionFailed(const QString
&)), this, SLOT(skypeConnectionFailed(const QString
&)));
97 connect(skype
, SIGNAL(connected(bool)), trayIcon
, SLOT(setColor(bool)));
100 void Recorder::setupCallHandler() {
101 callHandler
= new CallHandler(this, skype
);
103 connect(trayIcon
, SIGNAL(startRecording(int)), callHandler
, SLOT(startRecording(int)));
104 connect(trayIcon
, SIGNAL(stopRecording(int)), callHandler
, SLOT(stopRecording(int)));
105 connect(trayIcon
, SIGNAL(stopRecordingAndDelete(int)), callHandler
, SLOT(stopRecordingAndDelete(int)));
107 connect(callHandler
, SIGNAL(startedCall(int, const QString
&)), trayIcon
, SLOT(startedCall(int, const QString
&)));
108 connect(callHandler
, SIGNAL(stoppedCall(int)), trayIcon
, SLOT(stoppedCall(int)));
109 connect(callHandler
, SIGNAL(startedRecording(int)), trayIcon
, SLOT(startedRecording(int)));
110 connect(callHandler
, SIGNAL(stoppedRecording(int)), trayIcon
, SLOT(stoppedRecording(int)));
113 QString
Recorder::getConfigFile() const {
114 return QDir::homePath() + "/.skypecallrecorder.rc";
117 void Recorder::loadPreferences() {
118 preferences
.load(getConfigFile());
119 int c
= preferences
.count();
121 // since Pref::PreferencesVersion did not exist from the first version
122 // on, some people might not have it; but we cannot just let it receive
123 // the default value, as those old settings must be updated. If it is
124 // missing but Pref::OutputPath exists (which has always been around),
125 // then set Pref::PreferencesVersion to 1
126 if (!preferences
.exists(Pref::PreferencesVersion
) && preferences
.exists(Pref::OutputPath
))
127 preferences
.get(Pref::PreferencesVersion
).set(1);
129 #define X(n, v) preferences.get(n).setIfNotSet(v);
130 // default preferences
131 X(Pref::AutoRecordDefault
, "ask"); // "yes", "ask", "no"
132 X(Pref::AutoRecordAsk
, ""); // comma separated skypenames to always ask for
133 X(Pref::AutoRecordYes
, ""); // comma separated skypenames to always record
134 X(Pref::AutoRecordNo
, ""); // comma separated skypenames to never record
135 X(Pref::OutputPath
, "~/Skype Calls");
136 X(Pref::OutputPattern
, "Calls with &s/Call with &s, %a %b %d %Y, %H:%M:%S");
137 X(Pref::OutputFormat
, "mp3"); // "mp3", "vorbis" or "wav"
138 X(Pref::OutputFormatMp3Bitrate
, 64);
139 X(Pref::OutputFormatVorbisQuality
, 3);
140 X(Pref::OutputStereo
, true);
141 X(Pref::OutputStereoMix
, 0); // 0 .. 100
142 X(Pref::OutputSaveTags
, true);
143 X(Pref::SuppressLegalInformation
, false);
144 X(Pref::SuppressFirstRunInformation
, false);
145 X(Pref::PreferencesVersion
, 2);
146 X(Pref::NotifyRecordingStart
, true)
147 X(Pref::GuiWindowed
, false)
148 X(Pref::DebugWriteSyncFile
, false)
151 c
= preferences
.count() - c
;
154 debug(QString("Loading %1 built-in default preference(s)").arg(c
));
156 sanatizePreferences();
159 void Recorder::savePreferences() {
160 preferences
.save(getConfigFile());
161 // TODO: when failure?
164 void Recorder::sanatizePreferences() {
165 // this converts old preferences to new preferences
167 int v
= preferences
.get(Pref::PreferencesVersion
).toInt();
168 bool didSomething
= false;
172 didSomething
|= convertSettingsToV2();
175 didSomething
|= sanatizePreferencesGeneric();
181 bool Recorder::convertSettingsToV2() {
182 debug("Converting settings from v1 to v2");
184 QString s
= preferences
.get("output.channelmode").toString();
185 preferences
.remove("output.channelmode");
188 preferences
.get(Pref::OutputStereo
).set(true);
189 preferences
.get(Pref::OutputStereoMix
).set(0);
190 } else if (s
== "oerets") {
191 preferences
.get(Pref::OutputStereo
).set(true);
192 preferences
.get(Pref::OutputStereoMix
).set(100);
193 } else if (s
== "mono") {
194 preferences
.get(Pref::OutputStereo
).set(false);
195 preferences
.get(Pref::OutputStereoMix
).set(0);
198 preferences
.get(Pref::PreferencesVersion
).set(2);
203 bool Recorder::sanatizePreferencesGeneric() {
206 bool didSomething
= false;
208 s
= preferences
.get(Pref::AutoRecordDefault
).toString();
209 if (s
!= "ask" && s
!= "yes" && s
!= "no") {
210 preferences
.get(Pref::AutoRecordDefault
).set("ask");
214 s
= preferences
.get(Pref::OutputFormat
).toString();
215 if (s
!= "mp3" && s
!= "vorbis" && s
!= "wav") {
216 preferences
.get(Pref::OutputFormat
).set("mp3");
220 i
= preferences
.get(Pref::OutputFormatMp3Bitrate
).toInt();
221 if (i
< 8 || (i
< 64 && i
% 8 != 0) || (i
< 160 && i
% 16 != 0) || i
> 160) {
222 preferences
.get(Pref::OutputFormatMp3Bitrate
).set(64);
226 i
= preferences
.get(Pref::OutputFormatVorbisQuality
).toInt();
227 if (i
< -1 || i
> 10) {
228 preferences
.get(Pref::OutputFormatVorbisQuality
).set(3);
232 i
= preferences
.get(Pref::OutputStereoMix
).toInt();
233 if (i
< 0 || i
> 100) {
234 preferences
.get(Pref::OutputStereoMix
).set(0);
238 s
= preferences
.get(Pref::OutputPath
).toString();
239 if (s
.trimmed().isEmpty()) {
240 preferences
.get(Pref::OutputPath
).set("~/Skype Calls");
244 s
= preferences
.get(Pref::OutputPattern
).toString();
245 if (s
.trimmed().isEmpty()) {
246 preferences
.get(Pref::OutputPattern
).set("Calls with &s/Call with &s, %a %b %d %Y, %H:%M:%S");
251 debug("At least one preference has been reset to its default value, because it contained bogus data.");
256 void Recorder::about() {
258 aboutDialog
= new AboutDialog
;
260 aboutDialog
->raise();
261 aboutDialog
->activateWindow();
264 void Recorder::openWebsite() {
265 bool ret
= QDesktopServices::openUrl(QUrl::fromEncoded(websiteURL
));
268 QMessageBox::information(NULL
, PROGRAM_NAME
,
269 QString("Failed to open URL %1").arg(websiteURL
));
272 void Recorder::openPreferences() {
273 debug("Show preferences dialog");
275 if (!preferencesDialog
) {
276 preferencesDialog
= new PreferencesDialog();
277 connect(preferencesDialog
, SIGNAL(finished(int)), this, SLOT(savePreferences()));
280 preferencesDialog
->raise();
281 preferencesDialog
->activateWindow();
284 void Recorder::closePerCallerDialog() {
285 debug("Hide per-caller dialog");
286 if (preferencesDialog
)
287 preferencesDialog
->closePerCallerDialog();
290 void Recorder::browseCalls() {
291 QString path
= getOutputPath();
293 QUrl url
= QUrl(QString("file://") + path
);
294 bool ret
= QDesktopServices::openUrl(url
);
297 QMessageBox::information(NULL
, PROGRAM_NAME
,
298 QString("Failed to open URL %1").arg(QString(url
.toEncoded())));
301 void Recorder::quitConfirmation() {
302 debug("Request to quit");
307 void Recorder::skypeNotify(const QString
&s
) {
308 QStringList args
= s
.split(' ');
309 QString cmd
= args
.takeFirst();
311 callHandler
->callCmd(args
);
314 void Recorder::skypeConnected(bool conn
) {
316 debug("skype connection established");
318 debug("skype not connected");
321 void Recorder::skypeConnectionFailed(const QString
&reason
) {
322 debug("skype connection failed, reason: " + reason
);
324 QMessageBox::critical(NULL
, PROGRAM_NAME
" - Error",
325 QString("The connection to Skype failed! %1 cannot operate without this "
326 "connection, please make sure you haven't blocked access from within Skype.\n\n"
327 "Internal reason for failure: %2").arg(PROGRAM_NAME
, reason
));
330 void Recorder::debugMessage(const QString
&s
) {
331 std::cout
<< s
.toLocal8Bit().constData() << "\n";
334 int main(int argc
, char **argv
) {
335 Recorder
recorder(argc
, argv
);
337 return recorder
.exec();