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.

Fl_DevCfgGroup.cpp 29KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. #include <FL/Fl.H>
  2. #include <FL/Fl_Widget.H>
  3. #include <FL/Fl_Group.H>
  4. #include <FL/Fl_Tabs.H>
  5. #include <FL/Fl_Button.H>
  6. #include <FL/Fl_Check_Button.H>
  7. #include <FL/Fl_Box.H>
  8. #include <Fl/Fl_Input.H>
  9. #include <Fl/Fl_Value_Input.H>
  10. #include <Fl/Fl_Menu_Button.H>
  11. #include "cmGlobal.h"
  12. #include "cmFloatTypes.h"
  13. #include "cmRpt.h"
  14. #include "cmErr.h"
  15. #include "cmCtx.h"
  16. #include "cmMem.h"
  17. #include "cmMallocDebug.h"
  18. #include "cmThread.h"
  19. #include "cmJson.h"
  20. #include "cmTime.h"
  21. #include "cmAudioPort.h"
  22. #include "cmMidi.h"
  23. #include "cmMidiPort.h"
  24. #include "cmUdpPort.h"
  25. #include "cmRtSysMsg.h"
  26. #include "cmRtNet.h"
  27. #include "cmRtSys.h"
  28. #include "cmDevCfg.h"
  29. #include "Fl_DevCfgGroup.h"
  30. #define DEVCFG_NONE_STR "None"
  31. Fl_DevCfgGroup::Fl_DevCfgGroup(cmDevCfgH_t dcH,
  32. int xx, int yy, int ww, int hh, const char* label )
  33. : Fl_Group(xx,yy,ww,hh,label),
  34. _dcH(dcH)
  35. {
  36. typedef enum
  37. {
  38. kInvalidTId,
  39. kLabelTId,
  40. kBtnTId,
  41. kMenuBtnTId,
  42. kChkBtnTId,
  43. kInputTId,
  44. kValueTId
  45. } type_t;
  46. typedef struct
  47. {
  48. unsigned id;
  49. type_t tid;
  50. int x;
  51. int y;
  52. int w;
  53. int h;
  54. int flags;
  55. const char* label;
  56. } recd_t;
  57. const int r = -1; // current row
  58. const int rn = -2; // next row
  59. const int cn = -1; // next column
  60. int r00 = 50;
  61. int c0 = 2;
  62. int c3 = 400;
  63. int c4 = 650;
  64. int lw = 250; // device/port/preset label widths
  65. int vw = 75; // value widths
  66. int iw = 125;
  67. int dw = 400;
  68. int w = 100;
  69. int h = 25;
  70. int fl = 0;
  71. int fl1 = FL_WHEN_CHANGED;
  72. recd_t a[] =
  73. {
  74. { kLocLabelCId, kLabelTId, c0,r00, w, h, fl, "Location:" },
  75. { kLocMenuCId, kMenuBtnTId, c0, rn, lw, h, fl, NULL },
  76. { kLocDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" },
  77. { kLocStringCId, kInputTId, c0, rn, lw, h, fl1, NULL },
  78. { kLocStoreBtnCId, kBtnTId, cn, r, w, h, fl, "Create" },
  79. { kMidiLabelCId, kLabelTId, c0, rn, w, h, fl, "MIDI:" },
  80. { kMidiCfgMenuCId, kMenuBtnTId, c0, rn, lw, h, fl, NULL },
  81. { kMidiDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" },
  82. { kMidiCfgDescCId, kLabelTId, c0, rn, dw, h, fl, NULL },
  83. { kMidiCfgStringCId, kInputTId, c0, rn, lw, h, fl1, NULL },
  84. { kMidiApplyBtnCId, kBtnTId, cn, r, w, h, fl, "Store" },
  85. { kMidiDevMenuCId, kMenuBtnTId, c0, rn, lw, h, fl1, NULL },
  86. { kMidiDevLabelCId, kLabelTId, cn, r, w, h, fl, "MIDI Device"},
  87. { kMidiPortMenuCId, kMenuBtnTId, c0, rn, lw, h, fl1, NULL },
  88. { kMidiPortLabelCId, kLabelTId, cn, r, w, h, fl, "MIDI Port"},
  89. { kMidiInputCheckCId, kChkBtnTId, c0, rn, w, h, fl1, "Input"},
  90. { kAudioLabelCId, kLabelTId, c3,r00, w, h, fl, "Audio:" },
  91. { kAudioCfgMenuCId, kMenuBtnTId, c3, rn, lw, h, fl, NULL },
  92. { kAudioDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" },
  93. { kAudioCfgDescCId, kLabelTId, c3, rn, dw, h*2,fl, NULL },
  94. { kAudioCfgStringCId, kInputTId, c3, rn, lw, h, fl1, NULL },
  95. { kAudioApplyBtnCId, kBtnTId, cn, r, w, h, fl, "Store" },
  96. { kAudioInDevMenuCId, kMenuBtnTId, c3, rn, lw, h, fl1, NULL },
  97. { kAudioInDevLabelCId, kLabelTId, cn, r, w, h, fl, "Audio Input"},
  98. { kAudioOutDevMenuCId, kMenuBtnTId, c3, rn, lw, h, fl1, NULL },
  99. { kAudioOutDevLabelCId, kLabelTId, cn, r, w, h, fl1, "Audio Output"},
  100. { kAudioMsgQueSizeValCId,kValueTId, c3, rn, vw, h, fl1, "Msg Queue Bytes" },
  101. { kAudioDevFpCValCId, kValueTId, c4, r, vw, h, fl1, "Audio Frames" },
  102. { kAudioDspFpCValCId, kValueTId, c3, rn, vw, h, fl1, "DSP Frames" },
  103. { kAudioBufCntValCId, kValueTId, c4, r, vw, h, fl1, "Buffer Count" },
  104. { kAudioSrateMenuCId, kMenuBtnTId, c3, rn, w, h, fl1, "Rate" },
  105. { kAudioSyncInCheckCId, kChkBtnTId, c4, r, w, h, fl1, "Sync to Input"},
  106. { kAudioNetNodeStringCId,kInputTId, c3, rn, vw, h, fl1, "Net Node Label"},
  107. { kAudioBcastAddrStringCId,kInputTId, c4, r, iw, h, fl1, "Bcast Address"},
  108. { kAudioIpAddrStringCId, kInputTId, c3, rn, iw, h, fl1, "IP Address"},
  109. { kAudioIpPortValCId, kValueTId, c4, r, vw, h, fl1, "IP Port"},
  110. { kAudioActiveCheckCId, kChkBtnTId, c3, rn, w, h, fl1, "Active"},
  111. /*
  112. { kNetLabelCId, kLabelTId, c3, rn, w, h, fl, "Remote Network Nodes:" },
  113. { kNetCfgMenuCId, kMenuBtnTId, c3, rn, lw, h, fl, NULL },
  114. { kNetDeleteBtnCId, kBtnTId, cn, r, w, h, fl, "Delete" },
  115. { kNetCfgDescCId, kLabelTId, c3, rn, dw, h, fl, NULL },
  116. { kNetCfgStringCId, kInputTId, c3, rn, lw, h, fl, NULL },
  117. { kNetApplyBtnCId, kBtnTId, cn, r, w, h, fl, "Store" },
  118. { kNetSockAddrStringCId, kInputTId, c3, rn, w, h, fl1, "IP Address" },
  119. { kNetPortNumbValCId, kValueTId, c4, r, vw, h, fl1, "IP Port" },
  120. { kNetLocalCheckCId, kChkBtnTId, c3, rn, w, h, fl1, "Local"},
  121. { kNetActiveCheckCId, kChkBtnTId, cn, r, vw, h, fl1, "Active"},
  122. */
  123. { kInvalidCId, kInvalidTId, 0, 0, 0, 0, 0, NULL }
  124. };
  125. const recd_t* d = a;
  126. int y = r00;
  127. int x = c0;
  128. int ny = 0;
  129. int nx = 0;
  130. for(; d->id != kInvalidCId; ++d)
  131. {
  132. Fl_Widget* wp = NULL;
  133. ctl_t* c = new ctl_t;
  134. c->id = d->id;
  135. c->p = this;
  136. switch( d->y )
  137. {
  138. case r: break;
  139. case rn: y = ny; break;
  140. default: y = d->y; break;
  141. }
  142. switch( d->x )
  143. {
  144. case cn: x = nx; break;
  145. default: x = d->x; break;
  146. }
  147. switch( d->tid )
  148. {
  149. case kLabelTId:
  150. wp = c->u.box = new Fl_Box(x,y,d->w,d->h,d->label);
  151. wp->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
  152. break;
  153. case kBtnTId:
  154. wp = c->u.btn = new Fl_Button(x,y,d->w,d->h,d->label);
  155. break;
  156. case kMenuBtnTId:
  157. wp = c->u.mbt = new Fl_Menu_Button(x,y,d->w,d->h,d->label);
  158. break;
  159. case kChkBtnTId:
  160. wp = c->u.chk = new Fl_Check_Button(x,y,d->w,d->h,d->label);
  161. break;
  162. case kInputTId:
  163. wp = c->u.inp = new Fl_Input(x,y,d->w,d->h,d->label);
  164. wp->align(FL_ALIGN_RIGHT);
  165. break;
  166. case kValueTId:
  167. wp = c->u.val = new Fl_Value_Input(x,y,d->w,d->h,d->label);
  168. wp->align(FL_ALIGN_RIGHT);
  169. break;
  170. default:
  171. break;
  172. }
  173. if( wp != NULL )
  174. {
  175. if( cmIsFlag(d->flags,FL_WHEN_CHANGED) )
  176. wp->when(FL_WHEN_CHANGED);
  177. ny = y + d->h + 2;
  178. nx = x + d->w + 2;
  179. wp->callback(Fl_DevCfgGroup::_s_ctl_cb,c);
  180. _ctlV.push_back(c);
  181. }
  182. }
  183. //_loadMenuButtons();
  184. _syncLoc();
  185. }
  186. Fl_DevCfgGroup::~Fl_DevCfgGroup()
  187. {
  188. unsigned i;
  189. for(i=0; i<_ctlV.size(); ++i)
  190. delete _ctlV[i];
  191. }
  192. void Fl_DevCfgGroup::onEnableAudio( bool enableFl )
  193. {
  194. if( enableFl )
  195. {
  196. deactivate();
  197. }
  198. else
  199. {
  200. activate();
  201. parent()->redraw();
  202. }
  203. }
  204. bool Fl_DevCfgGroup::_loadLocBtn()
  205. {
  206. ctl_t* c;
  207. if((c = _idToCtl(kLocMenuCId)) == NULL )
  208. return false;
  209. int val = c->u.mbt->value();
  210. c->u.mbt->clear();
  211. unsigned i;
  212. for(i=0; i<cmDevCfgLocCount(_dcH); ++i)
  213. c->u.mbt->add(cmStringNullGuard(cmDevCfgLocLabel(_dcH,i)),0,_s_ctl_cb,c);
  214. _restoreMenuValue(kLocMenuCId, val );
  215. if((c = _idToCtl(kLocStoreBtnCId)) != NULL)
  216. c->u.btn->deactivate();
  217. return true;
  218. }
  219. void Fl_DevCfgGroup::_recallLoc()
  220. {
  221. ctl_t* c;
  222. const char* s;
  223. if((s = _getMenuCtl(kLocMenuCId)) == NULL )
  224. goto errLabel;
  225. if( cmDevCfgLocRecall(_dcH,s) != kOkDcRC )
  226. goto errLabel;
  227. if((c = _idToCtl(kLocStringCId)) == NULL )
  228. goto errLabel;
  229. c->u.inp->copy_label(s);
  230. errLabel:
  231. _syncLoc();
  232. }
  233. void Fl_DevCfgGroup::_storeLoc()
  234. {
  235. ctl_t* c;
  236. const char* s;
  237. if((c = _idToCtl(kLocStringCId)) == NULL )
  238. goto errLabel;
  239. if((s = c->u.inp->value()) == NULL )
  240. goto errLabel;
  241. if( cmDevCfgLocStore(_dcH,s) != kOkDcRC )
  242. goto errLabel;
  243. errLabel:
  244. _syncLoc();
  245. }
  246. void Fl_DevCfgGroup::_deleteLoc()
  247. {
  248. const char* s;
  249. if((s = _getMenuCtl(kLocMenuCId)) == NULL )
  250. goto errLabel;
  251. if( cmDevCfgLocDelete(_dcH,s) != kOkDcRC )
  252. goto errLabel;
  253. errLabel:
  254. _syncLoc();
  255. }
  256. // load MIDI device menu from the MIDI driver
  257. void Fl_DevCfgGroup::_loadMidiDevBtn()
  258. {
  259. unsigned j;
  260. ctl_t* c;
  261. if((c = _idToCtl(kMidiDevMenuCId)) == NULL )
  262. return;
  263. int val = c->u.mbt->value();
  264. c->u.mbt->clear();
  265. for(j=0; j<cmMpDeviceCount(); ++j)
  266. {
  267. c->u.mbt->add(cmStringNullGuard(cmMpDeviceName(j)),0,_s_ctl_cb,c);
  268. }
  269. _restoreMenuValue(kMidiDevMenuCId, val );
  270. }
  271. // Load the MIDI port menu from the MIDI driver accoring
  272. // to the MIDI device seleted in the MIDI device menu
  273. void Fl_DevCfgGroup::_loadMidiPortBtn()
  274. {
  275. ctl_t* c;
  276. if((c = _idToCtl(kMidiDevMenuCId)) == NULL )
  277. return;
  278. int devIdx = c->u.mbt->value();
  279. if((c = _idToCtl(kMidiInputCheckCId)) == NULL )
  280. return;
  281. unsigned flags = c->u.chk->value() ? kInMpFl : kOutMpFl;
  282. unsigned n = devIdx<0 ? 0 : cmMpDevicePortCount(devIdx,flags);
  283. if((c = _idToCtl(kMidiPortMenuCId)) == NULL )
  284. return;
  285. c->u.mbt->clear();
  286. int val = c->u.mbt->value();
  287. for(unsigned j=0; j<n; ++j)
  288. c->u.mbt->add(cmStringNullGuard(cmMpDevicePortName(devIdx,flags,j)),0,_s_ctl_cb,c);
  289. _restoreMenuValue(kMidiPortMenuCId, val );
  290. }
  291. // Load the audio device menu from the audio port driver.
  292. void Fl_DevCfgGroup::_loadAudioDevBtn( unsigned id, unsigned devIdx )
  293. {
  294. ctl_t* c;
  295. unsigned i;
  296. if((c = _idToCtl(id)) == NULL )
  297. return;
  298. unsigned n = cmApDeviceCount();
  299. bool inputFl = id == kAudioInDevMenuCId;
  300. int val = c->u.mbt->value();
  301. c->u.mbt->clear();
  302. for(i=0; i<n; ++i)
  303. if( cmApDeviceChannelCount( i, inputFl ) > 0 )
  304. {
  305. const cmChar_t* str;
  306. if((str = cmApDeviceLabel(i)) != NULL )
  307. {
  308. bool activeFl = cmDevCfgAudioIsDeviceActive(_dcH, str, inputFl );
  309. if( devIdx == i )
  310. activeFl = false;
  311. c->u.mbt->add(str,0,NULL,NULL, activeFl ? FL_MENU_INACTIVE : 0);
  312. }
  313. }
  314. c->u.mbt->add(DEVCFG_NONE_STR,0,_s_ctl_cb,c);
  315. _restoreMenuValue(id, val );
  316. if( devIdx == cmInvalidIdx )
  317. _setMenuBtnWithString(id,DEVCFG_NONE_STR);
  318. }
  319. // Load the sample rate menu with constant values.
  320. void Fl_DevCfgGroup::_loadAudioSrateBtn()
  321. {
  322. ctl_t* c;
  323. if((c = _idToCtl(kAudioSrateMenuCId)) == NULL )
  324. return;
  325. int val = c->u.mbt->value();
  326. char* p = 0;
  327. c->u.mbt->add("96000",0,NULL,p+96000);
  328. c->u.mbt->add("48000",0,NULL,p+48000);
  329. c->u.mbt->add("44100",0,NULL,p+44100);
  330. c->u.mbt->add("22050",0,NULL,p+22050);
  331. if( val < 0 || val >= c->u.mbt->size() )
  332. _setSrate(kAsDfltSrate);
  333. else
  334. if( c->u.mbt->size() > 0 )
  335. {
  336. c->u.mbt->value(val);
  337. c->u.mbt->copy_label( c->u.mbt->mvalue()->label() );
  338. }
  339. }
  340. // Load a cfg menu with the labels of the cfg records from cmDevCfg.
  341. // (but don't update the label yet).
  342. void Fl_DevCfgGroup::_loadCfgMenu(cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned deleteCtlId )
  343. {
  344. ctl_t* c;
  345. if((c = _idToCtl(menuCtlId)) == NULL )
  346. return;
  347. // get the current value of the menu
  348. int val = c->u.mbt->value();
  349. // empty the menu
  350. c->u.mbt->clear();
  351. // get the count of cfg recds
  352. unsigned n = cmDevCfgCount(_dcH,typeId);
  353. const cmChar_t* label;
  354. // reload the menu from cmDevCfg
  355. for(unsigned i=0; i<n; ++i)
  356. if((label = cmDevCfgLabel(_dcH,typeId,i)) != NULL )
  357. c->u.mbt->add(label,0,_s_ctl_cb,c);
  358. // get the count of menu items
  359. int sz = c->u.mbt->size();
  360. // if the original value is no longer valid then set the value to
  361. // the most likely valid value - zero.
  362. if( val < 0 || val >= sz )
  363. val = 0;
  364. // if the menu is not empty then set the value
  365. if( sz > 0 )
  366. c->u.mbt->value(val);
  367. // update the 'delete' btn
  368. if((c = _idToCtl(deleteCtlId)) != NULL )
  369. {
  370. // if the menu is empty deactivate the delete btn
  371. if( sz > 0 )
  372. c->u.btn->activate();
  373. else
  374. c->u.btn->deactivate();
  375. }
  376. }
  377. // Load the cfg label edit string, description and type
  378. // specific fields from the cmDevCfg based on the currently
  379. // selected cfg menu item.
  380. void Fl_DevCfgGroup::_recallCfg(cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned strCtlId, unsigned descCtlId, unsigned storeCtlId )
  381. {
  382. const Fl_Menu_Item* mip;
  383. ctl_t* c;
  384. // get the cfg menu
  385. if((c = _idToCtl(menuCtlId)) == NULL )
  386. return;
  387. // get the current value of the cfg menu
  388. int menuIdx = c->u.mbt->value();
  389. if( menuIdx == -1 )
  390. return;
  391. // get the current menu item from the cfg menu
  392. if((mip = c->u.mbt->mvalue()) == NULL)
  393. return;
  394. // update the cfg menu label
  395. c->u.mbt->copy_label( mip->label() );
  396. // set the cfg string text
  397. if((c = _idToCtl(strCtlId)) != NULL )
  398. c->u.inp->value( mip->label() );
  399. // set the desc string
  400. if((c = _idToCtl(descCtlId)) != NULL )
  401. {
  402. const cmChar_t* s = cmDevCfgDesc(_dcH, typeId, menuIdx );
  403. c->u.box->copy_label( s==NULL ? "" : s );
  404. }
  405. // disable to store btn
  406. if((c = _idToCtl(storeCtlId)) != NULL )
  407. c->u.btn->deactivate();
  408. switch( typeId )
  409. {
  410. case kMidiDcmTId:
  411. {
  412. const cmDcmMidi_t* r = cmDevCfgMidiCfg(_dcH,menuIdx);
  413. // set the midi device from the cfg recd
  414. _setMenuBtnWithString(kMidiDevMenuCId,r==NULL ? "" : r->devLabelStr);
  415. _setCheckCtl( kMidiInputCheckCId, r==NULL ? 0 : r->inputFl );
  416. // sync the midi port menu to the device
  417. _loadMidiPortBtn();
  418. }
  419. break;
  420. case kAudioDcmTId:
  421. {
  422. const cmDcmAudio_t* r = cmDevCfgAudioCfg(_dcH,menuIdx);
  423. _setMenuBtnWithString(kAudioInDevMenuCId, r==NULL ? "" : (r->inDevLabelStr==NULL ? DEVCFG_NONE_STR : r->inDevLabelStr));
  424. _setMenuBtnWithString(kAudioOutDevMenuCId,r==NULL ? "" : (r->outDevLabelStr==NULL ? DEVCFG_NONE_STR : r->outDevLabelStr));
  425. _setValueCtl(kAudioMsgQueSizeValCId, r==NULL ? 0 : r->rtSysArgs.msgQueueByteCnt);
  426. _setValueCtl(kAudioDevFpCValCId, r==NULL ? 0 : r->rtSysArgs.devFramesPerCycle);
  427. _setValueCtl(kAudioDspFpCValCId, r==NULL ? 0 : r->rtSysArgs.dspFramesPerCycle);
  428. _setValueCtl(kAudioBufCntValCId, r==NULL ? 0 : r->rtSysArgs.audioBufCnt);
  429. _setCheckCtl(kAudioSyncInCheckCId, r==NULL ? 0 : r->rtSysArgs.syncInputFl);
  430. _setInputCtl(kAudioNetNodeStringCId, r==NULL ? "" : r->netNodeLabel);
  431. _setInputCtl(kAudioBcastAddrStringCId, r==NULL ? "" : r->bcastAddr);
  432. _setInputCtl(kAudioIpAddrStringCId, r==NULL ? "" : r->ipAddr);
  433. _setValueCtl(kAudioIpPortValCId, r==NULL ? 0 : r->ipPort);
  434. _setCheckCtl(kAudioActiveCheckCId, r==NULL ? 0 : r->activeFl);
  435. _setSrate( r==NULL ? kAsDfltSrate : r->rtSysArgs.srate);
  436. //cmDevCfgAudioSetDefaultCfgIndex(_dcH,menuIdx);
  437. _loadAudioDevBtn(kAudioInDevMenuCId, r->rtSysArgs.inDevIdx );
  438. _loadAudioDevBtn(kAudioOutDevMenuCId, r->rtSysArgs.outDevIdx );
  439. }
  440. break;
  441. /*
  442. case kNetDcmTId:
  443. {
  444. const cmDcmNet_t* r = cmDevCfgNetCfg(_dcH,menuIdx);
  445. _setInputCtl(kNetSockAddrStringCId, r==NULL ? "" : r->sockAddr);
  446. _setValueCtl(kNetPortNumbValCId, r==NULL ? 0 : r->portNumber);
  447. _setCheckCtl(kNetActiveCheckCId, r==NULL ? 0 : r->activeFl);
  448. }
  449. break;
  450. */
  451. default:
  452. assert(0);
  453. break;
  454. }
  455. }
  456. void Fl_DevCfgGroup::_syncLoc()
  457. {
  458. ctl_t* c;
  459. unsigned idx;
  460. _loadLocBtn();
  461. if((idx = cmDevCfgLocCurIndex(_dcH)) == cmInvalidIdx )
  462. return;
  463. if((c = _idToCtl(kLocMenuCId)) == NULL )
  464. return;
  465. assert((int)idx < c->u.mbt->size() );
  466. if( (int)idx >= c->u.mbt->size() )
  467. return;
  468. c->u.mbt->value(idx);
  469. _setMenuBtnLabel(kLocMenuCId,kLocStringCId);
  470. // Load the menu's based on the currently
  471. // available hardware.
  472. _loadMidiDevBtn();
  473. _loadMidiPortBtn();
  474. _loadAudioDevBtn(kAudioInDevMenuCId,cmInvalidId);
  475. _loadAudioDevBtn(kAudioOutDevMenuCId,cmInvalidId);
  476. _loadAudioSrateBtn();
  477. // Set the default values for some fields. These values will only be
  478. // used if there is no availabe cmDevCfg data.
  479. _idToCtl(kAudioMsgQueSizeValCId)->u.val->value(kAsDfltMsgQueueByteCnt);
  480. _idToCtl(kAudioDevFpCValCId)->u.val->value(kAsDfltDevFramesPerCycle);
  481. _idToCtl(kAudioDspFpCValCId)->u.val->value(kAsDfltDspFramesPerCycle);
  482. _idToCtl(kAudioBufCntValCId)->u.val->value(kAsDfltBufCnt);
  483. _idToCtl(kAudioSyncInCheckCId)->u.chk->value(kAsDfltSyncToInputFl);
  484. // set the bounds for the IP port value
  485. _idToCtl(kAudioIpPortValCId)->u.val->bounds(0,65535);
  486. _idToCtl(kAudioIpPortValCId)->u.val->step(1);
  487. // Load the MIDI cfg information from cmDevCfg.
  488. _loadCfgMenu(kMidiDcmTId, kMidiCfgMenuCId, kMidiDeleteBtnCId );
  489. _recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId );
  490. // Load the Audio cfg information from cmDevCfg.
  491. _loadCfgMenu(kAudioDcmTId, kAudioCfgMenuCId, kAudioDeleteBtnCId );
  492. // Display the default audio configuration
  493. // if((c = _idToCtl(kAudioCfgMenuCId)) != NULL )
  494. // if((idx = cmDevCfgAudioGetDefaultCfgIndex(_dcH)) != cmInvalidIdx )
  495. // if( c->u.mbt->size() < (int)idx )
  496. // c->u.mbt->value(idx);
  497. _recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId );
  498. // Load the network cfg information from cmDevCfg.
  499. //_loadCfgMenu(kNetDcmTId, kNetCfgMenuCId, kNetDeleteBtnCId );
  500. //_recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId );
  501. }
  502. // Called when the MIDI 'Store' cfg button is pressed.
  503. // Creates or edits a MIDI cfg recd in cmDevCfg.
  504. void Fl_DevCfgGroup::_createMidiCfg()
  505. {
  506. const cmChar_t* cfgStr = _getInputCtl(kMidiCfgStringCId);
  507. const cmChar_t* devStr = _getMenuCtl(kMidiDevMenuCId);
  508. const cmChar_t* portStr = _getMenuCtl(kMidiPortMenuCId);
  509. bool inputFl = _getCheckCtl(kMidiInputCheckCId);
  510. // create or edit a MIDI cfg recd
  511. if( cmDevCfgNameMidiPort(_dcH,cfgStr,devStr,portStr,inputFl) == kOkDcRC )
  512. {
  513. // a MIDI cfg recd may have been created so reload the MIDI cfg menu btn
  514. _loadCfgMenu(kMidiDcmTId,kMidiCfgMenuCId,kMidiDeleteBtnCId);
  515. // set the MIDI cfg menu btn to display the label of the cfg just edited or creaed
  516. _setMenuBtnWithString(kMidiCfgMenuCId,cfgStr);
  517. // update the other MIDI fields based on the current cfg menu value
  518. _recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId );
  519. }
  520. }
  521. // Called when the Audio 'Store' button is pressed.
  522. // Creates or edits an audio cfg recd in the cmDevCfg.
  523. void Fl_DevCfgGroup::_createAudioCfg()
  524. {
  525. const cmChar_t* cfgStr = _getInputCtl(kAudioCfgStringCId);
  526. const cmChar_t* inDevStr = _getMenuCtl(kAudioInDevMenuCId);
  527. const cmChar_t* outDevStr = _getMenuCtl(kAudioOutDevMenuCId);
  528. bool syncInFl = _getCheckCtl(kAudioSyncInCheckCId);
  529. unsigned msgQueCnt = _getValueCtl(kAudioMsgQueSizeValCId);
  530. unsigned devFpC = _getValueCtl(kAudioDevFpCValCId);
  531. unsigned dspFpC = _getValueCtl(kAudioDspFpCValCId);
  532. unsigned bufCnt = _getValueCtl(kAudioBufCntValCId);
  533. const cmChar_t* nodeStr = _getInputCtl(kAudioNetNodeStringCId);
  534. const cmChar_t* bcastAddr = _getInputCtl(kAudioBcastAddrStringCId);
  535. const cmChar_t* ipAddr = _getInputCtl(kAudioIpAddrStringCId);
  536. cmUdpPort_t ipPort = _getValueCtl(kAudioIpPortValCId);
  537. bool activeFl = _getCheckCtl(kAudioActiveCheckCId);
  538. double srate = _getSrate();
  539. if( strcmp(inDevStr,DEVCFG_NONE_STR)==0 )
  540. inDevStr = NULL;
  541. if( strcmp(outDevStr,DEVCFG_NONE_STR)==0 )
  542. outDevStr = NULL;
  543. // create or edit a audio cfg recd
  544. if( cmDevCfgNameAudioPort(_dcH,cfgStr,inDevStr,outDevStr,syncInFl,msgQueCnt,devFpC,dspFpC,bufCnt,srate,nodeStr,bcastAddr,ipAddr,ipPort,activeFl) == kOkDcRC )
  545. {
  546. // a new cfg recd may have been created so reload audio cfg menu
  547. _loadCfgMenu(kAudioDcmTId,kAudioCfgMenuCId,kAudioDeleteBtnCId);
  548. // set the cfg menu to display the label of the cfg just edited or created
  549. _setMenuBtnWithString(kAudioCfgMenuCId,cfgStr);
  550. // update the other audio fields based on the current cfg menu value
  551. _recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId );
  552. }
  553. }
  554. /*
  555. // Called when the Net 'Store' button is pressed.
  556. // Creates or edits a net cfg recd in the cmDevCfg.
  557. void Fl_DevCfgGroup::_createNetCfg()
  558. {
  559. const cmChar_t* cfgStr = _idToCtl(kNetCfgStringCId)->u.inp->value();
  560. const cmChar_t* addrStr = _idToCtl(kNetSockAddrStringCId)->u.inp->value();
  561. unsigned portNum = _idToCtl(kNetPortNumbValCId)->u.val->value();
  562. bool activeFl= _idToCtl(kNetActiveCheckCId)->u.chk->value();
  563. // create or edit a NET cfg recd
  564. if( cmDevCfgNameNetPort(_dcH,cfgStr,addrStr,portNum,activeFl) == kOkDcRC )
  565. {
  566. // a NET cfg recd may have been created so reload the NET cfg menu btn
  567. _loadCfgMenu(kNetDcmTId,kNetCfgMenuCId,kNetDeleteBtnCId);
  568. // set the NET cfg menu btn to display the label of the cfg just edited or creaed
  569. _setMenuBtnWithString(kNetCfgMenuCId,cfgStr);
  570. // update the other net fields based on the current cfg menu value
  571. _recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId );
  572. }
  573. }
  574. */
  575. void Fl_DevCfgGroup::_deleteCfg( cmTypeDcmId_t typeId, unsigned menuCtlId, unsigned inpCtlId, unsigned descCtlId, unsigned storeCtlId, unsigned deleteCtlId )
  576. {
  577. ctl_t* c;
  578. const cmChar_t* s;
  579. int idx;
  580. if((s = _getMenuCtl(menuCtlId)) == NULL )
  581. goto errLabel;
  582. if(cmDevCfgDeleteCfg(_dcH, typeId, s ) != kOkDcRC )
  583. goto errLabel;
  584. if(( c = _idToCtl(menuCtlId)) == NULL )
  585. goto errLabel;
  586. if((idx = c->u.mbt->find_index(s)) < 0 )
  587. goto errLabel;
  588. c->u.mbt->remove(idx);
  589. if( c->u.mbt->size() > 0 )
  590. c->u.mbt->value(0);
  591. _loadCfgMenu(typeId,menuCtlId,deleteCtlId);
  592. _recallCfg(typeId,menuCtlId,inpCtlId,descCtlId,storeCtlId);
  593. errLabel:
  594. return;
  595. }
  596. void Fl_DevCfgGroup::_restoreMenuValue( unsigned menuCtlId, int val, int dfltVal )
  597. {
  598. ctl_t* c;
  599. if((c = _idToCtl(menuCtlId)) == NULL )
  600. return;
  601. if( val < 0 || val >= c->u.mbt->size() )
  602. val = dfltVal;
  603. if( c->u.mbt->size() > 0 )
  604. c->u.mbt->value(val);
  605. else
  606. c->u.mbt->value(-1);
  607. _setMenuBtnLabel(menuCtlId);
  608. }
  609. void Fl_DevCfgGroup::_setMenuBtnLabel( unsigned menuCtlId, unsigned inpCtlId )
  610. {
  611. ctl_t* c;
  612. const Fl_Menu_Item* mip;
  613. const char* s;
  614. if((c = _idToCtl(menuCtlId)) == NULL )
  615. goto errLabel;
  616. int v;
  617. if((v = c->u.mbt->value()) == -1 )
  618. goto errLabel;
  619. if((mip = c->u.mbt->mvalue()) == NULL )
  620. goto errLabel;
  621. if((s = mip->label()) == NULL || strlen(s)==0)
  622. s = ""; // the menu is empty or the label is invalid
  623. c->u.mbt->copy_label(s);
  624. if( inpCtlId != cmInvalidId )
  625. {
  626. if((c = _idToCtl(inpCtlId)) == NULL )
  627. goto errLabel;
  628. c->u.inp->copy_label(s);
  629. }
  630. errLabel:
  631. return;
  632. }
  633. void Fl_DevCfgGroup::_setMenuBtnWithString( unsigned menuCtlId, const char* string )
  634. {
  635. ctl_t* c;
  636. int idx;
  637. if((c = _idToCtl(menuCtlId)) == NULL )
  638. goto errLabel;
  639. if((idx = c->u.mbt->find_index(string)) < 0 )
  640. goto errLabel;
  641. c->u.mbt->value(idx);
  642. c->u.mbt->copy_label(string);
  643. errLabel:
  644. return;
  645. }
  646. void Fl_DevCfgGroup::_setCheckCtl( unsigned ctlId, int val )
  647. {
  648. ctl_t* c;
  649. if((c = _idToCtl(ctlId)) == NULL )
  650. return;
  651. c->u.chk->value(val);
  652. }
  653. void Fl_DevCfgGroup::_setValueCtl( unsigned ctlId, double val )
  654. {
  655. ctl_t* c;
  656. if((c = _idToCtl(ctlId)) == NULL )
  657. return;
  658. c->u.val->value(val);
  659. }
  660. void Fl_DevCfgGroup::_setInputCtl( unsigned ctlId, const cmChar_t* val )
  661. {
  662. ctl_t* c;
  663. if((c = _idToCtl(ctlId)) == NULL )
  664. return;
  665. c->u.inp->value(val);
  666. }
  667. const cmChar_t* Fl_DevCfgGroup::_getMenuCtl( unsigned ctlId )
  668. {
  669. ctl_t* c;
  670. const Fl_Menu_Item* mip;
  671. if((c = _idToCtl(ctlId)) == NULL)
  672. goto errLabel;
  673. if( c->u.mbt->value() == -1 )
  674. goto errLabel;
  675. if((mip = c->u.mbt->mvalue()) == NULL)
  676. goto errLabel;
  677. if( mip->label() == NULL )
  678. goto errLabel;
  679. return mip->label();
  680. errLabel:
  681. return "";
  682. }
  683. const cmChar_t* Fl_DevCfgGroup::_getInputCtl( unsigned ctlId )
  684. {
  685. ctl_t* c;
  686. if((c = _idToCtl(ctlId)) == NULL)
  687. goto errLabel;
  688. if( c->u.inp->value() == NULL )
  689. goto errLabel;
  690. return c->u.inp->value();
  691. errLabel:
  692. return "";
  693. }
  694. double Fl_DevCfgGroup::_getValueCtl( unsigned ctlId )
  695. {
  696. ctl_t* c;
  697. if((c = _idToCtl(ctlId)) == NULL)
  698. return 0;
  699. return c->u.val->value();
  700. }
  701. bool Fl_DevCfgGroup::_getCheckCtl( unsigned ctlId )
  702. {
  703. ctl_t* c;
  704. if((c = _idToCtl(ctlId)) == NULL)
  705. return 0;
  706. return c->u.chk->value();
  707. }
  708. double Fl_DevCfgGroup::_getSrate()
  709. {
  710. ctl_t* c;
  711. const Fl_Menu_Item* mip;
  712. if((c = _idToCtl(kAudioSrateMenuCId)) == NULL )
  713. return kAsDfltSrate;
  714. assert( c->u.mbt->value() != -1);
  715. if((mip = c->u.mbt->mvalue()) == NULL )
  716. return kAsDfltSrate;
  717. return (char*)mip->user_data() - (char*)NULL;
  718. }
  719. void Fl_DevCfgGroup::_setSrate( double srate )
  720. {
  721. ctl_t* c;
  722. if((c = _idToCtl(kAudioSrateMenuCId)) == NULL )
  723. return;
  724. int i;
  725. for(i=0; i<c->u.mbt->size(); ++i)
  726. {
  727. const Fl_Menu_Item* mip = &c->u.mbt->menu()[i];
  728. if( mip != NULL && ((char*)mip->user_data() - (char*)NULL) == srate)
  729. {
  730. c->u.mbt->value(i);
  731. c->u.mbt->copy_label( mip->label() );
  732. return;
  733. }
  734. }
  735. }
  736. void Fl_DevCfgGroup::_enableStoreBtn( unsigned ctlId )
  737. {
  738. ctl_t* c;
  739. if((c = _idToCtl(ctlId)) == NULL )
  740. return;
  741. c->u.btn->activate();
  742. }
  743. Fl_DevCfgGroup::ctl_t* Fl_DevCfgGroup::_idToCtl( unsigned id )
  744. {
  745. unsigned i = 0;
  746. for(i=0; i<_ctlV.size(); ++i)
  747. if( _ctlV[i]->id == id )
  748. return _ctlV[i];
  749. assert(0);
  750. return NULL;
  751. }
  752. void Fl_DevCfgGroup::_s_ctl_cb( Fl_Widget* w, void* arg )
  753. {
  754. ctl_t* c = (ctl_t*)arg;
  755. switch( c->id )
  756. {
  757. // ------------------------------------------------------------
  758. // Location
  759. case kLocLabelCId:
  760. break;
  761. case kLocMenuCId:
  762. c->p->_recallLoc();
  763. break;
  764. case kLocStoreBtnCId:
  765. c->p->_storeLoc();
  766. break;
  767. case kLocStringCId:
  768. c->p->_enableStoreBtn(kLocStoreBtnCId);
  769. break;
  770. case kLocDeleteBtnCId:
  771. c->p->_deleteLoc();
  772. break;
  773. // ------------------------------------------------------------
  774. // MIDI
  775. case kMidiCfgMenuCId:
  776. c->p->_recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId );
  777. break;
  778. case kMidiDeleteBtnCId:
  779. c->p->_deleteCfg(kMidiDcmTId,kMidiCfgMenuCId,kMidiCfgStringCId,kMidiCfgDescCId,kMidiApplyBtnCId,kMidiDeleteBtnCId);
  780. break;
  781. case kMidiCfgStringCId:
  782. c->p->_enableStoreBtn(kMidiApplyBtnCId);
  783. break;
  784. case kMidiApplyBtnCId:
  785. c->p->_createMidiCfg();
  786. c->p->_recallCfg(kMidiDcmTId, kMidiCfgMenuCId, kMidiCfgStringCId, kMidiCfgDescCId, kMidiApplyBtnCId );
  787. break;
  788. case kMidiDevMenuCId:
  789. c->p->_setMenuBtnLabel(c->id);
  790. c->p->_loadMidiPortBtn();
  791. c->p->_enableStoreBtn(kMidiApplyBtnCId);
  792. break;
  793. case kMidiPortMenuCId:
  794. c->p->_setMenuBtnLabel(c->id);
  795. c->p->_enableStoreBtn(kMidiApplyBtnCId);
  796. break;
  797. case kMidiInputCheckCId:
  798. c->p->_enableStoreBtn(kMidiApplyBtnCId);
  799. break;
  800. // ------------------------------------------------------------
  801. // Audio
  802. case kAudioLabelCId:
  803. break;
  804. case kAudioCfgMenuCId:
  805. c->p->_recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId );
  806. break;
  807. case kAudioDeleteBtnCId:
  808. c->p->_deleteCfg(kAudioDcmTId,kAudioCfgMenuCId,kAudioCfgStringCId,kAudioCfgDescCId, kAudioApplyBtnCId, kAudioDeleteBtnCId);
  809. break;
  810. case kAudioCfgStringCId:
  811. c->p->_enableStoreBtn(kAudioApplyBtnCId);
  812. break;
  813. case kAudioApplyBtnCId:
  814. c->p->_createAudioCfg();
  815. c->p->_recallCfg(kAudioDcmTId, kAudioCfgMenuCId, kAudioCfgStringCId, kAudioCfgDescCId, kAudioApplyBtnCId );
  816. break;
  817. case kAudioInDevMenuCId:
  818. c->p->_setMenuBtnLabel(c->id);
  819. c->p->_enableStoreBtn(kAudioApplyBtnCId);
  820. break;
  821. case kAudioOutDevMenuCId:
  822. c->p->_setMenuBtnLabel(c->id);
  823. c->p->_enableStoreBtn(kAudioApplyBtnCId);
  824. break;
  825. case kAudioSrateMenuCId:
  826. c->p->_setMenuBtnLabel(c->id);
  827. c->p->_enableStoreBtn(kAudioApplyBtnCId);
  828. break;
  829. case kAudioActiveCheckCId:
  830. case kAudioMsgQueSizeValCId:
  831. case kAudioDevFpCValCId:
  832. case kAudioDspFpCValCId:
  833. case kAudioBufCntValCId:
  834. case kAudioSyncInCheckCId:
  835. case kAudioNetNodeStringCId:
  836. case kAudioBcastAddrStringCId:
  837. case kAudioIpAddrStringCId:
  838. case kAudioIpPortValCId:
  839. c->p->_enableStoreBtn(kAudioApplyBtnCId);
  840. break;
  841. // ------------------------------------------------------------
  842. // Network
  843. /*
  844. case kNetLabelCId:
  845. break;
  846. case kNetCfgMenuCId:
  847. c->p->_recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId );
  848. break;
  849. case kNetDeleteBtnCId:
  850. c->p->_deleteCfg(kNetDcmTId,kNetCfgMenuCId,kNetCfgStringCId,kNetCfgDescCId, kNetApplyBtnCId, kNetDeleteBtnCId);
  851. break;
  852. case kNetCfgStringCId:
  853. c->p->_enableStoreBtn(kNetApplyBtnCId);
  854. break;
  855. case kNetApplyBtnCId:
  856. c->p->_createNetCfg();
  857. c->p->_recallCfg(kNetDcmTId, kNetCfgMenuCId, kNetCfgStringCId, kNetCfgDescCId, kNetApplyBtnCId );
  858. c->p->_enableStoreBtn(kNetApplyBtnCId);
  859. break;
  860. case kNetSockAddrStringCId:
  861. case kNetPortNumbValCId:
  862. case kNetActiveCheckCId:
  863. c->p->_enableStoreBtn(kNetApplyBtnCId);
  864. break;
  865. */
  866. default:
  867. break;
  868. }
  869. }