2024-12-01 19:35:24 +00:00
|
|
|
//| Copyright: (C) 2020-2024 Kevin Larke <contact AT larke DOT org>
|
|
|
|
//| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
|
2024-02-20 02:59:40 +00:00
|
|
|
#include "cwCommon.h"
|
|
|
|
#include "cwLog.h"
|
|
|
|
#include "cwCommonImpl.h"
|
2024-05-29 16:36:57 +00:00
|
|
|
#include "cwTest.h"
|
2024-02-20 02:59:40 +00:00
|
|
|
#include "cwMem.h"
|
|
|
|
#include "cwText.h"
|
|
|
|
#include "cwObject.h"
|
|
|
|
#include "cwCsv.h"
|
|
|
|
#include "cwFile.h"
|
|
|
|
#include "cwFileSys.h"
|
|
|
|
#include "cwGutimReg.h"
|
|
|
|
|
|
|
|
namespace cw
|
|
|
|
{
|
|
|
|
namespace gutim
|
|
|
|
{
|
|
|
|
namespace reg
|
|
|
|
{
|
|
|
|
typedef struct reg_file_str
|
|
|
|
{
|
|
|
|
char* player_name;
|
|
|
|
char* take_label;
|
|
|
|
char* path;
|
|
|
|
char* midi_fname;
|
|
|
|
file_t r;
|
|
|
|
} reg_file_t;
|
|
|
|
|
|
|
|
typedef struct reg_str
|
|
|
|
{
|
|
|
|
reg_file_t* fileA;
|
|
|
|
unsigned fileN;
|
|
|
|
} reg_t;
|
|
|
|
|
|
|
|
reg_t* _handleToPtr( handle_t h )
|
|
|
|
{ return handleToPtr<handle_t,struct reg_str>(h); }
|
|
|
|
|
|
|
|
rc_t _destroy( reg_t* p )
|
|
|
|
{
|
|
|
|
for(unsigned i=0; i<p->fileN; ++i)
|
|
|
|
{
|
|
|
|
mem::release(p->fileA[i].player_name);
|
|
|
|
mem::release(p->fileA[i].take_label);
|
|
|
|
mem::release(p->fileA[i].path);
|
|
|
|
mem::release(p->fileA[i].midi_fname);
|
|
|
|
}
|
|
|
|
mem::release(p->fileA);
|
|
|
|
mem::release(p);
|
|
|
|
|
|
|
|
return kOkRC;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cw::rc_t cw::gutim::reg::create( handle_t& hRef, const char* fname )
|
|
|
|
{
|
|
|
|
rc_t rc = kOkRC;
|
|
|
|
csv::handle_t csvH;
|
|
|
|
const char* colLabelA[] = {"player_name","take_label","session_number","take_number","beg_loc","end_loc","skip_score_follow_fl","path" };
|
|
|
|
unsigned colLabelN = sizeof(colLabelA)/sizeof(colLabelA[0]);
|
|
|
|
unsigned lineAllocN = 0;
|
|
|
|
filesys::pathPart_t* pathPart = nullptr;
|
|
|
|
|
|
|
|
auto cmp_func = [](const reg_file_t& r0, const reg_file_t& r1)
|
|
|
|
{
|
|
|
|
int cmp = textCompare(r0.player_name,r1.player_name);
|
|
|
|
|
|
|
|
if( cmp < 0 )
|
|
|
|
return true;
|
|
|
|
if( cmp > 0 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if( r0.r.session_number < r1.r.session_number )
|
|
|
|
return true;
|
|
|
|
if( r0.r.session_number > r1.r.session_number )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if( r0.r.take_number < r1.r.take_number )
|
|
|
|
return true;
|
|
|
|
if( r0.r.take_number > r1.r.take_number )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
if((rc = destroy(hRef)) != kOkRC )
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
reg_t* p = mem::allocZ<reg_t>();
|
|
|
|
|
|
|
|
// open the CSV
|
|
|
|
if((rc = create(csvH,fname,colLabelA,colLabelN)) != kOkRC )
|
|
|
|
{
|
|
|
|
rc = cwLogError(rc,"GUTIM reg CSV file open failed on '%s'.",cwStringNullGuard(fname));
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
// parse the reg CSV fname
|
|
|
|
pathPart = filesys::pathParts(fname);
|
|
|
|
|
|
|
|
// get the count of lines in the CSV file
|
|
|
|
if((rc = line_count(csvH,lineAllocN)) != kOkRC )
|
|
|
|
{
|
|
|
|
rc = cwLogError(rc,"CSV line count failed.");
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
// rewind CSV file
|
|
|
|
if((rc = rewind(csvH)) != kOkRC )
|
|
|
|
{
|
|
|
|
rc = cwLogError(rc,"GUTIM registry CSV '%s' rewind failed.",cwStringNullGuard(fname));
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
// verify that that the CSV is not tempy
|
|
|
|
if( lineAllocN <= 1 )
|
|
|
|
{
|
|
|
|
rc = cwLogError(kInvalidStateRC,"The GUTIM registry CSV '%s' is empty.",cwStringNullGuard(fname));
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
lineAllocN -= 1; // subtract one to account for column titles
|
|
|
|
|
|
|
|
p->fileA = mem::allocZ<reg_file_t>(lineAllocN);
|
|
|
|
|
|
|
|
// skip col. labels
|
|
|
|
if((rc = next_line(csvH)) != kOkRC )
|
|
|
|
{
|
|
|
|
rc = cwLogError(rc,"CSV line advance failed on first line.");
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(unsigned i=0; i<lineAllocN; ++i)
|
|
|
|
{
|
|
|
|
reg_file_t& fr = p->fileA[i];
|
|
|
|
|
|
|
|
if((rc = getv( csvH,
|
|
|
|
"player_name", fr.r.player_name,
|
|
|
|
"take_label", fr.r.take_label,
|
|
|
|
"path", fr.r.path,
|
|
|
|
"session_number", fr.r.session_number,
|
|
|
|
"take_number", fr.r.take_number,
|
|
|
|
"beg_loc", fr.r.beg_loc,
|
|
|
|
"end_loc", fr.r.end_loc,
|
|
|
|
"skip_score_follow_fl", fr.r.skip_score_follow_fl )) != kOkRC )
|
|
|
|
{
|
|
|
|
rc = cwLogError(rc,"GUTIM registry CSV parse failed.");
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
fr.player_name = mem::duplStr(fr.r.player_name);
|
|
|
|
fr.r.player_name = fr.player_name;
|
|
|
|
|
|
|
|
fr.take_label = mem::duplStr(fr.r.take_label);
|
|
|
|
fr.r.take_label = fr.take_label;
|
|
|
|
|
|
|
|
fr.path = mem::duplStr(fr.r.path);
|
|
|
|
fr.r.path = fr.path;
|
|
|
|
|
|
|
|
fr.midi_fname = filesys::makeFn(pathPart->dirStr, "midi", "mid", fr.r.path, nullptr );
|
|
|
|
fr.r.midi_fname = fr.midi_fname;
|
|
|
|
|
|
|
|
p->fileN += 1;
|
|
|
|
|
|
|
|
// advance the current CSV
|
|
|
|
if((rc = next_line( csvH )) != kOkRC )
|
|
|
|
{
|
|
|
|
if( rc == kEofRC )
|
|
|
|
{
|
|
|
|
rc = kOkRC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = cwLogError(rc,"CSV 'next line' failed on '%s'.",cwStringNullGuard(fname));
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::sort(p->fileA,p->fileA+p->fileN,cmp_func);
|
|
|
|
|
|
|
|
hRef.set(p);
|
|
|
|
|
|
|
|
errLabel:
|
|
|
|
if(rc != kOkRC )
|
2024-02-21 12:46:51 +00:00
|
|
|
_destroy(p);
|
2024-02-20 02:59:40 +00:00
|
|
|
|
|
|
|
destroy(csvH);
|
|
|
|
|
|
|
|
mem::release(pathPart);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
cw::rc_t cw::gutim::reg::destroy( handle_t& hRef )
|
|
|
|
{
|
|
|
|
rc_t rc = kOkRC;
|
|
|
|
|
|
|
|
if( !hRef.isValid() )
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
reg_t* p = _handleToPtr(hRef);
|
|
|
|
|
|
|
|
if((rc = _destroy(p)) != kOkRC )
|
|
|
|
{
|
|
|
|
cwLogError(rc,"Gutim registry destroy failed.");
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
hRef.clear();
|
|
|
|
|
|
|
|
errLabel:
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned cw::gutim::reg::file_count( handle_t h )
|
|
|
|
{
|
|
|
|
reg_t* p = _handleToPtr(h);
|
|
|
|
return p->fileN;
|
|
|
|
}
|
|
|
|
|
|
|
|
cw::gutim::reg::file_t cw::gutim::reg::file_record( handle_t h, unsigned file_idx )
|
|
|
|
{
|
|
|
|
reg_t* p = _handleToPtr(h);
|
|
|
|
return p->fileA[ file_idx ].r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cw::gutim::reg::report( handle_t h )
|
|
|
|
{
|
|
|
|
reg_t* p = _handleToPtr(h);
|
|
|
|
|
|
|
|
cwLogInfo("performer sess take b-loc e-loc skip path");
|
|
|
|
cwLogInfo("---------- ---- ---- ----- ----- ----- -------------------------------------------");
|
|
|
|
for(unsigned i=0; i<p->fileN; ++i)
|
|
|
|
{
|
|
|
|
const reg_file_t& fr = p->fileA[i];
|
|
|
|
const file_t& r = fr.r;
|
|
|
|
|
|
|
|
cwLogInfo("%10s %4i %4i %5i %5i %5s %s %s",
|
|
|
|
r.player_name,
|
|
|
|
r.session_number,
|
|
|
|
r.take_number,
|
|
|
|
r.beg_loc,
|
|
|
|
r.end_loc,
|
|
|
|
r.skip_score_follow_fl?"true":"false",
|
|
|
|
r.path,
|
|
|
|
r.midi_fname);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2024-02-21 12:46:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
cw::rc_t cw::gutim::reg::test( const object_t* cfg )
|
|
|
|
{
|
|
|
|
const char* dir = nullptr;
|
|
|
|
rc_t rc = kOkRC;
|
|
|
|
handle_t h;
|
|
|
|
|
|
|
|
if((rc = cfg->getv("dir",dir)) != kOkRC )
|
|
|
|
{
|
|
|
|
rc = cwLogError(rc,"The arg. parse GUTIM registry test.");
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((rc = create(h,dir)) != kOkRC )
|
|
|
|
{
|
|
|
|
rc = cwLogError(rc,"The GUTIM registry create failed.");
|
|
|
|
goto errLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
report(h);
|
|
|
|
|
|
|
|
errLabel:
|
|
|
|
destroy(h);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|