Programmable real-time audio signal processing application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kcApp.cpp 60KB

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