![]() |
Mixxx
|
00001 /*************************************************************************** 00002 main.cpp - description 00003 ------------------- 00004 begin : Mon Feb 18 09:48:17 CET 2002 00005 copyright : (C) 2002 by Tue and Ken Haste Andersen 00006 email : 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include <qapplication.h> 00019 #include <qfont.h> 00020 #include <qstring.h> 00021 #include <qtextcodec.h> 00022 #include <qtranslator.h> 00023 #include <qmessagebox.h> 00024 #include <qiodevice.h> 00025 #include <qfile.h> 00026 #include <qstringlist.h> 00027 #include <stdio.h> 00028 #include <math.h> 00029 #include "mixxx.h" 00030 #include "soundsourceproxy.h" 00031 #include "qpixmap.h" 00032 #include "qsplashscreen.h" 00033 #include "errordialoghandler.h" 00034 #include "defs_version.h" 00035 00036 #ifdef __LADSPA__ 00037 #include <ladspa/ladspaloader.h> 00038 #endif 00039 00040 #ifdef __WINDOWS__ 00041 #ifdef DEBUGCONSOLE 00042 #include <io.h> // Debug Console 00043 #include <windows.h> 00044 00045 void InitDebugConsole() { // Open a Debug Console so we can printf 00046 int fd; 00047 FILE *fp; 00048 00049 FreeConsole(); 00050 if (AllocConsole()) { 00051 SetConsoleTitleA("Mixxx Debug Messages"); 00052 00053 fd = _open_osfhandle((long) GetStdHandle(STD_OUTPUT_HANDLE), 0); 00054 fp = _fdopen(fd, "w"); 00055 00056 *stdout = *fp; 00057 setvbuf(stdout, NULL, _IONBF, 0); 00058 00059 fd = _open_osfhandle((long) GetStdHandle(STD_ERROR_HANDLE), 0); 00060 fp = _fdopen(fd, "w"); 00061 00062 *stderr = *fp; 00063 setvbuf(stderr, NULL, _IONBF, 0); 00064 } 00065 } 00066 #endif // DEBUGCONSOLE 00067 #endif // __WINDOWS__ 00068 00069 QApplication *a; 00070 00071 QStringList plugin_paths; //yes this is global. sometimes global is good. 00072 00073 //void qInitImages_mixxx(); 00074 00075 QFile Logfile; // global logfile variable 00076 00077 /* Debug message handler which outputs to both a logfile and a 00078 * and prepends the thread the message came from too. 00079 */ 00080 void MessageHandler(QtMsgType type, const char *input) 00081 { 00082 static QMutex mutex; 00083 QMutexLocker locker(&mutex); 00084 QByteArray ba; 00085 ba = "[" + QThread::currentThread()->objectName().toLocal8Bit() + "]: " + input + "\n"; 00086 00087 if(!Logfile.isOpen()) 00088 { 00089 QString logFileName = QDir::homePath().append("/").append(SETTINGS_PATH).append("/mixxx.log"); 00090 00091 // XXX will there ever be a case that we can't write to our current 00092 // working directory? 00093 Logfile.setFileName(logFileName); 00094 Logfile.open(QIODevice::WriteOnly | QIODevice::Text); 00095 } 00096 00097 ErrorDialogHandler* dialogHandler = ErrorDialogHandler::instance(); 00098 00099 switch (type) { 00100 case QtDebugMsg: 00101 #ifdef __WINDOWS__ //wtf? -kousu 2/2009 00102 if (strstr(input, "doneCurrent")) { 00103 break; 00104 } 00105 #endif 00106 fprintf(stderr, "Debug %s", ba.constData()); 00107 Logfile.write("Debug "); 00108 Logfile.write(ba); 00109 break; 00110 case QtWarningMsg: 00111 fprintf(stderr, "Warning %s", ba.constData()); 00112 Logfile.write("Warning "); 00113 Logfile.write(ba); 00114 // Don't use qWarning for reporting user-facing errors. 00115 //dialogHandler->requestErrorDialog(DLG_WARNING,input); 00116 break; 00117 case QtCriticalMsg: 00118 fprintf(stderr, "Critical %s", ba.constData()); 00119 Logfile.write("Critical "); 00120 Logfile.write(ba); 00121 Logfile.flush(); // Ensure the error is written to the log before exiting 00122 dialogHandler->requestErrorDialog(DLG_CRITICAL,input); 00123 // exit(-1); // Done in ErrorDialogHandler 00124 break; //NOTREACHED 00125 case QtFatalMsg: 00126 fprintf(stderr, "Fatal %s", ba.constData()); 00127 Logfile.write("Fatal "); 00128 Logfile.write(ba); 00129 Logfile.flush(); // Ensure the error is written to the log before aborting 00130 dialogHandler->requestErrorDialog(DLG_FATAL,input); 00131 // abort(); // Done in ErrorDialogHandler 00132 break; //NOTREACHED 00133 } 00134 Logfile.flush(); 00135 } 00136 00137 int main(int argc, char * argv[]) 00138 { 00139 // Check if an instance of Mixxx is already running 00140 // See http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Utilities/qtsingleapplication 00141 00142 // These need to be set early on (not sure how early) in order to trigger 00143 // logic in the OS X appstore support patch from QTBUG-16549. 00144 QCoreApplication::setOrganizationDomain("mixxx.org"); 00145 QCoreApplication::setOrganizationName("Mixxx"); 00146 00147 //it seems like this code should be inline in MessageHandler() but for some reason having it there corrupts the messages sometimes -kousu 2/2009 00148 00149 00150 #ifdef __WINDOWS__ 00151 #ifdef DEBUGCONSOLE 00152 InitDebugConsole(); 00153 #endif 00154 #endif 00155 qInstallMsgHandler(MessageHandler); 00156 00157 // Other things depend on this name to enforce thread exclusivity, 00158 // so if you change it here, change it also in: 00159 // * ErrorDialogHandler::errorDialog() 00160 QThread::currentThread()->setObjectName("Main"); 00161 QApplication a(argc, argv); 00162 00163 //Enumerate and load SoundSource plugins 00164 SoundSourceProxy::loadPlugins(); 00165 #ifdef __LADSPA__ 00166 //LADSPALoader ladspaloader; 00167 #endif 00168 00169 // Check if one of the command line arguments is "--no-visuals" 00170 // bool bVisuals = true; 00171 // for (int i=0; i<argc; ++i) 00172 // if(QString("--no-visuals")==argv[i]) 00173 // bVisuals = false; 00174 00175 // Construct a list of strings based on the command line arguments 00176 struct CmdlineArgs args; 00177 args.bStartInFullscreen = false; //Initialize vars 00178 00179 // Only match supported file types since command line options are also parsed elsewhere 00180 QRegExp fileRx(SoundSourceProxy::supportedFileExtensionsRegex(), Qt::CaseInsensitive); 00181 00182 for (int i = 0; i < argc; ++i) { 00183 if ( argv[i] == QString("-h") 00184 || argv[i] == QString("--h") 00185 || argv[i] == QString("--help") 00186 ) { 00187 fputs("Mixxx digital DJ software v",stdout); 00188 fputs(VERSION,stdout); 00189 fputs(" - Command line options",stdout); 00190 fputs( 00191 "\n(These are case-sensitive.)\n\n\ 00192 [FILE] Load the specified music file(s) at start-up.\n\ 00193 Each must be one of the following file types:\n\ 00194 ",stdout); 00195 00196 QString fileExtensions = SoundSourceProxy::supportedFileExtensionsString(); 00197 QByteArray fileExtensionsBA = QString(fileExtensions).toUtf8(); 00198 fputs(fileExtensionsBA.constData(),stdout); 00199 fputs("\n\n",stdout); 00200 fputs("\ 00201 Each file you specify will be loaded into the\n\ 00202 next virtual deck.\n\ 00203 \n\ 00204 --resourcePath PATH Top-level directory where Mixxx should look\n\ 00205 for its resource files such as MIDI mappings,\n\ 00206 overriding the default installation location.\n\ 00207 \n\ 00208 --pluginPath PATH Top-level directory where Mixxx shoud look\n\ 00209 for sound source plugins in addition to default\n\ 00210 locations.\n\ 00211 \n\ 00212 --midiDebug Causes Mixxx to display/log all of the MIDI\n\ 00213 messages it receives and script functions it loads\n\ 00214 \n\ 00215 --locale LOCALE Use a custom locale for loading translations\n\ 00216 (e.g 'fr')\n\ 00217 \n\ 00218 -f, --fullScreen Starts Mixxx in full-screen mode\n\ 00219 \n\ 00220 -h, --help Display this help message and exit",stdout); 00221 00222 fputs("\n\n(For more information, see http://mixxx.org/wiki/doku.php/command_line_options)\n",stdout); 00223 return(0); 00224 } 00225 00226 if (argv[i]==QString("-f").toLower() || argv[i]==QString("--f") || argv[i]==QString("--fullScreen")) 00227 { 00228 args.bStartInFullscreen = true; 00229 } else if (argv[i] == QString("--locale") && i+1 < argc) { 00230 args.locale = argv[i+1]; 00231 } else if (fileRx.indexIn(argv[i]) != -1) { 00232 args.qlMusicFiles += argv[i]; 00233 } 00234 } 00235 00236 // set up the plugin paths... 00237 /* 00238 qDebug() << "Setting up plugin paths..."; 00239 plugin_paths = QStringList(); 00240 QString ladspaPath = QString(getenv("LADSPA_PATH")); 00241 00242 if (!ladspaPath.isEmpty()) 00243 { 00244 // get the list of directories containing LADSPA plugins 00245 #ifdef __WINDOWS__ 00246 //paths.ladspaPath.split(';'); 00247 #else //this doesn't work, I think we need to iterate over the splitting to do it properly 00248 //paths = ladspaPath.split(':'); 00249 #endif 00250 } 00251 else 00252 { 00253 // add default path if LADSPA_PATH is not set 00254 #ifdef __LINUX__ 00255 plugin_paths.push_back ("/usr/lib/ladspa/"); 00256 plugin_paths.push_back ("/usr/lib64/ladspa/"); 00257 #elif __APPLE__ 00258 QDir dir(a.applicationDirPath()); 00259 dir.cdUp(); 00260 dir.cd("PlugIns"); 00261 plugin_paths.push_back ("/Library/Audio/Plug-ins/LADSPA"); 00262 plugin_paths.push_back (dir.absolutePath()); //ladspa_plugins directory in Mixxx.app bundle //XXX work in QApplication::appdir() 00263 #elif __WINDOWS__ 00264 // not tested yet but should work: 00265 QString programFiles = QString(getenv("ProgramFiles")); 00266 plugin_paths.push_back (programFiles+"\\LADSPA Plugins"); 00267 plugin_paths.push_back (programFiles+"\\Audacity\\Plug-Ins"); 00268 #endif 00269 } 00270 qDebug() << "...done."; 00271 */ 00272 00273 00274 #ifdef __APPLE__ 00275 QDir dir(QApplication::applicationDirPath()); 00276 // Set the search path for Qt plugins to be in the bundle's PlugIns 00277 // directory, but only if we think the mixxx binary is in a bundle. 00278 if (dir.path().contains(".app/")) { 00279 // If in a bundle, applicationDirPath() returns something formatted 00280 // like: .../Mixxx.app/Contents/MacOS 00281 dir.cdUp(); 00282 dir.cd("PlugIns"); 00283 qDebug() << "Setting Qt plugin search path to:" << dir.absolutePath(); 00284 // asantoni: For some reason we need to do setLibraryPaths() and not 00285 // addLibraryPath(). The latter causes weird problems once the binary 00286 // is bundled (happened with 1.7.2 when Brian packaged it up). 00287 QApplication::setLibraryPaths(QStringList(dir.absolutePath())); 00288 } 00289 #endif 00290 00291 MixxxApp* mixxx = new MixxxApp(&a, args); 00292 00293 //a.setMainWidget(mixxx); 00294 QObject::connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); 00295 00296 int result = -1; 00297 00298 if (!(ErrorDialogHandler::instance()->checkError())) { 00299 qDebug() << "Displaying mixxx"; 00300 mixxx->show(); 00301 00302 qDebug() << "Running Mixxx"; 00303 result = a.exec(); 00304 } 00305 00306 delete mixxx; 00307 00308 qDebug() << "Mixxx shutdown complete with code" << result; 00309 00310 qInstallMsgHandler(0); //Reset to default. 00311 00312 // Don't make any more output after this 00313 // or mixxx.log will get clobbered! 00314 if(Logfile.isOpen()) { 00315 Logfile.close(); 00316 } 00317 00318 //delete plugin_paths; 00319 return result; 00320 } 00321