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

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. }