app.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 1,488 行 · 第 1/4 页

CPP
1,488
字号
/***************************************************************************                      app.cpp  -  description                         -------------------begin                : Mit Okt 23 14:35:18 CEST 2002copyright            : (C) 2002 by Mark Kretschmannemail                : markey@web.de***************************************************************************//*************************************************************************** *                                                                         * *   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.                                   * *                                                                         * ***************************************************************************/#include "amarok.h"#include "amarokconfig.h"#include "amarokdcophandler.h"#include "app.h"#include "atomicstring.h"#include "config.h"#include "configdialog.h"#include "contextbrowser.h"#include "collectionbrowser.h"#include "dbsetup.h"             //firstRunWizard()#include "debug.h"#include "devicemanager.h"#include "mediadevicemanager.h"#include "enginebase.h"#include "enginecontroller.h"#include "equalizersetup.h"#include "firstrunwizard.h"#include "mediabrowser.h"#include "metabundle.h"#include "mountpointmanager.h"#include "osd.h"#include "playerwindow.h"#include "playlist.h"#include "playlistbrowser.h"#include "playlistwindow.h"#include "pluginmanager.h"#include "refreshimages.h"#include "scriptmanager.h"#include "scrobbler.h"#include "statusbar.h"#include "systray.h"#include "threadmanager.h"#include "tracktooltip.h"        //engineNewMetaData()#include <iostream>#include <kconfigdialogmanager.h>#include <kcombobox.h>           //firstRunWizard()#include <kcmdlineargs.h>        //initCliArgs()#include <kcursor.h>             //Amarok::OverrideCursor#include <kedittoolbar.h>        //slotConfigToolbars()#include <kglobalaccel.h>        //initGlobalShortcuts()#include <kglobalsettings.h>     //applyColorScheme()#include <kiconloader.h>         //amarok Icon#include <kkeydialog.h>          //slotConfigShortcuts()#include <klocale.h>#include <kmessagebox.h>         //applySettings(), genericEventHandler()#include <krun.h>                //Amarok::invokeBrowser()#include <kstandarddirs.h>#include <kurldrag.h>            //genericEventHandler()#include <kaboutdata.h>#include <kio/job.h>#include <qevent.h>              //genericEventHandler()#include <qeventloop.h>          //applySettings()#include <qfile.h>#include <qobjectlist.h>         //applyColorScheme()#include <qpalette.h>            //applyColorScheme()#include <qpixmap.h>             //QPixmap::setDefaultOptimization()#include <qpopupmenu.h>          //genericEventHandler#include <qtimer.h>              //showHyperThreadingWarning()#include <qtooltip.h>            //default tooltip for trayicon// For the HyperThreading fix#ifdef __linux__    #ifdef SCHEDAFFINITY_SUPPORT        #include <errno.h>        #include <sched.h>    #endif //SCHEDAFFINITY_SUPPORT#endif //__linux__QMutex Debug::mutex;QMutex Amarok::globalDirsMutex;int App::mainThreadId = 0;#ifdef Q_WS_MAC#include <qt_mac.h>static AEEventHandlerUPP appleEventProcessorUPP = 0;OSStatusappleEventProcessor(const AppleEvent *ae, AppleEvent *, long /*handlerRefCon*/){    OSType aeID = typeWildCard;    OSType aeClass = typeWildCard;    AEGetAttributePtr(ae, keyEventClassAttr, typeType, 0, &aeClass, sizeof(aeClass), 0);    AEGetAttributePtr(ae, keyEventIDAttr, typeType, 0, &aeID, sizeof(aeID), 0);    if(aeClass == kCoreEventClass)    {        if(aeID == kAEReopenApplication)        {            if( PlaylistWindow::self() )                PlaylistWindow::self()->show();        }        return noErr;    }    return eventNotHandledErr;}#endifLIBAMAROK_EXPORT KAboutData aboutData( "amarok",    I18N_NOOP( "Amarok" ), APP_VERSION,    I18N_NOOP( "The audio player for KDE" ), KAboutData::License_GPL,    I18N_NOOP( "(C) 2002-2003, Mark Kretschmann\n(C) 2003-2007, The Amarok Development Squad" ),    I18N_NOOP( "IRC:\nirc.freenode.net - #amarok, #amarok.de, #amarok.es\n\nFeedback:\namarok@kde.org\n\n(Build Date: " __DATE__ ")" ),             ( "http://amarok.kde.org" ) );App::App()        : KApplication()        , m_pPlayerWindow( 0 ) //will be created in applySettings(){    DEBUG_BLOCK#ifdef Q_WS_MAC    // this is inspired by OpenSceneGraph: osgDB/FilePath.cpp    // Start with the the Bundle PlugIns directory.    // Get the main bundle first. No need to retain or release it since    //  we are not keeping a reference    CFBundleRef myBundle = CFBundleGetMainBundle();    if( myBundle )    {        // CFBundleGetMainBundle will return a bundle ref even if        //  the application isn't part of a bundle, so we need to        //  check        //  if the path to the bundle ends in ".app" to see if it is        //  a        //  proper application bundle. If it is, the plugins path is        //  added        CFURLRef urlRef = CFBundleCopyBundleURL(myBundle);        if(urlRef)        {            char bundlePath[1024];            if( CFURLGetFileSystemRepresentation( urlRef, true, (UInt8 *)bundlePath, sizeof(bundlePath) ) )            {                QCString bp( bundlePath );                size_t len = bp.length();                if( len > 4 && bp.right( 4 ) == ".app" )                {                    bp.append( "/Contents/MacOS" );                    QCString path = getenv( "PATH" );                    if( path.length() > 0 )                    {                        path.prepend( ":" );                    }                    path.prepend( bp );                    debug() << "setting PATH=" << path << endl;                    setenv("PATH", path, 1);                }            }            // docs say we are responsible for releasing CFURLRef            CFRelease(urlRef);        }    }#endif    QPixmap::setDefaultOptimization( QPixmap::MemoryOptim );    //needs to be created before the wizard    new Amarok::DcopPlayerHandler(); // Must be created first    new Amarok::DcopPlaylistHandler();    new Amarok::DcopPlaylistBrowserHandler();    new Amarok::DcopContextBrowserHandler();    new Amarok::DcopCollectionHandler();    new Amarok::DcopMediaBrowserHandler();    new Amarok::DcopScriptHandler();    new Amarok::DcopDevicesHandler();    fixHyperThreading();    // tell AtomicString that this is the GUI thread    if ( !AtomicString::isMainThread() )        qWarning("AtomicString was initialized from a thread other than the GUI "                 "thread. This could lead to memory leaks.");#ifdef Q_WS_MAC    appleEventProcessorUPP = AEEventHandlerUPP(appleEventProcessor);    AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, appleEventProcessorUPP, (long)this, true);#endif    QTimer::singleShot( 0, this, SLOT( continueInit() ) );}App::~App(){    DEBUG_BLOCK    // Hiding the OSD before exit prevents crash    Amarok::OSD::instance()->hide();    EngineBase* const engine = EngineController::engine();    if ( AmarokConfig::resumePlayback() ) {        if ( engine->state() != Engine::Empty ) {            AmarokConfig::setResumeTrack( EngineController::instance()->playingURL().prettyURL() );            AmarokConfig::setResumeTime( engine->position() );        }        else AmarokConfig::setResumeTrack( QString::null ); //otherwise it'll play previous resume next time!    }    EngineController::instance()->endSession(); //records final statistics    EngineController::instance()->detach( this );    // do even if trayicon is not shown, it is safe    Amarok::config()->writeEntry( "HiddenOnExit", mainWindow()->isHidden() );    CollectionDB::instance()->stopScan();    delete m_pPlayerWindow;   //sets some XT keys    delete m_pPlaylistWindow; //sets some XT keys    ThreadManager::deleteInstance(); //waits for jobs to finish    // this must be deleted before the connection to the Xserver is    // severed, or we risk a crash when the QApplication is exited,    // I asked Trolltech! *smug*    delete Amarok::OSD::instance();    AmarokConfig::setVersion( APP_VERSION );    AmarokConfig::writeConfig();    //need to unload the engine before the kapplication is destroyed    PluginManager::unload( engine );}#include <dcopref.h>#include <qstringlist.h>namespace{    // grabbed from KsCD source, kompatctdisk.cpp    QString urlToDevice(const QString& device)    {        KURL deviceUrl(device);        if (deviceUrl.protocol() == "media" || deviceUrl.protocol() == "system")        {            DCOPRef mediamanager( "kded", "mediamanager" );            DCOPReply reply = mediamanager.call( "properties(QString)", deviceUrl.fileName() );            QStringList properties = reply;            if (!reply.isValid() || properties.count() < 6)            {                debug() << "Invalid reply from mediamanager" << endl;                return QString();            }            else            {                debug() << "Reply from mediamanager " << properties[5] << endl;                return properties[5];            }        }        return device;    }}void App::handleCliArgs() //static{    static char cwd[PATH_MAX];    KCmdLineArgs* const args = KCmdLineArgs::parsedArgs();    if ( args->isSet( "cwd" ) )    {        strncpy(cwd, args->getOption( "cwd" ), sizeof(cwd) );        cwd[sizeof(cwd)-1] = '\0';        KCmdLineArgs::setCwd( cwd );    }    bool haveArgs = false;    if ( args->count() > 0 )    {        haveArgs = true;        KURL::List list;        for( int i = 0; i < args->count(); i++ )        {            KURL url = args->url( i );            if( url.protocol() == "itpc" || url.protocol() == "pcast" )                PlaylistBrowser::instance()->addPodcast( url );            else                list << url;        }        int options = Playlist::DefaultOptions;        if( args->isSet( "queue" ) )           options = Playlist::Queue;        else if( args->isSet( "append" ) || args->isSet( "enqueue" ) )           options = Playlist::Append;        else if( args->isSet( "load" ) )            options = Playlist::Replace;        if( args->isSet( "play" ) )            options |= Playlist::DirectPlay;        Playlist::instance()->insertMedia( list, options );    }    //we shouldn't let the user specify two of these since it is pointless!    //so we prioritise, pause > stop > play > next > prev    //thus pause is the least destructive, followed by stop as brakes are the most important bit of a car(!)    //then the others seemed sensible. Feel free to modify this order, but please leave justification in the cvs log    //I considered doing some sanity checks (eg only stop if paused or playing), but decided it wasn't worth it    else if ( args->isSet( "pause" ) )    {        haveArgs = true;        EngineController::instance()->pause();    }    else if ( args->isSet( "stop" ) )    {        haveArgs = true;        EngineController::instance()->stop();    }    else if ( args->isSet( "play-pause" ) )    {        haveArgs = true;        EngineController::instance()->playPause();    }    else if ( args->isSet( "play" ) ) //will restart if we are playing    {        haveArgs = true;        EngineController::instance()->play();    }    else if ( args->isSet( "next" ) )    {        haveArgs = true;        EngineController::instance()->next();    }    else if ( args->isSet( "previous" ) )    {        haveArgs = true;        EngineController::instance()->previous();    }    else if (args->isSet("cdplay"))    {        haveArgs = true;        QString device = args->getOption("cdplay");        device = DeviceManager::instance()->convertMediaUrlToDevice( device );        KURL::List urls;        if (EngineController::engine()->getAudioCDContents(device, urls)) {            Playlist::instance()->insertMedia(                urls, Playlist::Replace|Playlist::DirectPlay);        } else { // Default behaviour            debug() <<                "Sorry, the engine doesn't support direct play from AudioCD..."                    << endl;        }    }    if ( args->isSet( "toggle-playlist-window" ) )    {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?