Merge branch 'master' of klarke.webfactional.com:webapps/git/repos/libcm with
spat lab mac.
This commit is contained in:
commit
c946234fde
512
app/cmScore.c
512
app/cmScore.c
@ -6,6 +6,7 @@
|
||||
#include "cmCtx.h"
|
||||
#include "cmMem.h"
|
||||
#include "cmMallocDebug.h"
|
||||
#include "cmLinkedHeap.h"
|
||||
#include "cmMidi.h"
|
||||
#include "cmLex.h"
|
||||
#include "cmCsv.h"
|
||||
@ -13,6 +14,7 @@
|
||||
#include "cmMidiFile.h"
|
||||
#include "cmAudioFile.h"
|
||||
#include "cmTimeLine.h"
|
||||
#include "cmText.h"
|
||||
#include "cmScore.h"
|
||||
#include "cmVectOpsTemplateMain.h"
|
||||
|
||||
@ -41,7 +43,8 @@ enum
|
||||
kFracColScIdx = 18,
|
||||
kDynColScIdx = 19,
|
||||
kSectionColScIdx = 20,
|
||||
kRemarkColScIdx = 21
|
||||
kRecdPlayColScIdx = 21,
|
||||
kRemarkColScIdx = 22
|
||||
};
|
||||
|
||||
|
||||
@ -75,6 +78,15 @@ typedef struct cmScSet_str
|
||||
struct cmScSet_str* link; //
|
||||
} cmScSet_t;
|
||||
|
||||
typedef struct cmScMark_str
|
||||
{
|
||||
cmMarkScMId_t cmdId;
|
||||
unsigned labelSymId;
|
||||
unsigned scoreIdx;
|
||||
unsigned csvRowIdx;
|
||||
struct cmScMark_str* link;
|
||||
} cmScMark_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cmErr_t err;
|
||||
@ -94,11 +106,15 @@ typedef struct
|
||||
cmScoreSection_t* sect;
|
||||
unsigned sectCnt;
|
||||
|
||||
unsigned* markLabelArray; // one symId per unique cmScoreMarker_t.labelSymId;
|
||||
unsigned markLabelCnt;
|
||||
|
||||
unsigned sciPitchLexTId; // sci pitch and section id lexer token id's
|
||||
unsigned sectionLexTId;
|
||||
|
||||
cmScSect_t* sectList; // lists used during parsing
|
||||
cmScSet_t* setList;
|
||||
cmScMark_t* markList;
|
||||
|
||||
cmScoreSet_t* sets;
|
||||
unsigned setCnt;
|
||||
@ -313,6 +329,17 @@ unsigned _cmScLexSectionIdMatcher( const cmChar_t* cp, unsigned cn )
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _cmScFreeMarkList( cmScMark_t* markList )
|
||||
{
|
||||
cmScMark_t* mp = markList;
|
||||
while( mp!=NULL )
|
||||
{
|
||||
cmScMark_t* np = mp->link;
|
||||
cmMemFree(mp);
|
||||
mp = np;
|
||||
}
|
||||
}
|
||||
|
||||
void _cmScFreeSetList( cmScSet_t* setList )
|
||||
{
|
||||
cmScSet_t* tp = setList;
|
||||
@ -366,6 +393,8 @@ cmScRC_t _cmScFinalize( cmSc_t* p )
|
||||
|
||||
_cmScFreeSetList(p->setList);
|
||||
|
||||
_cmScFreeMarkList(p->markList);
|
||||
|
||||
if( p->loc != NULL )
|
||||
{
|
||||
for(i=0; i<p->locCnt; ++i)
|
||||
@ -373,12 +402,23 @@ cmScRC_t _cmScFinalize( cmSc_t* p )
|
||||
cmMemFree(p->loc[i].evtArray);
|
||||
if( p->loc[i].begSectPtr != NULL )
|
||||
cmMemFree(p->loc[i].begSectPtr->setArray);
|
||||
|
||||
// free the marker list assoc'd with this location
|
||||
cmScoreMarker_t* smp = p->loc[i].markList;
|
||||
while( smp!=NULL )
|
||||
{
|
||||
cmScoreMarker_t* np = smp->link;
|
||||
cmMemFree(smp);
|
||||
smp = np;
|
||||
}
|
||||
|
||||
}
|
||||
cmMemFree(p->loc);
|
||||
}
|
||||
|
||||
cmMemPtrFree(&p->dynRefArray);
|
||||
|
||||
cmMemPtrFree(&p->dynRefArray);
|
||||
cmMemFree(p->markLabelArray);
|
||||
cmMemFree(p->sect);
|
||||
cmMemFree(p->fn);
|
||||
cmMemFree(p->array);
|
||||
@ -557,6 +597,79 @@ cmScRC_t _cmScParseAttr(cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsi
|
||||
return kOkScRC;
|
||||
}
|
||||
|
||||
// Parse a record/playback string
|
||||
cmScRC_t _cmScParseMarkers( cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsigned rowIdx )
|
||||
{
|
||||
const cmChar_t* cp = text;
|
||||
const cmChar_t* ip;
|
||||
const cmChar_t* ep;
|
||||
|
||||
// if no symbol table has been registered then don't bother storing markers.
|
||||
// (NOTE - THIS IS A HACK BECAUSE THE SCORE OBJECT USED IN THE cmdIf DOES NOT HAVE
|
||||
// A SYMBOL TABLE - WE COULD EASILY ADD ONE IF IT EVENTUALLY NEEDS ACCESS TO THE MARKERS
|
||||
// - OR A SYMBOL TABLE COULD BE ADDED TO THE SCORE ITSELF.)
|
||||
if( cmSymTblIsValid(p->stH) == false )
|
||||
return kOkScRC;
|
||||
|
||||
// go to command/id space
|
||||
if((ip = cmTextNextWhiteOrEosC(text)) == NULL )
|
||||
goto errLabel;
|
||||
|
||||
// goto label
|
||||
if((ip = cmTextNextNonWhiteC(ip)) == NULL )
|
||||
goto errLabel;
|
||||
|
||||
// goto end of label
|
||||
if((ep = cmTextNextWhiteOrEosC(ip)) == NULL )
|
||||
goto errLabel;
|
||||
else
|
||||
{
|
||||
unsigned n = (ep-ip)+1;
|
||||
cmChar_t markTextStr[n+1];
|
||||
strncpy(markTextStr,ip,n);
|
||||
|
||||
// for each command code
|
||||
// (there may be more than one character)
|
||||
for(; *cp && !isspace(*cp); ++cp)
|
||||
{
|
||||
cmMarkScMId_t cmdId = kInvalidScMId;
|
||||
|
||||
switch( *cp )
|
||||
{
|
||||
case 'c': cmdId = kRecdBegScMId; break;
|
||||
case 'e': cmdId = kRecdEndScMId; break;
|
||||
case 'p': cmdId = kPlayBegScMId; break;
|
||||
case 'd': cmdId = kPlayEndScMId; break;
|
||||
case 'f': cmdId = kFadeScMId; break;
|
||||
default:
|
||||
return cmErrMsg(&p->err,kSyntaxErrScRC,"Unrecognized marker command character '%c' at row index %i.",*cp,rowIdx);
|
||||
}
|
||||
|
||||
cmScMark_t* mp = cmMemAllocZ(cmScMark_t,1);
|
||||
mp->cmdId = cmdId;
|
||||
mp->labelSymId = cmSymTblRegisterSymbol(p->stH,markTextStr);
|
||||
mp->scoreIdx = scoreIdx;
|
||||
mp->csvRowIdx = rowIdx;
|
||||
|
||||
// insert the new mark at the end of the list
|
||||
if( p->markList == NULL )
|
||||
p->markList = mp;
|
||||
else
|
||||
{
|
||||
cmScMark_t* ep = p->markList;
|
||||
while( ep->link != NULL )
|
||||
ep = ep->link;
|
||||
|
||||
ep->link = mp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return kOkScRC;
|
||||
|
||||
errLabel:
|
||||
return cmErrMsg(&p->err,kSyntaxErrScRC,"Invalid record/playback field ('%s') on row index:%i.",cmStringNullGuard(text),rowIdx);
|
||||
}
|
||||
|
||||
void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList )
|
||||
{
|
||||
printf("%s\n",label);
|
||||
@ -658,6 +771,14 @@ cmScRC_t _cmScParseNoteOn( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned
|
||||
durSecs = 0.25;
|
||||
|
||||
|
||||
// parse the recd/play markers
|
||||
if((attr = cmCsvCellText(p->cH,rowIdx,kRecdPlayColScIdx)) != NULL )
|
||||
{
|
||||
if((rc = _cmScParseMarkers(p,scoreIdx,attr,rowIdx)) != kOkScRC )
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
s->type = kNonEvtScId;
|
||||
s->secs = secs;
|
||||
s->pitch = midiPitch;
|
||||
@ -870,6 +991,8 @@ cmScRC_t _cmScProcSets( cmSc_t* p )
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
|
||||
{
|
||||
cmScRC_t rc = kOkScRC;
|
||||
@ -935,6 +1058,153 @@ cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
|
||||
return rc;
|
||||
}
|
||||
|
||||
const cmScoreLoc_t* _cmScFindMarkLoc( cmSc_t* p, cmMarkScMId_t cmdId, unsigned labelSymId, const cmScoreMarker_t** markRef )
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<p->locCnt; ++i)
|
||||
{
|
||||
cmScoreMarker_t* smp = p->loc[i].markList;
|
||||
for(; smp!=NULL; smp=smp->link)
|
||||
{
|
||||
if( smp->markTypeId==cmdId && smp->labelSymId==labelSymId )
|
||||
return p->loc + i;
|
||||
|
||||
if( markRef != NULL )
|
||||
*markRef = smp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned _cmScMarkerLabelIndex( cmSc_t* p, unsigned labelSymId )
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<p->markLabelCnt; ++i)
|
||||
if( p->markLabelArray[i] == labelSymId )
|
||||
return i;
|
||||
|
||||
return cmInvalidIdx;
|
||||
}
|
||||
|
||||
|
||||
// Verify that the record/play begin/end and fade markers fall in the correct time order.
|
||||
// (e.g. 'begin' must be before 'end' and 'fade' must be between and 'begin' and 'end').
|
||||
cmScRC_t _cmScValidateMarkers( cmSc_t* p )
|
||||
{
|
||||
cmScRC_t rc = kOkScRC;
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i<p->locCnt; ++i)
|
||||
{
|
||||
cmScoreMarker_t* sm0p = p->loc[i].markList;
|
||||
for(; sm0p!=NULL; sm0p=sm0p->link)
|
||||
{
|
||||
const cmScoreLoc_t* sl0p;
|
||||
const cmScoreLoc_t* sl1p;
|
||||
|
||||
switch( sm0p->markTypeId )
|
||||
{
|
||||
case kRecdBegScMId:
|
||||
if((sl0p = _cmScFindMarkLoc(p,kRecdEndScMId, sm0p->labelSymId, NULL )) == NULL )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker at CSV row index %i does not have an associated 'record end' marker.",sm0p->csvRowIdx);
|
||||
else
|
||||
if( sl0p->index <= p->loc[i].index )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker comes before associated with the 'record begin' marker at CSV row index %i.",sm0p->csvRowIdx);
|
||||
break;
|
||||
|
||||
case kRecdEndScMId:
|
||||
if((sl0p = _cmScFindMarkLoc(p,kRecdBegScMId, sm0p->labelSymId, NULL )) == NULL )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker at CSV row index %i does not have an associated 'record begin' marker.",sm0p->csvRowIdx);
|
||||
else
|
||||
if( sl0p->index > p->loc[i].index )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker comes after the associated with the 'record end' marker at CSV row index %i.",sm0p->csvRowIdx);
|
||||
break;
|
||||
|
||||
case kFadeScMId:
|
||||
if((sl0p = _cmScFindMarkLoc(p,kRecdBegScMId, sm0p->labelSymId, NULL )) == NULL )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'record begin' marker.",sm0p->csvRowIdx);
|
||||
else
|
||||
if((sl1p = _cmScFindMarkLoc(p,kRecdEndScMId, sm0p->labelSymId, NULL )) == NULL )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'record end' marker.",sm0p->csvRowIdx);
|
||||
else
|
||||
if( sl0p->index > p->loc[i].index || sl1p->index < p->loc[i].index )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i is not between it's associated 'record begin' and 'record end' markers.",sm0p->csvRowIdx);
|
||||
break;
|
||||
|
||||
case kPlayBegScMId:
|
||||
if((sl0p = _cmScFindMarkLoc(p,kPlayEndScMId, sm0p->labelSymId, NULL )) == NULL )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker at CSV row index %i does not have an associated 'play end' marker.",sm0p->csvRowIdx);
|
||||
else
|
||||
if( sl0p->index <= p->loc[i].index )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker comes before associated with the 'play begin' marker at CSV row index %i.",sm0p->csvRowIdx);
|
||||
break;
|
||||
|
||||
case kPlayEndScMId:
|
||||
if((sl0p = _cmScFindMarkLoc(p,kPlayBegScMId, sm0p->labelSymId, NULL )) == NULL )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker at CSV row index %i does not have an associated 'play begin' marker.",sm0p->csvRowIdx);
|
||||
else
|
||||
if( sl0p->index > p->loc[i].index )
|
||||
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker comes after the associated with the 'play end' marker at CSV row index %i.",sm0p->csvRowIdx);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
cmScRC_t _cmScProcMarkers( cmSc_t* p )
|
||||
{
|
||||
// for each marker in the p->markList
|
||||
// (p->markList is created by _cmScParseMarkers() during CSV file parsing.)
|
||||
cmScMark_t* mp = p->markList;
|
||||
for(; mp!=NULL; mp=mp->link)
|
||||
{
|
||||
assert( mp->scoreIdx < p->cnt );
|
||||
|
||||
// get the score location assoc'd with this marker
|
||||
unsigned locIdx = p->array[ mp->scoreIdx ].locIdx;
|
||||
assert( locIdx < p->locCnt );
|
||||
|
||||
cmScoreLoc_t* slp = p->loc + locIdx;
|
||||
|
||||
// create a cmScoreMarker record.
|
||||
cmScoreMarker_t* smp = cmMemAllocZ(cmScoreMarker_t,1);
|
||||
smp->markTypeId = mp->cmdId;
|
||||
smp->labelSymId = mp->labelSymId;
|
||||
smp->csvRowIdx = mp->csvRowIdx;
|
||||
smp->scoreLocPtr = slp;
|
||||
|
||||
// attach the new scoreMarker record to the assoc'd score loc. recd
|
||||
if( slp->markList == NULL )
|
||||
slp->markList = smp;
|
||||
else
|
||||
{
|
||||
cmScoreMarker_t* sm0p = slp->markList;
|
||||
while( sm0p->link != NULL )
|
||||
sm0p = sm0p->link;
|
||||
sm0p->link = smp;
|
||||
}
|
||||
|
||||
// if the id represented by this marker
|
||||
if( _cmScMarkerLabelIndex(p,smp->labelSymId) == cmInvalidIdx )
|
||||
{
|
||||
p->markLabelArray = cmMemResizeP(unsigned,p->markLabelArray,p->markLabelCnt+1);
|
||||
p->markLabelArray[p->markLabelCnt] = smp->labelSymId;
|
||||
p->markLabelCnt += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// validate the markers
|
||||
return _cmScValidateMarkers(p);
|
||||
}
|
||||
|
||||
cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
|
||||
{
|
||||
cmScRC_t rc = kOkScRC;
|
||||
@ -1036,6 +1306,8 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
|
||||
break;
|
||||
}
|
||||
|
||||
if( rc == kOkScRC )
|
||||
{
|
||||
if( secs != DBL_MAX )
|
||||
cur_secs = secs;
|
||||
|
||||
@ -1058,6 +1330,7 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
|
||||
|
||||
barEvtIdx = cmInvalidIdx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1164,6 +1437,9 @@ cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, doubl
|
||||
if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
|
||||
goto errLabel;
|
||||
|
||||
if((rc = _cmScProcMarkers(p)) != kOkScRC )
|
||||
goto errLabel;
|
||||
|
||||
// load the dynamic reference array
|
||||
if( dynRefArray != NULL && dynRefCnt > 0)
|
||||
{
|
||||
@ -1409,6 +1685,30 @@ unsigned cmScoreSetCount( cmScH_t h )
|
||||
return p->setCnt;
|
||||
}
|
||||
|
||||
unsigned cmScoreMarkerLabelCount( cmScH_t h )
|
||||
{
|
||||
cmSc_t* p = _cmScHandleToPtr(h);
|
||||
return p->markLabelCnt;
|
||||
}
|
||||
|
||||
unsigned cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx )
|
||||
{
|
||||
cmSc_t* p = _cmScHandleToPtr(h);
|
||||
assert( idx < p->markLabelCnt );
|
||||
return p->markLabelArray[idx];
|
||||
}
|
||||
|
||||
const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId )
|
||||
{
|
||||
cmSc_t* p = _cmScHandleToPtr(h);
|
||||
const cmScoreMarker_t* smp = NULL;
|
||||
if( _cmScFindMarkLoc(p, markMId, labelSymId, &smp ) == NULL )
|
||||
return NULL;
|
||||
|
||||
return smp;
|
||||
}
|
||||
|
||||
|
||||
cmScRC_t cmScoreSeqNotify( cmScH_t h )
|
||||
{
|
||||
cmScRC_t rc = kOkScRC;
|
||||
@ -1955,6 +2255,214 @@ void cmScorePrint( cmScH_t h, cmRpt_t* rpt )
|
||||
}
|
||||
}
|
||||
|
||||
cmScRC_t cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn )
|
||||
{
|
||||
cmScRC_t rc = kOkScRC;
|
||||
cmMidiFileH_t mfH = cmMidiFileNullHandle;
|
||||
cmCsvH_t csvH = cmCsvNullHandle;
|
||||
cmErr_t err;
|
||||
cmChar_t* titles[] = {"id","trk","evt","opcode","dticks","micros","status","meta","ch","d0","d1","arg0","arg1","bar","skip","even","grace","tempo","t frac","dyn","section","remark", NULL };
|
||||
|
||||
cmErrSetup(&err,&ctx->rpt,"MIDI to Score");
|
||||
|
||||
if( cmMidiFileOpen(midiFn, &mfH, ctx ) != kOkMfRC )
|
||||
return cmErrMsg(&err,kMidiFileFailScRC,"Unable to open the MIDI file '%s'.",midiFn);
|
||||
|
||||
if( cmCsvInitialize(&csvH,ctx) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Unable to initialize the CSV file: '%s'.",scoreFn);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// Convert the track message 'dtick' field to delta-microseconds.
|
||||
cmMidiFileTickToMicros(mfH);
|
||||
|
||||
|
||||
unsigned msgCnt = cmMidiFileMsgCount(mfH);
|
||||
unsigned i;
|
||||
const cmMidiTrackMsg_t** tmpp = cmMidiFileMsgArray(mfH);
|
||||
double acc_secs = 0;
|
||||
unsigned lexTId = 0;
|
||||
cmCsvCell_t* cp = NULL;
|
||||
|
||||
|
||||
if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymText(csvH,titles[0]), kStrCsvTFl, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
for(i=1; titles[i]!=NULL; ++i)
|
||||
{
|
||||
if( cmCsvInsertTextColAfter(csvH, cp, &cp, titles[i], lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting column index '%i' label in '%s'.",i,cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
for(i=0; i<msgCnt; ++i)
|
||||
{
|
||||
const cmMidiTrackMsg_t* tmp = tmpp[i];
|
||||
const cmChar_t* opStr = NULL;
|
||||
unsigned midiCh = 0;
|
||||
unsigned d0 = 0;
|
||||
unsigned d1 = 0;
|
||||
unsigned metaId = 0;
|
||||
double dsecs = (double)tmp->dtick / 1000000.0;
|
||||
|
||||
acc_secs += dsecs;
|
||||
|
||||
if( tmp->status == kMetaStId )
|
||||
{
|
||||
opStr = cmMidiMetaStatusToLabel(tmp->metaId);
|
||||
metaId = tmp->metaId;
|
||||
|
||||
switch( tmp->metaId )
|
||||
{
|
||||
case kTempoMdId:
|
||||
d0 = tmp->u.iVal;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
opStr = cmMidiStatusToLabel(tmp->status);
|
||||
if( cmMidiIsChStatus( tmp->status ) )
|
||||
{
|
||||
midiCh = tmp->u.chMsgPtr->ch;
|
||||
d0 = tmp->u.chMsgPtr->d0;
|
||||
d1 = tmp->u.chMsgPtr->d1;
|
||||
}
|
||||
}
|
||||
|
||||
cp = NULL;
|
||||
|
||||
// skip note-off messages
|
||||
if( tmp->status == kNoteOffMdId )
|
||||
continue;
|
||||
|
||||
if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymUInt(csvH,i), kIntCsvTFl, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->trkIdx, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'trk' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 0, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'evt' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertTextColAfter(csvH, cp, &cp, opStr, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, dsecs, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'dticks' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, acc_secs, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'micros' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertHexColAfter(csvH, cp, &cp, tmp->status, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'status' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, metaId, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'meta' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, midiCh, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'ch' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d0, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd0' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d1, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd1' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
switch( tmp->status )
|
||||
{
|
||||
case kNoteOnMdId:
|
||||
if( cmCsvInsertTextColAfter(csvH, cp, &cp, cmMidiToSciPitch(tmp->u.chMsgPtr->d0,NULL,0), lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
case kMetaStId:
|
||||
switch( tmp->metaId )
|
||||
{
|
||||
case kTimeSigMdId:
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->num, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. numerator column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->den, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. denominator column in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
break;
|
||||
|
||||
case kTempoMdId:
|
||||
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 60000000/tmp->u.iVal, lexTId ) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'tempo' in '%s'.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if( cmCsvWrite(csvH,scoreFn) != kOkCsvRC )
|
||||
{
|
||||
cmErrMsg(&err,kCsvFailScRC,"The score output file '%s' could not be written.",cmStringNullGuard(scoreFn));
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
errLabel:
|
||||
cmMidiFileClose(&mfH);
|
||||
cmCsvFinalize(&csvH);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
|
||||
{
|
||||
cmScH_t h = cmScNullHandle;
|
||||
|
@ -12,8 +12,8 @@ extern "C" {
|
||||
kSyntaxErrScRC,
|
||||
kInvalidIdxScRC,
|
||||
kTimeLineFailScRC,
|
||||
kInvalidDynRefCntScRC
|
||||
|
||||
kInvalidDynRefCntScRC,
|
||||
kMidiFileFailScRC
|
||||
};
|
||||
|
||||
enum
|
||||
@ -36,12 +36,12 @@ extern "C" {
|
||||
// Flags used by cmScoreEvt_t.flags
|
||||
enum
|
||||
{
|
||||
kEvenScFl = 0x01, // This note is marked for evenness measurement
|
||||
kDynScFl = 0x02, // This note is marked for dynamics measurement
|
||||
kTempoScFl = 0x04, // This note is marked for tempo measurement
|
||||
kSkipScFl = 0x08, // This isn't a real event (e.g. tied note) skip over it
|
||||
kGraceScFl = 0x10, // This is a grace note
|
||||
kInvalidScFl = 0x20 // This note has a calculated time
|
||||
kEvenScFl = 0x001, // This note is marked for evenness measurement
|
||||
kDynScFl = 0x002, // This note is marked for dynamics measurement
|
||||
kTempoScFl = 0x004, // This note is marked for tempo measurement
|
||||
kSkipScFl = 0x008, // This isn't a real event (e.g. tied note) skip over it
|
||||
kGraceScFl = 0x010, // This is a grace note
|
||||
kInvalidScFl = 0x020 // This note has a calculated time
|
||||
};
|
||||
|
||||
|
||||
@ -104,6 +104,25 @@ extern "C" {
|
||||
struct cmScoreSet_str* llink; // cmScoreLoc_t setList link
|
||||
} cmScoreSet_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kInvalidScMId,
|
||||
kRecdBegScMId,
|
||||
kRecdEndScMId,
|
||||
kFadeScMId,
|
||||
kPlayBegScMId,
|
||||
kPlayEndScMId
|
||||
} cmMarkScMId_t;
|
||||
|
||||
// score markers
|
||||
typedef struct cmScoreMarker_str
|
||||
{
|
||||
cmMarkScMId_t markTypeId; // marker type
|
||||
unsigned labelSymId; // marker label
|
||||
struct cmScoreLoc_str* scoreLocPtr; // score location of the marker
|
||||
unsigned csvRowIdx; // score CSV file line assoc'd w/ this marker
|
||||
struct cmScoreMarker_str* link; // cmScoreLoc_t.markList links
|
||||
} cmScoreMarker_t;
|
||||
|
||||
// All events which are simultaneous are collected into a single
|
||||
// cmScoreLoc_t record.
|
||||
@ -116,6 +135,7 @@ extern "C" {
|
||||
unsigned barNumb; // Bar number this event is contained by.
|
||||
cmScoreSet_t* setList; // Set's which end on this time location (linked through cmScoreSet_t.llink)
|
||||
cmScoreSection_t* begSectPtr; // NULL if this location does not start a section
|
||||
cmScoreMarker_t* markList; // List of markers assigned to this location
|
||||
} cmScoreLoc_t;
|
||||
|
||||
typedef void (*cmScCb_t)( void* arg, const void* data, unsigned byteCnt );
|
||||
@ -170,6 +190,10 @@ extern "C" {
|
||||
// Return the count of sets.
|
||||
unsigned cmScoreSetCount( cmScH_t h );
|
||||
|
||||
unsigned cmScoreMarkerLabelCount( cmScH_t h );
|
||||
unsigned cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx );
|
||||
const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId );
|
||||
|
||||
// Make callbacks for all events in the score. The callbacks
|
||||
// contain cmScMsg_t records serialized as a byte stream.
|
||||
// Use cmScoreDecode() to convert the byte string to a
|
||||
@ -235,6 +259,9 @@ extern "C" {
|
||||
|
||||
void cmScorePrint( cmScH_t h, cmRpt_t* rpt );
|
||||
|
||||
// Generate a new score file from a MIDI file.
|
||||
cmScRC_t cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn );
|
||||
|
||||
void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn );
|
||||
|
||||
|
||||
|
58
cmCsv.c
58
cmCsv.c
@ -729,6 +729,20 @@ unsigned cmCsvInsertSymUInt( cmCsvH_t h, unsigned v )
|
||||
return cmInvalidId;
|
||||
}
|
||||
|
||||
unsigned cmCsvInsertSymHex( cmCsvH_t h, unsigned v )
|
||||
{
|
||||
const char* fmt = "0x%x";
|
||||
unsigned n = snprintf(NULL,0,fmt,v)+1;
|
||||
char buf[n];
|
||||
|
||||
buf[0]= 0;
|
||||
if( snprintf(buf,n,fmt,v) == n-1 )
|
||||
return cmCsvInsertSymText(h,buf);
|
||||
|
||||
_cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The unsigned int 0x%x could not be converted to text.",v);
|
||||
return cmInvalidId;
|
||||
}
|
||||
|
||||
unsigned cmCsvInsertSymFloat( cmCsvH_t h, float v )
|
||||
{
|
||||
const char* fmt = "%f";
|
||||
@ -812,6 +826,24 @@ cmCsvRC_t cmCsvSetCellUInt( cmCsvH_t h, unsigned row, unsigned col, unsigned
|
||||
return kOkCsvRC;
|
||||
}
|
||||
|
||||
cmCsvRC_t cmCsvSetCellHex( cmCsvH_t h, unsigned row, unsigned col, unsigned v )
|
||||
{
|
||||
cmCsvCell_t* cp;
|
||||
unsigned symId;
|
||||
|
||||
if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
|
||||
return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
|
||||
|
||||
if((symId = cmCsvInsertSymHex(h,v)) == cmInvalidId )
|
||||
return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
|
||||
|
||||
cp->symId = symId;
|
||||
cp->flags &= !kTypeTMask;
|
||||
cp->flags |= kIntCsvTFl;
|
||||
|
||||
return kOkCsvRC;
|
||||
}
|
||||
|
||||
cmCsvRC_t cmCsvSetCellFloat( cmCsvH_t h, unsigned row, unsigned col, float v )
|
||||
{
|
||||
cmCsvCell_t* cp;
|
||||
@ -985,7 +1017,7 @@ cmCsvRC_t cmCsvInsertTextColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
|
||||
cmCsvCell_t* ncp;
|
||||
|
||||
if( cellPtrPtr != NULL )
|
||||
cellPtrPtr = NULL;
|
||||
*cellPtrPtr = NULL;
|
||||
|
||||
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
|
||||
if((rc = cmCsvSetCellText(h, ncp->row, ncp->col, text )) == kOkCsvRC )
|
||||
@ -1001,7 +1033,7 @@ cmCsvRC_t cmCsvInsertIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
|
||||
cmCsvCell_t* ncp;
|
||||
|
||||
if( cellPtrPtr != NULL )
|
||||
cellPtrPtr = NULL;
|
||||
*cellPtrPtr = NULL;
|
||||
|
||||
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
|
||||
if((rc = cmCsvSetCellInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
|
||||
@ -1017,7 +1049,7 @@ cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
|
||||
cmCsvCell_t* ncp;
|
||||
|
||||
if( cellPtrPtr != NULL )
|
||||
cellPtrPtr = NULL;
|
||||
*cellPtrPtr = NULL;
|
||||
|
||||
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
|
||||
if((rc = cmCsvSetCellUInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
|
||||
@ -1027,13 +1059,29 @@ cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmCsvRC_t cmCsvInsertHexColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId )
|
||||
{
|
||||
cmCsvRC_t rc;
|
||||
cmCsvCell_t* ncp;
|
||||
|
||||
if( cellPtrPtr != NULL )
|
||||
*cellPtrPtr = NULL;
|
||||
|
||||
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
|
||||
if((rc = cmCsvSetCellHex(h, ncp->row, ncp->col, val )) == kOkCsvRC )
|
||||
if( cellPtrPtr != NULL )
|
||||
*cellPtrPtr = ncp;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmCsvRC_t cmCsvInsertFloatColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId )
|
||||
{
|
||||
cmCsvRC_t rc;
|
||||
cmCsvCell_t* ncp;
|
||||
|
||||
if( cellPtrPtr != NULL )
|
||||
cellPtrPtr = NULL;
|
||||
*cellPtrPtr = NULL;
|
||||
|
||||
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
|
||||
if((rc = cmCsvSetCellFloat(h, ncp->row, ncp->col, val )) == kOkCsvRC )
|
||||
@ -1049,7 +1097,7 @@ cmCsvRC_t cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
|
||||
cmCsvCell_t* ncp;
|
||||
|
||||
if( cellPtrPtr != NULL )
|
||||
cellPtrPtr = NULL;
|
||||
*cellPtrPtr = NULL;
|
||||
|
||||
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
|
||||
if((rc = cmCsvSetCellDouble(h, ncp->row, ncp->col, val )) == kOkCsvRC )
|
||||
|
4
cmCsv.h
4
cmCsv.h
@ -109,13 +109,16 @@ extern "C" {
|
||||
unsigned cmCsvInsertSymText( cmCsvH_t h, const char* text );
|
||||
unsigned cmCsvInsertSymInt( cmCsvH_t h, int v );
|
||||
unsigned cmCsvInsertSymUInt( cmCsvH_t h, unsigned v );
|
||||
unsigned cmCsvInsertSymHex( cmCsvH_t h, unsigned v );
|
||||
unsigned cmCsvInsertSymFloat( cmCsvH_t h, float v );
|
||||
unsigned cmCsvInsertSymDouble( cmCsvH_t h, double v );
|
||||
|
||||
|
||||
// Set the value associated with a cell.
|
||||
cmCsvRC_t cmCsvSetCellText( cmCsvH_t h, unsigned row, unsigned col, const char* text );
|
||||
cmCsvRC_t cmCsvSetCellInt( cmCsvH_t h, unsigned row, unsigned col, int v );
|
||||
cmCsvRC_t cmCsvSetCellUInt( cmCsvH_t h, unsigned row, unsigned col, unsigned v );
|
||||
cmCsvRC_t cmCsvSetCellHex( cmCsvH_t h, unsigned row, unsigned col, unsigned v );
|
||||
cmCsvRC_t cmCsvSetCellFloat( cmCsvH_t h, unsigned row, unsigned col, float v );
|
||||
cmCsvRC_t cmCsvSetCellDouble( cmCsvH_t h, unsigned row, unsigned col, double v );
|
||||
|
||||
@ -134,6 +137,7 @@ extern "C" {
|
||||
cmCsvRC_t cmCsvInsertTextColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* val, unsigned lexTId );
|
||||
cmCsvRC_t cmCsvInsertIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, int val, unsigned lexTId );
|
||||
cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId );
|
||||
cmCsvRC_t cmCsvInsertHexColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId );
|
||||
cmCsvRC_t cmCsvInsertFloatColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId );
|
||||
cmCsvRC_t cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, double val, unsigned lexTId );
|
||||
|
||||
|
598
cmData.h
598
cmData.h
@ -5,129 +5,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
kOkDtRC = cmOkRC,
|
||||
kCvtErrDtRC,
|
||||
kVarArgErrDtRC,
|
||||
kMissingFieldDtRC,
|
||||
kEolDtRC
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kInvalidDtChar = 0xff,
|
||||
kInvalidDtUChar = 0xff,
|
||||
kInvalidDtShort = 0xffff,
|
||||
kInvalidDtUShort = 0xffff,
|
||||
kInvalidDtInt = 0xffffffff,
|
||||
kInvalidDtUInt = 0xffffffff,
|
||||
kInvalidDtLong = 0xffffffff,
|
||||
kInvalidDtULong = 0xffffffff,
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kInvalidDtId,
|
||||
|
||||
kMinValDtId,
|
||||
|
||||
kNullDtId = kMinValDtId,
|
||||
kUCharDtId,
|
||||
kCharDtId,
|
||||
kUShortDtId,
|
||||
kShortDtId,
|
||||
kUIntDtId,
|
||||
kIntDtId,
|
||||
kULongDtId,
|
||||
kLongDtId,
|
||||
kFloatDtId,
|
||||
kDoubleDtId,
|
||||
|
||||
kStrDtId,
|
||||
kConstStrDtId,
|
||||
kMaxValDtId = kConstStrDtId,
|
||||
|
||||
kMinPtrDtId,
|
||||
kUCharPtrDtId = kMinPtrDtId, // cnt=array element count
|
||||
kCharPtrDtId,
|
||||
kUShortPtrDtId,
|
||||
kShortPtrDtId,
|
||||
kUIntPtrDtId,
|
||||
kIntPtrDtId,
|
||||
kULongPtrDtId,
|
||||
kLongPtrDtId,
|
||||
kFloatPtrDtId,
|
||||
kDoublePtrDtId,
|
||||
kVoidPtrDtId,
|
||||
kMaxPtrDtId = kVoidPtrDtId,
|
||||
|
||||
kMinStructDtId,
|
||||
kListDtId = kMinStructDtId, // children nodes are array elements, cnt=child count
|
||||
kPairDtId, // key/value pairs, cnt=2, first child is key, second is value
|
||||
kRecordDtId, // children nodes are pairs, cnt=pair count
|
||||
kMaxStructDtId,
|
||||
|
||||
kOptArgDtFl = 0x80000000
|
||||
} cmDataFmtId_t;
|
||||
|
||||
enum
|
||||
{
|
||||
kDynObjDtFl = 0x01, // object was dynamically allocated
|
||||
kDynPtrDtFl = 0x02 // ptr array was dynamically allocated
|
||||
};
|
||||
|
||||
typedef struct cmData_str
|
||||
{
|
||||
cmDataFmtId_t tid; // data format id
|
||||
unsigned flags; //
|
||||
struct cmData_str* parent; // this childs parent
|
||||
struct cmData_str* sibling; // this childs left sibling
|
||||
unsigned cnt; // array ele count
|
||||
|
||||
union
|
||||
{
|
||||
char c;
|
||||
unsigned char uc;
|
||||
short s;
|
||||
unsigned short us;
|
||||
int i;
|
||||
unsigned int ui;
|
||||
long l;
|
||||
unsigned long ul;
|
||||
float f;
|
||||
double d;
|
||||
|
||||
cmChar_t* z;
|
||||
const cmChar_t* cz;
|
||||
|
||||
void* vp;
|
||||
|
||||
char* cp;
|
||||
unsigned char* ucp;
|
||||
short* sp;
|
||||
unsigned short* usp;
|
||||
int* ip;
|
||||
unsigned int* uip;
|
||||
long* lp;
|
||||
unsigned long* ulp;
|
||||
float* fp;
|
||||
double* dp;
|
||||
|
||||
|
||||
struct cmData_str* child; // first child (array,record,pair)
|
||||
} u;
|
||||
|
||||
} cmData_t;
|
||||
|
||||
typedef unsigned cmDtRC_t;
|
||||
|
||||
extern cmData_t cmDataNull;
|
||||
|
||||
bool cmDataIsValue( const cmData_t* p );
|
||||
bool cmDataIsPtr( const cmData_t* p );
|
||||
bool cmDataIsStruct( const cmData_t* p ); // is a pair,list or record
|
||||
|
||||
/*
|
||||
TODO:
|
||||
0) Figure out a error handling scheme that does not rely on
|
||||
@ -170,40 +47,227 @@ extern "C" {
|
||||
|
||||
*/
|
||||
|
||||
bool canConvertType( cmDataFmtId_t srcId, cmDataFmtId_t dstId );
|
||||
bool willTruncate( cmDataFmtId_t srcId, cmDataFmtId_t dstId );
|
||||
bool canConvertObj( const cmData_t* srcObj, cmData_t* dstObj );
|
||||
bool willTruncateObj(const cmData_t* srcObj, cmData_t* dstObj );
|
||||
enum
|
||||
{
|
||||
kOkDtRC = cmOkRC,
|
||||
kAssertErrDtRC,
|
||||
kConstErrDtRC,
|
||||
kCvtErrDtRC,
|
||||
kInvalidContDtRC,
|
||||
kInvalidTypeDtRC,
|
||||
kEolDtRC
|
||||
};
|
||||
|
||||
typedef unsigned cmDtRC_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kInvalidTypeDtId,// 0
|
||||
kNullDtId, // 1 the data object exists but it has no data
|
||||
kUCharDtId, // 2
|
||||
kCharDtId, // 3
|
||||
kUShortDtId, // 4
|
||||
kShortDtId, // 5
|
||||
kUIntDtId, // 6
|
||||
kIntDtId, // 7
|
||||
kULongDtId, // 8
|
||||
kLongDtId, // 9
|
||||
kFloatDtId, // 10
|
||||
kDoubleDtId, // 11
|
||||
kStrDtId, // 12 zero terminated string
|
||||
kBlobDtId, // 13 application defined raw memory object
|
||||
kStructDtId // 14 node is a pair,list, or recd
|
||||
} cmDataTypeId_t;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kInvalidCntDtId, // 0
|
||||
kScalarDtId, // 1
|
||||
kArrayDtId, // 2
|
||||
kPairDtId, // 3
|
||||
kListDtId, // 4
|
||||
kRecordDtId // 5
|
||||
} cmDataContainerId_t;
|
||||
|
||||
enum
|
||||
{
|
||||
kNoFlagsDtFl = 0x00,
|
||||
|
||||
// Indicate that the memory used by the data object
|
||||
// was dynamically allocated and should be released
|
||||
// by cmDataFree().
|
||||
kFreeObjDtFl = 0x01,
|
||||
|
||||
// Indicate that the memory used by strings, blobs
|
||||
// and arrays should be freed by cmDataFree().
|
||||
kFreeValueDtFl = 0x02,
|
||||
|
||||
// Indicate that the value of the object cannot be changed.
|
||||
// (but the object could be reassigned as a new type).
|
||||
kConstValueDtFl = 0x04,
|
||||
|
||||
// Indicate that the type of the object cannot be changed.
|
||||
// (but the value may be changed).
|
||||
kConstObjDtFl = 0x08,
|
||||
|
||||
// Indicate that the array or string should not be
|
||||
// internally reallocated but rather the source pointer
|
||||
// should be taken as the new value of the object.
|
||||
kNoCopyDtFl = 0x10,
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef struct cmData_str
|
||||
{
|
||||
cmDataTypeId_t tid; // data format id
|
||||
cmDataContainerId_t cid; // container id
|
||||
unsigned flags; //
|
||||
struct cmData_str* parent; // this childs parent
|
||||
struct cmData_str* sibling; // this childs left sibling
|
||||
unsigned cnt; // byte cnt for strings/blobs and ele count for arrays
|
||||
|
||||
union
|
||||
{
|
||||
char c;
|
||||
unsigned char uc;
|
||||
short s;
|
||||
unsigned short us;
|
||||
int i;
|
||||
unsigned int ui;
|
||||
long l;
|
||||
unsigned long ul;
|
||||
float f;
|
||||
double d;
|
||||
|
||||
cmChar_t* z;
|
||||
|
||||
void* vp;
|
||||
|
||||
/*
|
||||
char* cp;
|
||||
unsigned char* ucp;
|
||||
short* sp;
|
||||
unsigned short* usp;
|
||||
int* ip;
|
||||
unsigned int* uip;
|
||||
long* lp;
|
||||
unsigned long* ulp;
|
||||
float* fp;
|
||||
double* dp;
|
||||
*/
|
||||
|
||||
struct cmData_str* child; // first child (list,record,pair)
|
||||
} u;
|
||||
|
||||
} cmData_t;
|
||||
|
||||
extern cmData_t cmDataNull;
|
||||
|
||||
const cmChar_t* cmDataTypeToLabel( cmDataTypeId_t tid );
|
||||
cmDataTypeId_t cmDataLabelToType( const cmChar_t* typeLabelStr );
|
||||
|
||||
// Returns 1 for kStrDtId.
|
||||
// Returns cmInvalidCnt if tid is not recognized.
|
||||
unsigned dmDataByteWidth( cmDataTypeId_t tid );
|
||||
|
||||
const cmChar_t* cmDataContainerIdToLabel( cmDataContainerId_t tid );
|
||||
cmDataContainerId_t cmDataLabelToContainerId( const cmChar_t* contLabelStr );
|
||||
|
||||
bool cmDataIsConstObj( const cmData_t* d );
|
||||
void cmDataEnableConstObj( cmData_t* d, bool enaFl );
|
||||
|
||||
bool cmDataIsConstValue( const cmData_t* d );
|
||||
void cmDataEnableConstValue( cmData_t* d, bool enaFl );
|
||||
|
||||
bool cmDataIsFreeValue( const cmData_t* d );
|
||||
void cmDataEnableFreeValue( cmData_t* d, bool enaFl );
|
||||
|
||||
// Returns true if this is a scalar or array node.
|
||||
bool cmDataIsLeaf( const cmData_t* d);
|
||||
|
||||
// Return true if this is NOT a scalar or array node.
|
||||
bool cmDataIsStruct( const cmData_t* d );
|
||||
|
||||
|
||||
|
||||
// Get the value of an object without conversion.
|
||||
// The data type id must match the return type or the
|
||||
// conversion must be an automatic C conversion.
|
||||
char cmDataChar( const cmData_t* p );
|
||||
unsigned char cmDataUChar( const cmData_t* p );
|
||||
short cmDataShort( const cmData_t* p );
|
||||
unsigned short cmDataUShort( const cmData_t* p );
|
||||
int cmDataInt( const cmData_t* p );
|
||||
unsigned int cmDataUInt( const cmData_t* p );
|
||||
long cmDataLong( const cmData_t* p );
|
||||
unsigned long cmDataULong( const cmData_t* p );
|
||||
float cmDataFloat( const cmData_t* p );
|
||||
double cmDataDouble( const cmData_t* p );
|
||||
cmChar_t* cmDataStr( const cmData_t* p );
|
||||
const cmChar_t* cmDataConstStr( const cmData_t* p );
|
||||
void* cmDataVoidPtr( const cmData_t* p );
|
||||
char* cmDataCharPtr( const cmData_t* p );
|
||||
unsigned char* cmDataUCharPtr( const cmData_t* p );
|
||||
short* cmDataShortPtr( const cmData_t* p );
|
||||
unsigned short* cmDataUShortPtr( const cmData_t* p );
|
||||
int* cmDataIntPtr( const cmData_t* p );
|
||||
unsigned int* cmDataUIntPtr( const cmData_t* p );
|
||||
long* cmDataLongPtr( const cmData_t* p );
|
||||
unsigned long* cmDataULongPtr( const cmData_t* p );
|
||||
float* cmDataFloatPtr( const cmData_t* p );
|
||||
double* cmDataDoublePtr( const cmData_t* p );
|
||||
//----------------------------------------------------------------------------
|
||||
// Scalar related functions
|
||||
//
|
||||
|
||||
// Dynamically allocate a scalar object and set it's value.
|
||||
// The 'flags' argument may include kConstValueDtFl and kConstObjDtFl.
|
||||
// The string and blob constructors may also use the
|
||||
// kNoCopyDtFl and the kFreeValueDtFl.
|
||||
|
||||
// Generic:
|
||||
// 'byteCnt' is ignored for all types other than strings and blobs.
|
||||
cmDtRC_t cmDataNewScalar( cmData_t* parent, cmDataTypeId_t tid, unsigned flags, void* vp, unsigned byteCnt, cmData_t** ref );
|
||||
|
||||
// Type specific
|
||||
cmDtRC_t cmDataNewNull( cmData_t* parent, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewChar( cmData_t* parent, unsigned flags, char v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewUChar( cmData_t* parent, unsigned flags, unsigned char v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewShort( cmData_t* parent, unsigned flags, short v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewUShort( cmData_t* parent, unsigned flags, unsigned short v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewInt( cmData_t* parent, unsigned flags, int v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewUInt( cmData_t* parent, unsigned flags, unsigned int v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewLong( cmData_t* parent, unsigned flags, long v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewULong( cmData_t* parent, unsigned flags, unsigned long v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewFloat( cmData_t* parent, unsigned flags, float v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewDouble( cmData_t* parent, unsigned flags, double v, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewStr( cmData_t* parent, unsigned flags, cmChar_t* str, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewConstStr( cmData_t* parent, unsigned flags, const cmChar_t* str, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewStrN( cmData_t* parent, unsigned flags, cmChar_t* str, unsigned charCnt, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewConstStrN(cmData_t* parent, unsigned flags, const cmChar_t* str, unsigned charCnt, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewBlob( cmData_t* parent, unsigned flags, void* vp, unsigned byteCnt, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewConstBlob(cmData_t* parent, unsigned flags, const void* vp, unsigned byteCnt, cmData_t** ref );
|
||||
|
||||
|
||||
|
||||
// Set the value and type of an existing scalar object.
|
||||
// These functions begin by releasing any resources held by *p
|
||||
// prior to resetting the type and value of the object.
|
||||
// The 'flags' argument to cmDataSetStr() and cmDataSetConstStr()
|
||||
// may use the kNoCopyDtFl and the kFreeValueDtFl
|
||||
cmDtRC_t cmDataSetScalarValue( cmData_t* d, cmDataTypeId_t tid, void* vp, unsigned byteCnt, unsigned flags );
|
||||
|
||||
cmDtRC_t cmDataSetNull( cmData_t* p );
|
||||
cmDtRC_t cmDataSetChar( cmData_t* p, char v );
|
||||
cmDtRC_t cmDataSetUChar( cmData_t* p, unsigned char v );
|
||||
cmDtRC_t cmDataSetShort( cmData_t* p, short v );
|
||||
cmDtRC_t cmDataSetUShort( cmData_t* p, unsigned short v );
|
||||
cmDtRC_t cmDataSetInt( cmData_t* p, int v );
|
||||
cmDtRC_t cmDataSetUInt( cmData_t* p, unsigned int v );
|
||||
cmDtRC_t cmDataSetLong( cmData_t* p, long v );
|
||||
cmDtRC_t cmDataSetULong( cmData_t* p, unsigned long v );
|
||||
cmDtRC_t cmDataSetFloat( cmData_t* p, float v );
|
||||
cmDtRC_t cmDataSetDouble( cmData_t* p, double v );
|
||||
cmDtRC_t cmDataSetStr( cmData_t* p, unsigned flags, cmChar_t* s );
|
||||
cmDtRC_t cmDataSetConstStr( cmData_t* p, unsigned flags, const cmChar_t* s );
|
||||
cmDtRC_t cmDataSetStrN( cmData_t* p, unsigned flags, cmChar_t* s, unsigned charCnt );
|
||||
cmDtRC_t cmDataSetConstStrN( cmData_t* p, unsigned flags, const cmChar_t* s, unsigned charCnt );
|
||||
cmDtRC_t cmDataSetBlob( cmData_t* p, unsigned flags, void* v, unsigned byteCnt );
|
||||
cmDtRC_t cmDataSetConstBlob( cmData_t* p, unsigned flags, const void* v, unsigned byteCnt );
|
||||
|
||||
// Get the value of an object. No conversion is applied the
|
||||
// type must match exactly or an error is generated.
|
||||
cmDtRC_t cmDataChar( const cmData_t* p, char* v );
|
||||
cmDtRC_t cmDataUChar( const cmData_t* p, unsigned char* v );
|
||||
cmDtRC_t cmDataShort( const cmData_t* p, short* v );
|
||||
cmDtRC_t cmDataUShort( const cmData_t* p, unsigned short* v );
|
||||
cmDtRC_t cmDataInt( const cmData_t* p, int* v );
|
||||
cmDtRC_t cmDataUInt( const cmData_t* p, unsigned int* v );
|
||||
cmDtRC_t cmDataLong( const cmData_t* p, long* v );
|
||||
cmDtRC_t cmDataULong( const cmData_t* p, unsigned long* v );
|
||||
cmDtRC_t cmDataFloat( const cmData_t* p, float* v );
|
||||
cmDtRC_t cmDataDouble( const cmData_t* p, double* v );
|
||||
cmDtRC_t cmDataStr( const cmData_t* p, cmChar_t** v );
|
||||
cmDtRC_t cmDataConstStr( const cmData_t* p, const cmChar_t** v );
|
||||
cmDtRC_t cmDataBlob( const cmData_t* p, cmChar_t** v, unsigned* byteCntRef );
|
||||
cmDtRC_t cmDataConstBlob( const cmData_t* p, const cmChar_t** v, unsigned* byteCntRef );
|
||||
|
||||
// Get the value of an object with conversion.
|
||||
cmDtRC_t cmDataGetChar( const cmData_t* p, char* v );
|
||||
@ -217,124 +281,95 @@ extern "C" {
|
||||
cmDtRC_t cmDataGetFloat( const cmData_t* p, float* v );
|
||||
cmDtRC_t cmDataGetDouble( const cmData_t* p, double* v );
|
||||
|
||||
// Returns the pointer - does not copy the data.
|
||||
cmDtRC_t cmDataGetStr( const cmData_t* p, char** v );
|
||||
cmDtRC_t cmDataGetConstStr( const cmData_t* p, const char** v );
|
||||
cmDtRC_t cmDataGetVoidPtr( const cmData_t* p, void** v );
|
||||
cmDtRC_t cmDataGetCharPtr( const cmData_t* p, char** v );
|
||||
cmDtRC_t cmDataGetUCharPtr( const cmData_t* p, unsigned char** v );
|
||||
cmDtRC_t cmDataGetShortPtr( const cmData_t* p, short** v );
|
||||
cmDtRC_t cmDataGetUShortPtr( const cmData_t* p, unsigned short** v );
|
||||
cmDtRC_t cmDataGetIntPtr( const cmData_t* p, int** v );
|
||||
cmDtRC_t cmDataGetUIntPtr( const cmData_t* p, unsigned int** v );
|
||||
cmDtRC_t cmDataGetLongPtr( const cmData_t* p, long** v );
|
||||
cmDtRC_t cmDataGetULongPtr( const cmData_t* p, unsigned long** v );
|
||||
cmDtRC_t cmDataGetFloatPtr( const cmData_t* p, float** v );
|
||||
cmDtRC_t cmDataGetDoublePtr( const cmData_t* p, double** v );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Array related functions
|
||||
//
|
||||
|
||||
// Notes:
|
||||
// 1) string arrays are arrays of string pointers.
|
||||
// 2) blob arrays (array of void pointers) are not supported because
|
||||
// there is no direct way to determine the length of each blob
|
||||
// and therefore they cannot be internally duplicated - a special scheme
|
||||
// could be devised (length goes in first 4 bytes) to make this
|
||||
// work but we will defer that until the need arises.
|
||||
|
||||
//
|
||||
// Dynamically allocate a new array data object.
|
||||
//
|
||||
// eleCnt referes to the number of elements in the array pointed
|
||||
// to by 'vp'. The number of bytes pointed to by 'vp' is then
|
||||
// cmDataByteWidth(tid)*eleCnt.
|
||||
//
|
||||
// If no flags are set then the array pointed to by 'vp' is reallocated
|
||||
// and kDataFreeDtFl is set.
|
||||
//
|
||||
// If kFreeValueDtFl is set then the object will take responsibility for
|
||||
// releasing the memory pointed to by 'vp' when the object is destroyed
|
||||
// or the array is reassigned.
|
||||
//
|
||||
// If kNoCopyDtFl is set then 'vp' becomes the internal array
|
||||
// value (vp[cnt]) is NOT reallocated). In this case the client is
|
||||
// responsibile for eventually releasing the associated memory - when
|
||||
// the data object is no longer valid.
|
||||
cmDtRC_t cmDataNewArray( cmData_t* parent, cmDataTypeId_t tid, void* vp, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
|
||||
cmDtRC_t cmDataNewCharArray( cmData_t* parent, char* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewUCharArray( cmData_t* parent, unsigned char* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewShortArray( cmData_t* parent, short* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewUShortArray( cmData_t* parent, unsigned short* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewIntArray( cmData_t* parent, int* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewUIntArray( cmData_t* parent, unsigned int* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewLongArray( cmData_t* parent, long* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewULongArray( cmData_t* parent, unsigned long* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewFloatArray( cmData_t* parent, float* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewDoubleArray( cmData_t* parent, double* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewStrArray( cmData_t* parent, cmChar_t** v, unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
cmDtRC_t cmDataNewConstStrArray( cmData_t* parent, const cmChar_t** v,unsigned eleCnt, unsigned flags, cmData_t** ref );
|
||||
|
||||
// Set the value and type of an existing scalar object.
|
||||
//
|
||||
// These functions begin by releasing any resources held by *p
|
||||
// prior to resetting the type and value of the object.
|
||||
cmData_t* cmDataSetNull( cmData_t* p );
|
||||
cmData_t* cmDataSetChar( cmData_t* p, char v );
|
||||
cmData_t* cmDataSetUChar( cmData_t* p, unsigned char v );
|
||||
cmData_t* cmDataSetShort( cmData_t* p, short v );
|
||||
cmData_t* cmDataSetUShort( cmData_t* p, unsigned short v );
|
||||
cmData_t* cmDataSetInt( cmData_t* p, int v );
|
||||
cmData_t* cmDataSetUInt( cmData_t* p, unsigned int v );
|
||||
cmData_t* cmDataSetLong( cmData_t* p, long v );
|
||||
cmData_t* cmDataSetULong( cmData_t* p, unsigned long v );
|
||||
cmData_t* cmDataSetFloat( cmData_t* p, float v );
|
||||
cmData_t* cmDataSetDouble( cmData_t* p, double v );
|
||||
cmData_t* cmDataSetStr( cmData_t* p, cmChar_t* s );
|
||||
cmData_t* cmDataSetConstStr( cmData_t* p, const cmChar_t* s );
|
||||
// The 'flags' argument may include kConstValueDtFl, kConstObjDtFl,
|
||||
// kNoCopyDtFl and the kFreeValueDtFl.
|
||||
|
||||
// Set the type and value of an existing data object to an external array.
|
||||
// These functions begin by releasing any resources help by *p.
|
||||
// The array pointed to by 'vp' is not copied or duplicated.
|
||||
// 'vp' is simply assigned as the data space for the object and therefore must remain
|
||||
// valid for the life of the object.
|
||||
cmData_t* cmDataSetVoidPtr( cmData_t* p, void* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetCharPtr( cmData_t* p, char* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetUCharPtr( cmData_t* p, unsigned char* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetShortPtr( cmData_t* p, short* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetUShortPtr( cmData_t* p, unsigned short* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetIntPtr( cmData_t* p, int* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetUIntPtr( cmData_t* p, unsigned int* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetLongPtr( cmData_t* p, long* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetULongPtr( cmData_t* p, unsigned long* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetFloatPtr( cmData_t* p, float* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetDoublePtr( cmData_t* p, double* vp, unsigned cnt );
|
||||
// Generic set array functions. 'vp' is assumed to point to an array
|
||||
// of the type defined by 'tid'.
|
||||
cmDtRC_t cmDataSetArrayValue( cmData_t* dt, cmDataTypeId_t tid, void* vp, unsigned eleCnt, unsigned flags );
|
||||
|
||||
// Set the value of an existing array based data object.
|
||||
// These functions begin by releasing any resources help by *p
|
||||
// and then dynamically allocate the internal array and copy
|
||||
// the array data into it.
|
||||
cmData_t* cmDataSetStrAlloc( cmData_t* p, const cmChar_t* s );
|
||||
cmData_t* cmDataSetConstStrAlloc( cmData_t* p, const cmChar_t* s );
|
||||
cmData_t* cmDataSetVoidAllocPtr( cmData_t* p, const void* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetCharAllocPtr( cmData_t* p, const char* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetUCharAllocPtr( cmData_t* p, const unsigned char* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetShortAllocPtr( cmData_t* p, const short* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetUShortAllocPtr( cmData_t* p, const unsigned short* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetIntAllocPtr( cmData_t* p, const int* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetUIntAllocPtr( cmData_t* p, const unsigned int* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetLongAllocPtr( cmData_t* p, const long* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetULongAllocPtr( cmData_t* p, const unsigned long* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetFloatAllocPtr( cmData_t* p, const float* vp, unsigned cnt );
|
||||
cmData_t* cmDataSetDoubleAllocPtr( cmData_t* p, const double* vp, unsigned cnt );
|
||||
// Type sepctific set array functions.
|
||||
cmDtRC_t cmDataSetCharArray( cmData_t* d, char* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetUCharArray( cmData_t* d, unsigned char* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetShortArray( cmData_t* d, short* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetUShortArray( cmData_t* d, unsigned short* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetIntArray( cmData_t* d, int* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetUIntArray( cmData_t* d, unsigned int* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetLongArray( cmData_t* d, long* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetULongArray( cmData_t* d, unsigned long* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetFloatArray( cmData_t* d, float* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetDoubleArray( cmData_t* d, double* v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetStrArray( cmData_t* d, cmChar_t** v, unsigned eleCnt, unsigned flags );
|
||||
cmDtRC_t cmDataSetConstStrArray(cmData_t* d,const cmChar_t** v,unsigned eleCnt, unsigned flags );
|
||||
|
||||
// Return the count of elements in a n array.
|
||||
unsigned cmDataArrayEleCount( const cmData_t* d );
|
||||
|
||||
// Dynamically allocate a data object and set it's value.
|
||||
cmData_t* cmDataAllocNull( cmData_t* parent );
|
||||
cmData_t* cmDataAllocChar( cmData_t* parent, char v );
|
||||
cmData_t* cmDataAllocUChar( cmData_t* parent, unsigned char v );
|
||||
cmData_t* cmDataAllocShort( cmData_t* parent, short v );
|
||||
cmData_t* cmDataAllocUShort( cmData_t* parent, unsigned short v );
|
||||
cmData_t* cmDataAllocInt( cmData_t* parent, int v );
|
||||
cmData_t* cmDataAllocUInt( cmData_t* parent, unsigned int v );
|
||||
cmData_t* cmDataAllocLong( cmData_t* parent, long v );
|
||||
cmData_t* cmDataAllocULong( cmData_t* parent, unsigned long v );
|
||||
cmData_t* cmDataAllocFloat( cmData_t* parent, float v );
|
||||
cmData_t* cmDataAllocDouble( cmData_t* parent, double v );
|
||||
|
||||
// Dynamically allocate a data object and set its array value to an external
|
||||
// array. v[cnt] is assigned as the internal data space for the object and
|
||||
// therefore must remain valid for the life of the object.
|
||||
// See the cmDataXXXAlocPtr() for equivalent functions which dynamically
|
||||
// allocate the intenal data space.
|
||||
cmData_t* cmDataAllocStr( cmData_t* parent, cmChar_t* str );
|
||||
cmData_t* cmDataAllocConstStr( cmData_t* parent, const cmChar_t* str );
|
||||
cmData_t* cmDataAllocCharPtr( cmData_t* parent, char* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocUCharPtr( cmData_t* parent, unsigned char* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocShortPtr( cmData_t* parent, short* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocUShortPtr( cmData_t* parent, unsigned short* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocIntPtr( cmData_t* parent, int* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocUIntPtr( cmData_t* parent, unsigned int* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocLongPtr( cmData_t* parent, long* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocULongPtr( cmData_t* parent, unsigned long* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocFloatPtr( cmData_t* parent, float* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocDoublePtr( cmData_t* parent, double* v, unsigned cnt );
|
||||
cmData_t* cmDataAllocVoidPtr( cmData_t* parent, void* v, unsigned cnt );
|
||||
|
||||
|
||||
// Dynamically allocate a data object and its array value.
|
||||
// These functions dynamically allocate the internal array data space
|
||||
// and copy v[cnt] into it.
|
||||
cmData_t* cmDataStrAlloc( cmData_t* parent, cmChar_t* str );
|
||||
cmData_t* cmDataConstStrAlloc( cmData_t* parent, const cmChar_t* str );
|
||||
cmData_t* cmDataCharAllocPtr( cmData_t* parent, const char* v, unsigned cnt );
|
||||
cmData_t* cmDataUCharAllocPtr( cmData_t* parent, const unsigned char* v, unsigned cnt );
|
||||
cmData_t* cmDataShortAllocPtr( cmData_t* parent, const short* v, unsigned cnt );
|
||||
cmData_t* cmDataUShortAllocPtr( cmData_t* parent, const unsigned short* v, unsigned cnt );
|
||||
cmData_t* cmDataIntAllocPtr( cmData_t* parent, const int* v, unsigned cnt );
|
||||
cmData_t* cmDataUIntAllocPtr( cmData_t* parent, const unsigned int* v, unsigned cnt );
|
||||
cmData_t* cmDataLongAllocPtr( cmData_t* parent, const long* v, unsigned cnt );
|
||||
cmData_t* cmDataULongAllocPtr( cmData_t* parent, const unsigned long* v, unsigned cnt );
|
||||
cmData_t* cmDataFloatAllocPtr( cmData_t* parent, const float* v, unsigned cnt );
|
||||
cmData_t* cmDataDoubleAllocPtr( cmData_t* parent, const double* v, unsigned cnt );
|
||||
cmData_t* cmDataVoidAllocPtr( cmData_t* parent, const void* v, unsigned cnt );
|
||||
// Get a pointer to the base of an array.
|
||||
// The type must match exactly or an error is generated.
|
||||
// Use cmDataEleCount() to determine the number of elements in the array.
|
||||
cmDtRC_t cmDataCharArray( const cmData_t* d, char** v );
|
||||
cmDtRC_t cmDataUCharArray( const cmData_t* d, unsigned char** v );
|
||||
cmDtRC_t cmDataShortArray( const cmData_t* d, short** v );
|
||||
cmDtRC_t cmDataUShortArray( const cmData_t* d, unsigned short** v );
|
||||
cmDtRC_t cmDataIntArray( const cmData_t* d, int** v );
|
||||
cmDtRC_t cmDataUIntArray( const cmData_t* d, unsigned int** v );
|
||||
cmDtRC_t cmDataLongArray( const cmData_t* d, long** v );
|
||||
cmDtRC_t cmDataULongArray( const cmData_t* d, unsigned long** v );
|
||||
cmDtRC_t cmDataFloatArray( const cmData_t* d, float** v );
|
||||
cmDtRC_t cmDataDoubleArray( const cmData_t* d, double** v );
|
||||
cmDtRC_t cmDataStrArray( const cmData_t* d, cmChar_t*** v );
|
||||
cmDtRC_t cmDataConstStrArray( const cmData_t* d, const cmChar_t*** v );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Structure related functions
|
||||
@ -428,6 +463,7 @@ extern "C" {
|
||||
cmData_t* cmDataAllocPairId( cmData_t* parent, unsigned keyId, cmData_t* value );
|
||||
|
||||
// Dynamically allocate the label but link (w/o realloc) the value.
|
||||
cmData_t* cmDataAllocPairLabelN(cmData_t* parent, const cmChar_t* label, unsigned charCnt, cmData_t* value);
|
||||
cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t* label, cmData_t* value );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -445,15 +481,15 @@ extern "C" {
|
||||
|
||||
|
||||
// Var-args fmt:
|
||||
// <typeId> <value> {<cnt>}
|
||||
// <contId> {<typeId>} <value> {<cnt>}
|
||||
// scalar types: <value> is literal,<cnt> is not included
|
||||
// null has no <value> or <cnt>
|
||||
// ptr types: <value> is pointer,<cnt> is element count
|
||||
// struct types: <value> is cmData_t, <cnt> is not included
|
||||
// array types: <value> is pointer,<cnt> is element count
|
||||
// struct types: <value> is cmData_t, <typeId> and <cnt> is not included
|
||||
// Indicate the end of argument list by setting <typeId> to kInvalidDtId.
|
||||
// The memory for array based data types is dynamically allocated.
|
||||
cmData_t* cmDataListAllocV(cmData_t* parent, va_list vl );
|
||||
cmData_t* cmDataListAllocA(cmData_t* parent, ... );
|
||||
cmRC_t cmDataListAllocV(cmData_t* parent, cmData_t** ref, va_list vl );
|
||||
cmRC_t cmDataListAllocA(cmData_t* parent, cmData_t** ref, ... );
|
||||
|
||||
// Returns a ptr to 'ele'.
|
||||
cmData_t* cmDataListAppendEle( cmData_t* p, cmData_t* ele );
|
||||
@ -464,9 +500,6 @@ extern "C" {
|
||||
cmData_t* cmDataListInsertEle( cmData_t* p, unsigned index, cmData_t* ele );
|
||||
cmData_t* cmDataListInsertEleN(cmData_t* p, unsigned index, cmData_t* ele[], unsigned n );
|
||||
|
||||
cmData_t* cmDataListUnlink( cmData_t* p, unsigned index );
|
||||
cmData_t* cmDataListFree( cmData_t* p, unsigned index );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Record related functions
|
||||
//
|
||||
@ -487,17 +520,17 @@ extern "C" {
|
||||
unsigned cmDataRecdKeyId( cmData_t* p, unsigned index );
|
||||
const cmChar_t* cmDataRecdKeyLabel( cmData_t* p, unsigned index );
|
||||
|
||||
cmData_t* cmRecdMake( cmData_t* parent, cmData_t* p );
|
||||
cmData_t* cmRecdAlloc( cmData_t* parent );
|
||||
cmData_t* cmDataRecdMake( cmData_t* parent, cmData_t* p );
|
||||
cmData_t* cmDataRecdAlloc( cmData_t* parent );
|
||||
|
||||
// Append a pair node by linking the pair node 'pair' to the record node 'p'.
|
||||
// 'pair' is simply linked to 'p' via cmDataAppendChild() no
|
||||
// reallocation or duplicattion takes place.
|
||||
cmData_t* cmRecdAppendPair( cmData_t* p, cmData_t* pair );
|
||||
cmData_t* cmDataRecdAppendPair( cmData_t* p, cmData_t* pair );
|
||||
|
||||
|
||||
// Var-args format:
|
||||
// <label|id> <typeId> <value> {<cnt>}
|
||||
// <label|id> {<cid>} <typeId> <value> {<cnt>}
|
||||
// scalar types: <value> is literal,<cnt> is not included
|
||||
// null type: has no <value> or <cnt>
|
||||
// ptr types: <value> is pointer, <cnt> is element count
|
||||
@ -530,12 +563,27 @@ extern "C" {
|
||||
cmDtRC_t cmDataSerialize( const cmData_t* p, void* buf, unsigned bufByteCnt );
|
||||
cmDtRC_t cmDataDeserialize( const void* buf, unsigned bufByteCnt, cmData_t** pp );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef cmHandle_t cmDataParserH_t;
|
||||
//static cmDataParserH_t cmDataParserNullHandle;
|
||||
|
||||
cmDtRC_t cmDataParserCreate( cmCtx_t* ctx, cmDataParserH_t* hp );
|
||||
cmDtRC_t cmDataParserDestroy( cmDataParserH_t* hp );
|
||||
bool cmDataParserIsValid( cmDataParserH_t h );
|
||||
|
||||
// Parse a text representation into a 'record' type.
|
||||
// Note that the text is wrapped with implied curly braces
|
||||
// (e.g. "{ text }"). The contents of the text should therefore
|
||||
// fit the record syntax (e.g. the first token should be a
|
||||
// 'pair' label.
|
||||
cmDtRC_t cmDataParserExec( cmDataParserH_t h, const cmChar_t* text, cmData_t** pp );
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void cmDataPrint( const cmData_t* p, cmRpt_t* rpt );
|
||||
|
||||
void cmDataTest( cmCtx_t* ctx );
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -60,7 +60,11 @@ extern "C" {
|
||||
// Draw the page.
|
||||
void cmGrPageDraw( cmGrPgH_t h, cmGrDcH_t dcH );
|
||||
|
||||
// Label callback functions are used to translate numeric axis values to
|
||||
// text strings. Multiple label callback functions can be registered with
|
||||
// a page and then assigned to a given view axis via cmGrViewSetLabelFunc().
|
||||
typedef void (*cmGrLabelFunc_t)( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value );
|
||||
|
||||
// Returns id of the new page label function.
|
||||
unsigned cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label );
|
||||
unsigned cmGrPageLabelFuncCount( cmGrPgH_t h );
|
||||
|
171
cmLex.c
171
cmLex.c
@ -7,6 +7,12 @@
|
||||
#include "cmMallocDebug.h"
|
||||
#include "cmFile.h"
|
||||
|
||||
enum
|
||||
{
|
||||
kRealFloatLexFl = 0x01,
|
||||
kIntUnsignedLexFl = 0x02
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned code;
|
||||
@ -29,6 +35,7 @@ cmLexErrorRecd cmLexErrorArray[] =
|
||||
{ kMemAllocErrLexRC, "An attempted memory allocation failed"},
|
||||
{ kEofRC, "The end of the input text was encountered (this is a normal condition not an error)"},
|
||||
{ kInvalidLexTIdLexRC, "An invalid token id was encountered."},
|
||||
{ kSignErrorLexRC, "A signed integer has a 'u' or 'U' suffix."},
|
||||
{ kInvalidLexRC, "Unknown lexer error code." }
|
||||
};
|
||||
|
||||
@ -75,6 +82,7 @@ typedef struct cmLex_str
|
||||
|
||||
cmChar_t* textBuf; // text buf used by cmLexSetFile()
|
||||
|
||||
unsigned attrFlags; // used to store the int and real suffix type flags
|
||||
} cmLex;
|
||||
|
||||
|
||||
@ -148,7 +156,7 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
|
||||
unsigned i = 0;
|
||||
unsigned n = 0; // decimal point counter
|
||||
unsigned d = 0; // digit counter
|
||||
bool fl = false; // true if this real includes an exponent
|
||||
bool fl = false; // expo flag
|
||||
|
||||
for(; i<cn && n<=1; ++i)
|
||||
{
|
||||
@ -170,10 +178,12 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
|
||||
// if there was at least one digit and the next char is an 'e'
|
||||
if( d>0 && i<cn && (cp[i] == 'e' || cp[i] == 'E') )
|
||||
{
|
||||
d=0;
|
||||
unsigned e=0;
|
||||
++i;
|
||||
unsigned j = i;
|
||||
|
||||
fl = false;
|
||||
|
||||
for(; i<cn; ++i)
|
||||
{
|
||||
if( i==j && cp[i]=='-' ) // allow the char following the e to be '-'
|
||||
@ -181,6 +191,7 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
|
||||
|
||||
if( isdigit(cp[i]) )
|
||||
{
|
||||
++e;
|
||||
++d;
|
||||
continue;
|
||||
}
|
||||
@ -190,17 +201,42 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
|
||||
}
|
||||
|
||||
// an exp exists if digits follwed the 'e'
|
||||
fl = d > 0;
|
||||
fl = e > 0;
|
||||
|
||||
}
|
||||
|
||||
return i>1 && (n==1 || fl) ? i : 0;
|
||||
// if at least one digit was found
|
||||
if( d>0 )
|
||||
{
|
||||
// Note that this path allows a string w/o a decimal pt to trigger a match.
|
||||
|
||||
if(i<cn)
|
||||
{
|
||||
// if the real has a suffix
|
||||
switch(cp[i])
|
||||
{
|
||||
case 'F':
|
||||
case 'f':
|
||||
p->attrFlags = cmSetFlag(p->attrFlags,kRealFloatLexFl);
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// match w/o suffix return
|
||||
if( d>0 && (fl || n==1 || cmIsFlag(p->attrFlags,kRealFloatLexFl)) )
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0; // no-match return
|
||||
}
|
||||
|
||||
unsigned _cmLexIntMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
|
||||
{
|
||||
unsigned i = 0;
|
||||
bool signFl = false;
|
||||
|
||||
for(; i<cn; ++i)
|
||||
{
|
||||
if( i==0 && cp[i]=='-' )
|
||||
@ -223,8 +259,34 @@ unsigned _cmLexIntMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
|
||||
// The current implementation recognizes all numeric strings
|
||||
// containing a decimal point as reals.
|
||||
|
||||
// if no integer was found
|
||||
if( (signFl && i==0) || i==0 )
|
||||
return 0;
|
||||
|
||||
return signFl && i==1 ? 0 : i;
|
||||
|
||||
// check for suffix
|
||||
if(i<cn )
|
||||
{
|
||||
|
||||
switch(cp[i])
|
||||
{
|
||||
case 'u':
|
||||
case 'U':
|
||||
if( signFl )
|
||||
_cmLexError(p,kSignErrorLexRC,"A signed integer has a 'u' or 'U' suffix.");
|
||||
else
|
||||
{
|
||||
p->attrFlags = cmSetFlag(p->attrFlags,kIntUnsignedLexFl);
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned _cmLexHexMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
|
||||
@ -387,23 +449,6 @@ cmLexH cmLexInit( const cmChar_t* cp, unsigned cn, unsigned flags, cmRpt_t* rpt
|
||||
|
||||
_cmLexSetTextBuffer( p, cp, cn );
|
||||
|
||||
/*
|
||||
p->cp = (cn==0) ? NULL : cp;
|
||||
p->cn = (cp==NULL) ? 0 : cn;
|
||||
|
||||
p->ci = 0;
|
||||
|
||||
|
||||
p->curTokenId = kErrorLexTId;
|
||||
p->curTokenCharIdx = cmInvalidIdx;
|
||||
p->curTokenCharCnt = 0;
|
||||
|
||||
p->curLine = 0;
|
||||
p->curCol = 0;
|
||||
p->nextLine = 0;
|
||||
p->nextCol = 0;
|
||||
*/
|
||||
|
||||
int init_mfn = 10;
|
||||
p->mfp = cmMemAllocZ( cmLexMatcher, init_mfn );
|
||||
p->mfn = init_mfn;
|
||||
@ -537,70 +582,6 @@ cmRC_t cmLexSetFile( cmLexH h, const cmChar_t* fn )
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
cmRC_t cmLexSetFile( cmLexH h, const cmChar_t* fn )
|
||||
{
|
||||
cmRC_t rc = kOkLexRC;
|
||||
FILE* fp = NULL;
|
||||
cmLex* p = _cmLexHandleToPtr(h);
|
||||
unsigned n = 0;
|
||||
|
||||
assert( fn != NULL && p != NULL );
|
||||
|
||||
// open the file
|
||||
if((fp = fopen(fn,"rb")) == NULL )
|
||||
return _cmLexError(p,kFileOpenErrLexRC,"Unable to open the file:'%s'.",fn);
|
||||
|
||||
// seek to the end
|
||||
if( fseek(fp,0,SEEK_END) != 0 )
|
||||
{
|
||||
rc= _cmLexError(p,kFileSeekErrLexRC,"Unable to seek to the end of '%s'.",fn);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// get the length of the file
|
||||
if( (n=ftell(fp)) == 0 )
|
||||
{
|
||||
rc = _cmLexError(p,kFileOpenErrLexRC,"The file '%s' appears to be empty.",fn);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// rewind the file
|
||||
if( fseek(fp,0,SEEK_SET) != 0 )
|
||||
{
|
||||
rc = _cmLexError(p,kFileSeekErrLexRC,"Unable to seek to the beginning of '%s'.",fn);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// allocate the text buffer
|
||||
if((p->textBuf = cmMemResizeZ( char, p->textBuf, n+1)) == NULL )
|
||||
{
|
||||
rc = _cmLexError(p,kMemAllocErrLexRC,"Unable to allocate the text file buffer for:'%s'.",fn);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// read the file into the text buffer
|
||||
if( fread(p->textBuf,n,1,fp) != 1 )
|
||||
{
|
||||
rc = _cmLexError(p,kFileReadErrLexRC,"File read failed on:'%s'.",fn);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if((rc = _cmLexSetTextBuffer( p, p->textBuf, n )) != kOkLexRC )
|
||||
goto errLabel;
|
||||
|
||||
errLabel:
|
||||
|
||||
// close the file
|
||||
if( fclose(fp) != 0 )
|
||||
{
|
||||
rc = _cmLexError(p,kFileCloseErrLexRC,"File close failed on:'%s'.",fn);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
*/
|
||||
|
||||
cmLexMatcher* _cmLexFindUserToken( cmLex* p, unsigned id, const cmChar_t* tokenStr )
|
||||
{
|
||||
@ -689,9 +670,9 @@ unsigned cmLexGetNextToken( cmLexH h )
|
||||
p->curTokenId = kErrorLexTId;
|
||||
p->curTokenCharIdx = cmInvalidIdx;
|
||||
p->curTokenCharCnt = 0;
|
||||
p->attrFlags = 0;
|
||||
|
||||
|
||||
// try each mater
|
||||
// try each matcher
|
||||
for(; mi<p->mfi; ++mi)
|
||||
if( p->mfp[mi].enableFl )
|
||||
{
|
||||
@ -701,6 +682,7 @@ unsigned cmLexGetNextToken( cmLexH h )
|
||||
else
|
||||
charCnt = p->mfp[mi].userPtr( p->cp + p->ci, p->cn - p->ci);
|
||||
|
||||
// notice if the matcher set the error code
|
||||
if( cmErrLastRC(&p->err) != kOkLexRC )
|
||||
return kErrorLexTId;
|
||||
|
||||
@ -823,6 +805,19 @@ float cmLexTokenFloat( cmLexH h )
|
||||
double cmLexTokenDouble( cmLexH h )
|
||||
{ return strtod( cmLexTokenText(h),NULL ); }
|
||||
|
||||
|
||||
bool cmLexTokenIsUnsigned( cmLexH h )
|
||||
{
|
||||
cmLex* p = _cmLexHandleToPtr(h);
|
||||
return p->curTokenId == kIntLexTId && cmIsFlag(p->attrFlags,kIntUnsignedLexFl);
|
||||
}
|
||||
|
||||
bool cmLexTokenIsSinglePrecision( cmLexH h )
|
||||
{
|
||||
cmLex* p = _cmLexHandleToPtr(h);
|
||||
return p->curTokenId == kRealLexTId && cmIsFlag(p->attrFlags,kRealFloatLexFl);
|
||||
}
|
||||
|
||||
unsigned cmLexCurrentLineNumber( cmLexH h )
|
||||
{
|
||||
cmLex* p = _cmLexHandleToPtr(h);
|
||||
|
15
cmLex.h
15
cmLex.h
@ -50,7 +50,8 @@ enum
|
||||
kMemAllocErrLexRC, //< 10 An attempted memory allocation failed
|
||||
kEofRC, //< 11 The end of the input text was encountered (this is a normal condition not an error)
|
||||
kInvalidLexTIdLexRC, //< 12 An invalid lex token id was encountered.
|
||||
kInvalidLexRC //< 13 Sentinal value.
|
||||
kSignErrorLexRC, //< 13 An signed integer has a 'u' or 'U' suffix."
|
||||
kInvalidLexRC //< 1r Sentinal value.
|
||||
|
||||
};
|
||||
|
||||
@ -119,15 +120,23 @@ unsigned cmLexTokenCharCount( cmLexH h );
|
||||
// Return the value of the current token as an integer.
|
||||
int cmLexTokenInt( cmLexH h );
|
||||
|
||||
// Return the value of the current token as an integer.
|
||||
// Return the value of the current token as an unsigned integer.
|
||||
unsigned cmLexTokenUInt( cmLexH h );
|
||||
|
||||
// Return the value of the current token as an integer.
|
||||
// Return the value of the current token as a float.
|
||||
float cmLexTokenFloat( cmLexH h );
|
||||
|
||||
// Return the value of the current token as a double.
|
||||
double cmLexTokenDouble( cmLexH h );
|
||||
|
||||
// Return true if the current token is an int and it was suffixed
|
||||
// with 'u' to indicate that it is unsigned.
|
||||
bool cmLexTokenIsUnsigned( cmLexH h );
|
||||
|
||||
// Return true if the current token is a real and it was suffexed
|
||||
// with 'f' to indicate that it is a single precision float.
|
||||
bool cmLexTokenIsSinglePrecision( cmLexH h );
|
||||
|
||||
// Return the line number associated with the current token
|
||||
unsigned cmLexCurrentLineNumber( cmLexH h );
|
||||
|
||||
|
@ -64,7 +64,7 @@ extern "C" {
|
||||
{
|
||||
unsigned uid; // uid's are unique among all msg's in the file
|
||||
unsigned dtick; // delta ticks
|
||||
unsigned atick;
|
||||
unsigned atick; // accumulated ticks
|
||||
cmMidiByte_t status; // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch)
|
||||
cmMidiByte_t metaId; //
|
||||
unsigned short trkIdx; //
|
||||
|
353
cmProc4.c
353
cmProc4.c
@ -4135,3 +4135,356 @@ cmRC_t cmScModulatorDump( cmScModulator* p )
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
//=======================================================================================================================
|
||||
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
|
||||
{
|
||||
cmRecdPlay* op = cmObjAlloc(cmRecdPlay,c,p);
|
||||
|
||||
if( cmRecdPlayInit(op,srate,fragCnt,chCnt,initFragSecs,maxLaSecs,curLaSecs) != cmOkRC )
|
||||
cmRecdPlayFree(&op);
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayFree( cmRecdPlay** pp )
|
||||
{
|
||||
cmRC_t rc = cmOkRC;
|
||||
if( pp==NULL || *pp==NULL )
|
||||
return rc;
|
||||
|
||||
cmRecdPlay* p = *pp;
|
||||
if((rc = cmRecdPlayFinal(p)) != cmOkRC )
|
||||
return rc;
|
||||
|
||||
cmObjFree(pp);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
|
||||
{
|
||||
cmRC_t rc;
|
||||
unsigned i;
|
||||
|
||||
if( curLaSecs > maxLaSecs )
|
||||
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The initial look-ahead time %f is greater than the maximum look-ahead time %f.",curLaSecs,maxLaSecs);
|
||||
|
||||
if((rc = cmRecdPlayFinal(p)) != cmOkRC )
|
||||
return rc;
|
||||
|
||||
if( chCnt == 0 )
|
||||
return cmOkRC;
|
||||
|
||||
p->frags = cmMemAllocZ(cmRecdPlayFrag,fragCnt);
|
||||
p->fragCnt = fragCnt;
|
||||
p->srate = srate;
|
||||
p->chCnt = chCnt;
|
||||
p->initFragSecs = initFragSecs;
|
||||
p->maxLaSmpCnt = floor(maxLaSecs*srate);
|
||||
p->curLaSmpCnt = floor(curLaSecs*srate);
|
||||
p->laChs = cmMemAllocZ(cmSample_t*,chCnt);
|
||||
p->laSmpIdx = 0;
|
||||
|
||||
for(i=0; i<chCnt; ++i)
|
||||
p->laChs[i] = cmMemAllocZ(cmSample_t,p->maxLaSmpCnt);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayFinal( cmRecdPlay* p )
|
||||
{
|
||||
unsigned i,j;
|
||||
// free the fragments
|
||||
for(i=0; i<p->fragCnt; ++i)
|
||||
{
|
||||
for(j=0; j<p->chCnt; ++j)
|
||||
cmMemFree(p->frags[i].chArray[j]);
|
||||
|
||||
cmMemFree(p->frags[i].chArray);
|
||||
}
|
||||
|
||||
// free the look-ahead buffers
|
||||
for(i=0; i<p->chCnt; ++i)
|
||||
cmMemFree(p->laChs[i]);
|
||||
|
||||
cmMemPtrFree(&p->laChs);
|
||||
cmMemPtrFree(&p->frags);
|
||||
p->fragCnt = 0;
|
||||
p->chCnt = 0;
|
||||
p->rlist = NULL;
|
||||
p->plist = NULL;
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayRegisterFrag( cmRecdPlay* p, unsigned fragIdx, unsigned labelSymId )
|
||||
{
|
||||
assert( fragIdx < p->fragCnt );
|
||||
|
||||
unsigned i;
|
||||
|
||||
p->frags[ fragIdx ].labelSymId = labelSymId;
|
||||
|
||||
p->frags[ fragIdx ].chArray = cmMemResizeZ(cmSample_t*,p->frags[fragIdx].chArray,p->chCnt);
|
||||
|
||||
for(i=0; i<p->chCnt; ++i)
|
||||
{
|
||||
|
||||
p->frags[ fragIdx ].allocCnt = floor(p->initFragSecs * p->srate);
|
||||
p->frags[ fragIdx ].chArray[i] = cmMemResizeZ(cmSample_t,p->frags[ fragIdx ].chArray[i],p->frags[fragIdx].allocCnt);
|
||||
}
|
||||
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayRewind( cmRecdPlay* p )
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
p->laSmpIdx = 0;
|
||||
|
||||
while( p->plist != NULL )
|
||||
cmRecdPlayEndPlay(p,p->plist->labelSymId);
|
||||
|
||||
while( p->rlist != NULL )
|
||||
cmRecdPlayEndRecord(p,p->plist->labelSymId);
|
||||
|
||||
for(i=0; i<p->fragCnt; ++i)
|
||||
p->frags[i].playIdx = 0;
|
||||
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
|
||||
cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId )
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i<p->fragCnt; ++i)
|
||||
if( p->frags[i].labelSymId == labelSymId )
|
||||
{
|
||||
// if the frag is not already on the recd list
|
||||
if( p->frags[i].rlink == NULL )
|
||||
{
|
||||
p->frags[i].recdIdx = 0;
|
||||
p->frags[i].playIdx = 0;
|
||||
p->frags[i].rlink = p->rlist;
|
||||
p->rlist = p->frags + i;
|
||||
|
||||
// handle LA buf longer than frag buf.
|
||||
int cpyCnt = cmMin(p->curLaSmpCnt,p->frags[i].allocCnt);
|
||||
|
||||
// go backwards in LA buf from newest sample to find init src offset
|
||||
int srcOffs = p->laSmpIdx - cpyCnt;
|
||||
|
||||
// if the src is before the first sample in the LA buf then wrap to end of buf
|
||||
if( srcOffs < 0 )
|
||||
srcOffs += p->maxLaSmpCnt;
|
||||
|
||||
assert( 0 <= srcOffs && srcOffs < p->maxLaSmpCnt );
|
||||
|
||||
// cnt of samples to copy from LA buf (limited by end of LA buf)
|
||||
int n0 = cmMin(cpyCnt,p->maxLaSmpCnt - srcOffs);
|
||||
|
||||
// if necessary wrap to begin of LA buf for remaining samples
|
||||
int n1 = cpyCnt>n0 ? n1 = cpyCnt-n0 : 0;
|
||||
int j;
|
||||
|
||||
assert(n0+n1 == cpyCnt );
|
||||
|
||||
for(j=0; j<p->chCnt; ++j)
|
||||
cmVOS_Copy(p->frags[i].chArray[j],n0,p->laChs[j]+srcOffs);
|
||||
|
||||
if( n1 > 0 )
|
||||
{
|
||||
for(j=0; j<p->chCnt; ++j)
|
||||
cmVOS_Copy(p->frags[i].chArray[j]+n0,n1,p->laChs[j]);
|
||||
}
|
||||
|
||||
p->frags[i].recdIdx = cpyCnt;
|
||||
|
||||
}
|
||||
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'begin record'.",labelSymId);
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayEndRecord( cmRecdPlay* p, unsigned labelSymId )
|
||||
{
|
||||
cmRecdPlayFrag* fp = p->rlist;
|
||||
cmRecdPlayFrag* pp = NULL;
|
||||
|
||||
for(; fp != NULL; fp=fp->rlink )
|
||||
{
|
||||
if( fp->labelSymId == labelSymId )
|
||||
{
|
||||
if( pp == NULL )
|
||||
p->rlist = fp->rlink;
|
||||
else
|
||||
pp->rlink = fp->rlink;
|
||||
|
||||
fp->rlink = NULL;
|
||||
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
pp = fp;
|
||||
}
|
||||
|
||||
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'end record'.",labelSymId);
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayBeginPlay( cmRecdPlay* p, unsigned labelSymId )
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i<p->fragCnt; ++i)
|
||||
if( p->frags[i].labelSymId == labelSymId )
|
||||
{
|
||||
// if the frag is not already on the play list
|
||||
if( p->frags[i].plink == NULL )
|
||||
{
|
||||
p->frags[i].playIdx = 0;
|
||||
p->frags[i].fadeSmpIdx = 0;
|
||||
p->frags[i].fadeDbPerSec = 0.0;
|
||||
p->frags[i].plink = p->plist;
|
||||
p->plist = p->frags + i;
|
||||
}
|
||||
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'begin play'.",labelSymId);
|
||||
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayEndPlay( cmRecdPlay* p, unsigned labelSymId )
|
||||
{
|
||||
cmRecdPlayFrag* fp = p->plist;
|
||||
cmRecdPlayFrag* pp = NULL;
|
||||
|
||||
for(; fp != NULL; fp=fp->plink )
|
||||
{
|
||||
if( fp->labelSymId == labelSymId )
|
||||
{
|
||||
if( pp == NULL )
|
||||
p->plist = fp->plink;
|
||||
else
|
||||
pp->plink = fp->plink;
|
||||
|
||||
fp->plink = NULL;
|
||||
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
pp = fp;
|
||||
}
|
||||
|
||||
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'end play'.",labelSymId);
|
||||
}
|
||||
|
||||
cmRC_t cmRecdPlayBeginFade( cmRecdPlay* p, unsigned labelSymId, double fadeDbPerSec )
|
||||
{
|
||||
cmRecdPlayFrag* fp = p->plist;
|
||||
|
||||
for(; fp != NULL; fp=fp->plink )
|
||||
if( fp->labelSymId == labelSymId )
|
||||
{
|
||||
fp->fadeDbPerSec = -fabs(fadeDbPerSec);
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'fade begin'.",labelSymId);
|
||||
}
|
||||
|
||||
|
||||
cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt )
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
chCnt = cmMin(chCnt, p->chCnt);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// copy incoming audio into the look-head buffers
|
||||
//
|
||||
|
||||
// if the number of incoming samples is longer than the look-head buffer
|
||||
// then copy exactly maxLaSmpCnt samples from the end of the incoming sample
|
||||
// buffer to the look-ahead buffer.
|
||||
unsigned srcOffs = 0;
|
||||
unsigned srcSmpCnt = smpCnt;
|
||||
if( srcSmpCnt > p->maxLaSmpCnt )
|
||||
{
|
||||
// advance incoming sample buffer so that there are maxLaSmpCnt samples remaining
|
||||
srcOffs = smpCnt-p->maxLaSmpCnt;
|
||||
srcSmpCnt = p->maxLaSmpCnt; // decrease the total samples to copy
|
||||
}
|
||||
|
||||
// count of samples from cur posn to end of the LA buffer.
|
||||
unsigned n0 = cmMin(srcSmpCnt, p->maxLaSmpCnt - p->laSmpIdx );
|
||||
|
||||
// count of samples past the end of the LA buffer to be wrapped into begin of buffer
|
||||
unsigned n1 = srcSmpCnt>n0 ? srcSmpCnt-n0 : 0;
|
||||
|
||||
assert(n0+n1 == srcSmpCnt);
|
||||
|
||||
// copy first block to end of LA buffer
|
||||
for(i=0; i<chCnt; ++i)
|
||||
cmVOS_Copy(p->laChs[i]+p->laSmpIdx,n0,iChs[i] + srcOffs);
|
||||
|
||||
p->laSmpIdx += n0;
|
||||
|
||||
if( n1!=0)
|
||||
{
|
||||
// copy second block to begin of LA buffer
|
||||
for(i=0; i<chCnt; ++i)
|
||||
cmVOS_Copy(p->laChs[i],n1,iChs[i] + srcOffs + n0);
|
||||
|
||||
p->laSmpIdx = n1;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// copy incoming audio into the active record buffers
|
||||
//
|
||||
cmRecdPlayFrag* fp = p->rlist;
|
||||
|
||||
for(; fp!=NULL; fp=fp->rlink)
|
||||
{
|
||||
assert( fp->recdIdx <= fp->allocCnt);
|
||||
unsigned n = cmMin(fp->allocCnt - fp->recdIdx,smpCnt);
|
||||
unsigned i;
|
||||
for(i=0; i<p->chCnt; ++i)
|
||||
{
|
||||
cmVOS_Copy(fp->chArray[i] + fp->recdIdx, n, iChs[i] );
|
||||
fp->recdIdx += n;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// copy outgoing audio out of the active play buffers
|
||||
//
|
||||
fp = p->plist;
|
||||
for(; fp!=NULL; fp=fp->rlink)
|
||||
{
|
||||
assert( fp->playIdx <= fp->recdIdx);
|
||||
|
||||
double gain = pow(10.0,((fp->fadeSmpIdx / p->srate) * fp->fadeDbPerSec)/20.0);
|
||||
unsigned n = cmMin(fp->recdIdx - fp->playIdx,smpCnt);
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i<p->chCnt; ++i)
|
||||
{
|
||||
cmVOS_MultVVS(oChs[i],n,fp->chArray[i] + fp->playIdx,gain);
|
||||
fp->playIdx += n;
|
||||
}
|
||||
|
||||
// if a fade rate has been set then advance the fade phase
|
||||
if(fp->fadeDbPerSec!=0.0)
|
||||
fp->fadeSmpIdx += smpCnt;
|
||||
}
|
||||
|
||||
return cmOkRC;
|
||||
}
|
||||
|
49
cmProc4.h
49
cmProc4.h
@ -626,6 +626,55 @@ extern "C" {
|
||||
cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx );
|
||||
cmRC_t cmScModulatorDump( cmScModulator* p );
|
||||
|
||||
//=======================================================================================================================
|
||||
|
||||
typedef struct cmRecdPlayFrag_str
|
||||
{
|
||||
unsigned labelSymId; // this fragments label
|
||||
cmSample_t** chArray; // record buffer chArray[cmRecdPlay.chCnt][allocCnt]
|
||||
unsigned allocCnt; // count of samples allocated to each channel
|
||||
unsigned playIdx; // index of next sample to play
|
||||
unsigned recdIdx; // index of next sample to receieve audio (count of full samples)
|
||||
double fadeDbPerSec; // fade rate in dB per second
|
||||
unsigned fadeSmpIdx;
|
||||
struct cmRecdPlayFrag_str* rlink; // cmRecdPlay.rlist link
|
||||
struct cmRecdPlayFrag_str* plink; // cmRecdPlay.plist link
|
||||
} cmRecdPlayFrag;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cmObj obj;
|
||||
cmRecdPlayFrag* frags; // frags[fragCnt] fragment array
|
||||
unsigned fragCnt; // count of fragments
|
||||
double srate; // system sample rate
|
||||
unsigned chCnt; // count of input and output audio channels
|
||||
double initFragSecs; // size initial memory allocated to each frag in seconds
|
||||
unsigned maxLaSmpCnt; // samples allocated to each channel of the look-ahead buffers.
|
||||
unsigned curLaSmpCnt; // current look-ahead time in samples (curLaSmpCnt<=maxLaSmpCnt)
|
||||
cmSample_t** laChs; // laChs[chCnt][maxLaSmpCnt] - look-ahead buffers
|
||||
int laSmpIdx; // next look-ahead buffer index to receive a sample
|
||||
cmRecdPlayFrag* plist; // currently playing frags
|
||||
cmRecdPlayFrag* rlist; // currently recording frags
|
||||
} cmRecdPlay;
|
||||
|
||||
|
||||
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
|
||||
cmRC_t cmRecdPlayFree( cmRecdPlay** pp );
|
||||
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned flagCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
|
||||
cmRC_t cmRecdPlayFinal( cmRecdPlay* p );
|
||||
|
||||
cmRC_t cmRecdPlayRegisterFrag( cmRecdPlay* p, unsigned fragIdx, unsigned labelSymId );
|
||||
|
||||
cmRC_t cmRecdPlayRewind( cmRecdPlay* p );
|
||||
cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId );
|
||||
cmRC_t cmRecdPlayEndRecord( cmRecdPlay* p, unsigned labelSymId );
|
||||
cmRC_t cmRecdPlayBeginPlay( cmRecdPlay* p, unsigned labelSymId );
|
||||
cmRC_t cmRecdPlayEndPlay( cmRecdPlay* p, unsigned labelSymId );
|
||||
|
||||
cmRC_t cmRecdPlayBeginFade( cmRecdPlay* p, unsigned labelSymId, double fadeDbPerSec );
|
||||
|
||||
cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -42,12 +42,15 @@ extern "C" {
|
||||
const void* cmStackTop( cmStackH_t h );
|
||||
|
||||
// Set the value of 'dataEleCnt' elements on the stack.
|
||||
// The top element is at index cmStackCount() - 1.
|
||||
cmStRC_t cmStackSet( cmStackH_t h, unsigned index, const void* data, unsigned dataEleCnt );
|
||||
|
||||
// Copy 'dataEleCnt' elements into the buffer pointed to by 'data'.
|
||||
// The top element is at index cmStackCount() - 1.
|
||||
cmStRC_t cmStackGetN( cmStackH_t h, unsigned index, void* data, unsigned dataEleCnt );
|
||||
|
||||
// Return a pointer to a single element on the stack.
|
||||
// The top element is at index cmStackCount() - 1.
|
||||
const void* cmStackGet( cmStackH_t h, unsigned index );
|
||||
|
||||
// Convert the internal representation of the stack to a linear array and return
|
||||
|
@ -5418,6 +5418,7 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
|
||||
cmActiveMeasClassCons,
|
||||
cmAmSyncClassCons,
|
||||
cmNanoMapClassCons,
|
||||
cmRecdPlayClassCons,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
261
dsp/cmDspKr.c
261
dsp/cmDspKr.c
@ -572,7 +572,7 @@ cmDspRC_t _cmDspScoreReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
|
||||
}
|
||||
|
||||
if((tlFn = cmDspStrcz(inst, kFnScId )) != NULL )
|
||||
if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, cmSymTblNullHandle ) != kOkTlRC )
|
||||
if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, ctx->stH ) != kOkTlRC )
|
||||
rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
|
||||
|
||||
errLabel:
|
||||
@ -2264,3 +2264,262 @@ struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx )
|
||||
|
||||
return &_cmNanoMapDC;
|
||||
}
|
||||
|
||||
//==========================================================================================================================================
|
||||
enum
|
||||
{
|
||||
kChCntPrId,
|
||||
kFnPrId,
|
||||
kSecsPrId,
|
||||
kMaxLaSecsPrId,
|
||||
kCurLaSecsPrId,
|
||||
kFadeRatePrId,
|
||||
kScLocIdxPrId,
|
||||
kCmdPrId,
|
||||
kInAudioBasePrId
|
||||
};
|
||||
|
||||
cmDspClass_t _cmRecdPlayDC;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cmDspInst_t inst;
|
||||
cmRecdPlay* rcdply;
|
||||
cmScH_t scH;
|
||||
unsigned onSymId;
|
||||
unsigned offSymId;
|
||||
unsigned audioOutBaseId;
|
||||
unsigned chCnt;
|
||||
unsigned scLocIdx;
|
||||
} cmDspRecdPlay_t;
|
||||
|
||||
cmDspRC_t _cmDspRecdPlayOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
|
||||
{
|
||||
cmDspRC_t rc =kOkDspRC;
|
||||
const cmChar_t* fn;
|
||||
|
||||
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
|
||||
|
||||
p->scLocIdx = 0;
|
||||
|
||||
|
||||
if((fn = cmDspStrcz(inst,kFnPrId)) == NULL || strlen(fn)==0 )
|
||||
return cmErrMsg(&inst->classPtr->err, kInvalidArgDspRC, "No score file name supplied.");
|
||||
|
||||
if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL, ctx->stH ) != kOkScRC )
|
||||
return cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to open the score '%s'.",fn);
|
||||
|
||||
if( cmScoreIsValid(p->scH) )
|
||||
{
|
||||
unsigned i;
|
||||
unsigned markerCnt = cmScoreMarkerLabelCount(p->scH);
|
||||
double initFragSecs = cmDspDouble(inst,kSecsPrId);
|
||||
double maxLaSecs = cmDspDouble(inst,kMaxLaSecsPrId);
|
||||
double curLaSecs = cmDspDouble(inst,kCurLaSecsPrId);
|
||||
|
||||
if((p->rcdply = cmRecdPlayAlloc(ctx->cmProcCtx, NULL, cmDspSampleRate(ctx), markerCnt, p->chCnt, initFragSecs, maxLaSecs, curLaSecs)) == NULL)
|
||||
return cmErrMsg(&inst->classPtr->err,kSubSysFailDspRC,"Unable to create the internal recorder-player object.");
|
||||
|
||||
for(i=0; i<markerCnt; ++i)
|
||||
cmRecdPlayRegisterFrag(p->rcdply,i, cmScoreMarkerLabelSymbolId(p->scH,i ));
|
||||
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
cmDspInst_t* _cmDspRecdPlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
|
||||
{
|
||||
|
||||
if( va_cnt < 1 )
|
||||
{
|
||||
cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'RecdPlay' constructor must have a count of input ports.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
va_list vl1;
|
||||
va_copy(vl1,vl);
|
||||
|
||||
int chCnt = va_arg(vl,int);
|
||||
unsigned audioOutBase = kInAudioBasePrId + chCnt;
|
||||
|
||||
cmDspRecdPlay_t* p = cmDspInstAllocV(cmDspRecdPlay_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl1,
|
||||
1, "chs", kChCntPrId, 0,0, kUIntDsvFl | kReqArgDsvFl, "channel count.",
|
||||
1, "fn", kFnPrId, 0,0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." ,
|
||||
1, "secs", kSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl | kReqArgDsvFl, "Initial fragment allocation in seconds.",
|
||||
1, "maxla", kMaxLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl, "Maximum look-ahead buffer in seconds.",
|
||||
1, "curla", kCurLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl, "Current look-head buffer in seconds.",
|
||||
1, "frate", kFadeRatePrId, 0,0, kInDsvFl | kDoubleDsvFl, "Fade rate in dB per second.",
|
||||
1, "index", kScLocIdxPrId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower location index.",
|
||||
1, "cmd", kCmdPrId, 0,0, kInDsvFl | kSymDsvFl, "on=reset off=stop.",
|
||||
chCnt, "in", kInAudioBasePrId,0,1, kInDsvFl | kAudioBufDsvFl, "Audio input",
|
||||
chCnt, "out", audioOutBase, 0,1, kOutDsvFl | kAudioBufDsvFl, "Audio output",
|
||||
0 );
|
||||
|
||||
va_end(vl1);
|
||||
|
||||
p->onSymId = cmSymTblId(ctx->stH,"on");
|
||||
p->offSymId = cmSymTblId(ctx->stH,"off");
|
||||
p->audioOutBaseId = audioOutBase;
|
||||
p->chCnt = chCnt;
|
||||
p->scLocIdx = 0;
|
||||
|
||||
cmDspSetDefaultDouble(ctx,&p->inst, kSecsPrId, 0, 10.0 );
|
||||
cmDspSetDefaultDouble(ctx,&p->inst, kMaxLaSecsPrId,0, 2.0);
|
||||
cmDspSetDefaultDouble(ctx,&p->inst, kCurLaSecsPrId,0, 0.5);
|
||||
cmDspSetDefaultDouble(ctx,&p->inst, kFadeRatePrId, 0, 1.0);
|
||||
|
||||
return &p->inst;
|
||||
}
|
||||
|
||||
cmDspRC_t _cmDspRecdPlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
||||
{
|
||||
cmDspRC_t rc = kOkDspRC;
|
||||
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
|
||||
|
||||
cmRecdPlayFree(&p->rcdply);
|
||||
|
||||
cmScoreFinalize(&p->scH);
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmDspRC_t _cmDspRecdPlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
||||
{
|
||||
cmDspApplyAllDefaults(ctx,inst);
|
||||
|
||||
return _cmDspRecdPlayOpenScore(ctx,inst);
|
||||
}
|
||||
|
||||
cmDspRC_t _cmDspRecdPlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
||||
{
|
||||
cmDspRC_t rc = kOkDspRC;
|
||||
|
||||
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
|
||||
|
||||
const cmSample_t* x[ p->chCnt ];
|
||||
cmSample_t* y[ p->chCnt ];
|
||||
unsigned n;
|
||||
unsigned i;
|
||||
unsigned actChCnt = 0;
|
||||
|
||||
for(i=0; i<p->chCnt; ++i)
|
||||
{
|
||||
if( i==0 )
|
||||
n = cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0);
|
||||
else
|
||||
{ assert( n == cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0)); }
|
||||
|
||||
x[i] = cmDspAudioBuf(ctx,inst,kInAudioBasePrId+i,0);
|
||||
|
||||
if( x[i] != NULL )
|
||||
{
|
||||
y[i] = cmDspAudioBuf(ctx,inst,p->audioOutBaseId+i,0);
|
||||
|
||||
if( y[i] != NULL )
|
||||
{
|
||||
assert( n == cmDspAudioBufSmpCount(ctx,inst,p->audioOutBaseId+i,0));
|
||||
|
||||
cmVOS_Zero(y[i],n);
|
||||
|
||||
actChCnt += 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cmRecdPlayExec(p->rcdply,x,y,actChCnt,n);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmDspRC_t _cmDspRecdPlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
|
||||
{
|
||||
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
|
||||
|
||||
cmDspSetEvent(ctx,inst,evt);
|
||||
|
||||
switch( evt->dstVarId )
|
||||
{
|
||||
case kCmdPrId:
|
||||
if( cmDspSymbol(inst,kCmdPrId) == p->onSymId )
|
||||
{
|
||||
printf("rewind\n");
|
||||
cmRecdPlayRewind(p->rcdply);
|
||||
p->scLocIdx = 0;
|
||||
}
|
||||
else
|
||||
if( cmDspSymbol(inst,kCmdPrId) == p->offSymId )
|
||||
{
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kCurLaSecsPrId:
|
||||
break;
|
||||
|
||||
case kScLocIdxPrId:
|
||||
{
|
||||
unsigned endScLocIdx = cmDspUInt(inst,kScLocIdxPrId) ;
|
||||
|
||||
for(; p->scLocIdx<=endScLocIdx; p->scLocIdx+=1)
|
||||
{
|
||||
cmScoreLoc_t* loc = cmScoreLoc(p->scH, p->scLocIdx );
|
||||
cmScoreMarker_t* mp = loc->markList;
|
||||
|
||||
for(; mp!=NULL; mp=mp->link)
|
||||
switch( mp->markTypeId )
|
||||
{
|
||||
case kRecdBegScMId:
|
||||
printf("recd-beg\n");
|
||||
cmRecdPlayBeginRecord(p->rcdply, mp->labelSymId );
|
||||
break;
|
||||
|
||||
case kRecdEndScMId:
|
||||
printf("recd-end\n");
|
||||
cmRecdPlayEndRecord(p->rcdply, mp->labelSymId );
|
||||
break;
|
||||
|
||||
case kPlayBegScMId:
|
||||
printf("play-beg\n");
|
||||
cmRecdPlayBeginPlay(p->rcdply, mp->labelSymId );
|
||||
break;
|
||||
|
||||
case kPlayEndScMId:
|
||||
printf("play-end\n");
|
||||
cmRecdPlayEndPlay(p->rcdply, mp->labelSymId );
|
||||
break;
|
||||
|
||||
case kFadeScMId:
|
||||
printf("fade-beg\n");
|
||||
cmRecdPlayBeginFade(p->rcdply, mp->labelSymId, cmDspDouble(inst,kFadeRatePrId) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p->scLocIdx = endScLocIdx+1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return kOkDspRC;
|
||||
}
|
||||
|
||||
struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx )
|
||||
{
|
||||
cmDspClassSetup(&_cmRecdPlayDC,ctx,"RecdPlay",
|
||||
NULL,
|
||||
_cmDspRecdPlayAlloc,
|
||||
_cmDspRecdPlayFree,
|
||||
_cmDspRecdPlayReset,
|
||||
_cmDspRecdPlayExec,
|
||||
_cmDspRecdPlayRecv,
|
||||
NULL,
|
||||
NULL,
|
||||
"Score controlled live recorder/player");
|
||||
|
||||
return &_cmRecdPlayDC;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ extern "C" {
|
||||
struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx );
|
||||
struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -97,7 +97,10 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
|
||||
double cmpWndMaxMs = 1000.0;
|
||||
double cmpWndMs = 200.0;
|
||||
|
||||
|
||||
double recdPlayInitAllocSecs = 10.0;
|
||||
double recdPlayMaxLaSecs = 2.0;
|
||||
double recdPlayCurLaSecs = 0.1;
|
||||
double recdPlayFadeRateDbPerSec = 4.0;
|
||||
|
||||
memset(&r,0,sizeof(r));
|
||||
cmErrSetup(&err,&cmCtx->rpt,"Kr Timeline");
|
||||
@ -122,6 +125,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
|
||||
cmDspInst_t* mop = cmDspSysAllocInst(h,"MidiOut", NULL, 2, r.midiDevice,r.midiOutPort);
|
||||
cmDspInst_t* sfp = cmDspSysAllocInst(h,"ScFol", NULL, 1, r.scFn );
|
||||
cmDspInst_t* amp = cmDspSysAllocInst(h,"ActiveMeas", NULL, 1, 100 );
|
||||
cmDspInst_t* rpp = cmDspSysAllocInst(h,"RecdPlay", NULL, 4, 2, r.scFn, recdPlayInitAllocSecs, recdPlayMaxLaSecs, recdPlayCurLaSecs, recdPlayFadeRateDbPerSec );
|
||||
cmDspInst_t* modp = cmDspSysAllocInst(h,"ScMod", NULL, 2, r.modFn, "m1" );
|
||||
cmDspInst_t* asp = cmDspSysAllocInst(h,"AmSync", NULL, 0 );
|
||||
|
||||
@ -173,14 +177,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
|
||||
cmDspInst_t* kr00 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
|
||||
cmDspInst_t* kr01 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
|
||||
cmDspInst_t* fad0 = cmDspSysAllocInst(h, "Xfader", NULL, 3, xfadeChCnt, xfadeMs, xfadeInitFl );
|
||||
cmDspInst_t* mix0 = cmDspSysAllocInst(h, "AMix", NULL, 3, xfadeChCnt, mixGain, mixGain );
|
||||
cmDspInst_t* mix0 = cmDspSysAllocInst(h, "AMix", NULL, 4, xfadeChCnt+1, mixGain, mixGain, mixGain );
|
||||
cmDspInst_t* cmp0 = cmDspSysAllocInst(h,"Compressor", NULL, 8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs );
|
||||
cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 0 );
|
||||
|
||||
cmDspInst_t* kr10 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
|
||||
cmDspInst_t* kr11 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
|
||||
cmDspInst_t* fad1 = cmDspSysAllocInst(h, "Xfader", NULL, 3, xfadeChCnt, xfadeMs, xfadeInitFl );
|
||||
cmDspInst_t* mix1 = cmDspSysAllocInst(h, "AMix", NULL, 3, xfadeChCnt, mixGain, mixGain );
|
||||
cmDspInst_t* mix1 = cmDspSysAllocInst(h, "AMix", NULL, 4, xfadeChCnt+1, mixGain, mixGain, mixGain );
|
||||
cmDspInst_t* cmp1 = cmDspSysAllocInst(h,"Compressor", NULL, 8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs );
|
||||
cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 1 );
|
||||
|
||||
@ -378,12 +382,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
|
||||
cmDspSysConnectAudio(h, wtp, "out", au0Sw, "a-in-0" ); // wt -> sw
|
||||
cmDspSysConnectAudio(h, ai0p, "out", au0Sw, "a-in-1" ); // ain -> sw
|
||||
cmDspSysConnectAudio(h, ai0p, "out", mi0p, "in" );
|
||||
cmDspSysConnectAudio(h, au0Sw,"a-out", rpp, "in-0"); // sw -> rcdply
|
||||
cmDspSysConnectAudio(h, au0Sw,"a-out", kr00, "in" ); // sw -> kr
|
||||
cmDspSysConnectAudio(h, kr00, "out", fad0, "in-0"); // kr -> fad
|
||||
cmDspSysConnectAudio(h, fad0, "out-0", mix0, "in-0"); // fad -> mix
|
||||
cmDspSysConnectAudio(h, au0Sw,"a-out", kr01, "in" ); // sw -> kr
|
||||
cmDspSysConnectAudio(h, kr01, "out", fad0, "in-1"); // kr -> fad
|
||||
cmDspSysConnectAudio(h, fad0, "out-1", mix0, "in-1"); // fad -> mix
|
||||
cmDspSysConnectAudio(h, rpp, "out-0", mix0, "in-2");
|
||||
cmDspSysConnectAudio(h, mix0, "out", cmp0, "in"); // mix -> cmp
|
||||
cmDspSysConnectAudio(h, cmp0, "out", ao0p, "in" ); // cmp -> aout
|
||||
|
||||
@ -391,12 +397,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
|
||||
cmDspSysConnectAudio(h, wtp, "out", au1Sw, "a-in-0" ); // wt -> kr
|
||||
cmDspSysConnectAudio(h, ai1p, "out", au1Sw, "a-in-1" );
|
||||
cmDspSysConnectAudio(h, ai1p, "out", mi1p, "in" );
|
||||
cmDspSysConnectAudio(h, au1Sw,"a-out", rpp, "in-1"); // sw -> rcdply
|
||||
cmDspSysConnectAudio(h, au1Sw,"a-out", kr10, "in" );
|
||||
cmDspSysConnectAudio(h, kr10, "out", fad1, "in-0");
|
||||
cmDspSysConnectAudio(h, fad1, "out-0", mix1, "in-0");
|
||||
cmDspSysConnectAudio(h, au1Sw,"a-out", kr11, "in" ); // wt -> kr
|
||||
cmDspSysConnectAudio(h, kr11, "out", fad1, "in-1");
|
||||
cmDspSysConnectAudio(h, fad1, "out-1", mix1, "in-1");
|
||||
cmDspSysConnectAudio(h, rpp, "out-0", mix1, "in-2");
|
||||
cmDspSysConnectAudio(h, mix1, "out", cmp1, "in");
|
||||
cmDspSysConnectAudio(h, cmp1, "out", ao1p, "in" ); // comp -> aout
|
||||
|
||||
@ -437,6 +445,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
|
||||
cmDspSysInstallCb(h, pts, "on", wtRt, "s-in", NULL );
|
||||
cmDspSysInstallCb(h, wtRt,"s-out-0", wtp, "cmd", NULL );
|
||||
cmDspSysInstallCb(h, pts, "on", modp, "cmd", NULL );
|
||||
cmDspSysInstallCb(h, pts, "on", rpp, "cmd", NULL );
|
||||
cmDspSysInstallCb(h, onb, "sym", amCmd, "rewind",NULL );
|
||||
cmDspSysInstallCb(h, onb, "out", achan0,"reset", NULL );
|
||||
cmDspSysInstallCb(h, onb, "out", achan1,"reset", NULL );
|
||||
@ -493,7 +502,8 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
|
||||
cmDspSysInstallCb(h, mip, "d0", sfp, "d0", NULL );
|
||||
cmDspSysInstallCb(h, mip, "status", sfp, "status", NULL );
|
||||
|
||||
// score follower to modulator and printers
|
||||
// score follower to recd_play,modulator and printers
|
||||
cmDspSysInstallCb(h, sfp, "out", rpp, "index", NULL );
|
||||
cmDspSysInstallCb(h, sfp, "out", modp, "index", NULL );
|
||||
cmDspSysInstallCb(h, sfp, "recent", prp, "in", NULL ); // report 'recent' but only act on 'max' loc index
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user