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 30KB

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