/* * Cantata * * Copyright (c) 2011-2014 Craig Drummond * * ---- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "application.h" #ifdef ENABLE_KDE_SUPPORT #include #include #include #else #include #include #include #include #include #include #endif #include "support/utils.h" #include "config.h" #include "settings.h" #include "initialsettingswizard.h" #include "mainwindow.h" #include "mpd-interface/song.h" #include "support/thread.h" #include "db/librarydb.h" // To enable debug... #include "mpd-interface/mpdconnection.h" #include "mpd-interface/mpdparseutils.h" #include "covers.h" #include "context/wikipediaengine.h" #include "context/lastfmengine.h" #include "context/metaengine.h" #ifdef ENABLE_DYNAMIC #include "dynamic/dynamic.h" #endif #ifdef ENABLE_DEVICES_SUPPORT #include "models/devicesmodel.h" #endif #include "streams/streamfetcher.h" #include "http/httpserver.h" #include "widgets/songdialog.h" #include "network/networkaccessmanager.h" #include "context/ultimatelyricsprovider.h" #ifdef ENABLE_EXTERNAL_TAGS #include "tags/taghelperiface.h" #endif #include "context/contextwidget.h" #include "scrobbling/scrobbler.h" #ifndef ENABLE_KDE_SUPPORT #include "gui/mediakeys.h" #endif #include #include #include #include static QMutex msgMutex; static bool firstMsg=true; #if QT_VERSION < 0x050000 static void cantataQtMsgHandler(QtMsgType, const char *msg) #else static void cantataQtMsgHandler(QtMsgType, const QMessageLogContext &, const QString &msg) #endif { QMutexLocker locker(&msgMutex); QFile f(Utils::cacheDir(QString(), true)+"cantata.log"); if (f.open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text)) { QTextStream stream(&f); if (firstMsg) { stream << "------------START------------" << endl; firstMsg=false; } stream << QDateTime::currentDateTime().toString(Qt::ISODate).replace("T", " ") << " - " << msg << endl; } } #ifndef ENABLE_KDE_SUPPORT // Taken from Clementine! // // We convert from .po files to .qm files, which loses context information. // This translator tries loading strings with an empty context if it can't // find any others. class PoTranslator : public QTranslator { public: #if QT_VERSION < 0x050000 QString translate(const char *context, const char *sourceText, const char *disambiguation = 0) const { QString ret = QTranslator::translate(context, sourceText, disambiguation); return !ret.isEmpty() ? ret : QTranslator::translate(NULL, sourceText, disambiguation); } #else QString translate(const char *context, const char *sourceText, const char *disambiguation = 0, int n=-1) const { QString ret = QTranslator::translate(context, sourceText, disambiguation, n); return !ret.isEmpty() ? ret : QTranslator::translate(NULL, sourceText, disambiguation, n); } #endif }; static void loadTranslation(const QString &prefix, const QString &path, const QString &overrideLanguage = QString()) { #if QT_VERSION < 0x040700 // QTranslator::load will try to open and read "cantata" if it exists, // without checking if it's a file first. // This was fixed in Qt 4.7 QFileInfo maybeCantataDirectory(path + "/cantata"); if (maybeCantataDirectory.exists() && !maybeCantataDirectory.isFile()) { return; } #endif QString language = overrideLanguage.isEmpty() ? QLocale::system().name() : overrideLanguage; QTranslator *t = new PoTranslator; if (t->load(prefix+"_"+language, path)) { QCoreApplication::installTranslator(t); } else { delete t; } #if QT_VERSION < 0x050000 QTextCodec::setCodecForTr(QTextCodec::codecForLocale()); #endif } #endif static void removeOldFiles(const QString &d, const QStringList &types) { if (!d.isEmpty()) { QDir dir(d); if (dir.exists()) { QFileInfoList files=dir.entryInfoList(types, QDir::Files|QDir::NoDotAndDotDot); foreach (const QFileInfo &file, files) { QFile::remove(file.absoluteFilePath()); } QString dirName=dir.dirName(); if (!dirName.isEmpty()) { dir.cdUp(); dir.rmdir(dirName); } } } } static void removeOldFiles() { // Remove Cantata 1.x XML cache files removeOldFiles(Utils::cacheDir("library"), QStringList() << "*.xml" << "*.xml.gz"); removeOldFiles(Utils::cacheDir("jamendo"), QStringList() << "*.xml.gz"); removeOldFiles(Utils::cacheDir("magnatune"), QStringList() << "*.xml.gz"); } enum Debug { Dbg_Mpd = 0x00000001, Dbg_MpdParse = 0x00000002, Dbg_Covers = 0x00000004, Dbg_Context_Wikipedia = 0x00000008, Dbg_Context_LastFm = 0x00000010, Dbg_Context_Meta = 0x00000020, Dbg_Context_Widget = 0x00000040, // Dbg_Context_Backdrop = 0x00000080, Dbg_Dynamic = 0x00000100, Dbg_StreamFetching = 0x00000200, Dbg_HttpServer = 0x00000400, Dbg_SongDialogs = 0x00000800, Dbg_NetworkAccess = 0x00001000, Dbg_Context_Lyrics = 0x00002000, Dbg_Threads = 0x00004000, Dbg_Tags = 0x00008000, Dbg_Scrobbling = 0x00010000, Dbg_Devices = 0x00020000, Dbg_Sql = 0x00040000, DBG_Other = 0x00080000, // NOTE: MUST UPDATE Dbg_All IF ADD NEW ITEMS!!! Dbg_All = 0x000FFFFF }; static void installDebugMessageHandler() { QString debug=qgetenv("CANTATA_DEBUG"); if (!debug.isEmpty()) { int dbg=0; if (debug.contains(QLatin1String("0x"))) { dbg=debug.startsWith(QLatin1Char('-')) ? (debug.mid(1).toInt(0, 16)*-1) : debug.toInt(0, 16); } else { dbg=debug.toInt(); } bool logToFile=dbg>0; if (dbg<0) { dbg*=-1; } if (dbg&Dbg_Mpd) { MPDConnection::enableDebug(); } if (dbg&Dbg_MpdParse) { MPDParseUtils::enableDebug(); } if (dbg&Dbg_Covers) { Covers::enableDebug(); } if (dbg&Dbg_Context_Wikipedia) { WikipediaEngine::enableDebug(); } if (dbg&Dbg_Context_LastFm) { LastFmEngine::enableDebug(); } if (dbg&Dbg_Context_Meta) { MetaEngine::enableDebug(); } if (dbg&Dbg_Context_Widget) { ContextWidget::enableDebug(); } #ifdef ENABLE_DYNAMIC if (dbg&Dbg_Dynamic) { Dynamic::enableDebug(); } #endif if (dbg&Dbg_StreamFetching) { StreamFetcher::enableDebug(); } if (dbg&Dbg_HttpServer) { HttpServer::enableDebug(); } if (dbg&Dbg_SongDialogs) { SongDialog::enableDebug(); } if (dbg&Dbg_NetworkAccess) { NetworkAccessManager::enableDebug(); } if (dbg&Dbg_Context_Lyrics) { UltimateLyricsProvider::enableDebug(); } if (dbg&Dbg_Threads) { ThreadCleaner::enableDebug(); } #ifdef ENABLE_EXTERNAL_TAGS if (dbg&Dbg_Tags) { TagHelperIface::enableDebug(); } #endif if (dbg&Dbg_Scrobbling) { Scrobbler::enableDebug(); } #ifdef ENABLE_DEVICES_SUPPORT if (dbg&Dbg_Devices) { DevicesModel::enableDebug(); } #endif if (dbg&Dbg_Sql) { LibraryDb::enableDebug(); } #ifndef ENABLE_KDE_SUPPORT if (dbg&DBG_Other) { MediaKeys::enableDebug(); } #endif if (dbg&Dbg_All && logToFile) { #if QT_VERSION < 0x050000 qInstallMsgHandler(cantataQtMsgHandler); #else qInstallMessageHandler(cantataQtMsgHandler); #endif } } } int main(int argc, char *argv[]) { QThread::currentThread()->setObjectName("GUI"); #ifdef ENABLE_KDE_SUPPORT KAboutData aboutData(PACKAGE_NAME, 0, ki18n("Cantata"), PACKAGE_VERSION_STRING, ki18n("A KDE client for MPD"), KAboutData::License_GPL_V3, ki18n("© 2011-2014 Craig Drummond"), KLocalizedString(), "https://github.com/CDrummond/cantata", "craig.p.drummond@gmail.com"); aboutData.addAuthor(ki18n("Craig Drummond"), ki18n("Maintainer"), "craig.p.drummond@gmail.com"); aboutData.addAuthor(ki18n("Piotr Wicijowski"), ki18n("UI Improvements"), "piotr.wicijowski@gmail.com"); aboutData.addAuthor(ki18n("Sander Knopper"), ki18n("QtMPC author"), QByteArray(), "http://qtmpc.lowblog.nl"); aboutData.addAuthor(ki18n("Roeland Douma"), ki18n("QtMPC author"), QByteArray(), "http://qtmpc.lowblog.nl"); aboutData.addAuthor(ki18n("Daniel Selinger"), ki18n("QtMPC author"), QByteArray(), "http://qtmpc.lowblog.nl"); aboutData.addAuthor(ki18n("Armin Walland"), ki18n("QtMPC author"), QByteArray(), "http://qtmpc.lowblog.nl"); aboutData.addCredit(ki18n("FanArt.tv"), ki18n("Context view backdrops (please consider uploading your own music fan-art to fanart.tv)"), QByteArray(), "www.fanart.tv"); aboutData.addCredit(ki18n("Wikipedia"), ki18n("Context view metadata"), QByteArray(), "www.wikipedia.org"); aboutData.addCredit(ki18n("Last.fm"), ki18n("Context view metadata"), QByteArray(), "www.last.fm"); KCmdLineArgs::init(argc, argv, &aboutData); #ifdef TAGLIB_FOUND KCmdLineOptions options; options.add("+[URL]", ki18n("URL to open")); KCmdLineArgs::addCmdLineOptions(options); KUniqueApplication::addCmdLineOptions(); #endif if (!KUniqueApplication::start()) { exit(0); } Application app; removeOldFiles(); installDebugMessageHandler(); #else // ENABLE_KDE_SUPPORT QCoreApplication::setApplicationName(PACKAGE_NAME); QCoreApplication::setOrganizationName(ORGANIZATION_NAME); Application app(argc, argv); if (!app.start()) { return 0; } // Set the permissions on the config file on Unix - it can contain passwords // for internet services so it's important that other users can't read it. // On Windows these are stored in the registry instead. #ifdef Q_OS_UNIX QSettings s; // Create the file if it doesn't exist already if (!QFile::exists(s.fileName())) { QFile file(s.fileName()); file.open(QIODevice::WriteOnly); } // Set -rw------- QFile::setPermissions(s.fileName(), QFile::ReadOwner | QFile::WriteOwner); #endif removeOldFiles(); installDebugMessageHandler(); // Translations QString lang=Settings::self()->lang(); #if defined Q_OS_WIN || defined Q_OS_MAC loadTranslation("qt", CANTATA_SYS_TRANS_DIR, lang); #else loadTranslation("qt", QLibraryInfo::location(QLibraryInfo::TranslationsPath), lang); #endif loadTranslation("cantata", CANTATA_SYS_TRANS_DIR, lang); Application::initObjects(); if (Settings::self()->firstRun()) { InitialSettingsWizard wz; if (QDialog::Rejected==wz.exec()) { return 0; } } MainWindow mw; #if defined Q_OS_WIN || defined Q_OS_MAC app.setActivationWindow(&mw); #endif // !defined Q_OS_MAC app.loadFiles(); if (!Settings::self()->startHidden()) { mw.show(); } #endif // ENABLE_KDE_SUPPORT return app.exec(); }