/********************************************************************** Audacity: A Digital Audio Editor ODWaveTrackTaskQueue.h Created by Michael Chinen (mchinen) on 6/11/08 Audacity(R) is copyright (c) 1999-2008 Audacity Team. License: GPL v2. See License.txt. ******************************************************************//** \class ODWaveTrackTaskQueue \brief watches over all to be done (not yet started and started but not finished) tasks associated with a WaveTrack. *//*******************************************************************/ #include "ODWaveTrackTaskQueue.h" #include "ODTask.h" #include "ODManager.h" /// Constructs an ODWaveTrackTaskQueue ODWaveTrackTaskQueue::ODWaveTrackTaskQueue() { } ODWaveTrackTaskQueue::~ODWaveTrackTaskQueue() { //we need to delete all ODTasks. We will have to block or wait until block for the active ones. for(unsigned int i=0;iTerminateAndBlock();//blocks if active. //small chance we may have rea-added the task back into the queue from a diff thread. - so remove it if we have. ODManager::Instance()->RemoveTaskIfInQueue(mTasks[i]); delete mTasks[i]; } } ///returns whether or not this queue's task list and another's can merge together, as when we make two mono tracks stereo. bool ODWaveTrackTaskQueue::CanMergeWith(ODWaveTrackTaskQueue* otherQueue) { //have to be very careful when dealing with two lists that need to be locked. if(GetNumTasks()!=otherQueue->GetNumTasks()) return false; mTasksMutex.Lock(); for(unsigned int i=0;iCanMergeWith(otherQueue->GetTask(i))) { mTasksMutex.Unlock(); return false; } } mTasksMutex.Unlock(); return true; } ///add track to the masterTrack's queue - this will allow future ODScheduling to affect them together. /// sets the NeedODUpdateFlag since we don't want the head task to finish without haven't dealt with the depednent /// ///@param track the track to bring into the tasks AND tracklist for this queue void ODWaveTrackTaskQueue::MergeWaveTrack(WaveTrack* track) { AddWaveTrack(track); mTasksMutex.Lock(); for(unsigned int i=0;iAddWaveTrack(track); mTasks[i]->SetNeedsODUpdate(); } mTasksMutex.Unlock(); } ///returns true if the argument is in the WaveTrack list. bool ODWaveTrackTaskQueue::ContainsWaveTrack(WaveTrack* track) { mTracksMutex.Lock(); for(unsigned int i=0;iGetNumWaveTracks();i++) { //task->GetWaveTrack(i) may return NULL, but we handle it by checking before using. //The other worry that the WaveTrack returned and was deleted in the meantime is also //handled since mQueuesMutex is locked one up in the stack from here, //and WaveTrack deletion is bound to that. mTracks.push_back(task->GetWaveTrack(i)); } mTracksMutex.Unlock(); } ///Removes a track from the list. Also notifies mTasks to stop using references ///to the instance in a thread-safe manner (may block) void ODWaveTrackTaskQueue::RemoveWaveTrack(WaveTrack* track) { if(track) { mTasksMutex.Lock(); for(unsigned int i=0;iStopUsingWaveTrack(track); mTasksMutex.Unlock(); mTracksMutex.Lock(); for(unsigned int i=0;iClone(); task->AddWaveTrack(track); //AddNewTask requires us to relinquish this lock. However, it is safe because ODManager::MakeWaveTrackIndependent //has already locked the m_queuesMutex. mTasksMutex.Unlock(); //AddNewTask locks the m_queuesMutex which is already locked by ODManager::MakeWaveTrackIndependent, //so we pass a boolean flag telling it not to lock again. ODManager::Instance()->AddNewTask(task,false); mTasksMutex.Lock(); } mTasksMutex.Unlock(); mTracksMutex.Lock(); break; } } mTracksMutex.Unlock(); } ///changes the tasks associated with this Waveform to process the task from a different point in the track ///@param track the track to update ///@param seconds the point in the track from which the tasks associated with track should begin processing from. void ODWaveTrackTaskQueue::DemandTrackUpdate(WaveTrack* track, double seconds) { if(track) { mTracksMutex.Lock(); for(unsigned int i=0;iDemandTrackUpdate(track,seconds); } mTracksMutex.Unlock(); } } //Replaces all instances of a wavetracck with a new one (effectively transferes the task.) void ODWaveTrackTaskQueue::ReplaceWaveTrack(WaveTrack* oldTrack, WaveTrack* newTrack) { if(oldTrack) { mTasksMutex.Lock(); for(unsigned int i=0;iReplaceWaveTrack(oldTrack,newTrack); mTasksMutex.Unlock(); mTracksMutex.Lock(); for(unsigned int i=0;i=0&&x=0&&xRecalculatePercentComplete(); bool ret; ret = mTasks[0]->IsComplete(); mTasksMutex.Unlock(); return ret; } mTasksMutex.Unlock(); return false; } ///Removes and deletes the front task from the list. void ODWaveTrackTaskQueue::RemoveFrontTask() { mTasksMutex.Lock(); if(mTasks.size()) { //wait for the task to stop running. delete mTasks[0]; mTasks.erase(mTasks.begin()); } mTasksMutex.Unlock(); } ///gets the front task for immediate execution ODTask* ODWaveTrackTaskQueue::GetFrontTask() { mTasksMutex.Lock(); if(mTasks.size()) { mTasksMutex.Unlock(); return mTasks[0]; } mTasksMutex.Unlock(); return NULL; } ///fills in the status bar message for a given track void ODWaveTrackTaskQueue::FillTipForWaveTrack( WaveTrack * t, const wxChar ** ppTip ) { if(ContainsWaveTrack(t) && GetNumTasks()) { // if(GetNumTasks()==1) mTipMsg.Printf(_("%s %2.0f%% complete. Click to change task focal point."), GetFrontTask()->GetTip(), GetFrontTask()->PercentComplete()*100.0 ); // else // msg.Printf(_("%s %n additional tasks remaining."), GetFrontTask()->GetTip().c_str(), GetNumTasks()); *ppTip = mTipMsg.c_str(); } }