source: qutecom-2.2/qutecom/src/presentation/main.cpp @ 645:ad35837e965d

Last change on this file since 645:ad35837e965d was 645:ad35837e965d, checked in by laurent, 3 years ago

QuteComis?

File size: 10.6 KB
Line 
1/*
2 * QuteCom, a voice over Internet phone
3 * Copyright (C) 2010 Mbdsys
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20#include <system/Processes.h>
21
22#include <model/QuteCom.h>
23#include <model/config/CommandLineParser.h>
24#include <model/config/Config.h>
25#include <model/config/ConfigImporter.h>
26#include <model/config/ConfigManagerFileStorage.h>
27#include <model/config/ConfigManager.h>
28#include <model/config/StartupSettingListener.h>
29#include <model/classic/ClassicExterminator.h>
30#include <model/commandserver/CommandClient.h>
31#include <locale>
32
33#include <control/CQuteCom.h>
34
35#ifdef GTKINTERFACE
36        #include <presentation/gtk/GtkFactory.h>
37#else
38        #include <presentation/qt/QtFactory.h>
39        #include <presentation/qt/QtLanguage.h>
40#endif
41
42#include <imwrapper/IMWrapperFactory.h>
43#include <sipwrapper/SipWrapperFactory.h>
44#include <sipwrapper/SipWrapper.h>
45
46#include <QuteComBuildId.h>
47
48#ifdef PHAPIWRAPPER
49        #include <PhApiFactory.h>
50        #include <../src/null/NullIMFactory.h>
51#elif defined(SIPXWRAPPER)
52        #include <SipXFactory.h>
53        #include <NullIMFactory.h>
54#elif defined (MULTIIMWRAPPER)
55        #include <PhApiFactory.h>
56        #include <multiim/MultiIMFactory.h>
57        #include <PurpleIMFactory.h>
58#else
59        #include <NullSipFactory.h>
60        #include <NullIMFactory.h>
61#endif
62
63#include <util/File.h>
64#include <util/Logger.h>
65#include <util/Path.h>
66#include <util/SafeDelete.h>
67#include <util/WebBrowser.h>
68
69#include <system/RegisterProtocol.h>
70
71#include <qtutil/FSResourceFileEngineHandler.h>
72
73#include <cutil/global.h>
74
75#if defined(ENABLE_CRASHREPORT)
76#if defined(CC_MSVC)
77        #include <memorydump/MSVCMemoryDump.h>
78#elif defined(CC_MINGW)
79        #include <winsock2.h>
80#elif defined(OS_LINUX)
81        #include <memorydump/UNIXMemoryDump.h>
82#elif defined(OS_MACOSX)
83        #include <memorydump/MACMemoryDump.h>
84#endif
85#endif // ENABLE_CRASHREPORT
86
87#if defined(OS_MACOSX) || defined(OS_LINUX)
88        #include <signal.h>
89        #include <sys/wait.h>
90#endif
91
92#include <QtGui/QtGui>
93
94#include <sstream>
95
96#include <buildconfig.h>
97
98#if defined(OS_LINUX)
99    #include <X11/Xlib.h>
100#endif
101
102static const char* CONFIG_SUBDIR = "/config/";
103
104
105/**
106 * Helper class to instantiate and delete factories based on the compilation
107 * flags.
108 */
109struct FactoryHelper {
110        FactoryHelper() {
111        #ifdef SIPXWRAPPER
112                _sipFactory = new SipXFactory();
113                _imFactory = new NullIMFactory();
114
115        #elif defined(PHAPIWRAPPER)
116                _sipFactory = new PhApiFactory();
117                _imFactory = new NullIMFactory();
118
119        #elif defined(MULTIIMWRAPPER)
120                PhApiFactory* phApiFactory = new PhApiFactory();
121                _sipFactory = phApiFactory;
122                _purpleIMFactory = new PurpleIMFactory();
123                _imFactory = new MultiIMFactory(*phApiFactory, *_purpleIMFactory);
124
125        #else
126                _sipFactory = new NullSipFactory();
127                _imFactory = new NullIMFactory();
128        #endif
129
130                SipWrapperFactory::setFactory(_sipFactory);
131                IMWrapperFactory::setFactory(_imFactory);
132        }
133
134        ~FactoryHelper() {
135                OWSAFE_DELETE(_sipFactory);
136                OWSAFE_DELETE(_imFactory);
137
138        #ifdef MULTIIMWRAPPER
139                OWSAFE_DELETE(_purpleIMFactory);
140        #endif
141        }
142
143        IMWrapperFactory * _imFactory;
144        SipWrapperFactory * _sipFactory;
145
146#if defined(MULTIIMWRAPPER)
147        PurpleIMFactory* _purpleIMFactory;
148#endif
149
150};
151
152
153/**
154 * Stub function to make GCC silent.
155 *
156 * @see http://www-eleves-isia.cma.fr/documentation/BoostDoc/boost_1_29_0/libs/test/doc/minimal.htm
157 */
158int test_main(int argc, char *argv[]) {
159        return 1;
160}
161
162static void initLogger(const std::string& userConfigDir) {
163        std::string logFileName = userConfigDir + BINARY_NAME + ".log";
164        // create directory if it doesn't exist
165        if (!File::exists(userConfigDir)) {
166                File::createPath(userConfigDir);
167        }
168        if (!File::isDirectory(userConfigDir)) {
169                LOG_FATAL("User configuration dir '" + userConfigDir + "' does not exist or is not a directory");
170        }
171
172        Logger::getInstance()->setLogFileName(logFileName);
173}
174
175static void initConfig(const CommandLineParser& cmdLineParser) {
176        ConfigManagerFileStorage configManagerStorage(ConfigManager::getInstance());
177
178        std::string resourcesDir = cmdLineParser.getResourcesDir();
179        if (!File::isDirectory(resourcesDir)) {
180                LOG_FATAL("Resources dir '" + resourcesDir + "' does not exist or is not a directory");
181        }
182
183        std::string userConfigDir = cmdLineParser.getUserConfigDir();
184        configManagerStorage.loadSystemConfig(resourcesDir + CONFIG_SUBDIR);
185        Config::setConfigDir(userConfigDir);
186        ConfigImporter importer;
187        importer.importConfig();
188        configManagerStorage.loadUserConfig(userConfigDir);
189
190        Config & config = ConfigManager::getInstance().getCurrentConfig();
191        config.setResourcesDir(resourcesDir);
192        WebBrowser::setBrowser(config.getLinuxPreferedBrowser());
193}
194
195static void registerHyperlinkProtocol(const Config& config, const std::string& executableName) {
196        RegisterProtocol registerProtocol(config.getHyperlinkProtocol());
197        std::string executableFullName = Path::getApplicationDirPath() + executableName;
198        registerProtocol.bind(executableFullName + " -c %1", executableFullName + ",0", config.getCompanyWebSiteUrl());
199}
200
201/**
202 * Callback additional info for MemoryDump.
203 */
204std::string getAdditionalInfo() {
205        Config & config = ConfigManager::getInstance().getCurrentConfig();
206        std::stringstream stream;
207        stream
208                << "User: " << config.getProfileLastUsedName() << std::endl
209                << "buildid: " << QuteComBuildId::getBuildId() << std::endl
210                << "revision: " << QuteComBuildId::getSvnRevision() << std::endl;
211        return stream.str();
212}
213
214#if defined(OS_MACOSX) || defined(OS_LINUX)
215static void sigpipe_catcher(int sig) {
216#ifndef NDEBUG
217        // Do not use LOG_DEBUG. There is only a limited set of functions you are
218        // allowed to call from withing a signal catcher. See signal man page.
219        static char msg[] = "Caught signal: SIGPIPE\n";
220        write(2, msg, sizeof(msg));
221#endif
222}
223#endif
224
225int main(int argc, char * argv[]) {
226        //Init presentation factories before parsing the command line so that Qt or
227        //Gtk get a chance to parse their command line options ('-style' for Qt for
228        //example)
229        int nocrashreport = 0;
230#if defined(OS_MACOSX)
231        std::locale  lc;
232#else
233        std::locale lc("");
234#endif
235        std::locale::global(lc);
236
237        PFactory * pFactory = NULL;
238#if defined(OS_LINUX)
239        XInitThreads();
240#endif
241
242#ifdef GTKINTERFACE
243        pFactory = new GtkFactory(argc, argv);
244#else
245        pFactory = new QtFactory(argc, argv);
246#endif
247       
248#if defined(OS_MACOSX)
249        QDir dir(QApplication::applicationDirPath());
250        dir.cdUp();
251        dir.cd("plugins");
252        QApplication::setLibraryPaths(QStringList(dir.absolutePath()));
253#endif
254       
255        PFactory::setFactory(pFactory);
256
257        CommandLineParser cmdLineParser(BINARY_NAME, argc, argv);
258        initLogger(cmdLineParser.getUserConfigDir());
259        LOG_DEBUG("Started");
260
261#if defined(OS_MACOSX) || defined(OS_LINUX)
262        signal(SIGPIPE, sigpipe_catcher);
263#endif
264
265        // Setup factories. These must be initialized before loading config because
266        // it's used when importing configuration from the Classic version.
267        FactoryHelper factoryHelper;
268
269        initConfig(cmdLineParser);
270
271        Config & config = ConfigManager::getInstance().getCurrentConfig();
272
273        SipWrapper* w = factoryHelper._sipFactory->createSipWrapper();
274       
275        w->setSipOptions("sip.register_timeout", QString::number(config.getSipRegisterTimeOut()).toStdString());
276        w->setSipOptions("sip.publish_timeout", QString::number(config.getSipPublishTimeOut()).toStdString());
277        if(config.getSipUseOptions())
278                w->setSipOptions("sip.use_options_request", "true");
279        else
280                w->setSipOptions("sip.use_options_request", "false");
281
282        if(config.getSipP2pPresence())
283                w->setSipOptions("sip.p2p_presence", "true");
284        else
285                w->setSipOptions("sip.p2p_presence", "false");
286
287        if(config.getSipChatWithoutPresence())
288                w->setSipOptions("sip.chat.without.presence", "true");
289        else
290                w->setSipOptions("sip.chat.without.presence", "false");
291
292        if(config.getSipUseTypingState())
293                w->setSipOptions("sip.use_typing_state", "true");
294        else
295                w->setSipOptions("sip.use_typing_state", "false");
296
297
298        //Remove QuteCom Classic from startup registry
299        ClassicExterminator::killClassicExecutable();
300
301        //Remove QuteCom Classic from startup registry
302        ClassicExterminator::removeClassicFromStartup();
303
304#ifdef ENABLE_CRASHREPORT
305        for(int i = 1; i < argc; i++) {
306          if (!strcmp(argv[i], "-nocrash")) {
307            nocrashreport = 1;
308            break;
309          }
310        }
311
312        if (!nocrashreport) {
313    #if defined(CC_MSVC)
314          MSVCMemoryDump * memoryDump = new MSVCMemoryDump("QuteCom", QuteComBuildId::getSvnRevision());
315        // This is needed for CRT to not show dialog for invalid param
316        // failures and instead let the code handle it.
317          _CrtSetReportMode(_CRT_ASSERT, 0);
318    #endif
319
320    #if defined(OS_MACOSX)
321          MACMemoryDump * memoryDump = new MACMemoryDump("QuteCom", QuteComBuildId::getSvnRevision());
322    #endif
323
324    #if defined(OS_LINUX)
325          UNIXMemoryDump * memoryDump = new UNIXMemoryDump("QuteCom", QuteComBuildId::getSvnRevision());
326    #endif
327
328          memoryDump->setGetAdditionalInfo(getAdditionalInfo);
329        }
330
331#endif // ENABLE_CRASHREPORT
332
333        // Uncomment to test crash report
334       
335        /*int* pointer;
336        pointer = 0;
337        *pointer = 12;*/
338       
339
340        //No 2 qtqutecom at the same time
341        if (Processes::isRunning(BINARY_NAME) && !cmdLineParser.isSeveralQuteComAllowed()) {
342                const std::string callFromCommandLine = cmdLineParser.getCommand();
343                CommandClient client;
344                client.connect();
345                if (!callFromCommandLine.empty()) {
346                        client.call(callFromCommandLine);
347                } else {
348                        client.bringToFront();
349                }
350                return EXIT_SUCCESS;
351        }
352
353        // Register protocol used to associate the application in HTML links
354        registerHyperlinkProtocol(config, cmdLineParser.getExecutableName());
355
356        // Make the application starts when user logs on computer
357        StartupSettingListener settingListener(cmdLineParser.getExecutableName());
358
359        // Init file system resource engine
360        FSResourceFileEngineHandler handler(QString::fromStdString(config.getResourcesDir()));
361
362        // CQuteCom creates PQuteCom (QtQuteCom, GtkQuteCom...)
363        // and then starts the model thread. This way the gui is shown as soon as
364        // possible
365        QuteCom & qutecomPhone = QuteCom::getInstance();
366        qutecomPhone.setStartupCall(cmdLineParser.getCommand());
367        CQuteCom cQuteCom(qutecomPhone, cmdLineParser.getRunInBackground()||config.getGeneralStartBackgroundMode());
368        pFactory->exec();
369
370        QuteCom::deleteInstance();
371        LOG_DEBUG("Ended");
372
373        return EXIT_SUCCESS;
374}
Note: See TracBrowser for help on using the repository browser.