1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-12-16 17:41:14 +01:00

Remove trailing spaces.

This commit is contained in:
benjamin.drung@gmail.com
2014-06-03 20:30:19 +00:00
parent d921c4969b
commit 277932dccb
380 changed files with 6489 additions and 6491 deletions

View File

@@ -35,41 +35,41 @@ class ODComputeSummaryTask:public ODTask
/// Constructs an ODTask
ODComputeSummaryTask();
virtual ~ODComputeSummaryTask(){};
virtual ODTask* Clone();
///Subclasses should override to return respective type.
virtual unsigned int GetODType(){return eODPCMSummary;}
///Return the task name
virtual const char* GetTaskName(){return "ODComputeSummaryTask";}
virtual const wxChar* GetTip(){return _("Import complete. Calculating waveform");}
virtual bool UsesCustomWorkUntilPercentage(){return true;}
virtual float ComputeNextWorkUntilPercentageComplete();
///releases memory that the ODTask owns. Subclasses should override.
virtual void Terminate();
protected:
///recalculates the percentage complete.
virtual void CalculatePercentComplete();
///Computes and writes the data for one BlockFile if it still has a refcount.
///Computes and writes the data for one BlockFile if it still has a refcount.
virtual void DoSomeInternal();
///Readjusts the blockfile order in the default manner. If we have had an ODRequest
///Then it updates in the OD manner.
virtual void Update();
///Orders the input as either On-Demand or default layered order.
void OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &unorderedBlocks);
///tells us whether or not Update has been run at least once.
///tells us whether or not Update has been run at least once.
void MarkUpdateRan();
bool HasUpdateRan();
//mBlockFiles is touched on several threads- the OD terminate thread, and the task thread, so we need to mutex it.
ODLock mBlockFilesMutex;
std::vector<ODPCMAliasBlockFile*> mBlockFiles;

View File

@@ -18,7 +18,7 @@
#include <wx/window.h>
#endif
#include "../Experimental.h"
#include "../Experimental.h"
#ifdef USE_FFMPEG
#ifdef EXPERIMENTAL_OD_FFMPEG
@@ -60,22 +60,22 @@ public:
///This should handle unicode converted to UTF-8 on mac/linux, but OD TODO:check on windows
ODFFmpegDecoder(const wxString & fileName, streamContext** scs, int numStreams,WaveTrack*** channels, AVFormatContext* formatContext, int streamIndex);
virtual ~ODFFmpegDecoder();
///Decodes the samples for this blockfile from the real file into a float buffer.
///Decodes the samples for this blockfile from the real file into a float buffer.
///This is file specific, so subclasses must implement this only.
///the buffer was defined like
///samplePtr sampleData = NewSamples(mLen, floatSample);
///this->ReadData(sampleData, floatSample, 0, mLen);
///This class should call ReadHeader() first, so it knows the length, and can prepare
///the file object if it needs to.
///This class should call ReadHeader() first, so it knows the length, and can prepare
///the file object if it needs to.
virtual int Decode(samplePtr & data, sampleFormat & format, sampleCount start, sampleCount len, unsigned int channel);
///This is a must implement abstract virtual in the superclass.
///This is a must implement abstract virtual in the superclass.
///However it doesn't do anything because ImportFFMpeg does all that for us.
virtual bool ReadHeader() {return true;}
bool SeekingAllowed() ;
private:
void InsertCache(FFMpegDecodeCache* cache);
@@ -85,13 +85,13 @@ private:
///! Reads next audio frame
///\return pointer to the stream context structure to which the frame belongs to or NULL on error, or 1 if stream is not to be imported.
streamContext* ReadNextFrame();
///! Decodes the frame
///\param sc - stream context (from ReadNextFrame)
///\param flushing - true if flushing (no more frames left), false otherwise
///\return 0 on success, -1 if it can't decode any further
int DecodeFrame(streamContext *sc, bool flushing);
int mNumStreams;
streamContext **mScs; //!< Array of pointers to stream contexts. Length is mNumStreams.
WaveTrack*** mChannels;
@@ -100,13 +100,13 @@ private:
int mNumSamplesInCache;
sampleCount mCurrentPos; //the index of the next sample to be decoded
sampleCount mCurrentLen; //length of the last packet decoded
bool mSeekingAllowedStatus;
int mStreamIndex;
};
//------ ODDecodeFFmpegTask definitions
//------ ODDecodeFFmpegTask definitions
ODDecodeFFmpegTask::ODDecodeFFmpegTask(void* scs,int numStreams, WaveTrack*** channels, void* formatContext, int streamIndex)
{
mScs=scs;
@@ -149,7 +149,7 @@ ODFileDecoder* ODDecodeFFmpegTask::CreateFileDecoder(const wxString & fileName)
/// subclasses need to override this if they cannot always seek.
/// seeking will be enabled once this is true.
bool ODFFmpegDecoder::SeekingAllowed()
bool ODFFmpegDecoder::SeekingAllowed()
{
return false;
/*
@@ -157,7 +157,7 @@ bool ODFFmpegDecoder::SeekingAllowed()
return mSeekingAllowedStatus == ODFFMPEG_SEEKING_TEST_SUCCESS;
//we can seek if the following checks pass:
//-sample rate is less than the reciprocal of the time_base of the seeking stream.
//-sample rate is less than the reciprocal of the time_base of the seeking stream.
//-a seek test has been made and dts updates as expected.
//we want to clone this to run a seek test.
AVFormatContext* ic = (AVFormatContext*)mFormatContext;
@@ -168,27 +168,27 @@ bool ODFFmpegDecoder::SeekingAllowed()
for (unsigned int i = 0; i < ic->nb_streams; i++)
{
if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioStreamExists = true;
{
audioStreamExists = true;
st = ic->streams[i];
if(st->duration <= 0 || st->codec->sample_rate <= 0)
goto test_failed;
//if the time base reciprocal is less than the sample rate it means we can't accurately represent a sample with the timestamp in av.
float time_base_inv = ((float)st->time_base.den/st->time_base.num);
//if the time base reciprocal is less than the sample rate it means we can't accurately represent a sample with the timestamp in av.
float time_base_inv = ((float)st->time_base.den/st->time_base.num);
if(time_base_inv < st->codec->sample_rate)
goto test_failed;
}
}
if(!audioStreamExists)
goto test_failed;
//TODO: now try a seek and see if dts/pts (decode/presentation timestamp) is updated as we expected it to be.
//TODO: now try a seek and see if dts/pts (decode/presentation timestamp) is updated as we expected it to be.
//This should be done using a new AVFormatContext clone so that we don't ruin the file pointer if we fail.
// url_fseek(mFormatContext->pb,0,SEEK_SET);
// url_fseek(mFormatContext->pb,0,SEEK_SET);
AVFormatContext* tempContext;
int err;
err = ufile_fopen_input(&tempContext, mFName);
@@ -230,8 +230,8 @@ mCurrentLen(0),
mSeekingAllowedStatus(ODFFMPEG_SEEKING_TEST_UNKNOWN),
mStreamIndex(streamIndex)
{
PickFFmpegLibs();
PickFFmpegLibs();
//do a shallow copy of the 2d array.
mChannels = new WaveTrack **[mNumStreams];
@@ -251,8 +251,8 @@ mStreamIndex(streamIndex)
stream_delay = mScs[streamIndex]->m_stream->start_time;
}
mCurrentPos = double(stream_delay) / AV_TIME_BASE;
//TODO: add a ref counter to scs? This will be necessary if we want to allow copy and paste of not-yet decoded
//TODO: add a ref counter to scs? This will be necessary if we want to allow copy and paste of not-yet decoded
//ODDecodeBlockFiles that point to FFmpeg files.
}
@@ -273,15 +273,15 @@ ODFFmpegDecoder::~ODFFmpegDecoder()
delete mScs[i];
}
free(mScs);
//delete our caches.
while(mDecodeCache.size())
{
free(mDecodeCache[0]->samplePtr);
delete mDecodeCache[0];
mDecodeCache.erase(mDecodeCache.begin());
mDecodeCache.erase(mDecodeCache.begin());
}
//free the channel pointer arrays
for (int s = 0; s < mNumStreams; s++)
{
@@ -295,7 +295,7 @@ ODFFmpegDecoder::~ODFFmpegDecoder()
//this value controls this amount. this should be a value that is much larger than the payload for a single packet, and around block file size around 1-10 secs.
#define kDecodeSampleAllowance 400000
//number of jump backwards seeks
#define kMaxSeekRewindAttempts 8
#define kMaxSeekRewindAttempts 8
int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount start, sampleCount len, unsigned int channel)
{
format = mScs[mStreamIndex]->m_osamplefmt;
@@ -303,17 +303,17 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
data = NewSamples(len, format);
samplePtr bufStart = data;
streamContext* sc = NULL;
int nChannels;
// printf("start %llu len %llu\n", start, len);
// printf("start %llu len %llu\n", start, len);
//TODO update this to work with seek - this only works linearly now.
if(mCurrentPos > start && mCurrentPos <= start+len + kDecodeSampleAllowance)
{
//this next call takes data, start and len as reference variables and updates them to reflect the new area that is needed.
FillDataFromCache(bufStart, format, start,len,channel);
}
bool seeking = false;
//look at the decoding timestamp and see if the next sample that will be decoded is not the next sample we need.
if(len && (mCurrentPos > start + len || mCurrentPos + kDecodeSampleAllowance < start ) && SeekingAllowed()) {
@@ -321,14 +321,14 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
AVStream* st = sc->m_stream;
int stindex = -1;
uint64_t targetts;
//printf("attempting seek to %llu\n", start);
//printf("attempting seek to %llu\n", start);
//we have to find the index for this stream.
for (unsigned int i = 0; i < mFormatContext->nb_streams; i++) {
if (mFormatContext->streams[i] == sc->m_stream )
stindex =i;
}
if(stindex >=0) {
int numAttempts = 0;
//reset mCurrentPos to a bogus value
@@ -336,18 +336,18 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
while(numAttempts++ < kMaxSeekRewindAttempts && mCurrentPos > start) {
//we want to move slightly before the start of the block file, but not too far ahead
targetts = (start-kDecodeSampleAllowance*numAttempts/kMaxSeekRewindAttempts) * ((double)st->time_base.den/(st->time_base.num * st->codec->sample_rate ));
if(targetts<0)
if(targetts<0)
targetts=0;
//printf("attempting seek to %llu, attempts %d\n", targetts, numAttempts);
//printf("attempting seek to %llu, attempts %d\n", targetts, numAttempts);
if(av_seek_frame(mFormatContext,stindex,targetts,0) >= 0){
//find out the dts we've seekd to.
//find out the dts we've seekd to.
sampleCount actualDecodeStart = 0.5 + st->codec->sample_rate * st->cur_dts * ((double)st->time_base.num/st->time_base.den); //this is mostly safe because den is usually 1 or low number but check for high values.
mCurrentPos = actualDecodeStart;
seeking = true;
//if the seek was past our desired position, rewind a bit.
//if the seek was past our desired position, rewind a bit.
//printf("seek ok to %llu samps, float: %f\n",actualDecodeStart,actualDecodeStartDouble);
} else {
printf("seek failed");
@@ -356,14 +356,14 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
}
if(mCurrentPos>start){
mSeekingAllowedStatus = (bool)ODFFMPEG_SEEKING_TEST_FAILED;
// url_fseek(mFormatContext->pb,sc->m_pkt.pos,SEEK_SET);
// url_fseek(mFormatContext->pb,sc->m_pkt.pos,SEEK_SET);
printf("seek fail, reverting to previous pos\n");
return -1;
}
}
}
bool firstpass = true;
//we decode up to the end of the blockfile
while (len>0 && (mCurrentPos < start+len) && (sc = ReadNextFrame()) != NULL)
{
@@ -378,7 +378,7 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
// for some formats
// The only other case for inserting silence is for initial offset and ImportFFmpeg.cpp does this for us
if (seeking) {
actualDecodeStart = 0.52 + (sc->m_stream->codec->sample_rate * sc->m_pkt.dts
actualDecodeStart = 0.52 + (sc->m_stream->codec->sample_rate * sc->m_pkt.dts
* ((double)sc->m_stream->time_base.num / sc->m_stream->time_base.den));
//this is mostly safe because den is usually 1 or low number but check for high values.
@@ -398,9 +398,9 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
FFMpegDecodeCache* cache = new FFMpegDecodeCache;
//printf("skipping/zeroing %i samples. - now:%llu (%f), last:%llu, lastlen:%llu, start %llu, len %llu\n",amt,actualDecodeStart, actualDecodeStartdouble, mCurrentPos, mCurrentLen, start, len);
//put it in the cache so the other channels can use it.
cache->numChannels = sc->m_stream->codec->channels;
cache->numChannels = sc->m_stream->codec->channels;
cache->len = amt;
cache->start=start;
// 8 bit and 16 bit audio output from ffmpeg means
@@ -414,7 +414,7 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
cache->samplePtr = (uint8_t*) malloc(amt * cache->numChannels * SAMPLE_SIZE(format));
memset(cache->samplePtr, 0, amt * cache->numChannels * SAMPLE_SIZE(format));
InsertCache(cache);
}
firstpass=false;
@@ -431,7 +431,7 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
{
av_free_packet(&sc->m_pkt);
sc->m_pktValid = 0;
}
}
}
}
@@ -446,14 +446,14 @@ int ODFFmpegDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount
{
av_free_packet(&mScs[i]->m_pkt);
mScs[i]->m_pktValid = 0;
}
}
}
}
}
//this next call takes data, start and len as reference variables and updates them to reflect the new area that is needed.
FillDataFromCache(bufStart, format, start, len, channel);
// CHECK: not sure if we need this. In any case it has to be updated for the new float case (not just int16)
//if for some reason we couldn't get the samples, fill them with silence
/*
@@ -475,10 +475,10 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
if(mDecodeCache.size() <= 0)
return 0;
int samplesFilled=0;
//do a search for the best position to start at.
//do a search for the best position to start at.
//Guess that the array is evenly spaced from end to end - (dictionary sort)
//assumes the array is sorted.
//assumes the array is sorted.
//all we need for this to work is a location in the cache array
//that has a start time of less than our start sample, but try to get closer with binary search
int searchStart = 0;
@@ -491,7 +491,7 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
while(searchStart+1<searchEnd)
{
guess = (searchStart+searchEnd)/2;//find a midpoint. //searchStart+ (searchEnd-searchStart)* ((float)start - mDecodeCache[searchStart]->start )/mDecodeCache[searchEnd]->start;
//we want guess to point at the first index that hits even if there are duplicate start times (which can happen)
if(mDecodeCache[guess]->start+mDecodeCache[guess]->len >= start)
searchEnd = --guess;
@@ -499,15 +499,15 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
searchStart = guess;
}
}
//this is a sorted array
for(int i=searchStart; i < (int)mDecodeCache.size(); i++)
{
{
//check for a cache hit - be careful to include the first/last sample an nothing more.
//we only accept cache hits that touch either end - no piecing out of the middle.
//this way the amount to be decoded remains set.
if(start < mDecodeCache[i]->start+mDecodeCache[i]->len &&
start + len > mDecodeCache[i]->start)
start + len > mDecodeCache[i]->start)
{
uint8_t* outBuf;
outBuf = (uint8_t*)data;
@@ -515,12 +515,12 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
//a method of dealing with this yet, and it won't happen very often.
if(start<mDecodeCache[i]->start && start+len > mDecodeCache[i]->start+mDecodeCache[i]->len)
continue;
int samplesHit;
int hitStartInCache;
int hitStartInRequest;
int nChannels = mDecodeCache[i]->numChannels;
samplesHit = FFMIN(start+len,mDecodeCache[i]->start+mDecodeCache[i]->len)
samplesHit = FFMIN(start+len,mDecodeCache[i]->start+mDecodeCache[i]->len)
- FFMAX(mDecodeCache[i]->start,start);
//find the start of the hit relative to the cache buffer start.
hitStartInCache = FFMAX(0,start-mDecodeCache[i]->start);
@@ -537,24 +537,24 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
//printf("u8 in %llu out %llu cachelen %llu outLen %llu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((int16_t *)outBuf)[outIndex] = (int16_t) (((uint8_t*)mDecodeCache[i]->samplePtr)[inIndex] - 0x80) << 8;
break;
case SAMPLE_FMT_S16:
//printf("u16 in %llu out %llu cachelen %llu outLen %llu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((int16_t *)outBuf)[outIndex] = ((int16_t*)mDecodeCache[i]->samplePtr)[inIndex];
break;
case SAMPLE_FMT_S32:
//printf("s32 in %llu out %llu cachelen %llu outLen %llu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
//printf("s32 in %llu out %llu cachelen %llu outLen %llu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((float *)outBuf)[outIndex] = (float) ((int32_t*)mDecodeCache[i]->samplePtr)[inIndex] * (1.0 / (1 << 31));
break;
case SAMPLE_FMT_FLT:
//printf("f in %llu out %llu cachelen %llu outLen %llu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((float *)outBuf)[outIndex] = (float) ((float*)mDecodeCache[i]->samplePtr)[inIndex];
break;
case SAMPLE_FMT_DBL:
//printf("dbl in %llu out %llu cachelen %llu outLen %llu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
//printf("dbl in %llu out %llu cachelen %llu outLen %llu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((float *)outBuf)[outIndex] = (float) ((double*)mDecodeCache[i]->samplePtr)[inIndex];
break;
@@ -566,7 +566,7 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
}
//update the cursor
samplesFilled += samplesHit;
//update the input start/len params - if the end was hit we can take off just len.
//otherwise, we can assume only the front of the request buffer was hit since we don't allow it to be split.
if(start < mDecodeCache[i]->start)
@@ -601,7 +601,7 @@ int ODFFmpegDecoder::DecodeFrame(streamContext *sc, bool flushing)
if (ret == 0 && sc->m_frameValid) {
//stick it in the cache.
//TODO- consider growing/unioning a few cache buffers like WaveCache does.
//TODO- consider growing/unioning a few cache buffers like WaveCache does.
//however we can't use wavecache as it isn't going to handle our stereo interleaved part, and isn't for samples
//However if other ODDecode tasks need this, we should do a new class for caching.
FFMpegDecodeCache* cache = new FFMpegDecodeCache;
@@ -613,7 +613,7 @@ int ODFFmpegDecoder::DecodeFrame(streamContext *sc, bool flushing)
cache->samplePtr = (uint8_t*) malloc(sc->m_decodedAudioSamplesValidSiz);
cache->samplefmt = sc->m_samplefmt;
memcpy(cache->samplePtr, sc->m_decodedAudioSamples, sc->m_decodedAudioSamplesValidSiz);
InsertCache(cache);
}
return ret;
@@ -621,11 +621,11 @@ int ODFFmpegDecoder::DecodeFrame(streamContext *sc, bool flushing)
void ODFFmpegDecoder::InsertCache(FFMpegDecodeCache* cache) {
int searchStart = 0;
int searchEnd = mDecodeCache.size(); //size() is also a valid insert index.
int searchEnd = mDecodeCache.size(); //size() is also a valid insert index.
int guess = 0;
//first just guess that the cache is contiguous and we can just use math to figure it out like a dictionary
//by guessing where our hit will be.
// printf("inserting cache start %llu, mCurrentPos %llu\n", cache->start, mCurrentPos);
while(searchStart<searchEnd)
{
@@ -641,13 +641,13 @@ void ODFFmpegDecoder::InsertCache(FFMpegDecodeCache* cache) {
searchStart = ++guess;
}
mCurrentLen = cache->len;
mCurrentPos=cache->start+cache->len;
mCurrentPos=cache->start+cache->len;
mDecodeCache.insert(mDecodeCache.begin()+guess, cache);
// mDecodeCache.push_back(cache);
mNumSamplesInCache+=cache->len;
//if the cache is too big, drop some.
//if the cache is too big, drop some.
while(mNumSamplesInCache>kMaxSamplesInCache)
{
int dropindex;
@@ -656,7 +656,7 @@ void ODFFmpegDecoder::InsertCache(FFMpegDecodeCache* cache) {
mNumSamplesInCache-=mDecodeCache[dropindex]->len;
free(mDecodeCache[dropindex]->samplePtr);
delete mDecodeCache[dropindex];
mDecodeCache.erase(mDecodeCache.begin()+dropindex);
mDecodeCache.erase(mDecodeCache.begin()+dropindex);
}
}

View File

@@ -34,8 +34,8 @@ class ODDecodeFFmpegTask:public ODDecodeTask
virtual ODTask* Clone();
///Creates an ODFileDecoder that decodes a file of filetype the subclass handles.
virtual ODFileDecoder* CreateFileDecoder(const wxString & fileName);
///Lets other classes know that this class handles the ffmpeg type
///Lets other classes know that this class handles the ffmpeg type
///Subclasses should override to return respective type.
virtual unsigned int GetODType(){return eODFFMPEG;}

View File

@@ -15,7 +15,7 @@
#include <wx/file.h>
#include <wx/ffile.h>
#ifdef USE_LIBID3TAG
#ifdef USE_LIBID3TAG
extern "C" {
#include <id3tag.h>
}
@@ -85,8 +85,8 @@ void ODFLACFile::metadata_callback(const FLAC__StreamMetadata *metadata)
void ODFLACFile::error_callback(FLAC__StreamDecoderErrorStatus status)
{
mWasError = true;
switch (status)
{
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
@@ -109,16 +109,16 @@ void ODFLACFile::error_callback(FLAC__StreamDecoderErrorStatus status)
FLAC__StreamDecoderWriteStatus ODFLACFile::write_callback(const FLAC__Frame *frame,
const FLAC__int32 * const buffer[])
{
unsigned int bytesToCopy = frame->header.blocksize;
if(bytesToCopy>mDecoder->mDecodeBufferLen-mDecoder->mDecodeBufferWritePosition)
bytesToCopy=mDecoder->mDecodeBufferLen-mDecoder->mDecodeBufferWritePosition;
//the decodeBuffer was allocated to be the same format as the flac buffer, so we can do a straight up memcpy.
memcpy(mDecoder->mDecodeBuffer+SAMPLE_SIZE(mDecoder->mFormat)*mDecoder->mDecodeBufferWritePosition,buffer[mDecoder->mTargetChannel],SAMPLE_SIZE(mDecoder->mFormat) * bytesToCopy);
mDecoder->mDecodeBufferWritePosition+=bytesToCopy;
/*
/*
short *tmp=new short[frame->header.blocksize];
for (unsigned int chn=0; chn<mDecoder->mNumChannels; chn++) {
@@ -142,10 +142,10 @@ FLAC__StreamDecoderWriteStatus ODFLACFile::write_callback(const FLAC__Frame *fra
*/
mDecoder->mSamplesDone += frame->header.blocksize;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
// return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
// mDecoder->mUpdateResult = mDecoder->mProgress->Update((wxULongLong_t) mDecoder->mSamplesDone, mDecoder->mNumSamples != 0 ? (wxULongLong_t)mDecoder->mNumSamples : 1);
/*
if (mDecoder->mUpdateResult != eProgressSuccess)
@@ -159,44 +159,44 @@ FLAC__StreamDecoderWriteStatus ODFLACFile::write_callback(const FLAC__Frame *fra
//--Decoder stuff:
///Decodes the samples for this blockfile from the real file into a float buffer.
///Decodes the samples for this blockfile from the real file into a float buffer.
///This is file specific, so subclasses must implement this only.
///the buffer was defined like
///samplePtr sampleData = NewSamples(mLen, floatSample);
///this->ReadData(sampleData, floatSample, 0, mLen);
///This class should call ReadHeader() first, so it knows the length, and can prepare
///the file object if it needs to.
///This class should call ReadHeader() first, so it knows the length, and can prepare
///the file object if it needs to.
int ODFlacDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount start, sampleCount len, unsigned int channel)
{
//we need to lock this so the target stays fixed over the seek/write callback.
mFlacFileLock.Lock();
bool usingCache=mLastDecodeStartSample==start;
if(usingCache)
{
//we've just decoded this, so lets use a cache. (often so for
//we've just decoded this, so lets use a cache. (often so for
}
mDecodeBufferWritePosition=0;
mDecodeBufferLen = len;
data = NewSamples(len, mFormat);
mDecodeBuffer=data;
format = mFormat;
mTargetChannel=channel;
if(!mFile->seek_absolute(start))
{
mFlacFileLock.Unlock();
return -1;
}
}
while(mDecodeBufferWritePosition<mDecodeBufferLen)
mFile->process_single();
mFlacFileLock.Unlock();
if(!usingCache)
{
@@ -206,9 +206,9 @@ int ODFlacDecoder::Decode(samplePtr & data, sampleFormat & format, sampleCount s
//calculate summary happen in ODDecodeBlockFile::WriteODDecodeBlockFile, where this method is also called.
return 1;
}
///Read header. Subclasses must override. Probably should save the info somewhere.
///Ideally called once per decoding of a file. This complicates the task because
///Ideally called once per decoding of a file. This complicates the task because
///returns true if the file exists and the header was read alright.
//Note:we are not using LEGACY_FLAC defs (see ImportFlac.cpp FlacImportFileHandle::Init()
@@ -219,7 +219,7 @@ bool ODFlacDecoder::ReadHeader()
//we want to use the native flac type for quick conversion.
/* (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);*/
if(mFile)
if(mFile)
delete mFile;
mFile = new ODFLACFile(this);
@@ -252,11 +252,11 @@ bool ODFlacDecoder::ReadHeader()
// This probably is not a FLAC file at all
return false;
}
MarkInitialized();
return true;
}
}
ODFLACFile* ODFlacDecoder::GetFlacFile()
{
@@ -264,7 +264,7 @@ ODFLACFile* ODFlacDecoder::GetFlacFile()
}
ODFlacDecoder::~ODFlacDecoder(){
if(mFile)
if(mFile)
{
mFile->finish();
delete mFile;
@@ -290,7 +290,7 @@ ODFileDecoder* ODDecodeFlacTask::CreateFileDecoder(const wxString & fileName)
cnt = binaryFile.Read(query, sizeof(query));
cnt = id3_tag_query(query, cnt);
binaryFile.Seek(cnt);
#endif
#endif
char buf[5];
cnt = binaryFile.Read(buf, 4);
@@ -298,9 +298,9 @@ ODFileDecoder* ODDecodeFlacTask::CreateFileDecoder(const wxString & fileName)
if (cnt == wxInvalidOffset || strncmp(buf, FLAC_HEADER, 4) != 0) {
// File is not a FLAC file
return NULL;
return NULL;
}
// Open the file for import
ODFlacDecoder *decoder = new ODFlacDecoder(fileName);
*/

View File

@@ -15,7 +15,7 @@
This is an abstract class that subclasses will have to derive the types
from. For any type there should only be one ODDecodeTask associated with
a given track.
a given track.
There could be the ODBlockFiles of several FLACs in one track (after copy and pasting),
so things aren't as simple as they seem - the implementation needs to be
robust enough to allow all the user changes such as copy/paste, delete, and so on.
@@ -49,13 +49,13 @@ class ODDecodeFlacTask:public ODDecodeTask
/// Constructs an ODTask
ODDecodeFlacTask(){}
virtual ~ODDecodeFlacTask();
virtual ODTask* Clone();
///Creates an ODFileDecoder that decodes a file of filetype the subclass handles.
virtual ODFileDecoder* CreateFileDecoder(const wxString & fileName);
///Lets other classes know that this class handles flac
///Lets other classes know that this class handles flac
///Subclasses should override to return respective type.
virtual unsigned int GetODType(){return eODFLAC;}
};
@@ -71,7 +71,7 @@ class ODFLACFile : public FLAC::Decoder::File
set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT);
set_metadata_respond(FLAC__METADATA_TYPE_STREAMINFO);
}
bool get_was_error() const
{
return mWasError;
@@ -81,7 +81,7 @@ class ODFLACFile : public FLAC::Decoder::File
ODFlacDecoder *mDecoder;
bool mWasError;
wxArrayString mComments;
protected:
virtual FLAC__StreamDecoderWriteStatus write_callback(const FLAC__Frame *frame,
const FLAC__int32 * const buffer[]);
@@ -98,20 +98,20 @@ public:
///This should handle unicode converted to UTF-8 on mac/linux, but OD TODO:check on windows
ODFlacDecoder(const wxString & fileName):ODFileDecoder(fileName),mSamplesDone(0){mFile=NULL;}
virtual ~ODFlacDecoder();
///Decodes the samples for this blockfile from the real file into a float buffer.
///Decodes the samples for this blockfile from the real file into a float buffer.
///This is file specific, so subclasses must implement this only.
///the buffer was defined like
///samplePtr sampleData = NewSamples(mLen, floatSample);
///this->ReadData(sampleData, floatSample, 0, mLen);
///This class should call ReadHeader() first, so it knows the length, and can prepare
///the file object if it needs to.
///This class should call ReadHeader() first, so it knows the length, and can prepare
///the file object if it needs to.
virtual int Decode(samplePtr & data, sampleFormat & format, sampleCount start, sampleCount len, unsigned int channel);
///Read header. Subclasses must override. Probably should save the info somewhere.
///Ideally called once per decoding of a file. This complicates the task because
virtual bool ReadHeader();
///Ideally called once per decoding of a file. This complicates the task because
virtual bool ReadHeader();
///FLAC specific file (inherited from FLAC::Decoder::File)
ODFLACFile* GetFlacFile();

View File

@@ -26,9 +26,9 @@ ODDecodeTask::ODDecodeTask()
mMaxBlockFiles = 0;
mComputedBlockFiles = 0;
}
///Computes and writes the data for one BlockFile if it still has a refcount.
///Computes and writes the data for one BlockFile if it still has a refcount.
void ODDecodeTask::DoSomeInternal()
{
if(mBlockFiles.size()<=0)
@@ -38,20 +38,20 @@ void ODDecodeTask::DoSomeInternal()
mPercentCompleteMutex.Unlock();
return;
}
ODDecodeBlockFile* bf;
ODFileDecoder* decoder;
sampleCount blockStartSample = 0;
sampleCount blockEndSample = 0;
bool success =false;
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
{
bf = mBlockFiles[0];
int ret = 1;
//first check to see if the ref count is at least 2. It should have one
//first check to see if the ref count is at least 2. It should have one
//from when we added it to this instance's mBlockFiles array, and one from
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
if(bf->RefCount()>=2)
@@ -67,7 +67,7 @@ void ODDecodeTask::DoSomeInternal()
bf->SetODFileDecoder(decoder);
ret = bf->DoWriteBlockFile();
bf->UnlockRead();
if(ret >= 0) {
success = true;
blockStartSample = bf->GetStart();
@@ -81,13 +81,13 @@ void ODDecodeTask::DoSomeInternal()
//because now there is less work to do.
mMaxBlockFiles--;
}
//Release the refcount we placed on it if we are successful
if(ret >= 0 ) {
bf->Deref();
//take it out of the array - we are done with it.
mBlockFiles.erase(mBlockFiles.begin());
//upddate the gui for all associated blocks. It doesn't matter that we're hitting more wavetracks then we should
//because this loop runs a number of times equal to the number of tracks, they probably are getting processed in
//the next iteration at the same sample window.
@@ -99,8 +99,8 @@ void ODDecodeTask::DoSomeInternal()
}
mWaveTrackMutex.Unlock();
}
}
}
//update percentage complete.
CalculatePercentComplete();
}
@@ -112,7 +112,7 @@ void ODDecodeTask::CalculatePercentComplete()
mPercentCompleteMutex.Unlock();
}
bool ODDecodeTask::SeekingAllowed()
bool ODDecodeTask::SeekingAllowed()
{
for (unsigned int i = 0; i < mDecoders.size(); i++) {
if(!mDecoders[i]->SeekingAllowed())
@@ -126,9 +126,9 @@ void ODDecodeTask::Update()
{
std::vector<ODDecodeBlockFile*> tempBlocks;
mWaveTrackMutex.Lock();
for(size_t j=0;j<mWaveTracks.size();j++)
{
if(mWaveTracks[j])
@@ -136,21 +136,21 @@ void ODDecodeTask::Update()
WaveClip *clip;
BlockArray *blocks;
Sequence *seq;
//gather all the blockfiles that we should process in the wavetrack.
WaveClipList::compatibility_iterator node = mWaveTracks[j]->GetClipIterator();
while(node) {
clip = node->GetData();
seq = clip->GetSequence();
//TODO:this lock is way to big since the whole file is one sequence. find a way to break it down.
seq->LockDeleteUpdateMutex();
//See Sequence::Delete() for why need this for now..
blocks = clip->GetSequenceBlockArray();
int i;
int insertCursor;
insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)
for(i=0; i<(int)blocks->GetCount(); i++)
{
@@ -160,24 +160,24 @@ void ODDecodeTask::Update()
blocks->Item(i)->f->Ref();
((ODDecodeBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start);
((ODDecodeBlockFile*)blocks->Item(i)->f)->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
while(insertCursor<(int)tempBlocks.size()&&
(sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) <
while(insertCursor<(int)tempBlocks.size()&&
(sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) <
(sampleCount)(((ODDecodeBlockFile*)blocks->Item(i)->f)->GetStart()+((ODDecodeBlockFile*)blocks->Item(i)->f)->GetClipOffset()))
insertCursor++;
tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODDecodeBlockFile*)blocks->Item(i)->f);
}
}
}
seq->UnlockDeleteUpdateMutex();
node = node->GetNext();
}
}
}
mWaveTrackMutex.Unlock();
//get the new order.
OrderBlockFiles(tempBlocks);
}
@@ -194,23 +194,23 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
//TODO:order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
//for now just put them in linear. We start the order from the first block that includes the ondemand sample
//(which the user sets by clicking.) note that this code is pretty hacky - it assumes that the array is sorted in time.
//find the startpoint
sampleCount processStartSample = GetDemandSample();
sampleCount processStartSample = GetDemandSample();
for(int i= ((int)unorderedBlocks.size())-1;i>= 0;i--)
{
//check to see if the refcount is at least two before we add it to the list.
//There should be one Ref() from the one added by this ODTask, and one from the track.
//There should be one Ref() from the one added by this ODTask, and one from the track.
//If there isn't, then the block was deleted for some reason and we should ignore it.
if(unorderedBlocks[i]->RefCount()>=2)
{
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
//and add ones that are closer.
//and add ones that are closer.
//since the order is linear right to left, this will add blocks so that the ones on the right side of the target
//are processed first, with the ones closer being processed earlier. Then the ones on the left side get processed.
if(mBlockFiles.size() &&
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
if(mBlockFiles.size() &&
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart()) )
{
//insert at the front of the list if we get blockfiles that are after the demand sample
@@ -230,11 +230,11 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
unorderedBlocks[i]->Deref();
}
}
}
}
///changes the tasks associated with this Waveform to process the task from a different point in the track
///this is overridden from ODTask because certain classes don't allow users to seek sometimes, or not at all.
void ODDecodeTask::DemandTrackUpdate(WaveTrack* track, double seconds)
@@ -266,7 +266,7 @@ ODFileDecoder* ODDecodeTask::GetOrCreateMatchingFileDecoder(ODDecodeBlockFile* b
break;
}
}
//otherwise, create and add one, and return it.
if(!ret)
{
@@ -297,7 +297,7 @@ bool ODFileDecoder::IsInitialized()
bool ret;
mInitedLock.Lock();
ret = mInited;
mInitedLock.Unlock();
mInitedLock.Unlock();
return ret;
}
@@ -306,6 +306,6 @@ void ODFileDecoder::MarkInitialized()
{
mInitedLock.Lock();
mInited=true;
mInitedLock.Unlock();
mInitedLock.Unlock();
}

View File

@@ -15,7 +15,7 @@
This is an abstract class that subclasses will have to derive the types
from. For any type there should only be one ODDecodeTask associated with
a given track.
a given track.
There could be the ODBlockFiles of several FLACs in one track (after copy and pasting),
so things aren't as simple as they seem - the implementation needs to be
robust enough to allow all the user changes such as copy/paste, delete, and so on.
@@ -42,26 +42,26 @@ class ODDecodeTask:public ODTask
public:
ODDecodeTask();
virtual ~ODDecodeTask(){};
virtual ODTask* Clone()=0;
virtual bool SeekingAllowed();
///changes the tasks associated with this Waveform to process the task from a different point in the track
///this is overridden from ODTask because certain classes don't allow users to seek sometimes, or not at all.
virtual void DemandTrackUpdate(WaveTrack* track, double seconds);
///Return the task name
virtual const char* GetTaskName(){return "ODDecodeTask";}
virtual const wxChar* GetTip(){return _("Decoding Waveform");}
///Subclasses should override to return respective type.
virtual unsigned int GetODType(){return eODNone;}
///Creates an ODFileDecoder that decodes a file of filetype the subclass handles.
virtual ODFileDecoder* CreateFileDecoder(const wxString & fileName)=0;
///there could be the ODBlockFiles of several FLACs in one track (after copy and pasting)
///so we keep a list of decoders that keep track of the file names, etc, and check the blocks against them.
///Blocks that have IsDataAvailable()==false are blockfiles to be decoded. if BlockFile::GetDecodeType()==ODDecodeTask::GetODType() then
@@ -69,27 +69,27 @@ class ODDecodeTask:public ODTask
///be called from the decoding thread.
virtual ODFileDecoder* GetOrCreateMatchingFileDecoder(ODDecodeBlockFile* blockFile);
virtual int GetNumFileDecoders();
protected:
///recalculates the percentage complete.
virtual void CalculatePercentComplete();
///Computes and writes the data for one BlockFile if it still has a refcount.
///Computes and writes the data for one BlockFile if it still has a refcount.
virtual void DoSomeInternal();
///Readjusts the blockfile order in the default manner. If we have had an ODRequest
///Then it updates in the OD manner.
virtual void Update();
///Orders the input as either On-Demand or default layered order.
void OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlocks);
std::vector<ODDecodeBlockFile*> mBlockFiles;
std::vector<ODFileDecoder*> mDecoders;
int mMaxBlockFiles;
int mComputedBlockFiles;

View File

@@ -23,7 +23,7 @@ in a background thread.
#include "../WaveTrack.h"
#include "../Project.h"
//temporarilly commented out till it is added to all projects
//#include "../Profiler.h"
//#include "../Profiler.h"
DEFINE_EVENT_TYPE(EVT_ODTASK_COMPLETE)
@@ -38,30 +38,30 @@ ODTask::ODTask()
mTerminate = false;
mNeedsODUpdate=false;
mIsRunning = false;
mTaskNumber=sTaskNumber++;
mDemandSample=0;
}
//outside code must ensure this task is not scheduled again.
void ODTask::TerminateAndBlock()
{
{
//one mutex pair for the value of mTerminate
mTerminateMutex.Lock();
mTerminate=true;
//release all data the derived class may have allocated
mTerminateMutex.Unlock();
//and one mutex pair for the exit of the function
mBlockUntilTerminateMutex.Lock();
//TODO lock mTerminate?
mBlockUntilTerminateMutex.Unlock();
//wait till we are out of doSome() to terminate.
//wait till we are out of doSome() to terminate.
Terminate();
}
///Do a modular part of the task. For example, if the task is to load the entire file, load one BlockFile.
///Relies on DoSomeInternal(), which is the subclasses must implement.
///@param amountWork the percent amount of the total job to do. 1.0 represents the entire job. the default of 0.0
@@ -74,11 +74,11 @@ void ODTask::DoSome(float amountWork)
// printf("%s %i subtask starting on new thread with priority\n", GetTaskName(),GetTaskNumber());
mDoingTask=mTaskStarted=true;
float workUntil = amountWork+PercentComplete();
//check periodically to see if we should exit.
mTerminateMutex.Lock();
if(mTerminate)
@@ -87,45 +87,45 @@ void ODTask::DoSome(float amountWork)
SetIsRunning(false);
mBlockUntilTerminateMutex.Unlock();
return;
}
}
mTerminateMutex.Unlock();
Update();
Update();
if(UsesCustomWorkUntilPercentage())
workUntil = ComputeNextWorkUntilPercentageComplete();
if(workUntil<PercentComplete())
workUntil = PercentComplete();
//Do Some of the task.
mTerminateMutex.Lock();
while(PercentComplete() < workUntil && PercentComplete() < 1.0 && !mTerminate)
{
wxThread::This()->Yield();
//release within the loop so we can cut the number of iterations short
DoSomeInternal(); //keep the terminate mutex on so we don't remo
mTerminateMutex.Unlock();
mTerminateMutex.Unlock();
//check to see if ondemand has been called
if(GetNeedsODUpdate() && PercentComplete() < 1.0)
ODUpdate();
//But add the mutex lock back before we check the value again.
mTerminateMutex.Lock();
}
mTerminateMutex.Unlock();
mDoingTask=false;
mTerminateMutex.Lock();
//if it is not done, put it back onto the ODManager queue.
if(PercentComplete() < 1.0&& !mTerminate)
{
ODManager::Instance()->AddTask(this);
//we did a bit of progress - we should allow a resave.
AudacityProject::AllProjectsDeleteLock();
for(unsigned i=0; i<gAudacityProjects.GetCount(); i++)
@@ -139,7 +139,7 @@ void ODTask::DoSome(float amountWork)
}
AudacityProject::AllProjectsDeleteUnlock();
// printf("%s %i is %f done\n", GetTaskName(),GetTaskNumber(),PercentComplete());
}
else
@@ -148,16 +148,16 @@ void ODTask::DoSome(float amountWork)
//static int tempLog =0;
//if(++tempLog % 5==0)
//END_TASK_PROFILING("On Demand Drag and Drop 5 80 mb files into audacity, 5 wavs per task");
//END_TASK_PROFILING("On Demand open an 80 mb wav stereo file");
//END_TASK_PROFILING("On Demand open an 80 mb wav stereo file");
wxCommandEvent event( EVT_ODTASK_COMPLETE );
AudacityProject::AllProjectsDeleteLock();
for(unsigned i=0; i<gAudacityProjects.GetCount(); i++)
{
if(IsTaskAssociatedWithProject(gAudacityProjects[i]))
{
//this assumes tasks are only associated with one project.
//this assumes tasks are only associated with one project.
gAudacityProjects[i]->AddPendingEvent( event );
//mark the changes so that the project can be resaved.
gAudacityProjects[i]->GetUndoManager()->SetODChangesFlag();
@@ -179,10 +179,10 @@ bool ODTask::IsTaskAssociatedWithProject(AudacityProject* proj)
TrackListIterator iter1(tracks);
Track *tr = iter1.First();
while (tr)
while (tr)
{
//go over all tracks in the project
if (tr->GetKind() == Track::Wave)
if (tr->GetKind() == Track::Wave)
{
//look inside our task's track list for one that matches this projects one.
mWaveTrackMutex.Lock();
@@ -199,7 +199,7 @@ bool ODTask::IsTaskAssociatedWithProject(AudacityProject* proj)
}
tr = iter1.Next();
}
return false;
}
@@ -216,7 +216,7 @@ void ODTask::SetIsRunning(bool value)
mIsRunning=value;
mIsRunningMutex.Unlock();
}
bool ODTask::IsRunning()
{
bool ret;
@@ -224,8 +224,8 @@ bool ODTask::IsRunning()
ret= mIsRunning;
mIsRunningMutex.Unlock();
return ret;
}
}
sampleCount ODTask::GetDemandSample()
{
sampleCount retval;
@@ -234,16 +234,16 @@ sampleCount ODTask::GetDemandSample()
mDemandSampleMutex.Unlock();
return retval;
}
void ODTask::SetDemandSample(sampleCount sample)
{
mDemandSampleMutex.Lock();
mDemandSample=sample;
mDemandSampleMutex.Unlock();
}
///return the amount of the task that has been completed. 0.0 to 1.0
float ODTask::PercentComplete()
{
@@ -252,8 +252,8 @@ float ODTask::PercentComplete()
mPercentCompleteMutex.Unlock();
return ret;
}
///return
///return
bool ODTask::IsComplete()
{
return PercentComplete() >= 1.0 && !IsRunning();
@@ -319,7 +319,7 @@ void ODTask::RecalculatePercentComplete()
CalculatePercentComplete();
}
}
///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.
@@ -330,18 +330,18 @@ void ODTask::DemandTrackUpdate(WaveTrack* track, double seconds)
for(size_t i=0;i<mWaveTracks.size();i++)
{
if(track == mWaveTracks[i])
{
{
sampleCount newDemandSample = (sampleCount)(seconds * track->GetRate());
demandSampleChanged = newDemandSample != GetDemandSample();
SetDemandSample(newDemandSample);
break;
}
}
}
mWaveTrackMutex.Unlock();
if(demandSampleChanged)
SetNeedsODUpdate();
}
@@ -366,6 +366,6 @@ void ODTask::ReplaceWaveTrack(WaveTrack* oldTrack,WaveTrack* newTrack)
{
mWaveTracks[i] = newTrack;
}
}
}
mWaveTrackMutex.Unlock();
}

View File

@@ -50,73 +50,73 @@ class ODTask
/// Constructs an ODTask
ODTask();
virtual ~ODTask(){};
//clones everything except information about the tracks.
virtual ODTask* Clone()=0;
///Subclasses should override to return respective type.
virtual unsigned int GetODType(){return eODNone;}
///Do a modular part of the task. For example, if the task is to load the entire file, load one BlockFile.
///Relies on DoSomeInternal(), which is the subclasses must implement.
///@param amountWork the percent amount of the total job to do. 1.0 represents the entire job. the default of 0.0
/// will do the smallest unit of work possible
void DoSome(float amountWork=0.0);
///Call DoSome until PercentComplete >= 1.0
void DoAll();
virtual float PercentComplete();
virtual bool UsesCustomWorkUntilPercentage(){return false;}
virtual float ComputeNextWorkUntilPercentageComplete(){return 1.0;}
///returns whether or not this task and another task can merge together, as when we make two mono tracks stereo.
///for Loading/Summarizing, this is not an issue because the entire track is processed
///Effects that affect portions of a track will need to check this.
virtual bool CanMergeWith(ODTask* otherTask){return strcmp(GetTaskName(),otherTask->GetTaskName())==0;}
virtual bool CanMergeWith(ODTask* otherTask){return strcmp(GetTaskName(),otherTask->GetTaskName())==0;}
virtual void StopUsingWaveTrack(WaveTrack* track);
///Replaces all instances to a wavetrack with a new one, effectively transferring the task.
///ODTask has no wavetrack, so it does nothing. But subclasses that do should override this.
virtual void ReplaceWaveTrack(WaveTrack* oldTrack,WaveTrack* newTrack);
///Adds a WaveTrack to do the task for
void AddWaveTrack(WaveTrack* track);
virtual int GetNumWaveTracks();
virtual WaveTrack* GetWaveTrack(int i);
///changes the tasks associated with this Waveform to process the task from a different point in the track
virtual void DemandTrackUpdate(WaveTrack* track, double seconds);
bool IsComplete();
void TerminateAndBlock();
///releases memory that the ODTask owns. Subclasses should override.
virtual void Terminate(){}
virtual const char* GetTaskName(){return "ODTask";}
virtual sampleCount GetDemandSample();
virtual void SetDemandSample(sampleCount sample);
///does an od update and then recalculates the data.
virtual void RecalculatePercentComplete();
///returns the number of tasks created before this instance.
int GetTaskNumber(){return mTaskNumber;}
void SetNeedsODUpdate();
bool GetNeedsODUpdate();
void ResetNeedsODUpdate();
virtual const wxChar* GetTip()=0;
///returns true if the task is associated with the project.
virtual bool IsTaskAssociatedWithProject(AudacityProject* proj);
@@ -124,26 +124,26 @@ class ODTask
protected:
///calculates the percentage complete from existing data.
virtual void CalculatePercentComplete() = 0;
///pure virtual function that does some part of the task this object represents.
///this function is meant to be called repeatedly until the IsComplete is true.
virtual void CalculatePercentComplete() = 0;
///pure virtual function that does some part of the task this object represents.
///this function is meant to be called repeatedly until the IsComplete is true.
///Does the smallest unit of work for this task.
virtual void DoSomeInternal() = 0;
///virtual method called before DoSomeInternal is used from DoSome.
virtual void Update(){}
///virtual method called in DoSome everytime the user has demanded some OD function so that the
///ODTask can readjust its computation order. By default just calls Update(), but subclasses with
///special needs can override this
virtual void ODUpdate();
void SetIsRunning(bool value);
int mTaskNumber;
volatile float mPercentComplete;
@@ -154,23 +154,23 @@ class ODTask
ODLock mTerminateMutex;
//for a function not a member var.
ODLock mBlockUntilTerminateMutex;
std::vector<WaveTrack*> mWaveTracks;
ODLock mWaveTrackMutex;
volatile sampleCount mDemandSample;
ODLock mDemandSampleMutex;
volatile bool mIsRunning;
ODLock mIsRunningMutex;
private:
volatile bool mNeedsODUpdate;
ODLock mNeedsODUpdateMutex;
};

View File

@@ -3,7 +3,7 @@
Audacity: A Digital Audio Editor
ODTaskThread.cpp
Created by Michael Chinen (mchinen) on 6/8/08
Audacity(R) is copyright (c) 1999-2008 Audacity Team.
License: GPL v2. See License.txt.
@@ -28,16 +28,16 @@ ODTaskThread::ODTaskThread(ODTask* task)
{
mTask=task;
#ifdef __WXMAC__
mDestroy = false;
mDestroy = false;
mThread = NULL;
#endif
}
}
#ifdef __WXMAC__
void ODTaskThread::Entry()
#else
#else
void *ODTaskThread::Entry()
#endif
@@ -46,11 +46,11 @@ void *ODTaskThread::Entry()
//wxThread::This()->SetPriority( 40);
//Do at least 5 percent of the task
mTask->DoSome(0.05f);
//release the thread count so that the ODManager knows how many active threads are alive.
ODManager::Instance()->DecrementCurrentThreads();
#ifndef __WXMAC__
return NULL;
#endif
@@ -65,7 +65,7 @@ ODCondition::ODCondition(ODLock *lock)
}
ODCondition::~ODCondition()
{
pthread_cond_destroy (condition);
pthread_cond_destroy (condition);
free(condition);
}
@@ -73,7 +73,7 @@ void ODCondition::Signal()
{
pthread_cond_signal(condition);
}
void ODCondition::Broadcast()
{
pthread_cond_broadcast(condition);
@@ -82,7 +82,6 @@ void ODCondition::Wait()
{
pthread_cond_wait(condition,m_lock->mutex);
}
#endif

View File

@@ -3,7 +3,7 @@
Audacity: A Digital Audio Editor
ODTaskThread.h
Created by Michael Chinen (mchinen) on 6/8/08
Audacity(R) is copyright (c) 1999-2008 Audacity Team.
License: GPL v2. See License.txt.
@@ -64,7 +64,7 @@ class ODTaskThread {
void Run() {
pthread_create(&mThread, NULL, callback, this);
}
///Specifies the priority the thread will run at. Currently doesn't work.
///@param priority value from 0 (min priority) to 100 (max priority)
void SetPriority(int priority)
@@ -86,7 +86,7 @@ class ODLock {
mutex = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
pthread_mutex_init (mutex, NULL);
}
void Lock()
{
pthread_mutex_lock (mutex);
@@ -96,19 +96,19 @@ class ODLock {
{
pthread_mutex_unlock (mutex);
}
virtual ~ODLock()
{
pthread_mutex_destroy (mutex);
pthread_mutex_destroy (mutex);
free(mutex);
}
private:
friend class ODCondition; //needs friendship for wait()
pthread_mutex_t *mutex ;
};
class ODCondition
class ODCondition
{
public:
ODCondition(ODLock *lock);
@@ -116,7 +116,7 @@ public:
void Signal();
void Broadcast();
void Wait();
protected:
pthread_cond_t *condition;
ODLock* m_lock;
@@ -160,7 +160,7 @@ public:
//void Signal();
//void Broadcast();
//void Wait();
protected:
};

View File

@@ -23,7 +23,7 @@ tasks associated with a WaveTrack.
ODWaveTrackTaskQueue::ODWaveTrackTaskQueue()
{
}
ODWaveTrackTaskQueue::~ODWaveTrackTaskQueue()
{
//we need to delete all ODTasks. We will have to block or wait until block for the active ones.
@@ -34,7 +34,7 @@ ODWaveTrackTaskQueue::~ODWaveTrackTaskQueue()
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.
@@ -43,7 +43,7 @@ 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;i<mTasks.size();i++)
{
@@ -88,15 +88,15 @@ bool ODWaveTrackTaskQueue::ContainsWaveTrack(WaveTrack* track)
}
mTracksMutex.Unlock();
return false;
}
}
///Adds a track to the associated list.
void ODWaveTrackTaskQueue::AddWaveTrack(WaveTrack* track)
{
mTracksMutex.Lock();
if(track)
mTracks.push_back(track);
mTracksMutex.Unlock();
}
@@ -105,18 +105,18 @@ void ODWaveTrackTaskQueue::AddTask(ODTask* task)
mTasksMutex.Lock();
mTasks.push_back(task);
mTasksMutex.Unlock();
//take all of the tracks in the task.
//take all of the tracks in the task.
mTracksMutex.Lock();
for(int i=0;i<task->GetNumWaveTracks();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,
//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();
}
@@ -127,22 +127,22 @@ void ODWaveTrackTaskQueue::RemoveWaveTrack(WaveTrack* track)
{
if(track)
{
mTasksMutex.Lock();
for(unsigned int i=0;i<mTasks.size();i++)
mTasks[i]->StopUsingWaveTrack(track);
mTasksMutex.Unlock();
mTracksMutex.Lock();
for(unsigned int i=0;i<mTracks.size();i++)
if(mTracks[i]==track)
mTracks.erase(mTracks.begin()+i--);//decrement i after the removal.
mTracksMutex.Unlock();
}
}
//if the wavetrack is in this queue, and is not the only wavetrack, clones the tasks and schedules it.
//if the wavetrack is in this queue, and is not the only wavetrack, clones the tasks and schedules it.
void ODWaveTrackTaskQueue::MakeWaveTrackIndependent(WaveTrack* track)
{
@@ -153,14 +153,14 @@ void ODWaveTrackTaskQueue::MakeWaveTrackIndependent(WaveTrack* track)
mTracksMutex.Unlock();
return;
}
for(unsigned int i=0;i<mTracks.size();i++)
{
if(mTracks[i]==track)
{
mTracksMutex.Unlock();//release the lock, since RemoveWaveTrack is a public threadsafe method.
RemoveWaveTrack(mTracks[i]);
//clone the items in order and add them to the ODManager.
mTasksMutex.Lock();
ODTask* task;
@@ -170,7 +170,7 @@ void ODWaveTrackTaskQueue::MakeWaveTrackIndependent(WaveTrack* track)
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();
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);
@@ -196,7 +196,7 @@ void ODWaveTrackTaskQueue::DemandTrackUpdate(WaveTrack* track, double seconds)
{
mTasks[i]->DemandTrackUpdate(track,seconds);
}
mTracksMutex.Unlock();
}
}
@@ -211,7 +211,7 @@ void ODWaveTrackTaskQueue::ReplaceWaveTrack(WaveTrack* oldTrack, WaveTrack* newT
for(unsigned int i=0;i<mTasks.size();i++)
mTasks[i]->ReplaceWaveTrack(oldTrack,newTrack);
mTasksMutex.Unlock();
mTracksMutex.Lock();
for(unsigned int i=0;i<mTracks.size();i++)
if(mTracks[i]==oldTrack)
@@ -250,7 +250,7 @@ int ODWaveTrackTaskQueue::GetNumTasks()
mTasksMutex.Unlock();
return ret;
}
///returns a ODTask at position x
ODTask* ODWaveTrackTaskQueue::GetTask(size_t x)
{
@@ -261,8 +261,8 @@ ODTask* ODWaveTrackTaskQueue::GetTask(size_t x)
mTasksMutex.Unlock();
return ret;
}
//returns true if either tracks or tasks are empty
bool ODWaveTrackTaskQueue::IsEmpty()
@@ -271,14 +271,14 @@ bool ODWaveTrackTaskQueue::IsEmpty()
mTracksMutex.Lock();
isEmpty = mTracks.size()<=0;
mTracksMutex.Unlock();
mTasksMutex.Lock();
isEmpty = isEmpty || mTasks.size()<=0;
isEmpty = isEmpty || mTasks.size()<=0;
mTasksMutex.Unlock();
return isEmpty;
}
//returns true if the foremost task exists and is empty.
bool ODWaveTrackTaskQueue::IsFrontTaskComplete()
{
@@ -288,16 +288,16 @@ bool ODWaveTrackTaskQueue::IsFrontTaskComplete()
//there is a chance the task got updated and now has more to do, (like when it is joined with a new track)
//check.
mTasks[0]->RecalculatePercentComplete();
bool ret;
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()
{
@@ -310,7 +310,7 @@ void ODWaveTrackTaskQueue::RemoveFrontTask()
}
mTasksMutex.Unlock();
}
///gets the front task for immediate execution
ODTask* ODWaveTrackTaskQueue::GetFrontTask()
{
@@ -329,13 +329,13 @@ void ODWaveTrackTaskQueue::FillTipForWaveTrack( WaveTrack * t, const wxChar ** p
{
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();
}
}

View File

@@ -36,74 +36,74 @@ class ODWaveTrackTaskQueue
/// Constructs an ODWaveTrackTaskQueue
ODWaveTrackTaskQueue();
virtual ~ODWaveTrackTaskQueue();
///Adds a track to the associated list.
void AddWaveTrack(WaveTrack* track);
///Removes a track from the list. Also notifies mTasks to stop using references
///to the instance in a thread-safe manner (may block)
void RemoveWaveTrack(WaveTrack* track);
void RemoveWaveTrack(WaveTrack* track);
///changes the tasks associated with this Waveform to process the task from a different point in the track
void DemandTrackUpdate(WaveTrack* track, double seconds);
///replaces all instances of a WaveTrack within this task with another.
void ReplaceWaveTrack(WaveTrack* oldTrack,WaveTrack* newTrack);
//if the wavetrack is in this queue, and is not the only wavetrack, clones the tasks and schedules it.
///replaces all instances of a WaveTrack within this task with another.
void ReplaceWaveTrack(WaveTrack* oldTrack,WaveTrack* newTrack);
//if the wavetrack is in this queue, and is not the only wavetrack, clones the tasks and schedules it.
void MakeWaveTrackIndependent(WaveTrack* track);
///returns whether or not this queue's task list and another's can merge together, as when we make two mono tracks stereo.
virtual bool CanMergeWith(ODWaveTrackTaskQueue* otherQueue);
virtual bool CanMergeWith(ODWaveTrackTaskQueue* otherQueue);
void MergeWaveTrack(WaveTrack* track);
//returns true if the agrument is in the WaveTrack list.
bool ContainsWaveTrack(WaveTrack* track);
//returns the wavetrack at position x.
WaveTrack* GetWaveTrack(size_t x);
///returns the number of wavetracks in this queue.
int GetNumWaveTracks();
///Add a task to the queue.
///Add a task to the queue.
void AddTask(ODTask* task);
//returns true if either tracks or tasks are empty
bool IsEmpty();
//returns true if the foremost task exists and is empty.
bool IsFrontTaskComplete();
///Removes and deletes the front task from the list.
void RemoveFrontTask();
///Schedules the front task for immediate execution
ODTask* GetFrontTask();
///returns the number of ODTasks in this queue
int GetNumTasks();
///returns a ODTask at position x
ODTask* GetTask(size_t x);
///fills in the status bar message for a given track
void FillTipForWaveTrack( WaveTrack * t, const wxChar ** ppTip );
protected:
//because we need to save this around for the tool tip.
wxString mTipMsg;
///the list of tracks associated with this queue.
std::vector<WaveTrack*> mTracks;
ODLock mTracksMutex;
///the list of tasks associated with the tracks. This class owns these tasks.
std::vector<ODTask*> mTasks;
ODLock mTasksMutex;