Mercurial > hg > beaglert
view core/WriteFile.cpp @ 556:ce391098f321 prerelease tip
THIS PROJECT HAS MOVED TO https://github.com/BelaPlatform/bela
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Sat, 25 Jun 2016 20:21:00 +0100 |
parents | a4e49a3d9948 |
children |
line wrap: on
line source
/* * WriteFile.cpp * * Created on: 5 Oct 2015 * Author: giulio */ #include "WriteFile.h" //initialise static members bool WriteFile::staticConstructed=false; AuxiliaryTask WriteFile::writeAllFilesTask=NULL; std::vector<WriteFile *> WriteFile::objAddrs(0); bool WriteFile::threadRunning; bool WriteFile::threadIsExiting; int WriteFile::sleepTimeMs; void WriteFile::staticConstructor(){ if(staticConstructed==true) return; staticConstructed=true; threadIsExiting=false; threadRunning=false; writeAllFilesTask = Bela_createAuxiliaryTask(WriteFile::run, 60, "writeAllFilesTask"); } WriteFile::WriteFile(){ buffer = NULL; format = NULL; header = NULL; footer = NULL; stringBuffer = NULL; }; void WriteFile::init(const char* filename){ //if you do not call this before using the object, results are undefined file = fopen(filename, "w"); variableOpen = false; lineLength = 0; setEcho(false); bufferLength = 0; textReadPointer = 0; binaryReadPointer = 0; writePointer = 0; sleepTimeMs = 1; stringBufferLength = 1000; stringBuffer = (char*)malloc(sizeof(char) * (stringBufferLength)); setHeader("variable=[\n"); setFooter("];\n"); staticConstructor(); //TODO: this line should be in the constructor, but cannot be because of a bug in Bela objAddrs.push_back(this); echoedLines = 0; echoPeriod = 1; } void WriteFile::setFileType(WriteFileType newFileType){ fileType = newFileType; if(fileType == kBinary) setLineLength(1); } void WriteFile::setEcho(bool newEcho){ echo=newEcho; } void WriteFile::setEchoInterval(int newEchoPeriod){ echoPeriod = newEchoPeriod; if(echoPeriod != 0) echo = true; else echo = false; } void WriteFile::print(const char* string){ if(echo == true){ echoedLines++; if (echoedLines >= echoPeriod){ echoedLines = 0; printf("%s", string); } } if(file != NULL && fileType != kBinary){ fprintf(file, "%s", string); } } void WriteFile::writeLine(){ if(echo == true || fileType != kBinary){ int stringBufferPointer = 0; for(unsigned int n = 0; n < formatTokens.size(); n++){ int numOfCharsWritten = snprintf( &stringBuffer[stringBufferPointer], stringBufferLength - stringBufferPointer, formatTokens[n], buffer[textReadPointer]); stringBufferPointer += numOfCharsWritten; textReadPointer++; if(textReadPointer >= bufferLength){ textReadPointer -= bufferLength; } } print(stringBuffer); } } void WriteFile::setLineLength(int newLineLength){ lineLength=newLineLength; free(buffer); bufferLength = lineLength * (int)1e7; // circular buffer of length 1e7 lineLenghts buffer = (float*)malloc(sizeof(float) * bufferLength); } void WriteFile::log(float value){ if(fileType != kBinary && (format == NULL || buffer == NULL)) return; buffer[writePointer] = value; writePointer++; if(writePointer == bufferLength){ writePointer = 0; } if((fileType == kText && writePointer == textReadPointer - 1) || (fileType == kBinary && writePointer == binaryReadPointer - 1)){ fprintf(stderr, "%d %d WriteFile: pointers crossed, you should probably slow down your writing to disk\n", writePointer, binaryReadPointer); } if(threadRunning == false){ startThread(); } } void WriteFile::log(const float* array, int length){ for(int n = 0; n < length; n++){ log(array[n]); } } WriteFile::~WriteFile() { free(format); free(buffer); free(header); free(footer); free(stringBuffer); } void WriteFile::setFormat(const char* newFormat){ allocateAndCopyString(newFormat, &format); for(unsigned int n = 0; n < formatTokens.size(); n++){ free(formatTokens[n]); } formatTokens.clear(); int tokenStart = 0; bool firstToken = true; for(unsigned int n = 0; n < strlen(format)+1; n++){ if(format[n] == '%' && format[n + 1] == '%'){ n++; } else if (format[n] == '%' || format[n] == 0){ if(firstToken == true){ firstToken = false; continue; } char* string; unsigned int tokenLength = n - tokenStart; if(tokenLength == 0) continue; string = (char*)malloc((1+tokenLength)*sizeof(char)); for(unsigned int i = 0; i < tokenLength; i++){ string[i] = format[tokenStart + i]; } string[tokenLength] = 0; formatTokens.push_back(string); tokenStart = n; } } setLineLength(formatTokens.size()); } int WriteFile::getNumInstances(){ return objAddrs.size(); } void WriteFile::startThread(){ Bela_scheduleAuxiliaryTask(writeAllFilesTask); } void WriteFile::stopThread(){ threadIsExiting=true; } bool WriteFile::threadShouldExit(){ return(gShouldStop || threadIsExiting); } bool WriteFile::isThreadRunning(){ return threadRunning; } float WriteFile::getBufferStatus(){ return 1-getOffset()/(float)bufferLength; } int WriteFile::getOffsetFromPointer(int aReadPointer){ int offset = writePointer - aReadPointer; if( offset < 0) offset += bufferLength; return offset; } int WriteFile::getOffset(){ if(fileType == kBinary){ return getOffsetFromPointer(binaryReadPointer); } else{ return getOffsetFromPointer(textReadPointer); } } void WriteFile::writeOutput(bool flush){ while((echo == true || fileType == kText) && getOffsetFromPointer(textReadPointer) >= lineLength){ //if there is less than one line worth of data to write, skip over. // So we make sure we only write full lines writeLine(); } if(fileType == kBinary){ int numBinaryElementsToWriteAtOnce = 3*(int)1e5; while(getOffsetFromPointer(binaryReadPointer) > numBinaryElementsToWriteAtOnce){ int elementsToEndOfBuffer = bufferLength - binaryReadPointer; int numberElementsToWrite = numBinaryElementsToWriteAtOnce < elementsToEndOfBuffer ? numBinaryElementsToWriteAtOnce : elementsToEndOfBuffer; numberElementsToWrite = fwrite(&(buffer[binaryReadPointer]), sizeof(float), numberElementsToWrite, file); binaryReadPointer += numberElementsToWrite; if(binaryReadPointer >= bufferLength){ binaryReadPointer = 0; } } if(flush == true){ // flush all the buffer to the file while(getOffsetFromPointer(binaryReadPointer) != 0){ binaryReadPointer += fwrite(&(buffer[binaryReadPointer]), sizeof(float), 1, file); if(binaryReadPointer >= bufferLength){ binaryReadPointer = 0; } } } } } void WriteFile::writeAllOutputs(bool flush){ for(unsigned int n = 0; n < objAddrs.size(); n++){ objAddrs[n] -> writeOutput(flush); } } void WriteFile::writeAllHeaders(){ for(unsigned int n = 0; n < objAddrs.size(); n++){ objAddrs[n] -> writeHeader(); } } void WriteFile::writeAllFooters(){ for(unsigned int n = 0; n < objAddrs.size(); n++){ objAddrs[n] -> writeFooter(); } } void WriteFile::writeHeader(){ print(header); } void WriteFile::writeFooter(){ print(footer); fflush(file); fclose(file); } void WriteFile::setHeader(const char* newHeader){ allocateAndCopyString(newHeader, &header); sanitizeString(header); } void WriteFile::setFooter(const char* newFooter){ allocateAndCopyString(newFooter, &footer); } void WriteFile::sanitizeString(char* string){ for(int unsigned n = 0; n < strlen(string); n++){ //purge %'s from the string if(string[n] == '%'){ string[n] = ' '; } } } void WriteFile::run(){ threadRunning = true; writeAllHeaders(); while(threadShouldExit()==false){ writeAllOutputs(false); usleep(sleepTimeMs*1000); } writeAllOutputs(true); writeAllFooters(); // when ctrl-c is pressed, the last line is closed and the file is closed threadRunning = false; } void WriteFile::allocateAndCopyString(const char* source, char** destination){ free(*destination); *destination = (char*)malloc(sizeof(char) * (strlen(source) + 1)); strcpy(*destination, source); }