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 + -
显示快捷键?