|
@@ -0,0 +1,724 @@
|
|
1
|
+#include "cmGlobal.h"
|
|
2
|
+#include "cmRpt.h"
|
|
3
|
+#include "cmErr.h"
|
|
4
|
+#include "cmCtx.h"
|
|
5
|
+#include "cmMem.h"
|
|
6
|
+#include "cmMallocDebug.h"
|
|
7
|
+#include "cmLinkedHeap.h"
|
|
8
|
+#include "cmLex.h"
|
|
9
|
+#include "cmCsv.h"
|
|
10
|
+#include "cmSdb.h"
|
|
11
|
+#include "cmText.h"
|
|
12
|
+
|
|
13
|
+typedef enum
|
|
14
|
+{
|
|
15
|
+ kUuidColIdx,
|
|
16
|
+ kBaseUuidColIdx,
|
|
17
|
+ kChIdxColIdx,
|
|
18
|
+ kObiColIdx,
|
|
19
|
+ kIbiColIdx,
|
|
20
|
+ kIeiColIdx,
|
|
21
|
+ kOeiColIdx,
|
|
22
|
+ kSrcColIdx,
|
|
23
|
+ kMidiColIdx,
|
|
24
|
+ kInstrColIdx,
|
|
25
|
+ kSrateColIdx,
|
|
26
|
+ kChCntColIdx,
|
|
27
|
+ kNotesColIdx,
|
|
28
|
+ kAfnColIdx,
|
|
29
|
+ kInvalidColIdx
|
|
30
|
+} cmSdbColIdx_t;
|
|
31
|
+
|
|
32
|
+struct cmSdb_str;
|
|
33
|
+
|
|
34
|
+typedef struct cmSdbRspBlk_str
|
|
35
|
+{
|
|
36
|
+ unsigned* indexV; // indexV[ cmSdb_t.blkIdxAllocCnt ]
|
|
37
|
+ unsigned cnt; // count of indexes used
|
|
38
|
+ struct cmSdbRspBlk_str* link; // cmSdbRsp_t.blocks link
|
|
39
|
+} cmSdbRspBlk_t;
|
|
40
|
+
|
|
41
|
+typedef struct cmSdbRsp_str
|
|
42
|
+{
|
|
43
|
+ struct cmSdb_str* p; //
|
|
44
|
+ cmSdbRspBlk_t* blocks; // first block ptr
|
|
45
|
+ cmSdbRspBlk_t* ebp; // end block ptr
|
|
46
|
+ unsigned cnt; // total count of indexes
|
|
47
|
+ struct cmSdbRsp_str* link; // cmSdb_t.responses link
|
|
48
|
+} cmSdbRsp_t;
|
|
49
|
+
|
|
50
|
+typedef struct cmSdb_str
|
|
51
|
+{
|
|
52
|
+ cmCtx_t ctx;
|
|
53
|
+ cmLHeapH_t lhH;
|
|
54
|
+ cmCsvH_t csvH;
|
|
55
|
+ cmSdbEvent_t* eV;
|
|
56
|
+ unsigned eN;
|
|
57
|
+ unsigned blkIdxAllocCnt;
|
|
58
|
+ struct cmSdbRsp_str* responses;
|
|
59
|
+} cmSdb_t;
|
|
60
|
+
|
|
61
|
+cmSdbH_t cmSdbNullHandle = cmSTATIC_NULL_HANDLE;
|
|
62
|
+cmSdbResponseH_t cmSdbResponseNullHandle = cmSTATIC_NULL_HANDLE;
|
|
63
|
+
|
|
64
|
+cmSdb_t* _cmSdbHandleToPtr( cmSdbH_t h )
|
|
65
|
+{
|
|
66
|
+ cmSdb_t* p = (cmSdb_t*)h.h;
|
|
67
|
+ assert( p != NULL );
|
|
68
|
+ return p;
|
|
69
|
+}
|
|
70
|
+
|
|
71
|
+cmSdbRsp_t* _cmSdbRspHandleToPtr( cmSdbResponseH_t h )
|
|
72
|
+{
|
|
73
|
+ cmSdbRsp_t* p = (cmSdbRsp_t*)h.h;
|
|
74
|
+ assert( p != NULL );
|
|
75
|
+ return p;
|
|
76
|
+}
|
|
77
|
+
|
|
78
|
+void _cmSdbRspBlkFree( cmSdb_t* p, cmSdbRspBlk_t* bp )
|
|
79
|
+{
|
|
80
|
+ cmLhFree(p->lhH, bp->indexV);
|
|
81
|
+ cmLhFree(p->lhH, bp);
|
|
82
|
+}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+cmSdbRspBlk_t* _cmSdbRspBlkUnlink( cmSdbRsp_t* rp, cmSdbRspBlk_t* bp )
|
|
86
|
+{
|
|
87
|
+ cmSdbRspBlk_t* dp = rp->blocks;
|
|
88
|
+ cmSdbRspBlk_t* pp = NULL;
|
|
89
|
+ for(; dp!=NULL; dp=dp->link)
|
|
90
|
+ {
|
|
91
|
+ if( dp == bp )
|
|
92
|
+ {
|
|
93
|
+ if( pp == NULL )
|
|
94
|
+ rp->blocks = dp->link;
|
|
95
|
+ else
|
|
96
|
+ pp->link = dp->link;
|
|
97
|
+
|
|
98
|
+ return bp;
|
|
99
|
+ }
|
|
100
|
+
|
|
101
|
+ pp = dp;
|
|
102
|
+ }
|
|
103
|
+
|
|
104
|
+ assert(0);
|
|
105
|
+ return NULL;
|
|
106
|
+}
|
|
107
|
+
|
|
108
|
+void _cmSdbRspInsertIndex( cmSdb_t* p, cmSdbRsp_t* rp, unsigned evtIndex )
|
|
109
|
+{
|
|
110
|
+
|
|
111
|
+ if( rp->ebp == NULL || rp->ebp->cnt == p->blkIdxAllocCnt )
|
|
112
|
+ {
|
|
113
|
+ cmSdbRspBlk_t* bp = cmLhAllocZ(p->lhH,cmSdbRspBlk_t,1);
|
|
114
|
+ bp->indexV = cmLhAllocZ(p->lhH,unsigned,p->blkIdxAllocCnt);
|
|
115
|
+
|
|
116
|
+ if( rp->ebp != NULL )
|
|
117
|
+ rp->ebp->link = bp;
|
|
118
|
+
|
|
119
|
+ if( rp->blocks == NULL )
|
|
120
|
+ rp->blocks = bp;
|
|
121
|
+
|
|
122
|
+ rp->ebp = bp;
|
|
123
|
+
|
|
124
|
+ }
|
|
125
|
+
|
|
126
|
+ assert( rp->ebp!=NULL && rp->ebp->cnt < p->blkIdxAllocCnt );
|
|
127
|
+
|
|
128
|
+ rp->ebp->indexV[ rp->ebp->cnt++ ] = evtIndex;
|
|
129
|
+ rp->cnt += 1;
|
|
130
|
+}
|
|
131
|
+
|
|
132
|
+void _cmSdbRspRelease( cmSdbRsp_t* rp )
|
|
133
|
+{
|
|
134
|
+ while( rp->blocks != NULL )
|
|
135
|
+ {
|
|
136
|
+ cmSdbRspBlk_t* np = rp->blocks->link;
|
|
137
|
+ cmSdbRspBlk_t* bp;
|
|
138
|
+
|
|
139
|
+ if((bp = _cmSdbRspBlkUnlink(rp,rp->blocks)) != NULL )
|
|
140
|
+ _cmSdbRspBlkFree(rp->p,bp);
|
|
141
|
+
|
|
142
|
+ rp->blocks = np;
|
|
143
|
+ }
|
|
144
|
+
|
|
145
|
+ cmLhFree(rp->p->lhH,rp);
|
|
146
|
+}
|
|
147
|
+
|
|
148
|
+cmSdbRsp_t* _cmSdbRspUnlink( cmSdbRsp_t* rp )
|
|
149
|
+{
|
|
150
|
+ cmSdb_t* p = rp->p;
|
|
151
|
+ cmSdbRsp_t* dp = p->responses;
|
|
152
|
+ cmSdbRsp_t* pp = NULL;
|
|
153
|
+
|
|
154
|
+ for(; dp!=NULL; dp=dp->link)
|
|
155
|
+ {
|
|
156
|
+ if( dp == rp )
|
|
157
|
+ {
|
|
158
|
+ if( pp == NULL )
|
|
159
|
+ p->responses = dp->link;
|
|
160
|
+ else
|
|
161
|
+ pp->link = dp->link;
|
|
162
|
+
|
|
163
|
+ return rp;
|
|
164
|
+ }
|
|
165
|
+
|
|
166
|
+ pp = dp;
|
|
167
|
+ }
|
|
168
|
+
|
|
169
|
+ assert( 0 );
|
|
170
|
+
|
|
171
|
+ return NULL;
|
|
172
|
+}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+void _cmSdbRspFree( cmSdbRsp_t* rp )
|
|
176
|
+{
|
|
177
|
+ _cmSdbRspUnlink(rp);
|
|
178
|
+ _cmSdbRspRelease(rp);
|
|
179
|
+}
|
|
180
|
+
|
|
181
|
+cmSdbRsp_t* _cmSdbRspAlloc( cmSdb_t* p, cmSdbResponseH_t* rhp )
|
|
182
|
+{
|
|
183
|
+ if( cmSdbResponseFree(rhp) != kOkSdbRC )
|
|
184
|
+ return NULL;
|
|
185
|
+
|
|
186
|
+ cmSdbRsp_t* rp = cmLhAllocZ(p->lhH,cmSdbRsp_t,1);
|
|
187
|
+ rp->p = p;
|
|
188
|
+ rp->link = p->responses;
|
|
189
|
+ p->responses = rp;
|
|
190
|
+
|
|
191
|
+ rhp->h = rp;
|
|
192
|
+
|
|
193
|
+ return rp;
|
|
194
|
+}
|
|
195
|
+
|
|
196
|
+cmSdbRC_t _cmSdbDestroy( cmSdb_t* p )
|
|
197
|
+{
|
|
198
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
199
|
+
|
|
200
|
+ if( cmCsvFinalize(&p->csvH) != kOkCsvRC )
|
|
201
|
+ rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file finalize failed.");
|
|
202
|
+
|
|
203
|
+ while( p->responses != NULL )
|
|
204
|
+ _cmSdbRspRelease(p->responses);
|
|
205
|
+
|
|
206
|
+ cmLHeapDestroy(&p->lhH);
|
|
207
|
+ cmMemFree(p);
|
|
208
|
+ return rc;
|
|
209
|
+}
|
|
210
|
+
|
|
211
|
+cmSdbRC_t cmSdbCreate( cmCtx_t* ctx, cmSdbH_t* hp, const cmChar_t* audioDir, const cmChar_t* csvFn )
|
|
212
|
+{
|
|
213
|
+ cmSdbRC_t rc;
|
|
214
|
+ if((rc = cmSdbDestroy(hp)) != kOkSdbRC )
|
|
215
|
+ return rc;
|
|
216
|
+
|
|
217
|
+ cmSdb_t* p = cmMemAllocZ(cmSdb_t,1);
|
|
218
|
+ p->ctx = *ctx;
|
|
219
|
+ p->blkIdxAllocCnt = 1024;
|
|
220
|
+
|
|
221
|
+ cmErrSetup(&p->ctx.err,&ctx->rpt,"sdb");
|
|
222
|
+
|
|
223
|
+ if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8192,ctx)) == false )
|
|
224
|
+ {
|
|
225
|
+ rc = cmErrMsg(&p->ctx.err,kLHeapFailSdbRC,"Linked heap mgr. allocation failed.");
|
|
226
|
+ goto errLabel;
|
|
227
|
+ }
|
|
228
|
+
|
|
229
|
+ hp->h = p;
|
|
230
|
+
|
|
231
|
+ if( csvFn != NULL )
|
|
232
|
+ if((rc = cmSdbLoad(*hp,csvFn)) != kOkSdbRC )
|
|
233
|
+ goto errLabel;
|
|
234
|
+
|
|
235
|
+ errLabel:
|
|
236
|
+ if( rc != kOkSdbRC )
|
|
237
|
+ _cmSdbDestroy(p);
|
|
238
|
+
|
|
239
|
+ return rc;
|
|
240
|
+}
|
|
241
|
+
|
|
242
|
+cmSdbRC_t cmSdbDestroy( cmSdbH_t* hp )
|
|
243
|
+{
|
|
244
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
245
|
+
|
|
246
|
+ if( hp==NULL || cmSdbIsValid(*hp)==false )
|
|
247
|
+ return rc;
|
|
248
|
+
|
|
249
|
+ cmSdb_t* p = _cmSdbHandleToPtr(*hp);
|
|
250
|
+
|
|
251
|
+ if((rc = _cmSdbDestroy(p)) != kOkSdbRC )
|
|
252
|
+ return rc;
|
|
253
|
+
|
|
254
|
+ hp->h = NULL;
|
|
255
|
+
|
|
256
|
+ return rc;
|
|
257
|
+}
|
|
258
|
+
|
|
259
|
+bool cmSdbIsValid( cmSdbH_t h )
|
|
260
|
+{ return h.h != NULL; }
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+cmSdbRC_t _cmSdbSyntaxError(cmSdb_t* p, const cmChar_t* csvFn, unsigned rowIdx, unsigned colIdx, const cmChar_t* colLabel )
|
|
264
|
+{
|
|
265
|
+ return cmErrMsg(&p->ctx.err,kSyntaxErrSdbRC,"A syntax error was found at row %i col %i (label:%s) in '%s'.",rowIdx+1,colIdx+1,cmStringNullGuard(colLabel),cmStringNullGuard(csvFn));
|
|
266
|
+}
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+cmSdbRC_t cmSdbLoad( cmSdbH_t h, const cmChar_t* csvFn )
|
|
270
|
+{
|
|
271
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
272
|
+ unsigned i;
|
|
273
|
+
|
|
274
|
+ cmSdb_t* p = _cmSdbHandleToPtr(h);
|
|
275
|
+
|
|
276
|
+ if( cmCsvInitializeFromFile(&p->csvH, csvFn, 0, &p->ctx ) != kOkCsvRC )
|
|
277
|
+ {
|
|
278
|
+ rc = cmErrMsg(&p->ctx.err,kCsvFailSdbRC,"CSV file load fail on '%s'.",cmStringNullGuard(csvFn));
|
|
279
|
+ goto errLabel;
|
|
280
|
+ }
|
|
281
|
+
|
|
282
|
+ p->eN = cmCsvRowCount(p->csvH)-1;
|
|
283
|
+
|
|
284
|
+ // release all the memory held by the linked heap
|
|
285
|
+ cmLHeapClear(p->lhH,true);
|
|
286
|
+
|
|
287
|
+ p->eV = cmLhAllocZ(p->lhH,cmSdbEvent_t,p->eN);
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+ for(i=0; rc==kOkSdbRC && i<p->eN; ++i)
|
|
291
|
+ {
|
|
292
|
+ unsigned rowIdx = i+1;
|
|
293
|
+
|
|
294
|
+ if((p->eV[i].uuid = cmCsvCellUInt(p->csvH,rowIdx,kUuidColIdx)) == UINT_MAX )
|
|
295
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kUuidColIdx,"uuid");
|
|
296
|
+
|
|
297
|
+ if((p->eV[i].baseUuid = cmCsvCellUInt(p->csvH,rowIdx,kBaseUuidColIdx)) == UINT_MAX )
|
|
298
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kBaseUuidColIdx,"baseUuid");
|
|
299
|
+
|
|
300
|
+ if((p->eV[i].chIdx = cmCsvCellUInt(p->csvH,rowIdx,kChIdxColIdx)) == UINT_MAX )
|
|
301
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChIdxColIdx,"chIdx");
|
|
302
|
+ else
|
|
303
|
+ p->eV[i].chIdx -= 1; // CSV channel index is 1 based
|
|
304
|
+
|
|
305
|
+ if((p->eV[i].obi = cmCsvCellUInt(p->csvH,rowIdx,kObiColIdx)) == UINT_MAX )
|
|
306
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kObiColIdx,"obi");
|
|
307
|
+ else
|
|
308
|
+ p->eV[i].obi -= 1;
|
|
309
|
+
|
|
310
|
+ if((p->eV[i].ibi = cmCsvCellUInt(p->csvH,rowIdx,kIbiColIdx)) == UINT_MAX )
|
|
311
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIbiColIdx,"ibi");
|
|
312
|
+ else
|
|
313
|
+ p->eV[i].ibi -= 1;
|
|
314
|
+
|
|
315
|
+ if((p->eV[i].iei = cmCsvCellUInt(p->csvH,rowIdx,kIeiColIdx)) == UINT_MAX )
|
|
316
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kIeiColIdx,"obi");
|
|
317
|
+ else
|
|
318
|
+ p->eV[i].iei -= 1;
|
|
319
|
+
|
|
320
|
+ if((p->eV[i].oei = cmCsvCellUInt(p->csvH,rowIdx,kOeiColIdx)) == UINT_MAX )
|
|
321
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kOeiColIdx,"ibi");
|
|
322
|
+ else
|
|
323
|
+ p->eV[i].oei -= 1;
|
|
324
|
+
|
|
325
|
+ if((p->eV[i].src = cmCsvCellText(p->csvH,rowIdx,kSrcColIdx)) == NULL )
|
|
326
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrcColIdx,"src");
|
|
327
|
+
|
|
328
|
+ if((p->eV[i].midi = cmCsvCellInt(p->csvH,rowIdx,kMidiColIdx)) == INT_MAX )
|
|
329
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kMidiColIdx,"midi");
|
|
330
|
+
|
|
331
|
+ if((p->eV[i].instr = cmCsvCellText(p->csvH,rowIdx,kInstrColIdx)) == NULL )
|
|
332
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kInstrColIdx,"instr");
|
|
333
|
+
|
|
334
|
+ if((p->eV[i].srate = cmCsvCellUInt(p->csvH,rowIdx,kSrateColIdx)) == UINT_MAX )
|
|
335
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kSrateColIdx,"srate");
|
|
336
|
+
|
|
337
|
+ if((p->eV[i].chCnt = cmCsvCellUInt(p->csvH,rowIdx,kChCntColIdx)) == UINT_MAX )
|
|
338
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kChCntColIdx,"chCnt");
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+ cmCsvCell_t* c;
|
|
342
|
+ if((c = cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx)) == NULL )
|
|
343
|
+ {
|
|
344
|
+ rc = cmErrMsg(&p->ctx.err,kSyntaxErrSdbRC,"Syntax Error: No 'notes' or 'audio file name' field for row %i in '%s'.",rowIdx+1,cmStringNullGuard(csvFn));
|
|
345
|
+ goto errLabel;
|
|
346
|
+ }
|
|
347
|
+
|
|
348
|
+ // count the number of 'notes'
|
|
349
|
+ unsigned nn = 0;
|
|
350
|
+ for(; c->rowPtr != NULL; c=c->rowPtr)
|
|
351
|
+ ++nn;
|
|
352
|
+
|
|
353
|
+ if( nn > 0 )
|
|
354
|
+ {
|
|
355
|
+ unsigned k = 0;
|
|
356
|
+
|
|
357
|
+ // allocate the 'notes' ptr array - the last entry is set to NULL.
|
|
358
|
+ p->eV[i].notesV = cmLhAllocZ(p->lhH,const cmChar_t*,nn+1);
|
|
359
|
+
|
|
360
|
+ // read each note
|
|
361
|
+ for(c=cmCsvCellPtr(p->csvH,rowIdx,kNotesColIdx); c!=NULL&&c->rowPtr!=NULL; c=c->rowPtr,++k)
|
|
362
|
+ if(( p->eV[i].notesV[k] = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+k)) == NULL )
|
|
363
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+k,"notes");
|
|
364
|
+
|
|
365
|
+ assert(k==nn);
|
|
366
|
+ }
|
|
367
|
+
|
|
368
|
+ // read the audio file name
|
|
369
|
+ if((p->eV[i].afn = cmCsvCellText(p->csvH,rowIdx,kNotesColIdx+nn)) == NULL )
|
|
370
|
+ rc = _cmSdbSyntaxError(p,csvFn,rowIdx,kNotesColIdx+nn,"afn");
|
|
371
|
+
|
|
372
|
+ }
|
|
373
|
+
|
|
374
|
+ errLabel:
|
|
375
|
+
|
|
376
|
+ return rc;
|
|
377
|
+
|
|
378
|
+}
|
|
379
|
+
|
|
380
|
+// Compare 'label' to every string in tV[i] and return true if any comparision is a match.
|
|
381
|
+// If 'subFlV[i]' is set then 'label' must only contain tV[i] as a substring to match.
|
|
382
|
+// If 'negFlV[i]' is set then return true if any comparision is a mismatch.
|
|
383
|
+bool _cmSdbSelectText( const cmSdbEvent_t* r, const cmChar_t** tV, const bool* subFlV, const bool* negFlV, const cmChar_t* label )
|
|
384
|
+{
|
|
385
|
+ unsigned i;
|
|
386
|
+
|
|
387
|
+ if( label == NULL )
|
|
388
|
+ return false;
|
|
389
|
+
|
|
390
|
+ if( tV == NULL )
|
|
391
|
+ return true;
|
|
392
|
+
|
|
393
|
+ for(i=0; tV[i]!=NULL; ++i)
|
|
394
|
+ {
|
|
395
|
+ bool matchFl = false;
|
|
396
|
+ if( subFlV[i] )
|
|
397
|
+ matchFl = strstr(label,tV[i]) != NULL;
|
|
398
|
+ else
|
|
399
|
+ matchFl = strcmp(tV[i],label)==0;
|
|
400
|
+
|
|
401
|
+ if( negFlV[i] )
|
|
402
|
+ matchFl = !matchFl;
|
|
403
|
+
|
|
404
|
+ if(matchFl)
|
|
405
|
+ return true;
|
|
406
|
+ }
|
|
407
|
+
|
|
408
|
+ return false;
|
|
409
|
+}
|
|
410
|
+
|
|
411
|
+unsigned _cmSdbStrVectCnt( const cmChar_t** v )
|
|
412
|
+{
|
|
413
|
+ unsigned n = 0;
|
|
414
|
+ unsigned i = 0;
|
|
415
|
+
|
|
416
|
+ if( v == NULL )
|
|
417
|
+ return 0;
|
|
418
|
+
|
|
419
|
+ for(i=0; v[i]!=NULL; ++i)
|
|
420
|
+ ++n;
|
|
421
|
+ return n;
|
|
422
|
+}
|
|
423
|
+
|
|
424
|
+void _cmSdbStrVectFlags( const cmChar_t** v, bool* sV, bool* nV )
|
|
425
|
+{
|
|
426
|
+ unsigned i = 0;
|
|
427
|
+ if( v == NULL )
|
|
428
|
+ return;
|
|
429
|
+
|
|
430
|
+ for(i=0; v[i]!=NULL; ++i)
|
|
431
|
+ {
|
|
432
|
+ nV[i] = false;
|
|
433
|
+ sV[i] = false;
|
|
434
|
+
|
|
435
|
+ if( strncmp(v[i],"*!",2)==0 || strncmp(v[i],"!*",2)==0)
|
|
436
|
+ {
|
|
437
|
+ sV[i] = nV[i] = true;
|
|
438
|
+ v[i] += 2;
|
|
439
|
+ }
|
|
440
|
+ else
|
|
441
|
+ {
|
|
442
|
+ if( strncmp(v[i],"!",1)==0 )
|
|
443
|
+ {
|
|
444
|
+ nV[i] = true;
|
|
445
|
+ v[i] += 1;
|
|
446
|
+ }
|
|
447
|
+
|
|
448
|
+ if( strncmp(v[i],"*",1)==0 )
|
|
449
|
+ {
|
|
450
|
+ sV[i] = true;
|
|
451
|
+ v[i] += 1;
|
|
452
|
+ }
|
|
453
|
+ }
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+ }
|
|
457
|
+}
|
|
458
|
+
|
|
459
|
+cmSdbRC_t cmSdbSelect(
|
|
460
|
+ cmSdbH_t h,
|
|
461
|
+ double srate,
|
|
462
|
+ const cmChar_t** instrV,
|
|
463
|
+ const cmChar_t** srcV,
|
|
464
|
+ const cmChar_t** notesV,
|
|
465
|
+ double minDurSec,
|
|
466
|
+ double maxDurSec,
|
|
467
|
+ unsigned minChCnt,
|
|
468
|
+ cmSdbResponseH_t* rhp )
|
|
469
|
+{
|
|
470
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
471
|
+ cmSdb_t* p = _cmSdbHandleToPtr(h);
|
|
472
|
+ unsigned i;
|
|
473
|
+
|
|
474
|
+ cmSdbRsp_t* rp = _cmSdbRspAlloc(p,rhp);
|
|
475
|
+
|
|
476
|
+ // get the length of each string vector
|
|
477
|
+ unsigned srcN = _cmSdbStrVectCnt(srcV);
|
|
478
|
+ unsigned insN = _cmSdbStrVectCnt(instrV);
|
|
479
|
+ unsigned notN = _cmSdbStrVectCnt(notesV);
|
|
480
|
+
|
|
481
|
+ // allocate flag vectors
|
|
482
|
+ bool srcSubFlV[ srcN ];
|
|
483
|
+ bool srcNegFlV[ srcN ];
|
|
484
|
+ bool insSubFlV[ insN ];
|
|
485
|
+ bool insNegFlV[ insN ];
|
|
486
|
+ bool notSubFlV[ notN ];
|
|
487
|
+ bool notNegFlV[ notN ];
|
|
488
|
+
|
|
489
|
+ // fill the flag vectors
|
|
490
|
+ _cmSdbStrVectFlags(srcV, srcSubFlV,srcNegFlV);
|
|
491
|
+ _cmSdbStrVectFlags(instrV,insSubFlV,insNegFlV);
|
|
492
|
+ _cmSdbStrVectFlags(notesV,notSubFlV,notNegFlV);
|
|
493
|
+
|
|
494
|
+ for(i=0; i<p->eN; ++i)
|
|
495
|
+ {
|
|
496
|
+ const cmSdbEvent_t* r = p->eV + i;
|
|
497
|
+ double durSec = (double)r->srate * (r->oei - r->obi);
|
|
498
|
+ unsigned j;
|
|
499
|
+
|
|
500
|
+ if( srate!=0 && srate!=r->srate )
|
|
501
|
+ continue;
|
|
502
|
+
|
|
503
|
+ if( durSec < minDurSec || (maxDurSec!=0 && maxDurSec < durSec) )
|
|
504
|
+ continue;
|
|
505
|
+
|
|
506
|
+ if( minChCnt!=0 && r->chCnt > minChCnt )
|
|
507
|
+ continue;
|
|
508
|
+
|
|
509
|
+ if( !_cmSdbSelectText(r,srcV,srcSubFlV,srcNegFlV,r->src) )
|
|
510
|
+ continue;
|
|
511
|
+
|
|
512
|
+ if( !_cmSdbSelectText(r,instrV,insSubFlV,insNegFlV,r->instr) )
|
|
513
|
+ continue;
|
|
514
|
+
|
|
515
|
+ if( r->notesV != NULL )
|
|
516
|
+ for(j=0; r->notesV[j]!=NULL; ++j)
|
|
517
|
+ if( _cmSdbSelectText(r,notesV,notSubFlV,notNegFlV,r->notesV[j]) == true )
|
|
518
|
+ break;
|
|
519
|
+
|
|
520
|
+ if( r->notesV[j]==NULL )
|
|
521
|
+ continue;
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+ _cmSdbRspInsertIndex(p,rp,i);
|
|
525
|
+ }
|
|
526
|
+
|
|
527
|
+ return rc;
|
|
528
|
+}
|
|
529
|
+
|
|
530
|
+cmSdbRC_t cmSdbSelectChPairs( cmSdbH_t h, const cmSdbEvent_t* ep, cmSdbResponseH_t* rhp )
|
|
531
|
+{
|
|
532
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
533
|
+ cmSdb_t* p = _cmSdbHandleToPtr(h);
|
|
534
|
+ cmSdbRsp_t* rp = _cmSdbRspAlloc(p,rhp);
|
|
535
|
+ unsigned i;
|
|
536
|
+
|
|
537
|
+ // for each channel of this event
|
|
538
|
+ for(i=0; i<ep->chCnt; ++i)
|
|
539
|
+ {
|
|
540
|
+ // if i channel is not the known events channel
|
|
541
|
+ if( ep->chIdx != i )
|
|
542
|
+ {
|
|
543
|
+ unsigned j;
|
|
544
|
+
|
|
545
|
+ // examine each record
|
|
546
|
+ for(j=0; j<p->eN; ++j)
|
|
547
|
+ // if eV[j] shares a baseUuid but is on a different channel than *ep ...
|
|
548
|
+ if( p->eV[j].baseUuid == ep->baseUuid && p->eV[j].chIdx==i )
|
|
549
|
+ {
|
|
550
|
+ // .. then a match has been found
|
|
551
|
+ _cmSdbRspInsertIndex(p,rp,j);
|
|
552
|
+ break;
|
|
553
|
+ }
|
|
554
|
+
|
|
555
|
+ if( j== p->eN )
|
|
556
|
+ {
|
|
557
|
+ rc = cmErrMsg(&p->ctx.err,kChPairNotFoundSdbRC,"The channel pair associated with 'id:%i instr:%s src:%s ch index:%i could not be found.",ep->uuid,cmStringNullGuard(ep->instr),cmStringNullGuard(ep->src),ep->chIdx);
|
|
558
|
+ }
|
|
559
|
+ }
|
|
560
|
+ }
|
|
561
|
+
|
|
562
|
+ return rc;
|
|
563
|
+
|
|
564
|
+}
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+unsigned cmSdbResponseCount( cmSdbResponseH_t rh )
|
|
568
|
+{
|
|
569
|
+ cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
|
|
570
|
+ return rp->cnt;
|
|
571
|
+}
|
|
572
|
+
|
|
573
|
+const cmSdbEvent_t* cmSdbResponseEvent( cmSdbResponseH_t rh, unsigned index )
|
|
574
|
+{
|
|
575
|
+ cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(rh);
|
|
576
|
+
|
|
577
|
+ if( index >= rp->cnt )
|
|
578
|
+ return NULL;
|
|
579
|
+
|
|
580
|
+ cmSdbRspBlk_t* bp = rp->blocks;
|
|
581
|
+ unsigned i;
|
|
582
|
+ for(i=0; bp!=NULL; i+=bp->cnt,bp=bp->link)
|
|
583
|
+ if( i <= index && index < (i + bp->cnt) )
|
|
584
|
+ return rp->p->eV + bp->indexV[index-i];
|
|
585
|
+
|
|
586
|
+ cmErrMsg(&rp->p->ctx.err,kInvalidRspIdxSdbRC,"Invalid query response index=%i.",index);
|
|
587
|
+ return NULL;
|
|
588
|
+}
|
|
589
|
+
|
|
590
|
+bool cmSdbResponseIsValid( cmSdbResponseH_t rh )
|
|
591
|
+{ return rh.h != NULL; }
|
|
592
|
+
|
|
593
|
+cmSdbRC_t cmSdbResponseFree( cmSdbResponseH_t* rhp )
|
|
594
|
+{
|
|
595
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
596
|
+
|
|
597
|
+ if( rhp == NULL || cmSdbResponseIsValid(*rhp)==false )
|
|
598
|
+ return rc;
|
|
599
|
+
|
|
600
|
+ cmSdbRsp_t* rp = _cmSdbRspHandleToPtr(*rhp);
|
|
601
|
+
|
|
602
|
+ _cmSdbRspFree(rp);
|
|
603
|
+
|
|
604
|
+ rhp->h = NULL;
|
|
605
|
+
|
|
606
|
+ return rc;
|
|
607
|
+}
|
|
608
|
+
|
|
609
|
+void cmSdbResponsePrint( cmSdbResponseH_t rh, cmRpt_t* rpt )
|
|
610
|
+{
|
|
611
|
+ unsigned n = cmSdbResponseCount(rh);
|
|
612
|
+ unsigned i;
|
|
613
|
+ for(i=0; i<n; ++i)
|
|
614
|
+ {
|
|
615
|
+ const cmSdbEvent_t* e = cmSdbResponseEvent(rh,i);
|
|
616
|
+ if( e != NULL )
|
|
617
|
+ cmRptPrintf(rpt,"%6i %6i %2i %12i %12i %12i %12i %2i %6i %2i %10s %15s\n",
|
|
618
|
+ e->uuid,e->baseUuid,e->chIdx,e->obi,e->ibi,e->iei,e->oei,e->midi,e->srate,e->chCnt,
|
|
619
|
+ cmStringNullGuard(e->src), cmStringNullGuard(e->instr) );
|
|
620
|
+ }
|
|
621
|
+}
|
|
622
|
+
|
|
623
|
+cmSdbRC_t cmSdbSyncChPairs( cmSdbH_t h )
|
|
624
|
+{
|
|
625
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
626
|
+ cmSdb_t* p = _cmSdbHandleToPtr(h);
|
|
627
|
+ unsigned i;
|
|
628
|
+ // for each multi-channel event
|
|
629
|
+ for(i=0; i<p->eN; ++i)
|
|
630
|
+ if(p->eV[i].chCnt > 1 )
|
|
631
|
+ {
|
|
632
|
+ const cmSdbEvent_t* ep = p->eV + i;
|
|
633
|
+ unsigned iV[ep->chCnt];
|
|
634
|
+ unsigned j,k;
|
|
635
|
+
|
|
636
|
+ // load iV[] with the event indexes of the channel pairs
|
|
637
|
+ for(j=0,k=0; j<p->eN && k<ep->chCnt; ++j)
|
|
638
|
+ if( p->eV[j].baseUuid == ep->baseUuid )
|
|
639
|
+ {
|
|
640
|
+ assert( p->eV[j].chIdx < ep->chCnt );
|
|
641
|
+
|
|
642
|
+ iV[p->eV[j].chIdx] = j;
|
|
643
|
+ ++k;
|
|
644
|
+ }
|
|
645
|
+
|
|
646
|
+ if( k != ep->chCnt )
|
|
647
|
+ rc = cmErrMsg(&p->ctx.err,kChPairNotFoundSdbRC,"The channel pair associated with 'id:%i instr:%s src:%s ch index:%i could not be found.",ep->uuid,cmStringNullGuard(ep->instr),cmStringNullGuard(ep->src),ep->chIdx);
|
|
648
|
+ else
|
|
649
|
+ {
|
|
650
|
+ unsigned mobi = ep->obi;
|
|
651
|
+ unsigned mibi = ep->ibi;
|
|
652
|
+ unsigned miei = ep->iei;
|
|
653
|
+ unsigned moei = ep->oei;
|
|
654
|
+
|
|
655
|
+ // get the min onsets and max offsets
|
|
656
|
+ for(j=0; j<ep->chCnt; ++j)
|
|
657
|
+ {
|
|
658
|
+ mobi = cmMin(mobi,p->eV[ iV[j] ].obi);
|
|
659
|
+ mibi = cmMin(mibi,p->eV[ iV[j] ].ibi);
|
|
660
|
+ miei = cmMax(miei,p->eV[ iV[j] ].iei);
|
|
661
|
+ moei = cmMax(moei,p->eV[ iV[j] ].oei);
|
|
662
|
+ }
|
|
663
|
+
|
|
664
|
+ // set the onsets to the min onset / offsets to max offsets
|
|
665
|
+ for(j=0; j<ep->chCnt; ++j)
|
|
666
|
+ {
|
|
667
|
+ p->eV[ iV[j] ].obi = mobi;
|
|
668
|
+ p->eV[ iV[j] ].ibi = mibi;
|
|
669
|
+ p->eV[ iV[j] ].iei = miei;
|
|
670
|
+ p->eV[ iV[j] ].oei = moei;
|
|
671
|
+ }
|
|
672
|
+ }
|
|
673
|
+ }
|
|
674
|
+
|
|
675
|
+ return rc;
|
|
676
|
+}
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+cmSdbRC_t cmSdbTest( cmCtx_t* ctx )
|
|
680
|
+{
|
|
681
|
+ cmSdbRC_t rc = kOkSdbRC;
|
|
682
|
+ cmSdbH_t h = cmSdbNullHandle;
|
|
683
|
+ const cmChar_t* audioDir = "/home/kevin/media/audio";
|
|
684
|
+ const cmChar_t* csvFn = "/home/kevin/temp/sdb0/sdb_master.csv";
|
|
685
|
+ cmErr_t err;
|
|
686
|
+
|
|
687
|
+ cmErrSetup(&err,&ctx->rpt,"sdb test");
|
|
688
|
+
|
|
689
|
+ if((rc = cmSdbCreate(ctx, &h, audioDir, csvFn )) != kOkSdbRC )
|
|
690
|
+ {
|
|
691
|
+ rc = cmErrMsg(&err,rc,"sdb create failed.");
|
|
692
|
+ goto errLabel;
|
|
693
|
+ }
|
|
694
|
+
|
|
695
|
+ if((rc = cmSdbSyncChPairs(h)) != kOkSdbRC )
|
|
696
|
+ {
|
|
697
|
+ rc = cmErrMsg(&err,rc,"sdb sync-ch-pairs failed.");
|
|
698
|
+ goto errLabel;
|
|
699
|
+ }
|
|
700
|
+
|
|
701
|
+ if(0)
|
|
702
|
+ {
|
|
703
|
+ cmSdbResponseH_t rH = cmSdbResponseNullHandle;
|
|
704
|
+
|
|
705
|
+ const cmChar_t* instrV[] = { "*viol", NULL };
|
|
706
|
+
|
|
707
|
+ if((rc = cmSdbSelect(h,0,instrV,NULL,NULL,0,0,0,&rH)) != kOkSdbRC )
|
|
708
|
+ {
|
|
709
|
+ rc = cmErrMsg(&err,rc,"sdb query failed.");
|
|
710
|
+ goto errLabel;
|
|
711
|
+ }
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+ cmSdbResponsePrint(rH,&ctx->rpt);
|
|
715
|
+
|
|
716
|
+ cmSdbResponseFree(&rH);
|
|
717
|
+ }
|
|
718
|
+
|
|
719
|
+ errLabel:
|
|
720
|
+ if((rc = cmSdbDestroy(&h)) != kOkSdbRC )
|
|
721
|
+ rc = cmErrMsg(&err,rc,"sdb destroy failed.");
|
|
722
|
+
|
|
723
|
+ return rc;
|
|
724
|
+}
|