diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 19768fcf7..d5e1844c8 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -32,6 +32,10 @@ extern "C" { #include "../../extern/adpcm/ymz_codec.h" } +DivSampleHistory::~DivSampleHistory() { + if (data!=NULL) delete[] data; +} + bool DivSample::save(const char* path) { SNDFILE* f; SF_INFO si; @@ -786,7 +790,48 @@ unsigned int DivSample::getCurBufLen() { return 0; } +DivSampleHistory* DivSample::prepareUndo(bool data) { + DivSampleHistory* h; + if (data) { + unsigned char* duplicate; + if (getCurBuf()==NULL) { + duplicate=NULL; + } else { + duplicate=new unsigned char[getCurBufLen()]; + memcpy(duplicate,getCurBuf(),getCurBufLen()); + } + h=new DivSampleHistory(duplicate,getCurBufLen(),samples,depth,rate,centerRate,loopStart); + } else { + h=new DivSampleHistory(depth,rate,centerRate,loopStart); + } + while (!redoHist.empty()) { + DivSampleHistory* h=redoHist.front(); + delete h; + redoHist.pop_front(); + } + undoHist.push_back(h); + return h; +} + +int DivSample::undo() { + return 0; +} + +int DivSample::redo() { + return 0; +} + DivSample::~DivSample() { + while (!undoHist.empty()) { + DivSampleHistory* h=undoHist.front(); + delete h; + undoHist.pop_front(); + } + while (!redoHist.empty()) { + DivSampleHistory* h=redoHist.front(); + delete h; + redoHist.pop_front(); + } if (data8) delete[] data8; if (data16) delete[] data16; if (data1) delete[] data1; diff --git a/src/engine/sample.h b/src/engine/sample.h index c697a9951..f07c7ef91 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -18,6 +18,7 @@ */ #include "../ta-utils.h" +#include enum DivResampleFilters { DIV_RESAMPLE_NONE=0, @@ -28,6 +29,33 @@ enum DivResampleFilters { DIV_RESAMPLE_BEST }; +struct DivSampleHistory { + unsigned char* data; + unsigned int length, samples; + unsigned char depth; + int rate, centerRate, loopStart; + bool hasSample; + DivSampleHistory(void* d, unsigned int l, unsigned int s, unsigned char de, int r, int cr, int ls): + data((unsigned char*)d), + length(l), + samples(s), + depth(de), + rate(r), + centerRate(cr), + loopStart(ls), + hasSample(true) {} + DivSampleHistory(unsigned char de, int r, int cr, int ls): + data(NULL), + length(0), + samples(0), + depth(de), + rate(r), + centerRate(cr), + loopStart(ls), + hasSample(false) {} + ~DivSampleHistory(); +}; + struct DivSample { String name; int rate, centerRate, loopStart, loopOffP; @@ -62,6 +90,9 @@ struct DivSample { unsigned int samples; + std::deque undoHist; + std::deque redoHist; + /** * @warning DO NOT USE - internal functions */ @@ -154,6 +185,27 @@ struct DivSample { * @return the sample data length. */ unsigned int getCurBufLen(); + + /** + * prepare an undo step for this sample. + * @param data whether to include sample data. + * @return the undo step. + */ + DivSampleHistory* prepareUndo(bool data); + + /** + * undo. you may need to call DivEngine::renderSamples afterwards. + * @warning do not attempt to undo outside of a synchronized block! + * @return 0 on failure; 1 on success and 2 on success (data changed). + */ + int undo(); + + /** + * redo. you may need to call DivEngine::renderSamples afterwards. + * @warning do not attempt to redo outside of a synchronized block! + * @return 0 on failure; 1 on success and 2 on success (data changed). + */ + int redo(); DivSample(): name(""), rate(32000),