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.

973 lines
29KB

  1. /* LADSPAPluginGUI.C
  2. * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
  3. * LADSPA Plugin by Nicolas Noble <nicolas@nobis-crew.org>
  4. * Modified by Mike Rawes <myk@waxfrenzy.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. #include <cstdio>
  21. #include <cmath>
  22. #include <cstring>
  23. #include <dlfcn.h>
  24. #include <vector>
  25. #include <algorithm>
  26. #include <FL/fl_draw.H>
  27. #include <FL/Fl_Tooltip.H>
  28. #include "LADSPAPluginGUI.h"
  29. #include "LADSPAInfo.h"
  30. LADSPAPluginGUI::LADSPAPluginGUI(int w, int h,
  31. LADSPAPlugin *o,
  32. ChannelHandler *ch,
  33. const HostInfo *Info,
  34. const vector<LADSPAInfo::PluginEntry> &PVec) :
  35. SpiralPluginGUI(w,h,o,ch)
  36. {
  37. m_GUIColour = (Fl_Color)Info->GUI_COLOUR;
  38. m_PluginList = PVec;
  39. // Get maximum input port count
  40. m_GUICH->GetData("GetMaxInputPortCount",&(m_MaxInputPortCount));
  41. // Set up buffers for data transfer via ChannelHandler
  42. m_InputPortNames = (char *)malloc(256 * m_MaxInputPortCount);
  43. m_InputPortSettings = (PortSetting *)malloc(sizeof(PortSetting) * m_MaxInputPortCount);
  44. m_InputPortValues = (PortValue *)calloc(m_MaxInputPortCount, sizeof(PortValue));
  45. m_InputPortDefaults = (float *)calloc(m_MaxInputPortCount, sizeof(float));
  46. if (!(m_InputPortNames && m_InputPortSettings &&
  47. m_InputPortValues && m_InputPortDefaults)) {
  48. cerr<<"LADSPA Plugin (GUI): Memory allocation error\n"<<endl;
  49. }
  50. // Set up widgets
  51. m_NameLabel = new Fl_Box(10,20,480,15,"None");
  52. m_NameLabel->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
  53. m_NameLabel->labelcolor(Info->GUI_COLOUR);
  54. m_NameLabel->labelsize(12);
  55. add(m_NameLabel);
  56. m_MakerLabel = new Fl_Box(10,40,480,15,"None");
  57. m_MakerLabel->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
  58. m_MakerLabel->labelcolor(Info->GUI_COLOUR);
  59. m_MakerLabel->labelsize(12);
  60. add(m_MakerLabel);
  61. m_Tab = new Fl_Tabs (5, 60, 490, 250, "");
  62. m_Tab->box (FL_PLASTIC_DOWN_BOX);
  63. m_Tab->callback((Fl_Callback *)cb_TabChange);
  64. add(m_Tab);
  65. m_ControlGroup = new Fl_Group (5, 80, 490, 230, "Control");
  66. m_ControlGroup->box (FL_PLASTIC_UP_BOX);
  67. m_ControlGroup->labelsize(12);
  68. m_ControlScroll = new Fl_Scroll (10, 85, 480, 220, "");
  69. m_ControlScroll->align(FL_ALIGN_TOP_LEFT);
  70. m_ControlScroll->type(Fl_Scroll::VERTICAL);
  71. m_ControlGroup->add(m_ControlScroll);
  72. m_ControlPack = new Fl_Pack (10, 85, 480, 220, "");
  73. m_ControlScroll->add(m_ControlPack);
  74. m_SetupGroup = new Fl_Group (5, 80, 490, 230, "Setup");
  75. m_SetupGroup->box (FL_PLASTIC_UP_BOX);
  76. m_SetupGroup->labelsize(12);
  77. m_Browser = new Fl_Choice(50,85,440,22,"Plugin:");
  78. m_Browser->labelsize(12);
  79. m_Browser->textsize(12);
  80. m_Browser->callback((Fl_Callback *)cb_Select);
  81. m_Browser->add("(None)");
  82. m_PluginIDLookup.push_back(0);
  83. // The plugin list is already formatted for addition to our drop-down,
  84. // so just add all items as they are
  85. unsigned long size = m_Browser->size();
  86. int depth = 1;
  87. for (vector<LADSPAInfo::PluginEntry>::iterator i=m_PluginList.begin();
  88. i!=m_PluginList.end(); i++)
  89. {
  90. m_Browser->add(i->Name.c_str());
  91. unsigned int dsize = m_Browser->size() - size;
  92. int ddepth = i->Depth - depth;
  93. size = m_Browser->size();
  94. depth = i->Depth;
  95. // Add blanks to ID Lookup vector to account for sub-menus
  96. for (unsigned long j = 1; j < (dsize - ddepth); j++) {
  97. m_PluginIDLookup.push_back(0);
  98. }
  99. // Add to ID Lookup vector (this maps Menu Items to Unique IDs)
  100. m_PluginIDLookup.push_back(i->UniqueID);
  101. }
  102. m_Browser->value(0);
  103. m_SetupGroup->add(m_Browser);
  104. m_InputScroll = new Fl_Scroll(10,130,480,145);
  105. m_InputScroll->labelsize(12);
  106. m_InputScroll->align(FL_ALIGN_TOP_LEFT);
  107. m_InputScroll->type(Fl_Scroll::VERTICAL);
  108. m_InputScroll->box(FL_DOWN_BOX);
  109. m_InputPack = new Fl_Pack(5,135,460,26,"");
  110. m_InputScroll->add(m_InputPack);
  111. m_SetupGroup->add(m_InputScroll);
  112. m_ValueLabel = new Fl_Box(15,115,60,15,"Value");
  113. m_ValueLabel->labelsize(12);
  114. m_SetupGroup->add(m_ValueLabel);
  115. m_DefaultLabel = new Fl_Box(77,115,60,15,"Default");
  116. m_DefaultLabel->labelsize(12);
  117. m_SetupGroup->add(m_DefaultLabel);
  118. m_MinLabel = new Fl_Box(139,115,60,15,"Min");
  119. m_MinLabel->labelsize(12);
  120. m_SetupGroup->add(m_MinLabel);
  121. m_MaxLabel = new Fl_Box(201,115,60,15,"Max");
  122. m_MaxLabel->labelsize(12);
  123. m_SetupGroup->add(m_MaxLabel);
  124. m_ClampLabel = new Fl_Box(280,115,10,15,"Clamp?");
  125. m_ClampLabel->labelsize(12);
  126. m_SetupGroup->add(m_ClampLabel);
  127. m_PortLabel = new Fl_Box(325,115,60,15,"Port Name");
  128. m_PortLabel->labelsize(12);
  129. m_SetupGroup->add(m_PortLabel);
  130. m_UpdateInputs = new Fl_LED_Button (10, 282, 25, 25, "Update input values?");
  131. m_UpdateInputs->labelsize(12);
  132. m_UpdateInputs->value(true);
  133. m_UpdateInputs->callback((Fl_Callback *)cb_UpdateInputs);
  134. m_SetupGroup->add(m_UpdateInputs);
  135. m_Tab->add(m_ControlGroup);
  136. m_Tab->add(m_SetupGroup);
  137. m_Tab->value(m_SetupGroup);
  138. m_TabIndex = 1;
  139. m_PortIndex = 0;
  140. end();
  141. }
  142. LADSPAPluginGUI::~LADSPAPluginGUI(void)
  143. {
  144. if (m_InputPortNames) free(m_InputPortNames);
  145. if (m_InputPortSettings) free(m_InputPortSettings);
  146. if (m_InputPortValues) free(m_InputPortValues);
  147. if (m_InputPortDefaults) free(m_InputPortDefaults);
  148. m_PluginIDLookup.clear();
  149. Fl::check();
  150. }
  151. // Rearrange knobs depending on connections
  152. // Knobs corresponding to connected ports are hidden,
  153. // the rest are shown
  154. void LADSPAPluginGUI::UpdatePortControlKnobs(void)
  155. {
  156. int column = 0;
  157. // First, clear out all groups in Pack
  158. // We need to remove all the knobs first, or they'll go
  159. // with the group. Which would be bad.
  160. while (m_ControlPack->children() > 0) {
  161. Fl_Group *Group = (Fl_Group *)m_ControlPack->child(0);
  162. while (Group->children() > 0) {
  163. Fl_Knob *Knob = (Fl_Knob *)Group->child(0);
  164. Group->remove(Knob);
  165. }
  166. m_ControlPack->remove(Group);
  167. }
  168. Fl_Group *NewGroup = new Fl_Group(0,0,460,65,"");
  169. NewGroup->box(FL_FLAT_BOX);
  170. m_ControlPack->add(NewGroup);
  171. for (unsigned long p = 0; p < m_InputPortCount; p++)
  172. {
  173. if (!m_InputPortValues[p].Connected) {
  174. m_PortControlKnobs[p]->position(50 + column * 105, 0);
  175. m_PortControlKnobs[p]->show();
  176. NewGroup->add(m_PortControlKnobs[p]);
  177. column++;
  178. if ((column > 3) && (p < m_InputPortCount - 1)) {
  179. NewGroup = new Fl_Group(0,0,460,65,"");
  180. NewGroup->box(FL_FLAT_BOX);
  181. m_ControlPack->add(NewGroup);
  182. column = 0;
  183. }
  184. } else {
  185. m_PortControlKnobs[p]->hide();
  186. }
  187. }
  188. m_ControlScroll->redraw();
  189. }
  190. // This lot is only done on patch load
  191. void LADSPAPluginGUI::UpdateValues(SpiralPlugin *o)
  192. {
  193. LADSPAPlugin* Plugin = (LADSPAPlugin*)o;
  194. SetUniqueID(Plugin->GetUniqueID());
  195. SetName(Plugin->GetName());
  196. SetMaker(Plugin->GetMaker());
  197. SetTabIndex(Plugin->GetTabIndex());
  198. SetUpdateInputs(Plugin->GetUpdateInputs());
  199. m_InputPortCount = Plugin->GetInputPortCount();
  200. const char *name;
  201. for (unsigned long p = 0; p < m_InputPortCount; p++) {
  202. name = Plugin->GetInputPortName(p);
  203. strncpy((char *)(m_InputPortNames + p * 256), name, 256);
  204. m_InputPortSettings[p] = Plugin->GetInputPortSetting(p);
  205. m_InputPortDefaults[p] = Plugin->GetInputPortDefault(p);
  206. AddPortInfo(p);
  207. SetPortSettings(p);
  208. SetPortControlKnobValue(p);
  209. }
  210. UpdatePortControlKnobs();
  211. m_PortIndex = m_InputPortCount;
  212. }
  213. // ****************************************************************************
  214. // ** Protected Member Functions **
  215. // ****************************************************************************
  216. const string LADSPAPluginGUI::GetHelpText(const string &loc)
  217. {
  218. // if (loc == "DE") {
  219. // } else if (loc == "FR") {
  220. // } else {
  221. // Default to English?
  222. return string("LADSPA Plugin\n")
  223. + "\n"
  224. + "This plugin allows you to use any LADSPA plugin in SSM.\n"
  225. + "\n"
  226. + "It grows or shrinks the device GUI to allow you to connect\n"
  227. + "up the ports as any other native SSM plugin, so you can\n"
  228. + "seamlessly use the plugins as part of your layouts.\n"
  229. + "\n"
  230. + "The GUI window has two tabbed sections, Control and Setup.\n"
  231. + "\n"
  232. + "Setup is used to choose which LADSPA plugin to use, and\n"
  233. + "allows you to configure port information.\n"
  234. + "\n"
  235. + "Once you have chosen a plugin, a row will appear for each\n"
  236. + "input port:\n"
  237. + "\n"
  238. + "Value\n"
  239. + " The value being input to the port from a connection.\n"
  240. + "Default\n"
  241. + " The value used as input if there is no connection. If\n"
  242. + " the port is connected, the default will use the value.\n"
  243. + " Upon disconnection, it will retain the last value\n"
  244. + " received.\n"
  245. + "Min, Max\n"
  246. + " The range of values to scale a connected signal to,\n"
  247. + " assuming the signal is in the range -1.0 to +1.0.\n"
  248. + "Clamp\n"
  249. + " Whether to scale inputs - if unchecked, the input is\n"
  250. + " not scaled.\n"
  251. + "Port Name\n"
  252. + " The name of the port, as supplied by the plugin.\n"
  253. + "\n"
  254. + "The Control tab will display a control knob for each port\n"
  255. + "that is not connected. This allows adjustment of input\n"
  256. + "directly.";
  257. // }
  258. }
  259. // ****************************************************************************
  260. // ** Private Member Functions **
  261. // ****************************************************************************
  262. void LADSPAPluginGUI::SetTabIndex(int index)
  263. {
  264. m_TabIndex = index;
  265. if (m_TabIndex == 0) {
  266. m_Tab->value(m_ControlGroup);
  267. } else {
  268. m_Tab->value(m_SetupGroup);
  269. }
  270. }
  271. void LADSPAPluginGUI::SetUpdateInputs(bool state)
  272. {
  273. m_UpdateInputState = state;
  274. m_UpdateInputs->value(m_UpdateInputState);
  275. }
  276. void LADSPAPluginGUI::SetUniqueID(unsigned long n)
  277. {
  278. m_UniqueID = n;
  279. vector<unsigned long>::iterator i = std::find(m_PluginIDLookup.begin(), m_PluginIDLookup.end(), m_UniqueID);
  280. if (i != m_PluginIDLookup.end()) {
  281. m_Browser->value(i - m_PluginIDLookup.begin());
  282. } else {
  283. m_Browser->value(0);
  284. }
  285. }
  286. void LADSPAPluginGUI::SetName(const char *s)
  287. {
  288. m_NameLabel->label(s);
  289. }
  290. void LADSPAPluginGUI::SetMaker(const char *s)
  291. {
  292. char temp[256];
  293. unsigned int len = strlen(s);
  294. strncpy(temp, s, len);
  295. // If this has got an "@" in it FLTK thinks it's a special character not an E.mail address
  296. int t=0;
  297. for (unsigned int f=0; f<len; f++) {
  298. if (t==255) break;
  299. if (temp[f]=='@') m_Maker[t++]='@';
  300. m_Maker[t++]=temp[f];
  301. }
  302. m_Maker[t]=0;
  303. m_MakerLabel->label (m_Maker);
  304. }
  305. void LADSPAPluginGUI::SetPortSettings(unsigned long p)
  306. {
  307. char temp[256];
  308. sprintf(temp,"%.4f", m_InputPortSettings[p].Min);
  309. m_PortMin[p]->value(temp);
  310. sprintf(temp,"%.4f", m_InputPortSettings[p].Max);
  311. m_PortMax[p]->value(temp);
  312. sprintf(temp, "%d", m_InputPortSettings[p].Clamp);
  313. m_PortClamp[p]->value(atoi(temp));
  314. sprintf(temp, "%.4f", m_InputPortDefaults[p]);
  315. m_PortDefault[p]->value(temp);
  316. }
  317. void LADSPAPluginGUI::SetPortControlKnobValue(unsigned long p)
  318. {
  319. // Set default adjust knob
  320. float min = atof(m_PortMin[p]->value());
  321. float max = atof(m_PortMax[p]->value());
  322. float value = atof(m_PortDefault[p]->value());
  323. if (m_InputPortSettings[p].LogBase > 1.0f) {
  324. // Logarithmic control - requires conversion
  325. if (min > 0.0f && max > 0.0f) {
  326. // Straight log
  327. value = logf(value) / logf(m_InputPortSettings[p].LogBase);
  328. } else if (min < 0.0f && max < 0.0f) {
  329. // Inverse, negated log
  330. value = -logf(-value) / logf(m_InputPortSettings[p].LogBase);
  331. } else {
  332. // Linear if asymptote present
  333. // Do nothing
  334. }
  335. }
  336. m_PortControlKnobs[p]->value(value);
  337. }
  338. void LADSPAPluginGUI::SetPortControlKnobRange(unsigned long p, float min, float max)
  339. {
  340. if (m_InputPortSettings[p].Integer) {
  341. // Integer control - integer steps between minimum and maximum
  342. min = floorf(min + 0.5f);
  343. max = floorf(max + 0.5f);
  344. m_PortControlKnobs[p]->minimum(min);
  345. m_PortControlKnobs[p]->maximum(max);
  346. m_PortControlKnobs[p]->step(1.0f);
  347. m_PortControlKnobs[p]->scaleticks((int)(max - min));
  348. } else {
  349. if (m_InputPortSettings[p].LogBase > 1.0f) {
  350. // Continuous logarithmic control
  351. if (min > 0.0f && max > 0.0f) {
  352. // Log of range
  353. min = logf(min) / logf(m_InputPortSettings[p].LogBase);
  354. max = logf(max) / logf(m_InputPortSettings[p].LogBase);
  355. } else if (min < 0.0f && max < 0.0f) {
  356. // Negative log of range
  357. min = -logf(-min) / logf(m_InputPortSettings[p].LogBase);
  358. max = -logf(-max) / logf(m_InputPortSettings[p].LogBase);
  359. } else {
  360. // Linear if asymptote present
  361. // Do nothing
  362. }
  363. m_PortControlKnobs[p]->minimum(min);
  364. m_PortControlKnobs[p]->maximum(max);
  365. m_PortControlKnobs[p]->step((max - min) / 10000.0f);
  366. } else {
  367. // Continuous linear control - 10000 steps between min and max
  368. m_PortControlKnobs[p]->minimum(min);
  369. m_PortControlKnobs[p]->maximum(max);
  370. m_PortControlKnobs[p]->step((max - min) / 10000.0f);
  371. }
  372. }
  373. }
  374. void LADSPAPluginGUI::AddPortInfo(unsigned long p)
  375. {
  376. Fl_Group* NewGroup = new Fl_Group(0,0,460,24,"");
  377. NewGroup->box(FL_FLAT_BOX);
  378. m_InputPack->add(NewGroup);
  379. // Value
  380. Fl_Output* NewOutput = new Fl_Output(10,0,60,18,"");
  381. NewOutput->value(0);
  382. NewOutput->textsize(10);
  383. NewOutput->color(FL_BACKGROUND_COLOR);
  384. NewOutput->readonly(1);
  385. NewGroup->add(NewOutput);
  386. m_PortValue.push_back(NewOutput);
  387. // Fixed Value/Default
  388. Fl_Input* NewInput = new Fl_Input(72,0,60,18,"");
  389. NewInput->value(0);
  390. NewInput->textsize(10);
  391. NewInput->callback((Fl_Callback *)cb_Default);
  392. NewGroup->add(NewInput);
  393. m_PortDefault.push_back(NewInput);
  394. // Min
  395. NewInput = new Fl_Input(134,0,60,18,"");
  396. NewInput->value(0);
  397. NewInput->textsize(10);
  398. NewInput->callback((Fl_Callback *)cb_Min);
  399. NewGroup->add(NewInput);
  400. m_PortMin.push_back(NewInput);
  401. // Max
  402. NewInput = new Fl_Input(196,0,60,18,"");
  403. NewInput->value(0);
  404. NewInput->textsize(10);
  405. NewInput->callback((Fl_Callback *)cb_Max);
  406. NewGroup->add(NewInput);
  407. m_PortMax.push_back(NewInput);
  408. // Clamp
  409. Fl_Check_Button* NewCheckButton = new Fl_Check_Button(265,0,10,18,"");
  410. NewCheckButton->value(0);
  411. NewCheckButton->callback((Fl_Callback *)cb_Clamp);
  412. NewGroup->add(NewCheckButton);
  413. m_PortClamp.push_back(NewCheckButton);
  414. // Port Name
  415. Fl_Box* NewText = new Fl_Box(320,0,10,18,"");
  416. NewText->label((const char *)(m_InputPortNames + p * 256));
  417. NewText->labelsize(10);
  418. NewText->tooltip((const char *)(m_InputPortNames + p * 256));
  419. NewText->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
  420. NewGroup->add(NewText);
  421. NewGroup->redraw();
  422. m_InputPack->redraw();
  423. m_InputScroll->redraw();
  424. // Control knobs - these aren't displayed yet, as their display will depend
  425. // on what is connected. All that is decided in UpdateControlKnobs()
  426. int len = strlen((const char *)(m_InputPortNames + p * 256));
  427. len -= 5; // Get rid of (CV), (AU) bit
  428. len = len > 20 ? 20 : len; // Truncate to fit
  429. char *label = (char *)malloc(len + 1);
  430. if (label)
  431. {
  432. strncpy(label, (const char *)(m_InputPortNames + p * 256), len);
  433. label[len] = '\0';
  434. }
  435. m_PortControlLabels.push_back(label);
  436. Fl_Knob* NewKnob = new Fl_Knob(0,0,40,40,"");
  437. NewKnob->label(m_PortControlLabels[m_PortControlLabels.size() - 1]);
  438. NewKnob->labelsize(10);
  439. NewKnob->color(m_GUIColour);
  440. NewKnob->callback((Fl_Callback *)cb_DefaultAdjust);
  441. NewKnob->hide();
  442. m_PortControlKnobs.push_back(NewKnob);
  443. // Set up range for knob (integer, logarithmic etc)
  444. SetPortControlKnobRange(p, m_InputPortSettings[p].Min, m_InputPortSettings[p].Max);
  445. }
  446. // This is done all the time
  447. void LADSPAPluginGUI::Update(void)
  448. {
  449. char temp[256];
  450. bool state_changed = false;
  451. m_GUICH->GetData("GetInputPortCount", &(m_InputPortCount));
  452. m_GUICH->GetData("GetInputPortValues", m_InputPortValues);
  453. m_GUICH->GetData("GetInputPortDefaults", m_InputPortDefaults);
  454. // Need to show that a connection is present
  455. // regardless of Refresh being set
  456. for (unsigned long p = 0; p < m_InputPortCount; p++) {
  457. // Check if plugin connect state is different to GUI state
  458. // A readonly default implies connection
  459. if ((m_InputPortValues[p].Connected &&
  460. !(m_PortDefault[p]->readonly())) ||
  461. (m_PortDefault[p]->readonly() &&
  462. !(m_InputPortValues[p].Connected))) {
  463. if (m_InputPortValues[p].Connected) {
  464. // Disable
  465. m_PortDefault[p]->readonly(1);
  466. m_PortDefault[p]->color(FL_BACKGROUND_COLOR);
  467. } else {
  468. // Enable
  469. m_PortDefault[p]->readonly(0);
  470. m_PortDefault[p]->color(FL_BACKGROUND2_COLOR);
  471. }
  472. sprintf(temp,"%.4f", m_InputPortDefaults[p]);
  473. m_PortDefault[p]->value(temp);
  474. m_PortDefault[p]->redraw();
  475. SetPortControlKnobValue(p);
  476. state_changed = true;
  477. }
  478. // Only update values if Refresh is set
  479. if (m_UpdateInputs->value()) {
  480. sprintf(temp,"%.4f", m_InputPortValues[p].Value);
  481. m_PortValue[p]->value(temp);
  482. if (m_InputPortValues[p].Connected) {
  483. sprintf(temp,"%.4f", m_InputPortDefaults[p]);
  484. m_PortDefault[p]->value(temp);
  485. }
  486. }
  487. }
  488. // If a connection has been added/removed, we need to
  489. // rearrange the knobs
  490. if (state_changed) UpdatePortControlKnobs();
  491. }
  492. void LADSPAPluginGUI::ClearPlugin(void)
  493. {
  494. m_InputPortCount = 0;
  495. m_PortIndex = 0;
  496. m_GUICH->SetCommand(LADSPAPlugin::CLEARPLUGIN);
  497. m_GUICH->Wait();
  498. // Clear out port info, and refresh
  499. m_InputScroll->remove(m_InputPack);
  500. delete m_InputPack;
  501. m_InputPack = new Fl_Pack(x()+5,y()+135,460,26,"");
  502. m_InputScroll->add(m_InputPack);
  503. // Oh, and the knobs...
  504. m_ControlScroll->remove(m_ControlPack);
  505. delete m_ControlPack;
  506. m_ControlPack = new Fl_Pack(x()+5,y()+90,460,50,"");
  507. m_ControlScroll->add(m_ControlPack);
  508. m_PortValue.clear();
  509. m_PortMin.clear();
  510. m_PortMax.clear();
  511. m_PortClamp.clear();
  512. m_PortDefault.clear();
  513. m_PortControlKnobs.clear();
  514. for (vector<char *>::iterator i = m_PortControlLabels.begin();
  515. i != m_PortControlLabels.end(); i++)
  516. {
  517. if (*i) free (*i);
  518. }
  519. m_PortControlLabels.clear();
  520. redraw();
  521. }
  522. void LADSPAPluginGUI::SelectPlugin(void)
  523. {
  524. // Now get the new values to populate GUI controls
  525. m_GUICH->GetData("GetName", m_Name);
  526. m_GUICH->GetData("GetMaker", m_Maker);
  527. m_GUICH->GetData("GetInputPortCount", &(m_InputPortCount));
  528. m_GUICH->GetData("GetInputPortNames", m_InputPortNames);
  529. m_GUICH->GetData("GetInputPortSettings", m_InputPortSettings);
  530. m_GUICH->GetData("GetInputPortDefaults", m_InputPortDefaults);
  531. SetName((const char *)m_Name);
  532. SetMaker((const char *)m_Maker);
  533. for (unsigned long p = 0; p < m_InputPortCount; p++) {
  534. AddPortInfo(p);
  535. SetPortSettings(p);
  536. SetPortControlKnobValue(p);
  537. }
  538. UpdatePortControlKnobs();
  539. m_PortIndex = m_InputPortCount;
  540. redraw();
  541. }
  542. // ****************************************************************************
  543. // ** Widget Callback Functions **
  544. // ****************************************************************************
  545. inline void LADSPAPluginGUI::cb_TabChange_i(Fl_Tabs *o)
  546. {
  547. m_TabIndex = o->find(o->value());
  548. m_GUICH->SetData("SetTabIndex", &m_TabIndex);
  549. m_GUICH->SetCommand(LADSPAPlugin::SETTABINDEX);
  550. }
  551. void LADSPAPluginGUI::cb_TabChange(Fl_Tabs *o)
  552. { // GUI
  553. ((LADSPAPluginGUI*)(o->parent()))->cb_TabChange_i(o);
  554. }
  555. inline void LADSPAPluginGUI::cb_Select_i(Fl_Choice* o)
  556. {
  557. ClearPlugin();
  558. unsigned long m_UniqueID = m_PluginIDLookup[o->value()];
  559. if (m_UniqueID != 0) {
  560. // Plugin selected
  561. m_GUICH->SetData("SetUniqueID",&m_UniqueID);
  562. m_GUICH->SetCommand(LADSPAPlugin::SELECTPLUGIN);
  563. m_GUICH->Wait();
  564. }
  565. SelectPlugin();
  566. // redraw();
  567. }
  568. void LADSPAPluginGUI::cb_Select(Fl_Choice* o)
  569. { // Group Tab GUI
  570. ((LADSPAPluginGUI*)(o->parent()->parent()->parent()))->cb_Select_i(o);
  571. }
  572. inline void LADSPAPluginGUI::cb_UpdateInputs_i(Fl_LED_Button* o)
  573. {
  574. m_UpdateInputState = (bool)(o->value());
  575. m_GUICH->SetData("SetUpdateInputs", &m_UpdateInputState);
  576. m_GUICH->SetCommand(LADSPAPlugin::SETUPDATEINPUTS);
  577. }
  578. void LADSPAPluginGUI::cb_UpdateInputs(Fl_LED_Button* o)
  579. { // Group Tab GUI
  580. ((LADSPAPluginGUI*)(o->parent()->parent()->parent()))->cb_UpdateInputs_i(o);
  581. }
  582. inline void LADSPAPluginGUI::cb_Default_i(Fl_Input* o)
  583. {
  584. // Which Default was changed?
  585. bool do_search = false;
  586. if (m_PortIndex == m_PortDefault.size()) { do_search = true; }
  587. if (!do_search) { do_search = (o != (m_PortDefault[m_PortIndex])) ? true : false; }
  588. if (do_search) {
  589. // Only bother to re-query if it is different from last one changed
  590. vector<Fl_Input *>::iterator i = std::find(m_PortDefault.begin(),
  591. m_PortDefault.end(),
  592. o);
  593. m_PortIndex = distance(m_PortDefault.begin(), i);
  594. }
  595. m_Default = atof(o->value());
  596. m_Min = atof(m_PortMin[m_PortIndex]->value());
  597. m_Max = atof(m_PortMax[m_PortIndex]->value());
  598. // Pass current port index
  599. m_GUICH->SetData("SetInputPortIndex", &m_PortIndex);
  600. // If default is out of [Min, Max] range, stretch range
  601. if (m_Default < m_Min) {
  602. m_PortMin[m_PortIndex]->value(m_PortDefault[m_PortIndex]->value());
  603. m_PortMin[m_PortIndex]->redraw();
  604. m_Min = m_Default;
  605. // Pass new Minimum to plugin
  606. m_GUICH->SetData("SetInputPortMin", &m_Min);
  607. m_GUICH->SetCommand(LADSPAPlugin::SETMAX);
  608. m_GUICH->Wait();
  609. // Reconfigure knob range
  610. SetPortControlKnobRange(m_PortIndex, m_Min, m_Max);
  611. } else if (m_Default > m_Max) {
  612. m_PortMax[m_PortIndex]->value(m_PortDefault[m_PortIndex]->value());
  613. m_PortMax[m_PortIndex]->redraw();
  614. m_Max = m_Default;
  615. // Pass new Maximum to plugin
  616. m_GUICH->SetData("SetInputPortMax", &m_Max);
  617. m_GUICH->SetCommand(LADSPAPlugin::SETMAX);
  618. m_GUICH->Wait();
  619. // Reconfigure knob range
  620. SetPortControlKnobRange(m_PortIndex, m_Min, m_Max);
  621. }
  622. // Pass new default to plugin
  623. m_GUICH->SetData("SetInputPortDefault", &m_Default);
  624. m_GUICH->SetCommand(LADSPAPlugin::SETDEFAULT);
  625. // Set knob to corresponding position
  626. SetPortControlKnobValue(m_PortIndex);
  627. }
  628. void LADSPAPluginGUI::cb_Default(Fl_Input* o)
  629. { // Group Pack Scroll Group Tab GUI
  630. ((LADSPAPluginGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()))->cb_Default_i(o);
  631. }
  632. inline void LADSPAPluginGUI::cb_Min_i(Fl_Input* o)
  633. {
  634. // Which Min was changed?
  635. bool do_search = false;
  636. if (m_PortIndex == m_PortMin.size()) { do_search = true; }
  637. if (!do_search) { do_search = (o != (m_PortMin[m_PortIndex])) ? true : false; }
  638. if (do_search) {
  639. // Only bother to re-query if it is different from last one changed
  640. vector<Fl_Input *>::iterator i = std::find(m_PortMin.begin(),
  641. m_PortMin.end(),
  642. o);
  643. m_PortIndex = distance(m_PortMin.begin(), i);
  644. }
  645. // Pass current port index
  646. m_GUICH->SetData("SetInputPortIndex", &m_PortIndex);
  647. // Check that min is really min and max is really max
  648. m_Min = atof(o->value());
  649. m_Max = atof(m_PortMax[m_PortIndex]->value());
  650. if (m_Min > m_Max) {
  651. // Swap min and max (need to set max as well)
  652. float min = m_Min;
  653. m_Min = m_Max;
  654. m_Max = min;
  655. m_GUICH->SetData("SetInputPortMax", &m_Max);
  656. m_GUICH->SetCommand(LADSPAPlugin::SETMAX);
  657. m_GUICH->Wait();
  658. // Swap displayed min and max
  659. char temp[256];
  660. strncpy(temp, m_PortMin[m_PortIndex]->value(), 256);
  661. m_PortMin[m_PortIndex]->value(m_PortMax[m_PortIndex]->value());
  662. m_PortMax[m_PortIndex]->value(temp);
  663. m_PortMin[m_PortIndex]->redraw();
  664. m_PortMax[m_PortIndex]->redraw();
  665. }
  666. m_GUICH->SetData("SetInputPortMin", &m_Min);
  667. m_GUICH->SetCommand(LADSPAPlugin::SETMIN);
  668. // Clip default to range
  669. m_Default = atof(m_PortDefault[m_PortIndex]->value());
  670. if (m_Default < m_Min) {
  671. m_Default = m_Min;
  672. m_GUICH->SetData("SetInputPortDefault",&m_Default);
  673. m_GUICH->Wait();
  674. m_GUICH->SetCommand(LADSPAPlugin::SETDEFAULT);
  675. // Print to displayed default
  676. char temp[256];
  677. sprintf(temp, "%.4f", m_Default);
  678. m_PortDefault[m_PortIndex]->value(temp);
  679. m_PortDefault[m_PortIndex]->redraw();
  680. }
  681. // Reposition and reconfigure knob to reflect new range
  682. SetPortControlKnobValue(m_PortIndex);
  683. SetPortControlKnobRange(m_PortIndex, m_Min, m_Max);
  684. }
  685. void LADSPAPluginGUI::cb_Min(Fl_Input* o)
  686. { // Group Pack Scroll Group Tab GUI
  687. ((LADSPAPluginGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()))->cb_Min_i(o);
  688. }
  689. inline void LADSPAPluginGUI::cb_Max_i(Fl_Input* o)
  690. {
  691. // Which Max was changed?
  692. bool do_search = false;
  693. if (m_PortIndex == m_PortMax.size()) { do_search = true; }
  694. if (!do_search) { do_search = (o != (m_PortMax[m_PortIndex])) ? true : false; }
  695. if (do_search) {
  696. // Only bother to re-query if it is different from last one changed
  697. vector<Fl_Input *>::iterator i = std::find(m_PortMax.begin(),
  698. m_PortMax.end(),
  699. o);
  700. m_PortIndex = distance(m_PortMax.begin(), i);
  701. }
  702. // Pass value to plugin
  703. m_GUICH->SetData("SetInputPortIndex", &m_PortIndex);
  704. // Check that min is really min and max is really max
  705. m_Max = atof(o->value());
  706. m_Min = atof(m_PortMin[m_PortIndex]->value());
  707. if (m_Min > m_Max) {
  708. // Swap min and max (need to set max as well)
  709. float max = m_Min;
  710. m_Min = m_Max;
  711. m_Max = max;
  712. m_GUICH->SetData("SetInputPortMin", &m_Min);
  713. m_GUICH->SetCommand(LADSPAPlugin::SETMIN);
  714. m_GUICH->Wait();
  715. // Swap displayed min and max
  716. char temp[256];
  717. strncpy(temp, m_PortMax[m_PortIndex]->value(), 256);
  718. m_PortMax[m_PortIndex]->value(m_PortMin[m_PortIndex]->value());
  719. m_PortMin[m_PortIndex]->value(temp);
  720. m_PortMax[m_PortIndex]->redraw();
  721. m_PortMin[m_PortIndex]->redraw();
  722. }
  723. m_GUICH->SetData("SetInputPortMax", &m_Max);
  724. m_GUICH->SetCommand(LADSPAPlugin::SETMAX);
  725. // Clip default to range
  726. m_Default = atof(m_PortDefault[m_PortIndex]->value());
  727. if (m_Default > m_Max) {
  728. m_Default = m_Max;
  729. m_GUICH->SetData("SetInputPortDefault",&m_Default);
  730. m_GUICH->Wait();
  731. m_GUICH->SetCommand(LADSPAPlugin::SETDEFAULT);
  732. // Print to displayed default
  733. char temp[256];
  734. sprintf(temp, "%.4f", m_Default);
  735. m_PortDefault[m_PortIndex]->value(temp);
  736. m_PortDefault[m_PortIndex]->redraw();
  737. }
  738. // Reposition and reconfigure knob to reflect new range
  739. SetPortControlKnobValue(m_PortIndex);
  740. SetPortControlKnobRange(m_PortIndex, m_Min, m_Max);
  741. }
  742. void LADSPAPluginGUI::cb_Max(Fl_Input* o)
  743. { // Group Pack Scroll Group Tab GUI
  744. ((LADSPAPluginGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()))->cb_Max_i(o);
  745. }
  746. inline void LADSPAPluginGUI::cb_Clamp_i(Fl_Check_Button* o)
  747. {
  748. // Which Clamp was changed?
  749. bool do_search = false;
  750. if (m_PortIndex == m_PortClamp.size()) { do_search = true; }
  751. if (!do_search) { do_search = (o != (m_PortClamp[m_PortIndex])) ? true : false; }
  752. if (do_search) {
  753. // Only bother to re-query if it is different from last one changed
  754. vector<Fl_Check_Button *>::iterator i = std::find(m_PortClamp.begin(),
  755. m_PortClamp.end(),
  756. o);
  757. m_PortIndex = distance(m_PortClamp.begin(), i);
  758. }
  759. m_Clamp = (bool)(o->value());
  760. // Pass value to plugin
  761. m_GUICH->SetData("SetInputPortIndex", &m_PortIndex);
  762. m_GUICH->SetData("SetInputPortClamp", &m_Clamp);
  763. m_GUICH->SetCommand(LADSPAPlugin::SETCLAMP);
  764. }
  765. void LADSPAPluginGUI::cb_Clamp(Fl_Check_Button* o)
  766. { // Group Pack Scroll Group Tab GUI
  767. ((LADSPAPluginGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()))->cb_Clamp_i(o);
  768. }
  769. inline void LADSPAPluginGUI::cb_DefaultAdjust_i(Fl_Knob *o)
  770. {
  771. // First, find which knob is being adjusted
  772. bool do_search = false;
  773. if (m_PortIndex == m_PortControlKnobs.size()) { do_search = true; }
  774. if (!do_search) { do_search = (o != (m_PortControlKnobs[m_PortIndex])) ? true : false; }
  775. if (do_search) {
  776. // Only bother to re-query knob if it is different from last one adjusted
  777. vector<Fl_Knob *>::iterator i = std::find(m_PortControlKnobs.begin(),
  778. m_PortControlKnobs.end(),
  779. o);
  780. m_PortIndex = distance(m_PortControlKnobs.begin(), i);
  781. }
  782. // Get value
  783. m_Default = o->value();
  784. if (m_InputPortSettings[m_PortIndex].LogBase > 1.0f) {
  785. // Logarithmic control - convert back to actual value
  786. float min = o->minimum();
  787. float max = o->maximum();
  788. if (min > 0.0f && max > 0.0f) {
  789. // Straight exp
  790. m_Default = powf(m_InputPortSettings[m_PortIndex].LogBase, m_Default);
  791. } else if (min < 0.0f && max < 0.0f) {
  792. // Inverse, negated exp
  793. m_Default = -powf(m_InputPortSettings[m_PortIndex].LogBase, -m_Default);
  794. } else {
  795. // Linear if asymptote present
  796. // Do nothing
  797. }
  798. }
  799. // Pass value to plugin
  800. m_GUICH->SetData("SetInputPortIndex", &m_PortIndex);
  801. m_GUICH->SetData("SetInputPortDefault", &m_Default);
  802. m_GUICH->SetCommand(LADSPAPlugin::SETDEFAULT);
  803. // Copy to Default field in Port Setup list
  804. char temp[256];
  805. sprintf(temp, "%.4f", m_Default);
  806. m_PortDefault[m_PortIndex]->value(temp);
  807. }
  808. void LADSPAPluginGUI::cb_DefaultAdjust(Fl_Knob *o)
  809. { // Group Pack Scroll Group Tab GUI
  810. ((LADSPAPluginGUI*)(o->parent()->parent()->parent()->parent()->parent()->parent()))->cb_DefaultAdjust_i(o);
  811. }