Programmable real-time audio signal processing application
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

kcApp.cpp 60KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526
  1. //| Copyright: (C) 2019-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include <FL/Fl.H>
  4. #include <FL/Fl_Double_Window.H>
  5. #include <FL/Fl_Menu_Item.H>
  6. #include <Fl/Fl_Menu_Bar.H>
  7. #include <Fl/Fl_Button.H>
  8. #include <Fl/Fl_Check_Button.H>
  9. #include <Fl/Fl_Text_Buffer.H>
  10. #include <Fl/Fl_Text_Display.H>
  11. #include <Fl/Fl_Box.H>
  12. #include <Fl/Fl_Tabs.H>
  13. #include <Fl/Fl_File_Chooser.H>
  14. #include <Fl/Fl_Value_Slider.H>
  15. #include <Fl/Fl_Menu_Button.H>
  16. #include <Fl/Fl_Select_Browser.H>
  17. #include <Fl/Fl_Value_Input.H>
  18. #include <Fl/Fl_Progress.H>
  19. #include "Fl_Vert_Progress.h"
  20. #include "Fl_File_Btn.h"
  21. #include "Fl_Splitter.h"
  22. #include "cmGlobal.h"
  23. #include "cmFloatTypes.h"
  24. #include "cmRpt.h"
  25. #include "cmErr.h"
  26. #include "cmCtx.h"
  27. #include "cmMem.h"
  28. #include "cmMallocDebug.h"
  29. #include "cmLinkedHeap.h"
  30. #include "cmText.h"
  31. #include "cmSymTbl.h"
  32. #include "cmJson.h"
  33. #include "cmFileSys.h"
  34. #include "cmPrefs.h"
  35. #include "cmAudioFile.h"
  36. #include "cmThread.h"
  37. #include "cmSymTbl.h"
  38. #include "cmProcTest.h"
  39. #include "cmDspValue.h"
  40. #include "cmMsgProtocol.h"
  41. #include "cmAudDspIF.h"
  42. #include "cmAudDspLocal.h"
  43. #include "cmAudioFile.h"
  44. #include "cmAudioFileMgr.h"
  45. #include "cmTime.h"
  46. #include "cmMidi.h"
  47. #include "cmMidiFile.h"
  48. #include "cmTimeLine.h"
  49. #include "cmScore.h"
  50. #include "cmTakeSeqBldr.h"
  51. #include "cmdIf.h"
  52. #include "tlCtl.h"
  53. #include "kcApp.h"
  54. #include "cmGr.h"
  55. #include "cmGrDevCtx.h"
  56. #include "cmGrPlot.h"
  57. #include "cmGrPage.h"
  58. #include "cmGrFltk.h"
  59. #include "cmGrFltk.h"
  60. #include "gvHashFunc.h"
  61. #include "cmGrTksbFltk.h"
  62. #include "cmGr2dFltk.h"
  63. #define TIMER_PERIOD (1.0/20.0) // 50ms
  64. kcApp::kcApp(cmCtx_t* ctx, cmPrH_t prH, cmTsMp1cH_t printqH, int w, int h, const cmChar_t* title, cmAiH_t aiH, int argc, char* argv[] )
  65. : Fl_Double_Window(w, h,title),
  66. _ctx(ctx),_prH(prH),_aiH(aiH),
  67. _menu(NULL),_con(NULL),_tabs(NULL),_mstr_grp(NULL),
  68. _as_btn(NULL),_ai_btn(NULL),_ao_btn(NULL),_pgm_btn(NULL),
  69. _ss_btn(NULL),_sr_btn(NULL),_ena_chk(NULL),
  70. _pageList(NULL),_ctlList(NULL),
  71. _stopTimerFl(false),_newPageFl(true),
  72. _incrColW(0),_colW(0),_horzBordFl(false),_horzBord(0),
  73. _ssCnt(0),_ssArray(0),_ssPhase(0),_ssUpdateFl(false),
  74. _printqH(printqH),_printFl(0),
  75. _tlCtl(NULL)
  76. {
  77. // install a callback to cleanup when the app window closes
  78. // (the btn callbacks and _getApp() rely on a pointer to 'this' being found in kcApp.user_data())
  79. callback(_s_callback,this);
  80. // the main window is divided between the menu bar on top
  81. // and a horizontal splitter on the bottom
  82. begin();
  83. _createMenu(w,kMenuH);
  84. end();
  85. // Create a tab view
  86. add(_tabs = new Fl_Tabs(this->x(),this->y()+kMenuH,this->w(),this->h()-kMenuH));
  87. _tabs->callback(_s_tab_cb,this);
  88. _tabs->end();
  89. int tx=x(),ty=y(),th=this->h(),tw=this->w();
  90. _tabs->client_area(tx,ty,tw,th);
  91. // Create the 'Setup' tab group
  92. Fl_Group* setup_grp = new Fl_Group(tx,ty,tw,th,"Setup");
  93. _tabs->add(setup_grp);
  94. _createSetupDlg(setup_grp);
  95. // Create the console window
  96. Fl_Group* con_grp = new Fl_Group(tx,ty,tw,th,"Console");
  97. _tabs->add(con_grp);
  98. Fl_Text_Buffer* buf = new Fl_Text_Buffer();
  99. _con = new Fl_Text_Display(tx,ty,tw,th);
  100. _con->buffer(buf);
  101. con_grp->add(_con);
  102. // Create the master group
  103. _tabs->add(_mstr_grp = new Fl_Group(tx,ty,tw,th,"Master"));
  104. // Create an empty tab group and make it resizable
  105. // to prevent the other tab groups from being resizable.
  106. Fl_Group* wdgt = new Fl_Group(tx,ty+30,1,1);
  107. _tabs->add(wdgt);
  108. _tabs->resizable(wdgt); // make other tabs non-resizable
  109. // make the splitter the resizable group element (thereby making the menu non-resizable).
  110. // see:http://fltk.org/articles.php?L415+I0+T+M1000+P1
  111. resizable(_tabs);
  112. show(argc, argv);
  113. // direct all output to the console window
  114. cmRptSetup(&_ctx->rpt,_s_print,_s_print, this);
  115. cmTsMp1cSetCbFunc(_printqH, _s_print_queue_cb, this );
  116. // install a timer to check for messages from the engine
  117. Fl::add_timeout(TIMER_PERIOD,_s_status_timeout_cb,this);
  118. }
  119. kcApp::~kcApp()
  120. {
  121. _clearCtlList(true);
  122. _clearSsArray();
  123. }
  124. void kcApp::resize(int x, int y, int w, int h)
  125. {
  126. Fl_Double_Window::resize(x, y, w, h);
  127. cmPrefsPathSetInt(_prH,"appWndW",w);
  128. cmPrefsPathSetInt(_prH,"appWndH",h);
  129. cmPrefsPathSetInt(_prH,"appWndX",x);
  130. cmPrefsPathSetInt(_prH,"appWndY",y);
  131. }
  132. void kcApp::tlCtlNewTimeLineFile( tlCtl* tlCtl, const cmChar_t* fn )
  133. {}
  134. void kcApp::tlCtlNewScoreFile( tlCtl* tlCtl, const cmChar_t* fn )
  135. {}
  136. void kcApp::_createSetupDlg( Fl_Group* grp )
  137. {
  138. int ctl_width = 200;
  139. int vBord = 5;
  140. int xx = grp->x() + 5;
  141. int yy = grp->y() + vBord;
  142. grp->begin();
  143. Fl_Button* btn = new Fl_Button(xx,yy,200,kMenuH,"Audio Device Report");
  144. btn->callback( _s_btn_cb, kAudDevRptBtnId );
  145. yy += btn->h() + vBord;
  146. _as_btn = new Fl_Menu_Button(xx,yy,ctl_width,kMenuH,"Audio System Cfg");
  147. _as_btn->callback( _s_btn_cb, kAudioSysCfgBtnId);
  148. yy += _as_btn->h() + vBord;
  149. _ai_btn = new Fl_Menu_Button(xx,yy,ctl_width,kMenuH,"Audio Input Devices");
  150. _ai_btn->callback( _s_btn_cb, kInAudDevBtnId);
  151. yy += _ai_btn->h() + vBord;
  152. _ao_btn = new Fl_Menu_Button(xx,yy,ctl_width,kMenuH,"Audio Output Devices");
  153. _ao_btn->callback( _s_btn_cb, kOutAudDevBtnId);
  154. yy += _ao_btn->h() + vBord;
  155. _pgm_btn = new Fl_Menu_Button(xx,yy,ctl_width,kMenuH,"Programs");
  156. _pgm_btn->callback( _s_btn_cb, kPgmBtnId);
  157. yy += _pgm_btn->h() + vBord;
  158. _ss_btn = new Fl_Menu_Button(xx,yy,ctl_width,kMenuH,"Sub-System");
  159. _ss_btn->callback( _s_btn_cb, kSubSystemIdxBtnId);
  160. yy += _ss_btn->h() + vBord;
  161. _sr_btn = new Fl_Menu_Button(xx,yy,ctl_width,kMenuH,"Sample Rate");
  162. _sr_btn->callback( _s_btn_cb, kSrateBtnId);
  163. _sr_btn->add("44100",0,NULL,(void*)44100,0);
  164. _sr_btn->add("48000",0,NULL,(void*)48000,0);
  165. _sr_btn->add("96000",0,NULL,(void*)96000,0);
  166. yy += _sr_btn->h() + vBord;
  167. btn = new Fl_Button(xx,yy,ctl_width,kMenuH,"Test");
  168. btn->callback( _s_btn_cb, kTestBtnId );
  169. yy += btn->h() + vBord;
  170. btn = new Fl_Button(xx,yy,200,kMenuH,"Print program");
  171. btn->callback( _s_btn_cb, kPrintPgmBtnId );
  172. yy += btn->h() + vBord;
  173. _ena_chk = new Fl_Check_Button(xx,yy,ctl_width,kMenuH,"Enable Audio");
  174. _ena_chk->callback( _s_btn_cb, kEnableBtnId );
  175. yy += _ena_chk->h() + vBord;
  176. // place this ctrl in the lower left corner to prevent the other controls from resizing
  177. Fl_Box* bx = new Fl_Box(FL_NO_BOX,xx+ctl_width,yy,10,10,NULL);
  178. grp->resizable(bx);
  179. grp->end();
  180. }
  181. void kcApp::_createMenu(int w, int h)
  182. {
  183. Fl_Menu_Item items[] =
  184. {
  185. { "kc", 0, 0, 0, FL_SUBMENU },
  186. { "&About", FL_COMMAND + 'a', (Fl_Callback*)_s_menu_cb, (void*)kAboutMenuId },
  187. { "&Quit", FL_COMMAND + 'q', (Fl_Callback*)_s_menu_cb, (void*)kQuitMenuId },
  188. { 0 },
  189. { 0 }
  190. };
  191. _menu = new Fl_Menu_Bar(0,0,w,h);
  192. _menu->copy(items);
  193. this->add(_menu);
  194. }
  195. kcApp::page_t* kcApp::_createPage( const char* title )
  196. {
  197. int tx,ty,th,tw;
  198. _tabs->client_area(tx,ty,tw,th);
  199. page_t* page = new page_t;
  200. page->link = _pageList;
  201. _pageList = page;
  202. _newPageFl = true;
  203. // Create the 'Controls' tab group
  204. _tabs->begin();
  205. page->grp = new Fl_Group(tx,ty,tw,th,title);
  206. page->grp->begin();
  207. Fl_Box* bx = new Fl_Box(FL_NO_BOX,page->grp->x()+page->grp->w(),page->grp->y()+page->grp->h(),1,1,NULL);
  208. page->grp->resizable(bx);
  209. page->grp->end();
  210. _tabs->end();
  211. return page;
  212. }
  213. // return the count of engine ctls
  214. unsigned kcApp::_getCtlCount() const
  215. {
  216. unsigned cnt = 0;
  217. ctl_t* cp = _ctlList;
  218. for(; cp!=NULL; cp=cp->linkPtr)
  219. ++cnt;
  220. return cnt;
  221. }
  222. // delete all engine ctls - (except maybe the master ctrl's)
  223. void kcApp::_clearCtlList(bool mstrFl)
  224. {
  225. ctl_t* ncl = NULL;
  226. ctl_t* cp = _ctlList;
  227. while( cp != NULL )
  228. {
  229. ctl_t* np = cp->linkPtr;
  230. // delete the ctrl unless it is a master ctl and the mstrFl is set
  231. if( cp->mstrFl==false || mstrFl )
  232. {
  233. delete cp;
  234. }
  235. else
  236. {
  237. // append the master ctl to the new ctl list
  238. cp->linkPtr = ncl;
  239. ncl = cp;
  240. }
  241. cp = np;
  242. }
  243. // clear the page groups and pages
  244. page_t* pg = _pageList;
  245. while( pg != NULL )
  246. {
  247. page_t* np = pg->link;
  248. pg->grp->clear();
  249. delete pg->grp;
  250. delete pg;
  251. pg = np;
  252. }
  253. _pageList = NULL;
  254. //ctl_grp->clear();
  255. _ctlList = ncl; // make the new ctl list the current ctl list
  256. if( mstrFl )
  257. _mstr_grp->clear();
  258. _tlCtl = NULL;
  259. }
  260. void kcApp::_clearSsArray()
  261. {
  262. if( _ssArray != NULL )
  263. {
  264. delete[] _ssArray;
  265. _ssArray = NULL;
  266. }
  267. _ssCnt = 0;
  268. }
  269. // find a engine ui ctl given a dsp instance id
  270. kcApp::ctl_t* kcApp::_findCtl( unsigned instId, unsigned asSubIdx, unsigned mstrFl )
  271. {
  272. ctl_t* cp = _ctlList;
  273. for(; cp!=NULL; cp=cp->linkPtr)
  274. if( cp->instId == instId && cp->asSubIdx==asSubIdx && cp->mstrFl==mstrFl )
  275. return cp;
  276. //printf("not found:0x%x ssi:%i mstr:%i\n",instId,asSubIdx,mstrFl);
  277. return NULL;
  278. }
  279. // calc. the position and size of a new ctl being created
  280. // at the request of the engine
  281. void kcApp::_getNewCtlPosn( const cmDspUiHdr_t* m, int& x, int& y, int& w, int& h )
  282. {
  283. enum { kPageH=700, kCtlH=30, kCtlW=200, kHBord=2, kVBord=2 };
  284. // if this is control is being placed in the 'master' group
  285. if( m->uiId == cmInvalidId )
  286. {
  287. //unsigned devIdx = cmAudioSysUiInstIdToDevIndex(m->instId);
  288. unsigned chIdx = cmAudioSysUiInstIdToChIndex(m->instId);
  289. unsigned outFl = !cmAudioSysUiInstIdToInFlag(m->instId);
  290. unsigned ctlId = cmAudioSysUiInstIdToCtlId(m->instId);
  291. int xOffs = 20;
  292. int yOffs = 100;
  293. int chH = 205;
  294. int chW = 44;
  295. int sldrH = 120;
  296. int sldrW = 20;
  297. int chkH = 20;
  298. int chkW = 35;
  299. x = xOffs + (chIdx * chW);
  300. y = yOffs + (m->asSubIdx * 2 * chH) + (outFl * chH);
  301. switch( ctlId )
  302. {
  303. // slider
  304. case kSliderUiAsId: w=sldrW; h=sldrH; break;
  305. // meter
  306. case kMeterUiAsId: w=sldrW; h=sldrH; x+=sldrW; break;
  307. // mute
  308. case kMuteUiAsId: w=chkW; h=chkH; y+=sldrH + 2; break;
  309. // tone
  310. case kToneUiAsId: w=chkW; h=chkH; y+=sldrH + chkH + 4; break;
  311. // pass
  312. case kPassUiAsId: w=chkW; h=chkH; y+=sldrH + 2*chkH + 6; break;
  313. default:
  314. { assert(0); }
  315. }
  316. return;
  317. }
  318. // if this control is being placed in the 'controls' group
  319. ctl_t* cp = _ctlList;
  320. if( w == 0 )
  321. {
  322. if( _colW == 0 )
  323. _colW = kCtlW;
  324. w = _colW;
  325. }
  326. if( h == 0 )
  327. h = kCtlH;
  328. // skip over controls that are assigned to the 'master' group
  329. while(cp != NULL && cp->mstrFl )
  330. cp = cp->linkPtr;
  331. // if the page list is empty - create a default blank page
  332. if( _pageList == NULL )
  333. _createPage("Controls");
  334. Fl_Group* ctl_grp = _pageList->grp;
  335. // if the ctl list is empty
  336. if( cp == NULL || _newPageFl )
  337. {
  338. _newPageFl = false;
  339. x = kHBord + ctl_grp->x();
  340. y = kVBord + ctl_grp->y();
  341. _horzBord = y;
  342. }
  343. else
  344. {
  345. // if a new horizontal - upper border was requested
  346. if( _horzBordFl )
  347. {
  348. _horzBordFl = false;
  349. // locate the current control with the max bottom coordinate
  350. ctl_t* tp = cp;
  351. if( tp != NULL )
  352. {
  353. int maxY = tp->wdgtPtr->y() + tp->wdgtPtr->h();
  354. while(tp!=NULL)
  355. {
  356. if( tp->mstrFl == false && (tp->wdgtPtr->y() + tp->wdgtPtr->h()) > maxY )
  357. maxY = tp->wdgtPtr->y() + tp->wdgtPtr->h();
  358. tp = tp->linkPtr;
  359. }
  360. // set the new upper boundary to just below the bottom of
  361. // the lowest control
  362. _horzBord = maxY + kVBord*2;
  363. }
  364. x = kHBord + ctl_grp->x();
  365. y = _horzBord;
  366. }
  367. else
  368. {
  369. // use the last ctl inserted in the list
  370. // (the first ctl in the list)
  371. // to position the next ctl
  372. x = cp->wdgtPtr->x();
  373. y = cp->wdgtPtr->y() + cp->wdgtPtr->h() + kVBord;
  374. // if this control goes off the page or a new col was requested
  375. if( y+h > kPageH || _incrColW )
  376. {
  377. x += _colW + kHBord;
  378. _colW = _incrColW;
  379. _incrColW = 0;
  380. y = _horzBord;
  381. }
  382. }
  383. }
  384. }
  385. kcApp::ctl_t* kcApp::_createCtl( const cmDspUiHdr_t* m, unsigned typeId, int& x, int& y, int& w, int& h, bool posnFl )
  386. {
  387. ctl_t* cp = new ctl_t;
  388. cp->thisPtr = this;
  389. cp->asSubIdx = m->asSubIdx;
  390. cp->instId = m->instId;
  391. cp->typeId = typeId;
  392. cp->mstrFl = m->uiId == cmInvalidId;
  393. if( posnFl )
  394. _getNewCtlPosn(m,x,y,w,h);
  395. return cp;
  396. }
  397. void kcApp::_insertNewCtl( ctl_t* cp, const cmDspUiHdr_t* m, Fl_Widget* wdgt, unsigned* varIdArray, unsigned varIdCnt )
  398. {
  399. unsigned i;
  400. // _genNewCtlPosn() should have been called before this - where a new page list would have been created.
  401. assert( cp->mstrFl || (cp->mstrFl==false && _pageList != NULL) );
  402. Fl_Group* grp = cp->mstrFl ? _mstr_grp : _pageList->grp;
  403. cp->wdgtPtr = wdgt;
  404. cp->wdgtPtr->callback(_s_ctl_cb, cp );
  405. grp->add(cp->wdgtPtr);
  406. const unsigned* srcVarIdArray = cmDsvUIntCMtx(&m->value);
  407. assert( varIdArray != NULL && cmDsvEleCount(&m->value)==varIdCnt);
  408. for(i=0; i<varIdCnt; ++i)
  409. varIdArray[i] = srcVarIdArray[i];
  410. cp->linkPtr = _ctlList;
  411. _ctlList = cp;
  412. }
  413. // create a slider ctl at the request of the engine
  414. void kcApp::_createSlider( const cmDspUiHdr_t* m )
  415. {
  416. int x,y,w=0,h=0;
  417. ctl_t* cp = _createCtl(m, m->selId==kSliderDuiId? kSldrTypeId : kNumbTypeId, x,y,w,h );
  418. switch(m->selId)
  419. {
  420. case kSliderDuiId:
  421. cp->u.sldr.u.sldr = new Fl_Value_Slider(x,y,w,h);
  422. cp->u.sldr.val = static_cast<Fl_Valuator*>(cp->u.sldr.u.sldr);
  423. cp->u.sldr.u.sldr->type(cp->mstrFl ? FL_VERT_NICE_SLIDER : FL_HOR_NICE_SLIDER);
  424. break;
  425. case kNumberDuiId:
  426. cp->u.sldr.u.numb = new Fl_Value_Input(x,y,w/2,h);
  427. cp->u.sldr.u.numb->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE );
  428. cp->u.sldr.val = static_cast<Fl_Valuator*>(cp->u.sldr.u.numb);
  429. break;
  430. }
  431. _insertNewCtl(cp, m, cp->u.sldr.val, cp->u.sldr.varIdArray, kSldrVarCnt );
  432. }
  433. // handle slider value msg's arriving from the engine
  434. void kcApp::_setSldrValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  435. {
  436. unsigned i=0;
  437. Fl_Valuator* sp = cp->u.sldr.val;
  438. for(i=0; i<kSldrVarCnt; ++i)
  439. if( cp->u.sldr.varIdArray[i] == instVarId )
  440. {
  441. switch(i)
  442. {
  443. case kSldrMinArgIdx:
  444. sp->minimum(cmDsvGetDouble(vp));
  445. //sp->step((sp->maximum()-sp->minimum())/sp->w());
  446. break;
  447. case kSldrMaxArgIdx:
  448. sp->maximum(cmDsvGetDouble(vp));
  449. //sp->step((sp->maximum()-sp->minimum())/sp->w());
  450. break;
  451. case kSldrStpArgIdx:
  452. sp->step(cmDsvGetDouble(vp));
  453. break;
  454. case kSldrValArgIdx:
  455. sp->value(cmDsvGetDouble(vp));
  456. break;
  457. case kSldrLblArgIdx:
  458. {
  459. int ww=0,hh=0;
  460. if( cmDsvStrcz(vp) == NULL )
  461. {
  462. sp->label(NULL);
  463. sp->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER );
  464. }
  465. else
  466. {
  467. sp->copy_label( cmDsvStrcz(vp) );
  468. sp->align(FL_ALIGN_RIGHT);
  469. }
  470. if( cp->typeId == kSldrTypeId )
  471. {
  472. sp->measure_label(ww,hh);
  473. sp->resize( sp->x(), sp->y(), sp->w() - ww, sp->h());
  474. sp->redraw();
  475. }
  476. }
  477. break;
  478. default:
  479. { assert(0); }
  480. }
  481. break;
  482. }
  483. }
  484. void kcApp::_createText( const cmDspUiHdr_t* m )
  485. {
  486. int x,y,w=0,h=0;
  487. ctl_t* cp = _createCtl(m, kTextTypeId, x,y,w,h );
  488. cp->u.text.text = new Fl_Input(x,y,w,h);
  489. cp->u.text.text->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY | FL_WHEN_NOT_CHANGED);
  490. _insertNewCtl(cp, m, cp->u.text.text, cp->u.text.varIdArray, kTextVarCnt );
  491. }
  492. void kcApp::_setTextValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  493. {
  494. unsigned i=0;
  495. Fl_Input* tp = cp->u.text.text;
  496. for(i=0; i<kTextVarCnt; ++i)
  497. if( cp->u.text.varIdArray[i] == instVarId )
  498. {
  499. switch(i)
  500. {
  501. case kTextValArgIdx:
  502. tp->value( cmDsvStrcz(vp));
  503. break;
  504. case kTextLblArgIdx:
  505. {
  506. const char* lbl = cmDsvStrcz(vp);
  507. if( lbl == NULL )
  508. tp->label(NULL);
  509. else
  510. tp->copy_label( lbl );
  511. tp->align(FL_ALIGN_RIGHT);
  512. tp->resize( tp->x(), tp->y(), tp->w()/2, tp->h());
  513. tp->redraw();
  514. }
  515. break;
  516. default:
  517. { assert(0); }
  518. }
  519. }
  520. }
  521. void kcApp::_createFnameCtl( const cmDspUiHdr_t* m )
  522. {
  523. int x,y,w=0,h=0;
  524. ctl_t* cp = _createCtl(m, kFnamTypeId, x,y,w,h );
  525. cp->u.fnam.fnam = new Fl_File_Btn(x,y,w,h);
  526. _insertNewCtl(cp, m, cp->u.fnam.fnam, cp->u.fnam.varIdArray, kFnamVarCnt );
  527. }
  528. void kcApp::_setFnamValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  529. {
  530. unsigned i=0;
  531. Fl_File_Btn* bp = cp->u.fnam.fnam;
  532. for(i=0; i<kFnamVarCnt; ++i)
  533. if( cp->u.fnam.varIdArray[i] == instVarId )
  534. {
  535. switch(i)
  536. {
  537. case kFnamValArgIdx:
  538. assert( cmDsvIsType( vp, kStrzDsvFl ) );
  539. bp->filename( cmDsvStrcz(vp) );
  540. bp->redraw();
  541. break;
  542. case kFnamPatArgIdx:
  543. assert( cmDsvIsType( vp, kStrzDsvFl ) );
  544. bp->pattern_string( cmDsvStrcz(vp) );
  545. break;
  546. case kFnamDirArgIdx:
  547. bp->type( cmDsvBool(vp) ? Fl_File_Btn::kDir_Type_Id : Fl_File_Btn::kFile_Type_Id );
  548. break;
  549. default:
  550. { assert(0); }
  551. }
  552. }
  553. }
  554. void kcApp::_createMlistCtl( const cmDspUiHdr_t* m )
  555. {
  556. const unsigned* varIdArray = cmDsvUIntCMtx(&m->value);
  557. assert( varIdArray != NULL && cmDsvEleCount(&m->value)==kMlstVarCnt);
  558. int x,y,w=0;
  559. int h = varIdArray[kMlstHgtArgIdx];
  560. bool menuBtnFl = h==0;
  561. h = menuBtnFl ? kMenuH : kMenuH * h;
  562. ctl_t* cp = _createCtl(m, kMlstTypeId, x,y,w,h );
  563. Fl_Widget* wdgt;
  564. if(menuBtnFl)
  565. {
  566. cp->u.mlst.mlst = NULL;
  567. wdgt = cp->u.mlst.mbtn = new Fl_Menu_Button(x,y,w,h);
  568. }
  569. else
  570. {
  571. cp->u.mlst.mbtn = NULL;
  572. wdgt = cp->u.mlst.mlst = new Fl_Select_Browser(x,y,w,h);
  573. }
  574. _insertNewCtl(cp, m, wdgt, cp->u.mlst.varIdArray, kMlstVarCnt );
  575. }
  576. kcApp::kcKmRC_t kcApp::_loadMlist( ctl_t* cp, const cmJsonNode_t* np )
  577. {
  578. assert( cmJsonIsArray(np) );
  579. kcKmRC_t rc = kOkKmRC;
  580. unsigned n = cmJsonChildCount(np);
  581. unsigned ri = 0;
  582. // empty the ctl data list
  583. if( cp->u.mlst.mbtn == NULL )
  584. cp->u.mlst.mlst->clear();
  585. else
  586. cp->u.mlst.mbtn->clear();
  587. // for each element (row) in the JSON array
  588. for(ri=0; ri<n && rc==kOkKmRC; ++ri)
  589. {
  590. const cmJsonNode_t* cnp = cmJsonArrayElementC(np,ri);
  591. unsigned m = cmJsonChildCount(cnp);
  592. unsigned bufCharCnt = 511;
  593. cmChar_t buf[ bufCharCnt + 1 ]; // buffer to hold one row of text
  594. cmChar_t* bbp = buf;
  595. cmChar_t* bep = bbp + bufCharCnt;
  596. unsigned j;
  597. buf[0] = 0;
  598. // for each element (column) of row i
  599. for(j=0; j<m; ++j)
  600. {
  601. const cmJsonNode_t* ep = cmJsonArrayElementC(cnp,j);
  602. cmJsRC_t jsRC;
  603. // convert the element to a string
  604. if( (jsRC = cmJsonLeafToString( ep, bbp, bep - bbp )) != kOkJsRC )
  605. {
  606. switch(jsRC)
  607. {
  608. case kBufTooSmallJsRC:
  609. rc = cmErrMsg(&_ctx->err,kMlistLoadFailKmRC,"The msg list line character buffer is too small at JSON array element index %i.",ri);
  610. break;
  611. case kInvalidNodeTypeJsRC:
  612. rc = cmErrMsg(&_ctx->err,kMlistLoadFailKmRC,"The msg list array element at index %i is not a JSON leaf node.",ri);
  613. break;
  614. default:
  615. rc = cmErrMsg(&_ctx->err,kMlistLoadFailKmRC,"JSON to msg list text conversion failed on array element %i.",ri);
  616. break;
  617. }
  618. break;
  619. }
  620. bbp = buf + strlen(buf);
  621. assert(bbp <= bep);
  622. // add the tab column marker
  623. if( j+1 < m )
  624. {
  625. if( bep - bbp < 1 )
  626. rc = cmErrMsg(&_ctx->err,kMlistLoadFailKmRC,"The msg list line buffer is too small.");
  627. else
  628. {
  629. *bbp++ = '\t';
  630. *bbp = 0;
  631. }
  632. }
  633. }
  634. // insert the text for row i and skip the title row
  635. // See the _setMListValue() and _ctl_cb() for the associated index incr/decr.
  636. // so that the engine list indexes and UI list indexes match
  637. if( rc == kOkKmRC && ri > 0)
  638. {
  639. if( cp->u.mlst.mbtn==NULL)
  640. cp->u.mlst.mlst->add(buf);
  641. else
  642. cp->u.mlst.mbtn->add(buf);
  643. }
  644. }
  645. if( rc == kOkKmRC )
  646. if( cp->u.mlst.mbtn != NULL )
  647. {
  648. if( cp->u.mlst.sel < cp->u.mlst.mbtn->size() )
  649. cp->u.mlst.mbtn->label(cp->u.mlst.mbtn->text(cp->u.mlst.sel));;
  650. }
  651. return rc;
  652. }
  653. void kcApp::_setMlistValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  654. {
  655. unsigned i=0;
  656. for(i=0; i<kMlstVarCnt; ++i)
  657. if( cp->u.mlst.varIdArray[i] == instVarId )
  658. {
  659. switch(i)
  660. {
  661. case kMlstHgtArgIdx:
  662. break;
  663. case kMlstSelArgIdx:
  664. {
  665. unsigned idx = cmDsvUInt(vp);
  666. // decr. to account for skipping title row
  667. // (see the complementary incrementn in _ctl_cb())
  668. if( idx > 0 && cp->u.mlst.mbtn!=NULL)
  669. --idx;
  670. if( cp->u.mlst.mbtn==NULL)
  671. cp->u.mlst.mlst->value(idx);
  672. else
  673. {
  674. cp->u.mlst.sel = idx;
  675. if( cp->u.mlst.sel < cp->u.mlst.mbtn->size() )
  676. {
  677. cp->u.mlst.mbtn->value(cp->u.mlst.sel);
  678. cp->u.mlst.mbtn->label( cp->u.mlst.mbtn->text(cp->u.mlst.sel) );
  679. }
  680. }
  681. cp->wdgtPtr->redraw();
  682. }
  683. break;
  684. case kMlstLstArgIdx:
  685. _loadMlist( cp, cmDsvJson(vp) );
  686. break;
  687. default:
  688. { assert(0); }
  689. }
  690. }
  691. }
  692. // create a meter ctl at the request of the engine
  693. void kcApp::_createMeter( const cmDspUiHdr_t* m )
  694. {
  695. int x,y,w=0,h=15;
  696. ctl_t* cp = _createCtl(m,kMetrTypeId, x,y,w,h);
  697. if( cp->mstrFl )
  698. cp->u.metr.prog = new Fl_Vert_Progress(x,y,w,h);
  699. else
  700. cp->u.metr.prog = new Fl_Progress(x,y,w,h);
  701. cp->u.metr.prog->color( fl_rgb_color((unsigned char)256),fl_rgb_color((unsigned char)128));
  702. _insertNewCtl(cp,m,cp->u.metr.prog,cp->u.metr.varIdArray,kMetrVarCnt);
  703. }
  704. // handle meter value msg's arriving from the engine
  705. void kcApp::_setMeterValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  706. {
  707. unsigned i = 0;
  708. Fl_Progress* sp = cp->u.metr.prog;
  709. bool redrawFl = false;
  710. for(i=0; i<kMetrVarCnt; ++i)
  711. if( cp->u.metr.varIdArray[i] == instVarId )
  712. {
  713. switch(i)
  714. {
  715. case kMetrMinArgIdx:
  716. sp->minimum(cmDsvGetDouble(vp));
  717. redrawFl = true;
  718. break;
  719. case kMetrMaxArgIdx:
  720. sp->maximum(cmDsvGetDouble(vp));
  721. redrawFl = true;
  722. break;
  723. case kMetrValArgIdx:
  724. {
  725. double v = cmDsvGetDouble(vp);
  726. if( sp->value() != v )
  727. {
  728. sp->value(v);
  729. redrawFl = true;
  730. }
  731. break;
  732. }
  733. case kMetrLblArgIdx:
  734. {
  735. int ww=0,hh=0;
  736. sp->copy_label( cmDsvStrcz(vp) );
  737. sp->align(FL_ALIGN_RIGHT);
  738. sp->measure_label(ww,hh);
  739. sp->resize( sp->x(), sp->y(), sp->w() - ww, sp->h());
  740. redrawFl = true;
  741. }
  742. break;
  743. default:
  744. { assert(0); }
  745. }
  746. break;
  747. }
  748. if( redrawFl )
  749. sp->redraw();
  750. }
  751. // create a button ctl at the request of the engine
  752. void kcApp::_createButton( const cmDspUiHdr_t* m )
  753. {
  754. int x,y,w=0,h=0;
  755. ctl_t* cp = _createCtl(m,kButnTypeId, x,y,w,h);
  756. cp->u.butn.butn = new Fl_Button(x,y,w,h);
  757. _insertNewCtl(cp,m,cp->u.butn.butn,cp->u.butn.varIdArray,kButnVarCnt);
  758. }
  759. // handle button value msg's arriving from the engine
  760. void kcApp::_setButtonValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  761. {
  762. unsigned i = 0;
  763. Fl_Button* sp = cp->u.butn.butn;
  764. bool redrawFl = false;
  765. for(i=0; i<kButnVarCnt; ++i)
  766. if( cp->u.butn.varIdArray[i] == instVarId )
  767. {
  768. switch(i)
  769. {
  770. case kButnValArgIdx:
  771. cp->u.butn.val = cmDsvGetDouble(vp);
  772. break;
  773. case kButnLblArgIdx:
  774. {
  775. sp->copy_label( cmDsvStrcz(vp) );
  776. redrawFl = true;
  777. }
  778. break;
  779. default:
  780. { assert(0); }
  781. }
  782. break;
  783. }
  784. if( redrawFl )
  785. sp->redraw();
  786. }
  787. // create a button ctl at the request of the engine
  788. void kcApp::_createCheck( const cmDspUiHdr_t* m )
  789. {
  790. int x,y,w=0,h=0;
  791. ctl_t* cp = _createCtl(m,kChckTypeId, x,y,w,h);
  792. cp->u.chck.chck = new Fl_Check_Button(x,y,w,h);
  793. _insertNewCtl(cp,m,cp->u.chck.chck,cp->u.chck.varIdArray,kChckVarCnt);
  794. }
  795. // handle check button value msg's arriving from the engine
  796. void kcApp::_setCheckValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  797. {
  798. unsigned i = 0;
  799. Fl_Button* sp = cp->u.chck.chck;
  800. bool redrawFl = false;
  801. for(i=0; i<kChckVarCnt; ++i)
  802. if( cp->u.chck.varIdArray[i] == instVarId )
  803. {
  804. switch(i)
  805. {
  806. case kChckValArgIdx:
  807. cp->u.chck.val = cmDsvGetDouble(vp);
  808. cp->u.chck.chck->value(cmDsvGetDouble(vp)>0);
  809. break;
  810. case kChckLblArgIdx:
  811. {
  812. int ww=0,hh=0;
  813. sp->copy_label( cmDsvStrcz(vp) );
  814. sp->align(FL_ALIGN_RIGHT);
  815. sp->measure_label(ww,hh);
  816. sp->resize( sp->x(), sp->y(), sp->w() - ww, sp->h());
  817. redrawFl = true;
  818. }
  819. break;
  820. default:
  821. { assert(0); }
  822. }
  823. break;
  824. }
  825. if( redrawFl )
  826. sp->redraw();
  827. }
  828. void kcApp::_createLabel( const cmDspUiHdr_t* m )
  829. {
  830. int x,y,w=0,h=0;
  831. ctl_t* cp = _createCtl(m,kLablTypeId, x,y,w,h);
  832. cp->u.labl.box = new Fl_Box(x,y,w,h);
  833. _insertNewCtl(cp,m,cp->u.labl.box,cp->u.labl.varIdArray,kLablVarCnt);
  834. }
  835. void kcApp::_setLabelValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  836. {
  837. unsigned i = 0;
  838. Fl_Box* sp = cp->u.labl.box;
  839. bool redrawFl = false;
  840. for(i=0; i<kLablVarCnt; ++i)
  841. if( cp->u.labl.varIdArray[i] == instVarId )
  842. {
  843. switch(i)
  844. {
  845. case kLablValArgIdx:
  846. sp->copy_label(cmDsvStrcz(vp));
  847. redrawFl = true;
  848. break;
  849. case kLablAlignArgIdx:
  850. switch( cmDsvUInt(vp) )
  851. {
  852. case kRightAlignDuiId:
  853. sp->align(FL_ALIGN_RIGHT | FL_ALIGN_INSIDE);
  854. break;
  855. case kLeftAlignDuiId:
  856. sp->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
  857. break;
  858. case kCenterAlignDuiId:
  859. sp->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
  860. break;
  861. default:
  862. { assert(0); }
  863. }
  864. redrawFl = true;
  865. break;
  866. default:
  867. {assert(0);}
  868. }
  869. }
  870. if( redrawFl )
  871. sp->redraw();
  872. }
  873. void kcApp::_createTmln( const cmDspUiHdr_t* m )
  874. {
  875. int x,y,w=0,h=0;
  876. page_t* pg = _createPage("TimeLine");
  877. ctl_t* cp = _createCtl(m, kTmlnTypeId, x,y,w,h, true );
  878. w = pg->grp->w();
  879. h = pg->grp->h();
  880. // currently we only support one score control because
  881. // we have not yet implmenented a method of providing
  882. // timer callbacks to a list of UI controls
  883. if( _tlCtl != NULL )
  884. cp->u.tmln.tlctl = _tlCtl;
  885. else
  886. {
  887. _tlCtl = new tlCtl(_ctx,this,_menu,this);
  888. cp->u.tmln.tlctl = _tlCtl;
  889. }
  890. Fl_Widget* wdgt = cp->u.tmln.tlctl->initTimeLineCtlr(x,y,w,h);
  891. _insertNewCtl(cp,m,wdgt,cp->u.tmln.varIdArray,kTmlnVarCnt);
  892. }
  893. void kcApp::_setTmlnValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  894. {
  895. unsigned i=0;
  896. for(i=0; i<kTmlnVarCnt; ++i)
  897. if( cp->u.tmln.varIdArray[i] == instVarId )
  898. {
  899. switch(i)
  900. {
  901. case kTmlnFileArgIdx:
  902. {
  903. const char* fn;
  904. if((fn = cmDsvStrcz(vp)) != NULL )
  905. {
  906. cp->u.tmln.tlctl->openTlFile(fn);
  907. //cp->u.tmln.tlctl->redraw();
  908. }
  909. }
  910. break;
  911. case kTmlnPathArgIdx:
  912. {
  913. const char* path;
  914. if((path = cmDsvStrcz(vp)) != NULL )
  915. {
  916. cp->u.tmln.tlctl->setAudioFilePath(path);
  917. }
  918. }
  919. break;
  920. case kTmlnSelArgIdx:
  921. //tp->value( cmDsvStrcz(vp));
  922. break;
  923. case kTmlnMeasArgIdx:
  924. cp->u.tmln.tlctl->setTimeLineSelectBar( cmDsvUInt(vp));
  925. break;
  926. case kTmlnCursArgIdx:
  927. cp->u.tmln.tlctl->setAudioFileCursor(cmDsvUInt(vp));
  928. break;
  929. default:
  930. { assert(0); }
  931. }
  932. }
  933. }
  934. void kcApp::_createScor( const cmDspUiHdr_t* m )
  935. {
  936. int x,y,w=0,h=0;
  937. page_t* pg = _createPage("Score");
  938. ctl_t* cp = _createCtl(m, kScorTypeId, x,y,w,h, true );
  939. w = pg->grp->w();
  940. h = pg->grp->h();
  941. // currently we only support one score control because
  942. // we have not yet implmenented a method of providing
  943. // timer callbacks to a list of UI controls
  944. if( _tlCtl != NULL )
  945. cp->u.scor.tlctl = _tlCtl;
  946. else
  947. {
  948. _tlCtl = new tlCtl(_ctx,this,_menu,this);
  949. cp->u.scor.tlctl = _tlCtl;
  950. cp->u.scor.smpIdx = cmInvalidIdx;
  951. }
  952. Fl_Widget* wdgt = cp->u.scor.tlctl->initScoreCtlr(x,y,w,h);
  953. _insertNewCtl(cp,m,wdgt,cp->u.scor.varIdArray,kScorVarCnt);
  954. }
  955. void kcApp::_setScorValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  956. {
  957. unsigned i=0;
  958. //tlCtl* tp = cp->u.scor.tlctl;
  959. for(i=0; i<kScorVarCnt; ++i)
  960. if( cp->u.scor.varIdArray[i] == instVarId )
  961. {
  962. switch(i)
  963. {
  964. case kScorSelArgIdx:
  965. //tp->value( cmDsvStrcz(vp));
  966. break;
  967. case kScorFileArgIdx:
  968. {
  969. const char* fn;
  970. if((fn = cmDsvStrcz(vp)) != NULL )
  971. {
  972. cp->u.scor.tlctl->openScoreFile(fn);
  973. //cp->u.scor.tlctl->redraw();
  974. }
  975. }
  976. break;
  977. case kScorSmpIdxArgIdx:
  978. cp->u.scor.smpIdx = cmDsvUInt(vp);
  979. break;
  980. case kScorPitchArgIdx:
  981. cp->u.scor.pitch = cmDsvUInt(vp);
  982. break;
  983. case kScorVelArgIdx:
  984. cp->u.scor.vel = cmDsvUInt(vp);
  985. break;
  986. case kScorEvtIdxArgIdx:
  987. cp->u.scor.evtIdx = cmDsvUInt(vp);
  988. break;
  989. case kScorDynArgIdx:
  990. {
  991. assert(cp->u.scor.evtIdx!=cmInvalidIdx);
  992. _tlCtl->setScoreDynLevel(cp->u.scor.evtIdx,cmDsvUInt(vp));
  993. cp->u.scor.evtIdx = cmInvalidIdx;
  994. }
  995. break;
  996. case kScorLocIdxArgIdx:
  997. {
  998. assert( cp->u.scor.smpIdx != cmInvalidIdx );
  999. cp->u.scor.locIdx = cmDsvUInt(vp);
  1000. _tlCtl->setScoreLocation(cp->u.scor.locIdx,cp->u.scor.smpIdx,cp->u.scor.pitch,cp->u.scor.vel);
  1001. cp->u.scor.smpIdx = cmInvalidIdx;
  1002. }
  1003. break;
  1004. case kScorValTypeArgIdx:
  1005. cp->u.scor.varId = cmDsvUInt(vp);
  1006. break;
  1007. case kScorValueArgIdx:
  1008. _tlCtl->setScoreVarValue(cp->u.scor.locIdx,cp->u.scor.varId, cmDsvDouble(vp));
  1009. break;
  1010. case kScorMeasArgIdx:
  1011. _tlCtl->setScoreSelectBar( cmDsvUInt(vp));
  1012. break;
  1013. default:
  1014. { assert(0); }
  1015. }
  1016. }
  1017. }
  1018. void kcApp::_createTksb( const cmDspUiHdr_t* m )
  1019. {
  1020. int x,y,w=0,h=0;
  1021. page_t* pg = _createPage("Bldr");
  1022. ctl_t* cp = _createCtl(m, kTksbTypeId, x,y,w,h, true );
  1023. w = pg->grp->w();
  1024. h = pg->grp->h();
  1025. // currently we only support one Take sequence builder control because
  1026. // we have not yet implmenented a method of providing
  1027. // timer callbacks to a list of UI controls
  1028. if( _tlCtl != NULL )
  1029. cp->u.tksb.tlctl = _tlCtl;
  1030. else
  1031. {
  1032. _tlCtl = new tlCtl(_ctx,this,_menu,this);
  1033. cp->u.tksb.tlctl = _tlCtl;
  1034. }
  1035. Fl_Widget* wdgt = cp->u.tksb.tlctl->initTakeSeqBldrCtlr(x,y,w,h);
  1036. _insertNewCtl(cp,m,wdgt,cp->u.tksb.varIdArray,kTksbVarCnt);
  1037. }
  1038. void kcApp::_setTksbValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  1039. {
  1040. unsigned i;
  1041. for(i=0; i<kTksbVarCnt; ++i)
  1042. if( cp->u.tksb.varIdArray[i] == instVarId )
  1043. {
  1044. switch(i)
  1045. {
  1046. case kTksbFileArgIdx:
  1047. break;
  1048. case kTksbPtrArgIdx:
  1049. if( _tlCtl != NULL )
  1050. _tlCtl->openTakeSeqBldr(cmDsvPtr(vp));
  1051. break;
  1052. case kTksbSelArgIdx:
  1053. // TODO: call cmGrTksbFltk from here to to animate the time cursor
  1054. // with a new location
  1055. break;
  1056. case kTksbRefreshArgIdx:
  1057. break;
  1058. default:
  1059. { assert(0); }
  1060. }
  1061. }
  1062. }
  1063. void kcApp::_createTksr( const cmDspUiHdr_t* m )
  1064. {
  1065. int x,y,w=0,h=0;
  1066. page_t* pg = _createPage("Rndr");
  1067. ctl_t* cp = _createCtl(m, kTksrTypeId, x,y,w,h, true );
  1068. w = pg->grp->w();
  1069. h = pg->grp->h();
  1070. // currently we only support one Take sequence builder control because
  1071. // we have not yet implmenented a method of providing
  1072. // timer callbacks to a list of UI controls
  1073. if( _tlCtl != NULL )
  1074. cp->u.tksr.tlctl = _tlCtl;
  1075. else
  1076. {
  1077. _tlCtl = new tlCtl(_ctx,this,_menu,this);
  1078. cp->u.tksr.tlctl = _tlCtl;
  1079. }
  1080. Fl_Widget* wdgt = cp->u.tksr.tlctl->initTakeSeqRendCtlr(x,y,w,h);
  1081. _insertNewCtl(cp,m,wdgt,cp->u.tksr.varIdArray,kTksrVarCnt);
  1082. }
  1083. void kcApp::_setTksrValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  1084. {
  1085. unsigned i;
  1086. for(i=0; i<kTksrVarCnt; ++i)
  1087. if( cp->u.tksr.varIdArray[i] == instVarId )
  1088. {
  1089. switch(i)
  1090. {
  1091. case kTksrPtrArgIdx:
  1092. if( _tlCtl != NULL )
  1093. _tlCtl->openTakeSeqRend(cmDsvPtr(vp));
  1094. break;
  1095. case kTksrRefreshArgIdx:
  1096. if( _tlCtl != NULL )
  1097. _tlCtl->refreshTakeSeqRend();
  1098. break;
  1099. case kTksrSelArgIdx:
  1100. break;
  1101. default:
  1102. { assert(0); }
  1103. }
  1104. }
  1105. }
  1106. void kcApp::_createTwod( const cmDspUiHdr_t* m )
  1107. {
  1108. int x,y,w=0,h=0;
  1109. page_t* pg = _createPage("2-D");
  1110. ctl_t* cp = _createCtl(m, kTwodTypeId, x,y,w,h, true );
  1111. w = pg->grp->w();
  1112. h = pg->grp->h();
  1113. // currently we only support one Take sequence builder control because
  1114. // we have not yet implmenented a method of providing
  1115. // timer callbacks to a list of UI controls
  1116. if( _tlCtl != NULL )
  1117. cp->u.twod.tlctl = _tlCtl;
  1118. else
  1119. {
  1120. _tlCtl = new tlCtl(_ctx,this,_menu,this);
  1121. cp->u.twod.tlctl = _tlCtl;
  1122. }
  1123. Fl_Widget* wdgt = cp->u.twod.tlctl->init2dCtlr(x,y,w,h);
  1124. _insertNewCtl(cp,m,wdgt,cp->u.twod.varIdArray,kTwodVarCnt);
  1125. }
  1126. void kcApp::_setTwodValue( ctl_t* cp, unsigned instVarId, const cmDspValue_t* vp )
  1127. {
  1128. unsigned i;
  1129. for(i=0; i<kTwodVarCnt; ++i)
  1130. if( cp->u.twod.varIdArray[i] == instVarId )
  1131. {
  1132. switch(i)
  1133. {
  1134. case kTwodXArgIdx:
  1135. case kTwodYArgIdx:
  1136. case kTwodAngleArgIdx:
  1137. case kTwodRadiusArgIdx:
  1138. break;
  1139. default:
  1140. { assert(0); }
  1141. }
  1142. }
  1143. }
  1144. void kcApp::_newColumn( const cmDspUiHdr_t* m )
  1145. {
  1146. _incrColW = cmDsvGetUInt(&m->value);
  1147. if( _incrColW == 0 )
  1148. _incrColW = 200;
  1149. }
  1150. void kcApp::_insertAudioSysCfgLabel(unsigned long idx, const char* label)
  1151. {
  1152. if( idx == 0 )
  1153. _as_btn->clear();
  1154. _as_btn->add(label,0,NULL,(void*)idx,0);
  1155. }
  1156. void kcApp::_setDfltAudioSysCfg(unsigned long idx, const char* label )
  1157. {
  1158. int i;
  1159. if((i = _as_btn->find_index(label)) != -1 )
  1160. {
  1161. _setMenuButton(_as_btn,i,"Audio System Cfg");
  1162. cmAdIfSetAudioSysCfg(_aiH,_as_btn->mvalue()->argument());
  1163. }
  1164. }
  1165. void kcApp::_insertDeviceLabel( unsigned long devIdx, bool inputFl, const cmChar_t* label )
  1166. {
  1167. Fl_Menu_Button* bp = inputFl ? _ai_btn : _ao_btn;
  1168. // ??? if( idx == 0 )
  1169. // bp->clear();
  1170. bp->add(label,0,NULL,(void*)devIdx,0);
  1171. }
  1172. void kcApp::_insertProgramLabel( unsigned long idx, const cmChar_t* label )
  1173. {
  1174. if( idx == 0 )
  1175. _pgm_btn->clear();
  1176. _pgm_btn->add(label,0,NULL,(void*)idx,0);
  1177. }
  1178. void kcApp::_setDfltProgram(unsigned long idx, const char* label )
  1179. {
  1180. int i;
  1181. if((i = _pgm_btn->find_index(label)) != -1 )
  1182. {
  1183. _setMenuButton(_pgm_btn,i,"Programs");
  1184. cmAdIfLoadProgram(_aiH,_getCurAudioSubSysIdx(),_pgm_btn->mvalue()->argument());
  1185. }
  1186. }
  1187. void kcApp::_insertSubSysCnt( unsigned long subSysCnt )
  1188. {
  1189. long unsigned i;
  1190. int bufByteCnt = 15;
  1191. char buf[bufByteCnt+1];
  1192. for(i=0; i<subSysCnt+1; ++i)
  1193. {
  1194. const char* label;
  1195. unsigned long id;
  1196. if( i==0 )
  1197. {
  1198. label = "All";
  1199. id = cmInvalidIdx;
  1200. }
  1201. else
  1202. {
  1203. snprintf(buf,bufByteCnt,"%li",i);
  1204. label = buf;
  1205. id = i-1;
  1206. }
  1207. _ss_btn->add(label,0,NULL,(void*)id);
  1208. }
  1209. _ss_btn->value(0);
  1210. _ss_btn->copy_label( _ss_btn->mvalue()->label() );
  1211. }
  1212. unsigned kcApp::_getCurAudioSubSysIdx()
  1213. {
  1214. const Fl_Menu_Item* mip;
  1215. unsigned retVal = 0;
  1216. if( (mip = _ss_btn->mvalue()) != NULL)
  1217. retVal = mip->argument();
  1218. return retVal;
  1219. }
  1220. void kcApp::_setMenuButton( Fl_Menu_Button* b, unsigned value, const char* dfltLabel )
  1221. {
  1222. const Fl_Menu_Item* mip;
  1223. bool fl = value != cmInvalidIdx;
  1224. // if value is a valid menu index then make it the current menu selection
  1225. if( fl )
  1226. b->value(value);
  1227. // get the new current menu item and set its label
  1228. if( (mip = b->mvalue()) != NULL )
  1229. b->copy_label( fl ? mip->label() : dfltLabel );
  1230. }
  1231. void kcApp::_setDeviceMenuButton( unsigned asSubIdx, bool inputFl, unsigned devIdx )
  1232. {
  1233. // don't set the device name if the currenly selected sub-system is not the
  1234. // same as the one the device is assigned to
  1235. if( _getCurAudioSubSysIdx() != asSubIdx )
  1236. return;
  1237. Fl_Menu_Button* mbp = inputFl ? _ai_btn : _ao_btn;
  1238. const Fl_Menu_Item* map = mbp->menu();
  1239. unsigned n = mbp->size();
  1240. unsigned i;
  1241. char* di = 0; di += devIdx; // BEWARE: devious int to ptr trick
  1242. for(i=0; i<n; ++i)
  1243. if( map[i].user_data() == di )
  1244. break;
  1245. if( i < n )
  1246. {
  1247. _setMenuButton(mbp,i,"<not found>");
  1248. }
  1249. }
  1250. void kcApp::_setSampleRateBtn( unsigned value )
  1251. {
  1252. unsigned i;
  1253. unsigned n = _sr_btn->size();
  1254. for(i=0; i<n-1; ++i)
  1255. {
  1256. if( _sr_btn->menu()[i].argument() == (int)value )
  1257. {
  1258. _sr_btn->value(i);
  1259. _sr_btn->copy_label( _sr_btn->mvalue()->label() );
  1260. return;
  1261. }
  1262. }
  1263. _sr_btn->copy_label("Sample Rate?");
  1264. }
  1265. void kcApp::_updateMeters( unsigned asSubIdx, unsigned devIdx, unsigned inFl, const double* meterArray, unsigned meterCnt )
  1266. {
  1267. unsigned i;
  1268. for(i=0; i<meterCnt; ++i)
  1269. {
  1270. ctl_t* cp;
  1271. cmDspValue_t v;
  1272. unsigned instId = cmAudioSysFormUiInstId(devIdx,i,inFl,kMeterUiAsId);
  1273. if((cp = _findCtl(instId,asSubIdx,true)) != NULL )
  1274. {
  1275. cmDsvSetDouble(&v,meterArray[i]);
  1276. _setMeterValue(cp, kMetrValArgIdx, &v);
  1277. }
  1278. }
  1279. }
  1280. void kcApp::_printStatusCounts()
  1281. {
  1282. const ss_t* ssp = _ssArray;
  1283. printf("Upd:%i Wake:%i Msg:%i Audio:%i\n",ssp->cnt[kUpdateSsIdx],ssp->cnt[kWakeupSsIdx],ssp->cnt[kMsgSsIdx],ssp->cnt[kAudioCbSsIdx]);
  1284. }
  1285. void kcApp::_updateSsStatusIndicator( unsigned asSubIdx, unsigned indicatorIdx, unsigned cnt )
  1286. {
  1287. ss_t* ss = _ssArray + asSubIdx;
  1288. float val = ss->cnt[indicatorIdx] != cnt;
  1289. ss->cnt[indicatorIdx] = cnt;
  1290. if( ss->prog[indicatorIdx]->value() != val )
  1291. {
  1292. ss->prog[indicatorIdx]->value(val);
  1293. ss->prog[indicatorIdx]->redraw();
  1294. }
  1295. }
  1296. void kcApp::_handleStatusMsg(const cmAudioSysStatus_t* st, const double* iMeterArray, const double* oMeterArray )
  1297. {
  1298. //unsigned asSubIdx = ((const unsigned*)msgBuf)[0];
  1299. //const cmAudioSysStatus_t* st = (const cmAudioSysStatus_t*)(msgBuf + (2 * sizeof(unsigned)));
  1300. //const double* iMeterArray = (const double*)(st + 1);
  1301. //const double* oMeterArray = iMeterArray + st->iMeterCnt;
  1302. _updateMeters(st->asSubIdx, st->iDevIdx,1,iMeterArray,st->iMeterCnt);
  1303. _updateMeters(st->asSubIdx, st->oDevIdx,0,oMeterArray,st->oMeterCnt);
  1304. assert( st->asSubIdx < _ssCnt );
  1305. _updateSsStatusIndicator(st->asSubIdx, kUpdateSsIdx, st->updateCnt );
  1306. _updateSsStatusIndicator(st->asSubIdx, kWakeupSsIdx, st->wakeupCnt );
  1307. _updateSsStatusIndicator(st->asSubIdx, kMsgSsIdx, st->msgCbCnt );
  1308. _updateSsStatusIndicator(st->asSubIdx, kAudioCbSsIdx,st->audioCbCnt );
  1309. }
  1310. void kcApp::_clearStatusIndicators()
  1311. {
  1312. for(unsigned i=0; i<_ssCnt; ++i)
  1313. {
  1314. _updateSsStatusIndicator(i, kUpdateSsIdx, _ssArray[i].cnt[kUpdateSsIdx] );
  1315. _updateSsStatusIndicator(i, kWakeupSsIdx, _ssArray[i].cnt[kWakeupSsIdx] );
  1316. _updateSsStatusIndicator(i, kMsgSsIdx, _ssArray[i].cnt[kMsgSsIdx] );
  1317. _updateSsStatusIndicator(i, kAudioCbSsIdx,_ssArray[i].cnt[kAudioCbSsIdx] );
  1318. }
  1319. }
  1320. // Create a master control UI msg and send it to _handleUiMsg(). This function is intended to
  1321. // mimic the reception of a cmDspUiHdr_t msg from the audio system. It is used to create
  1322. // and send values to the controls on the master page.
  1323. void kcApp::_sendMasterUiMsg( unsigned asSubIdx, unsigned selId, unsigned instId, unsigned instVarId, const cmDspValue_t* vp )
  1324. {
  1325. // Determine the size of the message buffer
  1326. unsigned valByteCnt = cmDsvSerialDataByteCount(vp);
  1327. unsigned bufByteCnt = sizeof(cmDspUiHdr_t) + valByteCnt;
  1328. char buf[ bufByteCnt ];
  1329. cmDspUiHdr_t* h = (cmDspUiHdr_t*)buf;
  1330. h->asSubIdx = asSubIdx;
  1331. h->uiId = cmInvalidId; // the uiId field of master controls is always set to cmInvalidId
  1332. h->selId = selId;
  1333. h->flags = 0;
  1334. h->instId = instId;
  1335. h->instVarId = instVarId;
  1336. // Serialize 'v' into the buffer beginning at the address of h->value.
  1337. // (this function relies on the 'hdr.value' field being the last field in 'h')
  1338. cmDsvSerialize( vp, &h->value, sizeof(cmDspValue_t) + valByteCnt);
  1339. _handleUiMsg(h);
  1340. }
  1341. // Send a value to a control on the master page.
  1342. void kcApp::_sendMasterUiValue( unsigned asSubIdx, unsigned instId, const double* v, unsigned vn, const cmChar_t* text )
  1343. {
  1344. cmDspValue_t val;
  1345. unsigned i;
  1346. for(i=0; i<vn; ++i)
  1347. {
  1348. cmDsvSetDouble(&val,v[i]);
  1349. _sendMasterUiMsg(asSubIdx, kValueDuiId, instId, i, &val );
  1350. }
  1351. if( text != NULL )
  1352. {
  1353. cmDsvSetStrcz(&val,text);
  1354. _sendMasterUiMsg(asSubIdx, kValueDuiId, instId, i, &val );
  1355. }
  1356. }
  1357. // Create a control on the master page.
  1358. void kcApp::_createMasterCtl( unsigned asSubIdx, unsigned selId, unsigned instId, unsigned varCnt, const double* dv, unsigned dn, const cmChar_t* label)
  1359. {
  1360. // Create the control variable id array.
  1361. // This array gives the id's used to identify each control variable.
  1362. unsigned varIdArray[ varCnt ];
  1363. unsigned i;
  1364. cmDspValue_t v;
  1365. // Set the var id's for master controls to be the same as the var indexes.
  1366. for(i=0; i<varCnt; ++i)
  1367. varIdArray[i] = i;
  1368. // Encode varIdArray[] as a cmDsvValue.
  1369. cmDsvSetUIntMtx(&v,varIdArray,varCnt,1);
  1370. // create the control
  1371. _sendMasterUiMsg(asSubIdx, selId, instId, cmInvalidId, &v );
  1372. // set the controls initial configuration
  1373. _sendMasterUiValue(asSubIdx, instId, dv, dn, label );
  1374. }
  1375. void kcApp::_handleSsInitMsg( const cmAudioSysSsInitMsg_t* m, const cmChar_t* inDevLabel, const cmChar_t* outDevLabel )
  1376. {
  1377. unsigned i,j;
  1378. if( _ssCnt == 0 )
  1379. {
  1380. _clearSsArray();
  1381. _ssCnt = m->asSubCnt;
  1382. _ssArray = new ss_t[ _ssCnt ];
  1383. }
  1384. assert( m->asSubIdx < _ssCnt );
  1385. ss_t* ss = _ssArray + m->asSubIdx;
  1386. int x = 20;
  1387. int y = 30 + kMenuH;
  1388. int w = 80;
  1389. int h = 20;
  1390. char lblArray[][10] = { "Update","Wakeup","Mesg","Audio" };
  1391. // create the sub-system status indicators
  1392. for(i=0; i<kProgSsCnt; ++i)
  1393. {
  1394. Fl_Progress* prog = new Fl_Progress(x,y,w,h,NULL);
  1395. prog->color( FL_RED, FL_GREEN );
  1396. prog->minimum(0);
  1397. prog->maximum(1);
  1398. prog->copy_label(lblArray[i]);
  1399. _mstr_grp->add(prog);
  1400. ss->cnt[i] = 0;
  1401. ss->prog[i] = prog;
  1402. x += ss->prog[i]->w() + 4;
  1403. }
  1404. for(i=0; i<2; ++i)
  1405. {
  1406. unsigned inFl = i==0;
  1407. unsigned chCnt = inFl ? m->inChCnt : m->outChCnt;
  1408. unsigned devIdx = inFl ? m->inDevIdx : m->outDevIdx;
  1409. double zero = 0;
  1410. for(j=0; j<chCnt; ++j)
  1411. {
  1412. // there are limits on the ranges of the dev and ch due to the need to pack dev/ch/infl/ctl into a 32 bit int.
  1413. assert( devIdx < 0xffff && j < 0x0fff);
  1414. unsigned instId = cmAudioSysFormUiInstId(devIdx,j,inFl,0);
  1415. //printf("ssi:%i instId:0x%x\n",m->asSubIdx,instId+kMeterUiAsId);
  1416. // create the volume slider
  1417. double sv[] = { 3, 0, 0.01, 1 };
  1418. unsigned sn = sizeof(sv)/sizeof(sv[0]);
  1419. _createMasterCtl( m->asSubIdx, kSliderDuiId, instId + kSliderUiAsId, kSldrVarCnt, sv, sn, NULL);
  1420. // create the meter
  1421. double mv[] = { 0, 1.0, 0 };
  1422. unsigned mn = sizeof(mv)/sizeof(mv[0]);
  1423. _createMasterCtl( m->asSubIdx, kMeterDuiId, instId + kMeterUiAsId, kMetrVarCnt, mv, mn, NULL);
  1424. // create the mute button
  1425. _createMasterCtl( m->asSubIdx, kCheckDuiId, instId + kMuteUiAsId, kChckVarCnt, &zero, 1, "M");
  1426. // create the tone button
  1427. _createMasterCtl( m->asSubIdx, kCheckDuiId, instId + kToneUiAsId, kChckVarCnt, &zero, 1, "T");
  1428. // create the pass button
  1429. _createMasterCtl( m->asSubIdx, kCheckDuiId, instId + kPassUiAsId, kChckVarCnt, &zero, 1, "P");
  1430. }
  1431. }
  1432. }
  1433. // handle kValueDuiId messages coming from the engine
  1434. void kcApp::_onRecvValue( const cmDspUiHdr_t* m )
  1435. {
  1436. ctl_t* cp;
  1437. if((cp = _findCtl(m->instId,m->asSubIdx,m->uiId==cmInvalidId)) == NULL )
  1438. return;
  1439. switch( cp->typeId )
  1440. {
  1441. case kNumbTypeId:
  1442. case kSldrTypeId:
  1443. _setSldrValue(cp, m->instVarId, &m->value );
  1444. break;
  1445. case kTextTypeId:
  1446. _setTextValue(cp, m->instVarId, &m->value );
  1447. break;
  1448. case kButnTypeId:
  1449. _setButtonValue(cp, m->instVarId, &m->value);
  1450. break;
  1451. case kChckTypeId:
  1452. _setCheckValue(cp, m->instVarId, &m->value);
  1453. break;
  1454. case kLablTypeId:
  1455. _setLabelValue(cp, m->instVarId, &m->value);
  1456. break;
  1457. case kFnamTypeId:
  1458. _setFnamValue(cp, m->instVarId, &m->value);
  1459. break;
  1460. case kMlstTypeId:
  1461. _setMlistValue(cp, m->instVarId, &m->value);
  1462. break;
  1463. case kMetrTypeId:
  1464. _setMeterValue(cp, m->instVarId, &m->value);
  1465. break;
  1466. case kTmlnTypeId:
  1467. _setTmlnValue(cp, m->instVarId, &m->value);
  1468. break;
  1469. case kScorTypeId:
  1470. _setScorValue(cp, m->instVarId, &m->value);
  1471. break;
  1472. case kTksbTypeId:
  1473. _setTksbValue(cp, m->instVarId, &m->value);
  1474. break;
  1475. case kTksrTypeId:
  1476. _setTksrValue(cp, m->instVarId, &m->value);
  1477. break;
  1478. case kTwodTypeId:
  1479. _setTwodValue(cp, m->instVarId, &m->value);
  1480. break;
  1481. default:
  1482. assert(0);
  1483. }
  1484. }
  1485. // This is the main UI<-Engine msg handler/dispatch function
  1486. void kcApp::_handleUiMsg( const cmDspUiHdr_t* m )
  1487. {
  1488. switch( m->selId )
  1489. {
  1490. case kPrintDuiId:
  1491. cmDsvPrint(&m->value,NULL,&_ctx->rpt);
  1492. break;
  1493. case kNumberDuiId:
  1494. case kSliderDuiId:
  1495. _createSlider(m);
  1496. break;
  1497. case kTextDuiId:
  1498. _createText(m);
  1499. break;
  1500. case kButtonDuiId:
  1501. _createButton(m);
  1502. break;
  1503. case kLabelDuiId:
  1504. _createLabel(m);
  1505. break;
  1506. case kCheckDuiId:
  1507. _createCheck(m);
  1508. break;
  1509. case kFnameDuiId:
  1510. _createFnameCtl(m);
  1511. break;
  1512. case kMsgListDuiId:
  1513. _createMlistCtl(m);
  1514. break;
  1515. case kMeterDuiId:
  1516. _createMeter(m);
  1517. break;
  1518. case kTimeLineDuiId:
  1519. _createTmln(m);
  1520. break;
  1521. case kScoreDuiId:
  1522. _createScor(m);
  1523. break;
  1524. case kTakeSeqBldrDuiId:
  1525. _createTksb(m);
  1526. break;
  1527. case kTakeSeqRendDuiId:
  1528. _createTksr(m);
  1529. break;
  1530. case kTwodDuiId:
  1531. _createTwod(m);
  1532. break;
  1533. case kValueDuiId:
  1534. _onRecvValue(m);
  1535. break;
  1536. case kColumnDuiId:
  1537. _newColumn(m);
  1538. break;
  1539. case kHBorderDuiId:
  1540. _horzBordFl = true;
  1541. break;
  1542. case kPageDuiId:
  1543. _createPage(cmDsvStrcz(&m->value));
  1544. break;
  1545. case kAudioSysCfgDuiId:
  1546. _insertAudioSysCfgLabel(m->instId,cmDsvStrcz(&m->value));
  1547. break;
  1548. case kAudioSysCfgDfltDuiId:
  1549. _setDfltAudioSysCfg(m->instId,cmDsvStrcz(&m->value));
  1550. break;
  1551. case kDeviceDuiId:
  1552. _insertDeviceLabel(m->instId,m->flags,cmDsvStrcz(&m->value));
  1553. break;
  1554. case kProgramDuiId:
  1555. _insertProgramLabel(m->instId,cmDsvStrcz(&m->value));
  1556. break;
  1557. case kProgramDfltDuiId:
  1558. _setDfltProgram(m->instId,cmDsvStrcz(&m->value));
  1559. break;
  1560. // the below codes are used to notify the application
  1561. // of changes in state of the audio DSP system
  1562. case kSubSysCntDuiId:
  1563. _insertSubSysCnt(cmDsvUInt(&m->value));
  1564. break;
  1565. case kSetAudioCfgDuiId:
  1566. _setMenuButton(_as_btn,cmDsvUInt(&m->value),"Audio System Cfg");
  1567. break;
  1568. case kSetAudioDevDuiId:
  1569. _setDeviceMenuButton( m->asSubIdx, m->flags, cmDsvUInt(&m->value) );
  1570. break;
  1571. case kSetSampleRateDuiId:
  1572. _setSampleRateBtn(cmDsvUInt(&m->value));
  1573. break;
  1574. case kSetPgmDuiId:
  1575. _setMenuButton(_pgm_btn,cmDsvUInt(&m->value),"Program?");
  1576. _clearCtlList(false);
  1577. break;
  1578. case kEnableDuiId:
  1579. _ena_chk->value(m->flags);
  1580. break;
  1581. }
  1582. }
  1583. // Check for and forward any messages sent to the UI
  1584. // that are waiting in the audio DSP msg queue.
  1585. void kcApp::_getEngMsg()
  1586. {
  1587. if( cmAdIfIsValid(_aiH) )
  1588. {
  1589. unsigned i;
  1590. for(i=0; i<10; ++i)
  1591. {
  1592. cmAiRC_t aiRC;
  1593. // cmAdIfDispatchMsgToHost() results in calls to
  1594. // the _s_handleXXX() message handlers
  1595. if((aiRC = cmAdIfDispatchMsgToHost(_aiH)) != kOkAiRC)
  1596. {
  1597. if( aiRC == kNoMsgAiRC )
  1598. break;
  1599. cmErrMsg(&_ctx->err,kEngFailKmRC,"Audio DSP dispatch message request failed.");
  1600. break;
  1601. }
  1602. }
  1603. }
  1604. }
  1605. kcApp* kcApp::_getApp( Fl_Widget* w )
  1606. {
  1607. // walk up the widget tree until the top widget is found
  1608. Fl_Group* gp = w->parent();
  1609. while( gp->parent() != NULL )
  1610. gp=gp->parent();
  1611. // the user data for the top widget is a pointer kcApp()
  1612. return (kcApp*)gp->user_data();
  1613. }
  1614. void kcApp::_onCloseApp()
  1615. {
  1616. if( _tlCtl != NULL )
  1617. {
  1618. delete _tlCtl;
  1619. _tlCtl = NULL;
  1620. }
  1621. _stopTimerFl = true;
  1622. // When all windows are windows are closed then the app.
  1623. // will close - so hiding the application window
  1624. // causes the program to close.
  1625. //
  1626. // Note that simply returning from this callback will
  1627. // prevent the application from closing. Because the existence
  1628. // of the callback alone is enough to disable default
  1629. // event handling.
  1630. hide();
  1631. }
  1632. void kcApp::_testStub()
  1633. {
  1634. /*
  1635. cmAudioFileTest(
  1636. // "/Users/kevin/media/audio/20100819-Kreisberg/fragments/Bass End_21a.wav",
  1637. "/Users/kevin/media/audio/McGill-1/1 Audio Track.aiff",
  1638. "/Users/kevin/src/octave/cm_audio_file_test.m",_ctx->err.rpt );
  1639. */
  1640. //cmSymTblTest(&_ctx);
  1641. //_kcTranslateFile("/Users/kevin/src/kc/src/data/Sec1_14.txt","/Users/kevin/src/kc/src/data/Sec1_14_out.txt",&_ctx);
  1642. //_kcTranslateFile("/Users/kevin/src/kc/src/data/Mix_17-20.txt","/Users/kevin/src/kc/src/data/Mix_17-20_out.txt",&_ctx);
  1643. /*
  1644. ctl_t* cp = _ctlList;
  1645. for(; cp!=NULL; cp=cp->linkPtr)
  1646. printf("%i %i %i\n", cp->instId,cp->asSubIdx,cp->mstrFl );
  1647. */
  1648. //_printStatusCounts();
  1649. //cmProcTestNoInit(&_ctx);
  1650. _tlCtl->testStub();
  1651. }
  1652. void kcApp::_printPgm()
  1653. {
  1654. const char* pathStr = cmFsUserDir(); // make the default dir the user's home dir
  1655. const char patStr[] = ""; //"Text Files (*.txt)\tAudio Files (*.{wav,aif,aiff})"; // All Files (*.*) is append to this automatically
  1656. const char titleStr[] = "JSON output file name";
  1657. Fl_File_Chooser fc = Fl_File_Chooser(pathStr,patStr,Fl_File_Chooser::CREATE,titleStr);
  1658. fc.preview(0); // default the previous option to 'off'.
  1659. fc.show(); // show the chooser
  1660. // make the chooser modal
  1661. while( fc.shown() )
  1662. Fl::wait();
  1663. if( fc.count() > 0)
  1664. cmAdIfPrintPgm(_aiH, cmInvalidIdx, fc.value(0) );
  1665. }
  1666. void kcApp::_s_callback(Fl_Widget* wp, void* data)
  1667. { ((kcApp*)data)->_callback(NULL); }
  1668. // this callback is called when the window is closing
  1669. void kcApp::_callback(void* data)
  1670. {
  1671. if( Fl::event() == FL_CLOSE )
  1672. {
  1673. _onCloseApp();
  1674. }
  1675. }
  1676. void kcApp::_s_status_timeout_cb(void* userPtr)
  1677. {
  1678. if( ((kcApp*)userPtr)->_status_timeout_cb() )
  1679. Fl::repeat_timeout(TIMER_PERIOD,_s_status_timeout_cb,userPtr);
  1680. }
  1681. bool kcApp::_status_timeout_cb()
  1682. {
  1683. if( cmTsMp1cIsValid(_printqH) )
  1684. _checkPrintQueue();
  1685. if( !_stopTimerFl )
  1686. {
  1687. _getEngMsg();
  1688. if( _tlCtl != NULL )
  1689. _tlCtl->onIdle();
  1690. }
  1691. if( _ssUpdateFl )
  1692. {
  1693. ++_ssPhase;
  1694. if( _ssPhase >= kSsPhaseMax )
  1695. {
  1696. _clearStatusIndicators();
  1697. _ssPhase = 0;
  1698. }
  1699. }
  1700. if( _stopTimerFl==false && cmAdIfIsValid(_aiH) )
  1701. cmAdIfDispatchMsgToHost(_aiH);
  1702. //if( !_stopTimerFl )
  1703. // _getEngStatus();
  1704. return _stopTimerFl==false || cmTsMp1cIsValid(_printqH);
  1705. }
  1706. void kcApp::_s_menu_cb(Fl_Widget *w, void *data)
  1707. {
  1708. const Fl_Menu_Item* mip;
  1709. kcApp* p;
  1710. if((p=_getApp(w)) == NULL )
  1711. return;
  1712. if((mip = p->_menu->mvalue()) == NULL )
  1713. return;
  1714. unsigned id = (long int)mip->user_data();
  1715. switch(id)
  1716. {
  1717. case kAboutMenuId:
  1718. fl_message("%s Compiled:%s %s",PACKAGE_STRING,__DATE__,__TIME__);
  1719. break;
  1720. case kQuitMenuId:
  1721. p->_onCloseApp();
  1722. break;
  1723. }
  1724. }
  1725. void kcApp::_s_tab_cb(Fl_Widget* w, void* data)
  1726. { ((kcApp*)data)->_tab_cb(w); }
  1727. void kcApp::_tab_cb(Fl_Widget*)
  1728. {
  1729. Fl_Widget* w = _tabs->value();
  1730. _ssUpdateFl = w == (Fl_Widget*)_mstr_grp;
  1731. _ssPhase = kSsPhaseMax;
  1732. if( cmAdIfIsValid(_aiH) )
  1733. {
  1734. if( cmAdIfEnableStatusNotify(_aiH, _ssUpdateFl ) != kOkAiRC )
  1735. cmErrMsg(&_ctx->err,kEngFailKmRC,"A request to enable/disable status notification failed.");
  1736. }
  1737. }
  1738. void kcApp::_s_btn_cb(Fl_Widget* w, long data)
  1739. {
  1740. _getApp(w)->_btn_cb(w,data);
  1741. }
  1742. void kcApp::_btn_cb(Fl_Widget* w, long data)
  1743. {
  1744. unsigned arg = w->argument();
  1745. switch( arg )
  1746. {
  1747. case kAudDevRptBtnId:
  1748. cmAdIfDeviceReport(_aiH);
  1749. break;
  1750. case kEnableBtnId:
  1751. cmAdIfEnableAudio(_aiH,static_cast<Fl_Check_Button*>(w)->value()!=0);
  1752. break;
  1753. case kAudioSysCfgBtnId:
  1754. cmAdIfSetAudioSysCfg(_aiH,static_cast<Fl_Menu_Button*>(w)->mvalue()->argument());
  1755. break;
  1756. case kInAudDevBtnId:
  1757. cmAdIfSetAudioDevice(_aiH,_getCurAudioSubSysIdx(),true,static_cast<Fl_Menu_Button*>(w)->mvalue()->argument());
  1758. break;
  1759. case kOutAudDevBtnId:
  1760. cmAdIfSetAudioDevice(_aiH,_getCurAudioSubSysIdx(),false,static_cast<Fl_Menu_Button*>(w)->mvalue()->argument());
  1761. break;
  1762. case kPgmBtnId:
  1763. cmAdIfLoadProgram(_aiH,_getCurAudioSubSysIdx(),static_cast<Fl_Menu_Button*>(w)->mvalue()->argument());
  1764. break;
  1765. case kSubSystemIdxBtnId:
  1766. // TODO: change device and sample rate menu's to reflect the device and srate assigned to this asSubIdx.
  1767. break;
  1768. case kSrateBtnId:
  1769. cmAdIfSetSampleRate(_aiH,_getCurAudioSubSysIdx(),static_cast<Fl_Menu_Button*>(w)->mvalue()->argument());
  1770. break;
  1771. case kTestBtnId:
  1772. _testStub();
  1773. break;
  1774. case kPrintPgmBtnId:
  1775. _printPgm();
  1776. break;
  1777. default:
  1778. { assert(0); }
  1779. }
  1780. }
  1781. void kcApp::_s_ctl_cb(Fl_Widget* w, void* data)
  1782. {
  1783. ctl_t* cp = ((ctl_t*)data);
  1784. cp->thisPtr->_ctl_cb(cp);
  1785. }
  1786. void kcApp::_ctl_cb(ctl_t* cp)
  1787. {
  1788. cmDspValue_t value = cmDspNullValue;
  1789. unsigned instVarId = cmInvalidId;
  1790. switch( cp->typeId )
  1791. {
  1792. case kNumbTypeId:
  1793. case kSldrTypeId:
  1794. instVarId = cp->u.sldr.varIdArray[ kSldrValArgIdx ];
  1795. cmDsvSetDouble(&value,cp->u.sldr.val->value());
  1796. break;
  1797. case kTextTypeId:
  1798. instVarId = cp->u.text.varIdArray[ kTextValArgIdx ];
  1799. cmDsvSetStrz(&value,(cmChar_t*)cp->u.text.text->value());
  1800. break;
  1801. case kButnTypeId:
  1802. instVarId = cp->u.butn.varIdArray[ kButnValArgIdx ];
  1803. cmDsvSetDouble(&value,cp->u.butn.val);
  1804. break;
  1805. case kChckTypeId:
  1806. {
  1807. bool fl = cp->u.chck.chck->value();
  1808. instVarId = cp->u.chck.varIdArray[ kChckValArgIdx ];
  1809. cmDsvSetDouble(&value, fl ? 1.0 : 0.0 );
  1810. }
  1811. break;
  1812. case kFnamTypeId:
  1813. instVarId = cp->u.fnam.varIdArray[ kFnamValArgIdx ];
  1814. cmDsvSetStrz( &value, (cmChar_t*)cp->u.fnam.fnam->filename());
  1815. break;
  1816. case kMlstTypeId:
  1817. instVarId = cp->u.mlst.varIdArray[ kMlstSelArgIdx ];
  1818. // add one to the selected index to account for skipping title row
  1819. if( cp->u.mlst.mbtn==NULL)
  1820. {
  1821. unsigned idx = cp->u.mlst.mlst->value();
  1822. //printf("list:%i\n",idx);
  1823. cmDsvSetUInt( &value, idx);
  1824. }
  1825. else
  1826. {
  1827. unsigned idx = cp->u.mlst.mbtn->value();
  1828. //printf("mbtn:%i\n",idx);
  1829. cmDsvSetUInt( &value, idx + 1);
  1830. cp->u.mlst.mbtn->label( cp->u.mlst.mbtn->text(idx) );
  1831. }
  1832. break;
  1833. case kTmlnTypeId:
  1834. {
  1835. instVarId = cp->u.tmln.varIdArray[ kTmlnSelArgIdx ];
  1836. unsigned selMarkerId = cp->u.tmln.tlctl->timeLineSelectedMarkerId();
  1837. cmDsvSetUInt(&value, selMarkerId );
  1838. }
  1839. break;
  1840. case kScorTypeId:
  1841. {
  1842. instVarId = cp->u.scor.varIdArray[ kScorSelArgIdx ];
  1843. unsigned selEleIdx = cp->u.scor.tlctl->scoreSelectedEleIndex();
  1844. cmDsvSetUInt(&value, selEleIdx );
  1845. }
  1846. break;
  1847. case kTksbTypeId:
  1848. {
  1849. cmGrTksbFltk* tksbCtl = dynamic_cast<cmGrTksbFltk*>(cp->wdgtPtr);
  1850. switch( tksbCtl->cbTypeId() )
  1851. {
  1852. case cmGrTksbFltk::kSelectTId:
  1853. {
  1854. instVarId = cp->u.tksb.varIdArray[ kTksbSelArgIdx ];
  1855. unsigned selEleIdx = cp->u.tksb.tlctl->tksbSelectedEleIndex();
  1856. cmDsvSetUInt(&value, selEleIdx );
  1857. }
  1858. break;
  1859. case cmGrTksbFltk::kRefreshTId:
  1860. instVarId = cp->u.tksb.varIdArray[ kTksbRefreshArgIdx ];
  1861. cmDsvSetInt(&value,0);
  1862. break;
  1863. default:
  1864. { assert(0); }
  1865. }
  1866. }
  1867. break;
  1868. case kTksrTypeId:
  1869. {
  1870. }
  1871. break;
  1872. case kTwodTypeId:
  1873. {
  1874. cmGr2dFltk* twodCtl = dynamic_cast<cmGr2dFltk*>(cp->wdgtPtr);
  1875. unsigned i;
  1876. for(i=0; i<kTwodVarCnt; ++i)
  1877. {
  1878. switch( i )
  1879. {
  1880. case kTwodXArgIdx:
  1881. cmDsvSetDouble(&value,twodCtl->x());
  1882. break;
  1883. case kTwodYArgIdx:
  1884. cmDsvSetDouble(&value,twodCtl->y());
  1885. break;
  1886. case kTwodAngleArgIdx:
  1887. cmDsvSetDouble(&value,twodCtl->angle());
  1888. break;
  1889. case kTwodRadiusArgIdx:
  1890. cmDsvSetDouble(&value,twodCtl->radius());
  1891. break;
  1892. }
  1893. cmAdIfSendMsgToAudioDSP(_aiH,cp->asSubIdx,kUiSelAsId,kValueDuiId,0,cp->instId,cp->u.twod.varIdArray[i],&value);
  1894. }
  1895. instVarId = cmInvalidId;
  1896. }
  1897. break;
  1898. default:
  1899. {assert(0);}
  1900. }
  1901. if( instVarId != cmInvalidId )
  1902. if( cmAdIfSendMsgToAudioDSP(
  1903. _aiH,
  1904. cp->asSubIdx,
  1905. cp->mstrFl ? kUiMstrSelAsId : kUiSelAsId,
  1906. kValueDuiId,
  1907. 0,
  1908. cp->instId,
  1909. instVarId,
  1910. &value) != kOkAiRC)
  1911. {
  1912. cmErrMsg(&_ctx->err,kEngFailKmRC,"An attempt to send a UI message to the audio DSP interface failed.");
  1913. }
  1914. }
  1915. void kcApp::vprint(const char* fmt, va_list vl )
  1916. {
  1917. int bufCharCnt = 511;
  1918. char buf[bufCharCnt+1];
  1919. int n = vsnprintf(buf,bufCharCnt,fmt,vl);
  1920. if( n > 0 )
  1921. {
  1922. // if the print queue exists (it might not during startup or shutdown) ...
  1923. if( cmTsMp1cIsValid(_printqH) )
  1924. {
  1925. // ... enqueue the text to print
  1926. if( cmTsMp1cEnqueueMsg(_printqH,buf,n+1) != kOkThRC && _printFl==0 )
  1927. {
  1928. // use _printFl to guard against recursion which would eventually overflow the stack.
  1929. ++_printFl;
  1930. cmErrMsg(&_ctx->err,kQueueFailKmRC,"Print enqueue failed on msg:%s.",buf);
  1931. --_printFl;
  1932. }
  1933. }
  1934. else
  1935. _print(buf); // ... otherwise just send the text directly to the output console
  1936. }
  1937. }
  1938. void kcApp::print( const char* fmt, ... )
  1939. {
  1940. va_list vl;
  1941. va_start(vl,fmt);
  1942. vprint(fmt,vl);
  1943. va_end(vl);
  1944. }
  1945. void kcApp::_s_print( void* userPtr, const char* text )
  1946. { ((kcApp*)userPtr)->print(text); }
  1947. cmRC_t kcApp::_s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
  1948. {
  1949. kcApp* ap = (kcApp*)userCbPtr;
  1950. ap->_print((const char*)msgDataPtr);
  1951. return cmOkRC;
  1952. }
  1953. void kcApp::_checkPrintQueue()
  1954. {
  1955. while( cmTsMp1cMsgWaiting(_printqH) )
  1956. if( cmTsMp1cDequeueMsg(_printqH, NULL, 0) != kOkThRC && _printFl==0 )
  1957. {
  1958. ++_printFl;
  1959. cmErrMsg(&_ctx->err,kPrintQueFailKmRC,"Print dequeue failed.");
  1960. --_printFl;
  1961. }
  1962. }
  1963. void kcApp::_print( const char* text )
  1964. {
  1965. if( _con != NULL )
  1966. _con->insert(text);
  1967. #ifndef NDEBUG
  1968. fputs(text,stdout);
  1969. #endif
  1970. }