moodbar.cpp

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

CPP
1,387
字号
    m_mutex.lock();    // Check if the currently running job is for that URL    if( m_currentProcess != 0  &&        m_currentData.m_url == bundle->url() )      {        debug() << "MoodServer::queueJob: Not re-queueing already-running job "                << bundle->url().path() << endl;        m_mutex.unlock();        return true;      }    // Check if there's already a job in the queue for that URL    QValueList<ProcData>::iterator it;    for( it = m_jobQueue.begin(); it != m_jobQueue.end(); ++it )      {        if( (*it).m_url == bundle->url() )          {            (*it).m_refcount++;            debug() << "MoodServer::queueJob: Job for " << bundle->url().path()                    << " already in queue, increasing refcount to "                    << (*it).m_refcount << endl;            m_mutex.unlock();            return false;          }      }    m_jobQueue.append( ProcData( bundle->url(),                                 bundle->url().path(),                                 bundle->moodbar().moodFilename( bundle->url() ) ) );    debug() << "MoodServer::queueJob: Queued job for " << bundle->url().path()            << ", " << m_jobQueue.size() << " jobs in queue." << endl;    m_mutex.unlock();    // New jobs *must* be started from the GUI thread!    QTimer::singleShot( 1000, this, SLOT( slotNewJob( void ) ) );    return false;}// Decrements the refcount of the job for the given URL// and deletes that job if necessary.voidMoodServer::deQueueJob( KURL url ){    m_mutex.lock();    // Can't de-queue running jobs    if( m_currentProcess != 0  &&        m_currentData.m_url == url )      {        debug() << "MoodServer::deQueueJob: Not de-queueing already-running job "                << url.path() << endl;        m_mutex.unlock();        return;      }    // Check if there's already a job in the queue for that URL    QValueList<ProcData>::iterator it;    for( it = m_jobQueue.begin(); it != m_jobQueue.end(); ++it )      {        if( (*it).m_url == url )          {            (*it).m_refcount--;            if( (*it).m_refcount == 0 )              {                debug() << "MoodServer::deQueueJob: nobody cares about "                        << (*it).m_url.path()                        << " anymore, deleting from queue" << endl;                m_jobQueue.erase( it );              }            else              debug() << "MoodServer::deQueueJob: decrementing refcount of "                      << (*it).m_url.path() << " to " << (*it).m_refcount                      << endl;            m_mutex.unlock();            return;          }      }    debug() << "MoodServer::deQueueJob: tried to delete nonexistent job "            << url.path() << endl;    m_mutex.unlock();}// This slot exists so that jobs can be started from the GUI thread,// just in case queueJob() is run from another thread.  Only run// directly if you're in the GUI thread!voidMoodServer::slotNewJob( void ){  if( m_moodbarBroken )    return;  m_mutex.lock();  // Are we already running a process?  if( m_jobQueue.isEmpty()  ||  m_currentProcess != 0 )    {      m_mutex.unlock();      return;    }  m_currentData = m_jobQueue.first();  m_jobQueue.pop_front();  debug() << "MoodServer::slotNewJob: starting new analyzer process: "          << "moodbar -o " << m_currentData.m_outfile << ".tmp "          << m_currentData.m_infile << endl;  debug() << "MoodServer::slotNewJob: " << m_jobQueue.size()          << " jobs left in queue." << endl;  // Write to outfile.mood.tmp so that new Moodbar instances  // don't think the mood data exists while the analyzer is  // running.  Then rename the file later.  m_currentProcess = new Amarok::Process( this );  m_currentProcess->setPriority( 18 );  // Nice the process  *m_currentProcess << KStandardDirs::findExe( "moodbar" ) << "-o"                    << (m_currentData.m_outfile + ".tmp")                    << m_currentData.m_infile;  connect( m_currentProcess, SIGNAL( processExited( KProcess* ) ),           SLOT( slotJobCompleted( KProcess* ) ) );  // We have to enable KProcess::Stdout (even though we don't monitor  // it) since otherwise the child process crashes every time in  // KProcess::start() (but only when started from the loader!).  I  // have no idea why, but I imagine it's a bug in KDE.  if( !m_currentProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) )    {      // If we have an error starting the process, it's never      // going to work, so call moodbarBroken()      warning() << "Can't start moodbar analyzer process!" << endl;      delete m_currentProcess;      m_currentProcess = 0;      m_mutex.unlock();      setMoodbarBroken();      return;    }  // Extreme reentrancy pedatry :)  KURL url = m_currentData.m_url;  m_mutex.unlock();  emit jobEvent( url, Moodbar::JobStateRunning );}// This always run in the GUI thread.  It is called// when an analyzer process terminatesvoidMoodServer::slotJobCompleted( KProcess *proc ){    m_mutex.lock();    // Pedantry    if( proc != m_currentProcess )      warning() << "MoodServer::slotJobCompleted: proc != m_currentProcess!" << endl;    ReturnStatus returnval;    if( !m_currentProcess->normalExit() )      returnval = Crash;    else      returnval = (ReturnStatus) m_currentProcess->exitStatus();    bool success = (returnval == Success);    KURL url = m_currentData.m_url;    if( success )      {        QString file = m_currentData.m_outfile;        QString dir = file.left( file.findRev( '/' ) );        file = file.right( file.length() - file.findRev( '/' ) - 1 );        QDir( dir ).rename( file + ".tmp", file );      }    else      QFile::remove( m_currentData.m_outfile + ".tmp" );    delete m_currentProcess;    m_currentProcess = 0;    // If the moodbar was disabled, we killed the process    if( !AmarokConfig::showMoodbar() )      {        debug() << "MoodServer::slotJobCompleted: moodbar disabled, job killed" << endl;        m_mutex.unlock();        emit jobEvent( url, Moodbar::JobStateFailed );        return;      }    switch( returnval )      {      case Success:        debug() << "MoodServer::slotJobCompleted: job completed successfully" << endl;        m_mutex.unlock();        slotNewJob();        break;        // Crash and NoFile don't mean that moodbar is broken.        // Something bad happened, but it's probably a problem with this file        // Just log an error message and emit jobEvent().      case Crash:        debug() << "MoodServer::slotJobCompleted: moodbar crashed on "                << m_currentData.m_infile << endl;        m_mutex.unlock();        slotNewJob();        break;      case NoFile:        debug() << "MoodServer::slotJobCompleted: moodbar had a problem with "                << m_currentData.m_infile << endl;        m_mutex.unlock();        slotNewJob();        break;        // NoPlugin and CommandLine mean the moodbar is broken        // The moodbar analyzer is not likely to work ever, so let the        // user know about it and disable new jobs.      default:        m_mutex.unlock();        setMoodbarBroken();        break;      }    emit jobEvent( url, success ? Moodbar::JobStateSucceeded                                : Moodbar::JobStateFailed );}// This is called whenever "Ok" or "Apply" is pressed on the configuration// dialog.  If the moodbar is disabled, kill the current process and// clear the queuevoidMoodServer::slotMoodbarPrefs( bool show, bool moodier, int alter, bool withMusic ){    if( show == true)      return;    (void) moodier;  (void) alter;  (void) withMusic;    // If we have a current process, kill it.  Cleanup happens in    // slotJobCompleted() above.  We do *not* want to lock the    // mutex when calling this!    if( m_currentProcess != 0 )      m_currentProcess->kill();    clearJobs();}// When a file is deleted, either manually using Organize Collection or// automatically detected using AFT, delete the corresponding mood file.voidMoodServer::slotFileDeleted( const QString &path ){    QString mood = Moodbar::moodFilename( KURL::fromPathOrURL( path ) );    if( mood.isEmpty()  ||  !QFile::exists( mood ) )      return;    debug() << "MoodServer::slotFileDeleted: deleting " << mood << endl;    QFile::remove( mood );}// When a file is moved, either manually using Organize Collection or// automatically using AFT, move the corresponding mood file.voidMoodServer::slotFileMoved( const QString &srcPath, const QString &dstPath ){    QString srcMood = Moodbar::moodFilename( KURL::fromPathOrURL( srcPath ) );    QString dstMood = Moodbar::moodFilename( KURL::fromPathOrURL( dstPath ) );    if( srcMood.isEmpty()   ||  dstMood.isEmpty()  ||        srcMood == dstMood  ||  !QFile::exists( srcMood ) )      return;    debug() << "MoodServer::slotFileMoved: moving " << srcMood << " to "            << dstMood << endl;    Moodbar::copyFile( srcMood, dstMood );    QFile::remove( srcMood );}// This is called when we decide that the moodbar analyzer is// never going to work.  Disable further jobs, and let the user// know about it.  This should only be called when m_currentProcess == 0.voidMoodServer::setMoodbarBroken( void ){    warning() << "Uh oh, it looks like the moodbar analyzer is not going to work"              << endl;    Amarok::StatusBar::instance()->longMessage( i18n(        "The Amarok moodbar analyzer program seems to be broken. "        "This is probably because the moodbar package is not installed "        "correctly.  The moodbar package, installation instructions, and "        "troubleshooting help can be found on the wiki page at <a href='"        WEBPAGE "'>" WEBPAGE "</a>. "        "When the problem is fixed, please restart Amarok."),        KDE::StatusBar::Error );    m_moodbarBroken = true;    clearJobs();}// Clear the job list and emit signalsvoidMoodServer::clearJobs( void ){    // We don't want to emit jobEvent (or really do anything    // external) while the mutex is locked.    m_mutex.lock();    QValueList<ProcData> queueCopy      = QDeepCopy< QValueList<ProcData> > ( m_jobQueue );    m_jobQueue.clear();    m_mutex.unlock();    QValueList<ProcData>::iterator it;    for( it = queueCopy.begin(); it != queueCopy.end(); ++it )      emit jobEvent( (*it).m_url, Moodbar::JobStateFailed );}///////////////////////////////////////////////////////////////////////////////// Moodbar class///////////////////////////////////////////////////////////////////////////////// The moodbar behavior is nearly identical in the JobQueued and// JobRunning states, but we have to keep track anyway so the

⌨️ 快捷键说明

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