From d32b7a891f44ffb399a7d368dda2a6bc4871ef79 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 19 Feb 2024 21:57:54 -0500 Subject: [PATCH 1/7] cwCsv.h/cpp : Added parse_field(...,bool). --- cwCsv.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ cwCsv.h | 3 +++ 2 files changed, 45 insertions(+) diff --git a/cwCsv.cpp b/cwCsv.cpp index dff0ae8..c6aa024 100644 --- a/cwCsv.cpp +++ b/cwCsv.cpp @@ -310,7 +310,37 @@ namespace cw return rc; } + rc_t _parse_bool_field( csv_t* p, unsigned colIdx, bool& valRef ) + { + rc_t rc = kOkRC; + const char* fieldStr = nullptr; + if((rc = _get_field_str(p,colIdx,fieldStr)) != kOkRC ) + goto errLabel; + else + { + if( textIsEqualI(fieldStr,"true") ) + valRef = true; + else + if( textIsEqualI(fieldStr,"false") ) + valRef = false; + else + rc = cwLogError(kSyntaxErrorRC,"The value of a boolean must be either 'true' or 'false'."); + } + + errLabel: + return rc; + } + + rc_t _parse_bool_field( csv_t* p, const char* colLabel, bool& valRef ) + { + unsigned colIdx; + if((colIdx = _title_to_col_index(p, colLabel)) == kInvalidIdx ) + return cwLogError(kInvalidArgRC,"The column label '%s' is not valid.",cwStringNullGuard(colLabel)); + + return _parse_bool_field(p,colIdx,valRef); + } + } } @@ -496,6 +526,12 @@ cw::rc_t cw::csv::field_char_count( handle_t h, unsigned colIdx, unsigned& charC return rc; } +cw::rc_t cw::csv::parse_field( handle_t h, unsigned colIdx, bool& valRef ) +{ + csv_t* p = _handleToPtr(h); + return _parse_bool_field( p, colIdx, valRef ) ; +} + cw::rc_t cw::csv::parse_field( handle_t h, unsigned colIdx, uint8_t& valRef ) { csv_t* p = _handleToPtr(h); @@ -526,6 +562,12 @@ cw::rc_t cw::csv::parse_field( handle_t h, unsigned colIdx, const char*& valRef return _parse_string_field( p, colIdx, valRef ); } +cw::rc_t cw::csv::parse_field( handle_t h, const char* colLabel, bool& valRef ) +{ + csv_t* p = _handleToPtr(h); + return _parse_bool_field(p, colLabel, valRef ); +} + cw::rc_t cw::csv::parse_field( handle_t h, const char* colLabel, uint8_t& valRef ) { csv_t* p = _handleToPtr(h); diff --git a/cwCsv.h b/cwCsv.h index ec4c2b6..36c3c3f 100644 --- a/cwCsv.h +++ b/cwCsv.h @@ -43,6 +43,8 @@ namespace cw rc_t parse_field( handle_t h, unsigned colIdx, unsigned& valRef ); rc_t parse_field( handle_t h, unsigned colIdx, int& valRef ); rc_t parse_field( handle_t h, unsigned colIdx, double& valRef ); + rc_t parse_field( handle_t h, unsigned colIdx, bool& valRef ); + // The returned pointer is a pointer into an internal 'line' buffer. // The reference is therefore only valid until the next call to next_line(). @@ -52,6 +54,7 @@ namespace cw rc_t parse_field( handle_t h, const char* colLabel, unsigned& valRef ); rc_t parse_field( handle_t h, const char* colLabel, int& valRef ); rc_t parse_field( handle_t h, const char* colLabel, double& valRef ); + rc_t parse_field( handle_t h, const char* colLabel, bool& valRef ); // The returned pointer is a pointer into an internal 'line' buffer. // The reference is therefore only valid until the next call to next_line(). From 4d0fda113432b42cdee355bf1cf1f22ed2b3af58 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 19 Feb 2024 21:58:50 -0500 Subject: [PATCH 2/7] cwText.h,cpp : Added case insensitve compare. --- cwText.cpp | 65 +++++++++++++++++++++++++++++++++++++----------------- cwText.h | 21 ++++++++++++++++-- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/cwText.cpp b/cwText.cpp index 6e12f90..f6b4e7a 100644 --- a/cwText.cpp +++ b/cwText.cpp @@ -30,23 +30,6 @@ namespace cw return eosFl ? s : nullptr; } - /* - unsigned _toText( char* buf, unsigned bufN, unsigned char v ) - { - if( bufN < 1 ) - return 0; - buf[0] = v; - return 1; - } - - unsigned _toText( char* buf, unsigned bufN, char v ) - { - if( bufN < 1 ) - return 0; - buf[0] = v; - return 1; - } - */ } @@ -77,21 +60,43 @@ const char* cw::textCopy( char* dst, unsigned dstN, const char* src, unsigned sr return dst; } - -void textToLower( char* s ) +void cw::textToLower( char* s ) { if( s != nullptr ) for(; *s; ++s) *s = std::tolower(*s); } -void textToUpper( char* s ) +void cw::textToUpper( char* s ) { if( s != nullptr ) for(; *s; ++s) *s = std::toupper(*s); } +void cw::textToLower( char* dst, const char* src, unsigned dstN ) +{ + if( src != nullptr && dstN>0 ) + { + unsigned sn = std::min(dstN,textLength(src)+1); + unsigned i; + for(i=0; i0 ) + { + unsigned sn = std::min(dstN,textLength(src)+1); + unsigned i; + for(i=0; i Date: Mon, 19 Feb 2024 21:59:40 -0500 Subject: [PATCH 3/7] cwGutimReg.h,cpp : Initial commit. --- Makefile.am | 4 +- cwGutimReg.cpp | 250 +++++++++++++++++++++++++++++++++++++++++++++++++ cwGutimReg.h | 39 ++++++++ 3 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 cwGutimReg.cpp create mode 100644 cwGutimReg.h diff --git a/Makefile.am b/Makefile.am index b12a5a1..b4a126a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,8 +71,8 @@ libcwSRC += src/libcw/cwIo.cpp src/libcw/cwIoTest.cpp src/libcw/cwIoMinTest.cp libcwHDR += src/libcw/cwIoMidiRecordPlay.h src/libcw/cwIoAudioRecordPlay.h src/libcw/cwIoAudioMidiApp.h src/libcw/cwIoFlow.h libcwSRC += src/libcw/cwIoMidiRecordPlay.cpp src/libcw/cwIoAudioRecordPlay.cpp src/libcw/cwIoAudioMidiApp.cpp src/libcw/cwIoFlow.cpp -libcwHDR += src/libcw/cwIoPresetSelApp.h src/libcw/cwPianoScore.h src/libcw/cwPresetSel.h src/libcw/cwVelTableTuner.h -libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/libcw/cwPresetSel.cpp src/libcw/cwVelTableTuner.cpp +libcwHDR += src/libcw/cwIoPresetSelApp.h src/libcw/cwPianoScore.h src/libcw/cwPresetSel.h src/libcw/cwVelTableTuner.h src/libcw/cwGutimReg.h +libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/libcw/cwPresetSel.cpp src/libcw/cwVelTableTuner.cpp src/libcw/cwGutimReg.cpp libcwHDR += src/libcw/cwDynRefTbl.h src/libcw/cwScoreParse.h src/libcw/cwSfScore.h libcwSRC += src/libcw/cwDynRefTbl.cpp src/libcw/cwScoreParse.cpp src/libcw/cwSfScore.cpp diff --git a/cwGutimReg.cpp b/cwGutimReg.cpp new file mode 100644 index 0000000..47b6e6d --- /dev/null +++ b/cwGutimReg.cpp @@ -0,0 +1,250 @@ +#include "cwCommon.h" +#include "cwLog.h" +#include "cwCommonImpl.h" +#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(h); } + + rc_t _destroy( reg_t* p ) + { + for(unsigned i=0; ifileN; ++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(); + + // 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(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; ifileA[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 ) + rc = _destroy(p); + + 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; ifileN; ++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); + + } + +} diff --git a/cwGutimReg.h b/cwGutimReg.h new file mode 100644 index 0000000..1e79c8a --- /dev/null +++ b/cwGutimReg.h @@ -0,0 +1,39 @@ +#ifndef cwGutimReg_h +#define cwGutimReg_h + +namespace cw +{ + namespace gutim + { + namespace reg + { + typedef handle handle_t; + + typedef struct file_str + { + const char* player_name; + const char* take_label; + const char* path; + const char* midi_fname; + bool skip_score_follow_fl; + unsigned session_number; + unsigned take_number; + unsigned beg_loc; + unsigned end_loc; + } file_t; + + + rc_t create( handle_t& hRef, const char* fname ); + rc_t destroy( handle_t& hRef ); + + unsigned file_count( handle_t h ); + file_t file_record( handle_t h, unsigned file_idx ); + + void report( handle_t h ); + + + } + } +} + +#endif From e8e69159901fbcb586c2edb7a7946718adf011e4 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 21 Feb 2024 07:46:51 -0500 Subject: [PATCH 4/7] cwGutimReg.h/cpp : Added test(). --- cwGutimReg.cpp | 29 ++++++++++++++++++++++++++++- cwGutimReg.h | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/cwGutimReg.cpp b/cwGutimReg.cpp index 47b6e6d..32e746c 100644 --- a/cwGutimReg.cpp +++ b/cwGutimReg.cpp @@ -183,7 +183,7 @@ cw::rc_t cw::gutim::reg::create( handle_t& hRef, const char* fname ) errLabel: if(rc != kOkRC ) - rc = _destroy(p); + _destroy(p); destroy(csvH); @@ -248,3 +248,30 @@ void cw::gutim::reg::report( handle_t h ) } } + + +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; +} diff --git a/cwGutimReg.h b/cwGutimReg.h index 1e79c8a..de25753 100644 --- a/cwGutimReg.h +++ b/cwGutimReg.h @@ -30,7 +30,7 @@ namespace cw file_t file_record( handle_t h, unsigned file_idx ); void report( handle_t h ); - + rc_t test( const object_t* cfg ); } } From 8177ff71fcca3b033609390b55c3bb13a7348ecf Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 21 Feb 2024 07:47:09 -0500 Subject: [PATCH 5/7] cwMidiDevice.cpp : Updated comments. --- cwMidiDevice.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cwMidiDevice.cpp b/cwMidiDevice.cpp index 7e364cc..0a3e4ba 100644 --- a/cwMidiDevice.cpp +++ b/cwMidiDevice.cpp @@ -144,6 +144,9 @@ namespace cw } + // TODO: Consider replacing the poll() with epoll_wait2() is apparently + // optimized for more accurate time outs. + // Block here waiting for ALSA events or timeout when the next file msg should be sent int sysRC = poll( p->alsaPollfdA, p->alsaPollfdN, sleep_millis ); From e3ff4828b0021978e30e55ca05caf9312ab4beba Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 21 Feb 2024 07:49:28 -0500 Subject: [PATCH 6/7] cwMidiDevice,cwMidiFileDev : Added midi::file_dev.msg_count() and midi::device.loadMsgPacket(). --- cwMidiDevice.cpp | 35 ++++++++++++++++++++++++++++++++++- cwMidiDevice.h | 2 ++ cwMidiFileDev.cpp | 13 +++++++++++++ cwMidiFileDev.h | 2 ++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/cwMidiDevice.cpp b/cwMidiDevice.cpp index 7e364cc..3abdc49 100644 --- a/cwMidiDevice.cpp +++ b/cwMidiDevice.cpp @@ -511,13 +511,46 @@ cw::rc_t cw::midi::device::openMidiFile( handle_t h, unsigned devIdx, unsigned p errLabel: return rc; +} +cw::rc_t cw::midi::device::loadMsgPacket( handle_t h, const packet_t& pkt ) +{ + rc_t rc = kOkRC; + device_t* p = _handleToPtr(h); + + if( _devIdxToFileDevIdx(p,pkt.devIdx) == kInvalidIdx ) + { + cwLogError(kInvalidArgRC,"The device index %i does not identify a valid file device.",pkt.devIdx); + goto errLabel; + } + + if((rc = load_messages( p->fileDevH, pkt.portIdx, pkt.msgArray, pkt.msgCnt)) != kOkRC ) + goto errLabel; + +errLabel: + return rc; +} + +unsigned cw::midi::device::msgCount( handle_t h, unsigned devIdx, unsigned portIdx ) +{ + device_t* p = _handleToPtr(h); + + if(_devIdxToFileDevIdx(p,devIdx) == kInvalidIdx ) + { + cwLogError(kInvalidArgRC,"The device index %i does not identify a valid file device.",devIdx); + goto errLabel; + } + + return msg_count( p->fileDevH, portIdx); + +errLabel: + return 0; } cw::rc_t cw::midi::device::seekToMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx ) { rc_t rc = kOkRC; - device_t* p = _handleToPtr(h); + device_t* p = _handleToPtr(h); if(_devIdxToFileDevIdx(p,devIdx) == kInvalidIdx ) { diff --git a/cwMidiDevice.h b/cwMidiDevice.h index 4fa87f8..7461356 100644 --- a/cwMidiDevice.h +++ b/cwMidiDevice.h @@ -52,6 +52,8 @@ namespace cw rc_t sendData( handle_t h, unsigned devIdx, unsigned portIdx, const uint8_t* dataPtr, unsigned byteCnt ); rc_t openMidiFile( handle_t h, unsigned devIdx, unsigned portIdx, const char* fname ); + rc_t loadMsgPacket(handle_t h, const packet_t& pkt ); // Note: Set devIdx/portIdx via pkt.devIdx/pkt.portIdx + unsigned msgCount( handle_t h, unsigned devIdx, unsigned portIdx ); rc_t seekToMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx ); rc_t setEndMsg( handle_t h, unsigned devIdx, unsigned portidx, unsigned msgIdx ); diff --git a/cwMidiFileDev.cpp b/cwMidiFileDev.cpp index 9e448af..44947cb 100644 --- a/cwMidiFileDev.cpp +++ b/cwMidiFileDev.cpp @@ -716,6 +716,19 @@ errLabel: return rc; } +unsigned cw::midi::device::file_dev::msg_count( handle_t h, unsigned file_idx ) +{ + file_dev_t* p = _handleToPtr(h); + rc_t rc; + + if((rc = _validate_file_existence(p,file_idx)) != kOkRC ) + goto errLabel; + + return p->msgN; + +errLabel: + return 0; +} cw::rc_t cw::midi::device::file_dev::seek_to_msg_index( handle_t h, unsigned file_idx, unsigned msg_idx ) { diff --git a/cwMidiFileDev.h b/cwMidiFileDev.h index 9973a06..08e6e13 100644 --- a/cwMidiFileDev.h +++ b/cwMidiFileDev.h @@ -66,6 +66,8 @@ namespace cw } exec_result_t; + unsigned msg_count( handle_t h, unsigned file_idx ); + // Set the next msg to be returned. rc_t seek_to_msg_index( handle_t h, unsigned file_idx, unsigned msg_idx ); rc_t set_end_msg_index( handle_t h, unsigned file_idx, unsigned msg_idx ); From 68e36aad6bf96529bcb3e1f821cd45a391016820 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 21 Feb 2024 07:50:52 -0500 Subject: [PATCH 7/7] cwIo : Added MIDI file device interface. --- cwIo.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ cwIo.h | 9 +++++++++ 2 files changed, 51 insertions(+) diff --git a/cwIo.cpp b/cwIo.cpp index 483910e..74de76f 100644 --- a/cwIo.cpp +++ b/cwIo.cpp @@ -2703,6 +2703,48 @@ cw::rc_t cw::io::midiDeviceSend( handle_t h, unsigned devIdx, unsigned portIdx, return midi::device::send( p->midiH, devIdx, portIdx, status, d0, d1 ); } +cw::rc_t cw::io::midiOpenMidiFile( handle_t h, unsigned devIdx, unsigned portIdx, const char* fname ) +{ + return midi::device::openMidiFile( _handleToPtr(h)->midiH, devIdx, portIdx, fname ); +} + +cw::rc_t cw::io::midiLoadMsgPacket( handle_t h, const midi::packet_t& pkt ) +{ + return midi::device::loadMsgPacket( _handleToPtr(h)->midiH, pkt ); +} + +unsigned cw::io::midiMsgCount( handle_t h, unsigned devIdx, unsigned portIdx ) +{ + return midi::device::msgCount( _handleToPtr(h)->midiH, devIdx, portIdx ); +} + +cw::rc_t cw::io::midiSeekToMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx ) +{ + return midi::device::seekToMsg( _handleToPtr(h)->midiH, devIdx, portIdx, msgIdx ); +} + +cw::rc_t cw::io::midiSetEndMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx ) +{ + return midi::device::setEndMsg( _handleToPtr(h)->midiH, devIdx, portIdx, msgIdx ); +} + +cw::rc_t cw::io::midiFileStart( handle_t h ) +{ + return midi::device::start( _handleToPtr(h)->midiH ); +} + +cw::rc_t cw::io::midiFileStop( handle_t h ) +{ + return midi::device::stop( _handleToPtr(h)->midiH ); +} + +cw::rc_t cw::io::midiFilePause( handle_t h, bool pauseFl ) +{ + return midi::device::pause( _handleToPtr(h)->midiH, pauseFl ); +} + + + //---------------------------------------------------------------------------------------------------------- // // Audio diff --git a/cwIo.h b/cwIo.h index 0137e72..ce2fbdd 100644 --- a/cwIo.h +++ b/cwIo.h @@ -228,6 +228,15 @@ namespace cw const char* midiDevicePortName( handle_t h, unsigned devIdx, bool inputFl, unsigned portIdx ); unsigned midiDevicePortIndex( handle_t h, unsigned devIdx, bool inputFl, const char* portName ); rc_t midiDeviceSend( handle_t h, unsigned devIdx, unsigned portIdx, uint8_t status, uint8_t d0, uint8_t d1 ); + + rc_t midiOpenMidiFile( handle_t h, unsigned devIdx, unsigned portIdx, const char* fname ); + rc_t midiLoadMsgPacket( handle_t h, const midi::packet_t& pkt ); // Note: Set devIdx/portIdx via pkt.devIdx/pkt.portIdx + unsigned midiMsgCount( handle_t h, unsigned devIdx, unsigned portIdx ); + rc_t midiSeekToMsg( handle_t h, unsigned devIdx, unsigned portIdx, unsigned msgIdx ); + rc_t midiSetEndMsg( handle_t h, unsigned devIdx, unsigned portidx, unsigned msgIdx ); + rc_t midiFileStart( handle_t h ); + rc_t midiFileStop( handle_t h ); + rc_t midiFilePause( handle_t h, bool pauseFl ); //----------------------------------------------------------------------------------------------------------