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.

578 lines
14KB

  1. /* SpiralSound
  2. * Copyleft (C) 2001 David Griffiths <dave@pawfal.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "LADSPAPlugin.h"
  19. #include "LADSPAPluginGUI.h"
  20. #include <stdio.h>
  21. #include "SpiralIcon.xpm"
  22. #include "utils.h"
  23. #include <algorithm>
  24. ////////////////////////////////////////////
  25. /* FIXME: No matter what, I can't let this as it!! */
  26. static LADSPAPlugin * lg = NULL;
  27. void describePluginLibrary(const char * pcFullFilename, void * pvPluginHandle,
  28. LADSPA_Descriptor_Function pfDescriptorFunction) {
  29. const LADSPA_Descriptor * psDescriptor;
  30. long lIndex;
  31. unsigned long lPluginIndex;
  32. unsigned long lPortIndex;
  33. unsigned long lLength;
  34. LADSPA_PortRangeHintDescriptor iHintDescriptor;
  35. LADSPA_Data fBound;
  36. #define testcond(c,s) { \
  37. if (!(c)) { \
  38. cerr << (s); \
  39. failure = 1; \
  40. } \
  41. }
  42. for (lIndex = 0; (psDescriptor = pfDescriptorFunction(lIndex)) != NULL; lIndex++) {
  43. int failure = 0;
  44. testcond(!LADSPA_IS_REALTIME(psDescriptor->Properties), "ERROR: PLUGIN MUST RUN REAL TIME.\n");
  45. testcond(psDescriptor->instantiate, "ERROR: PLUGIN HAS NO INSTANTIATE FUNCTION.\n");
  46. testcond(psDescriptor->connect_port, "ERROR: PLUGIN HAS NO CONNECT_PORT FUNCTION.\n");
  47. testcond(psDescriptor->run, "ERROR: PLUGIN HAS NO RUN FUNCTION.\n");
  48. testcond(!(psDescriptor->run_adding != 0 && psDescriptor->set_run_adding_gain == 0),
  49. "ERROR: PLUGIN HAS RUN_ADDING FUNCTION BUT NOT SET_RUN_ADDING_GAIN.\n");
  50. testcond(!(psDescriptor->run_adding == 0 && psDescriptor->set_run_adding_gain != 0),
  51. "ERROR: PLUGIN HAS SET_RUN_ADDING_GAIN FUNCTION BUT NOT RUN_ADDING.\n");
  52. testcond(psDescriptor->cleanup, "ERROR: PLUGIN HAS NO CLEANUP FUNCTION.\n");
  53. testcond(!LADSPA_IS_INPLACE_BROKEN(psDescriptor->Properties),
  54. "ERROR: THIS PLUGIN CANNOT USE IN-PLACE PROCESSING.\n");
  55. testcond(psDescriptor->PortCount, "ERROR: PLUGIN HAS NO PORTS.\n");
  56. if (!failure) {
  57. LPluginInfo pi;
  58. pi.Filename = pcFullFilename;
  59. pi.Label = psDescriptor->Label;
  60. pi.Name = psDescriptor->Name;
  61. /* ARGH! I really can't stand this ugly hack */
  62. lg->m_LADSPAList.push_back(pi);
  63. } else {
  64. cerr << "Plugin ignored...\n\n";
  65. }
  66. }
  67. dlclose(pvPluginHandle);
  68. }
  69. void LADSPAPlugin::LoadPluginList(void)
  70. {
  71. m_LADSPAList.clear();
  72. m_CurrentPlugin.Name = "";
  73. m_CurrentPlugin.Filename = "";
  74. m_CurrentPlugin.Label = "";
  75. lg = this;
  76. LADSPAPluginSearch(describePluginLibrary);
  77. lg = NULL;
  78. sort(m_LADSPAList.begin(), m_LADSPAList.end(), LPluginInfoSortAsc());
  79. }
  80. ////////////////////////////////////////////////////
  81. extern "C" {
  82. SpiralPlugin* CreateInstance()
  83. {
  84. return new LADSPAPlugin;
  85. }
  86. char** GetIcon()
  87. {
  88. return SpiralIcon_xpm;
  89. }
  90. int GetID()
  91. {
  92. return 0x0016;
  93. }
  94. }
  95. ///////////////////////////////////////////////////////
  96. LADSPAPlugin::LADSPAPlugin() :
  97. PlugHandle(0),
  98. PlugDesc(NULL),
  99. m_Gain(1.0f),
  100. m_Amped(false)
  101. {
  102. m_Version=3;
  103. m_PluginInfo.Name="LADSPA";
  104. m_PluginInfo.Width=600;
  105. m_PluginInfo.Height=300;
  106. m_PluginInfo.NumInputs=0;
  107. m_PluginInfo.NumOutputs=1;
  108. m_PluginInfo.PortTips.push_back("Nuffink yet");
  109. m_AudioCH->Register("Gain",&m_Gain);
  110. m_AudioCH->Register("Amped",&m_Amped);
  111. m_AudioCH->RegisterData("Desc",ChannelHandler::OUTPUT,&PlugDesc,sizeof(PlugDesc));
  112. m_AudioCH->Register("Num",&m_GUIArgs.Num);
  113. m_AudioCH->Register("Value",&m_GUIArgs.Value);
  114. m_AudioCH->Register("Clamp",&m_GUIArgs.Clamp);
  115. m_AudioCH->RegisterData("Filename",ChannelHandler::INPUT,&m_GUIArgs.Filename,sizeof(m_GUIArgs.Filename));
  116. m_AudioCH->RegisterData("Label",ChannelHandler::INPUT,&m_GUIArgs.Label,sizeof(m_GUIArgs.Label));
  117. LoadPluginList();
  118. }
  119. LADSPAPlugin::~LADSPAPlugin()
  120. {
  121. }
  122. PluginInfo &LADSPAPlugin::Initialise(const HostInfo *Host)
  123. {
  124. PluginInfo& Info = SpiralPlugin::Initialise(Host);
  125. LADSPA_Data *NewPort = new LADSPA_Data[m_HostInfo->BUFSIZE];
  126. m_LADSPABufVec.push_back(NewPort);
  127. return Info;
  128. }
  129. SpiralGUIType *LADSPAPlugin::CreateGUI()
  130. {
  131. return new LADSPAPluginGUI(m_PluginInfo.Width,m_PluginInfo.Height,this,m_AudioCH,m_HostInfo,m_LADSPAList);
  132. }
  133. void LADSPAPlugin::Execute()
  134. {
  135. if (PlugDesc)
  136. {
  137. // convert inputs if exist (zero if not)
  138. for (int n=0; n<m_PluginInfo.NumInputs; n++)
  139. {
  140. if (GetInput(n))
  141. {
  142. if (m_PortClamp[n]) {
  143. // scale input to match hinted range
  144. float Offset=m_PortMin[n];
  145. float Scale=m_PortMax[n]-m_PortMin[n];
  146. //cerr<<n<<" ["<<Scale<<"] ["<<Offset<<"]"<<endl;
  147. for (int i=0; i<m_HostInfo->BUFSIZE; i++)
  148. {
  149. m_LADSPABufVec[n][i]=Offset+(GetInput(n,i)*0.5f+0.5f)*Scale;
  150. //cerr<<Scale<<" "<<Offset<<" "<<m_LADSPABufVec[n][i]<<endl;
  151. }
  152. } else {
  153. // pass input as is
  154. for (int i=0; i<m_HostInfo->BUFSIZE; i++)
  155. {
  156. m_LADSPABufVec[n][i]=GetInput(n,i);
  157. }
  158. }
  159. // Update the GUI outputs with the first value in the buffer
  160. //((LADSPAPluginGUI*)m_GUI)->UpdatePortDisplay(n,m_LADSPABufVec[n][0]);
  161. }
  162. else // zero
  163. {
  164. for (int i=0; i<m_HostInfo->BUFSIZE; i++) m_LADSPABufVec[n][i]=0;
  165. }
  166. }
  167. // run plugin
  168. PlugDesc->run(PlugInstHandle,m_HostInfo->BUFSIZE);
  169. // convert outputs
  170. for (int n=0; n<m_PluginInfo.NumOutputs; n++)
  171. {
  172. /*if (m_Amped)
  173. {
  174. for (int i=0; i<m_HostInfo->BUFSIZE; i++)
  175. {
  176. SetOutput(n,i,m_LADSPABufVec[n+m_PluginInfo.NumInputs][i]*m_Gain*10);
  177. }
  178. }
  179. else*/
  180. {
  181. for (int i=0; i<m_HostInfo->BUFSIZE; i++)
  182. {
  183. SetOutput(n,i,m_LADSPABufVec[n+m_PluginInfo.NumInputs][i]*m_Gain);
  184. }
  185. }
  186. }
  187. }
  188. }
  189. void LADSPAPlugin::ExecuteCommands()
  190. {
  191. if (m_AudioCH->IsCommandWaiting())
  192. {
  193. switch(m_AudioCH->GetCommand())
  194. {
  195. case (SETMIN) : SetMin(m_GUIArgs.Num,m_GUIArgs.Value); break;
  196. case (SETMAX) : SetMax(m_GUIArgs.Num,m_GUIArgs.Value); break;
  197. case (SETCLAMP) : SetPortClamp(m_GUIArgs.Num,m_GUIArgs.Clamp); break;
  198. case (UPDATEPLUGIN) : UpdatePlugin(m_GUIArgs.Num); break;
  199. };
  200. }
  201. }
  202. void LADSPAPlugin::StreamOut(ostream &s)
  203. {
  204. s<<m_Version<<" ";
  205. switch (m_Version)
  206. {
  207. case 3:
  208. {
  209. s<<m_Gain<<" ";
  210. s<<m_CurrentPlugin.Filename<<" ";
  211. s<<m_CurrentPlugin.Label<<" ";
  212. s<<m_PortMin.size()<<" ";
  213. assert(m_PortMin.size()==m_PortMax.size());
  214. assert(m_PortMin.size()==m_PortClamp.size());
  215. for (vector<float>::iterator i=m_PortMin.begin();
  216. i!=m_PortMin.end(); i++)
  217. {
  218. s<<*i<<" ";
  219. }
  220. for (vector<float>::iterator i=m_PortMax.begin();
  221. i!=m_PortMax.end(); i++)
  222. {
  223. s<<*i<<" ";
  224. }
  225. for (vector<bool>::iterator i=m_PortClamp.begin();
  226. i!=m_PortClamp.end(); i++)
  227. {
  228. s<<*i<<" ";
  229. }
  230. }
  231. break;
  232. case 2:
  233. // Here for consistency - should never actually happen, as
  234. // version is always 3!
  235. {
  236. s<<m_Gain<<" ";
  237. s<<m_CurrentPlugin.Filename<<" ";
  238. s<<m_CurrentPlugin.Label<<" ";
  239. s<<m_PortMin.size()<<" ";
  240. assert(m_PortMin.size()==m_PortMax.size());
  241. for (vector<float>::iterator i=m_PortMin.begin();
  242. i!=m_PortMin.end(); i++)
  243. {
  244. s<<*i<<" ";
  245. }
  246. for (vector<float>::iterator i=m_PortMax.begin();
  247. i!=m_PortMax.end(); i++)
  248. {
  249. s<<*i<<" ";
  250. }
  251. }
  252. break;
  253. case 1:
  254. {
  255. s<<m_Gain<<" ";
  256. s<<m_CurrentPlugin.Filename<<" ";
  257. s<<m_CurrentPlugin.Label<<" ";
  258. }
  259. break;
  260. }
  261. }
  262. void LADSPAPlugin::StreamIn(istream &s)
  263. {
  264. int version;
  265. s>>version;
  266. switch (version)
  267. {
  268. case 3:
  269. {
  270. s>>m_Gain;
  271. string Filename,Label;
  272. s>>Filename>>Label;
  273. int PortCount;
  274. s>>PortCount;
  275. float min,max;
  276. bool clamp;
  277. for (int n=0; n<PortCount; n++)
  278. {
  279. s>>min;
  280. m_PortMin.push_back(min);
  281. }
  282. for (int n=0; n<PortCount; n++)
  283. {
  284. s>>max;
  285. m_PortMax.push_back(max);
  286. }
  287. for (int n=0; n<PortCount; n++)
  288. {
  289. s>>clamp;
  290. m_PortClamp.push_back(clamp);
  291. }
  292. if (Filename!="None")
  293. {
  294. UpdatePlugin(Filename.c_str(), Label.c_str(), false);
  295. }
  296. m_CurrentPlugin.Ports.reserve(PortCount);
  297. for (int n=0; n<PortCount; n++)
  298. {
  299. m_CurrentPlugin.Ports[n].Min=m_PortMin[n];
  300. m_CurrentPlugin.Ports[n].Max=m_PortMax[n];
  301. m_CurrentPlugin.Ports[n].Clamped=m_PortClamp[n];
  302. }
  303. }
  304. break;
  305. case 2:
  306. {
  307. s>>m_Gain;
  308. string Filename,Label;
  309. s>>Filename>>Label;
  310. int PortCount;
  311. s>>PortCount;
  312. float min,max;
  313. for (int n=0; n<PortCount; n++)
  314. {
  315. s>>min;
  316. m_PortMin.push_back(min);
  317. }
  318. for (int n=0; n<PortCount; n++)
  319. {
  320. s>>max;
  321. m_PortMax.push_back(max);
  322. }
  323. for (int n=0; n<PortCount; n++)
  324. {
  325. // Set PortClamp to true as default
  326. m_PortClamp.push_back(true);
  327. }
  328. if (Filename!="None")
  329. {
  330. UpdatePlugin(Filename.c_str(), Label.c_str(), false);
  331. }
  332. m_CurrentPlugin.Ports.reserve(PortCount);
  333. for (int n=0; n<PortCount; n++)
  334. {
  335. m_CurrentPlugin.Ports[n].Min=m_PortMin[n];
  336. m_CurrentPlugin.Ports[n].Max=m_PortMax[n];
  337. m_CurrentPlugin.Ports[n].Clamped=m_PortClamp[n];
  338. }
  339. }
  340. break;
  341. case 1:
  342. {
  343. s>>m_Gain;
  344. string Filename,Label;
  345. s>>Filename>>Label;
  346. if (Filename!="None")
  347. {
  348. UpdatePlugin(Filename.c_str(), Label.c_str());
  349. }
  350. }
  351. break;
  352. }
  353. }
  354. bool LADSPAPlugin::UpdatePlugin(int n)
  355. {
  356. return UpdatePlugin(m_LADSPAList[n].Filename.c_str(),m_LADSPAList[n].Label.c_str());
  357. }
  358. bool LADSPAPlugin::UpdatePlugin(const char * filename, const char * label, bool PortClampReset=true)
  359. {
  360. // first call with same info, to clear the ports
  361. UpdatePluginInfoWithHost();
  362. if (PlugHandle) {
  363. if (PlugDesc->deactivate) PlugDesc->deactivate(PlugInstHandle);
  364. PlugDesc->cleanup(PlugInstHandle);
  365. unloadLADSPAPluginLibrary(PlugHandle);
  366. PlugHandle = 0;
  367. }
  368. if ((PlugHandle = loadLADSPAPluginLibrary(filename))) {
  369. if (!(PlugDesc = findLADSPAPluginDescriptor(PlugHandle, filename, label))) {
  370. unloadLADSPAPluginLibrary(PlugHandle);
  371. PlugHandle = 0;
  372. } else {
  373. /* Now we can instantiate the LADSPA Plugin and wire it to the datas bytes */
  374. if (!(PlugInstHandle = PlugDesc->instantiate(PlugDesc, m_HostInfo->SAMPLERATE))) {
  375. cerr << "LADSPA Plugin error to instantiate...\n";
  376. unloadLADSPAPluginLibrary(PlugHandle);
  377. PlugDesc = 0;
  378. PlugHandle = 0;
  379. return 0;
  380. }
  381. m_PluginInfo.NumInputs=getPortCountByType(PlugDesc, LADSPA_PORT_INPUT);
  382. m_PluginInfo.NumOutputs=getPortCountByType(PlugDesc, LADSPA_PORT_OUTPUT);
  383. /////////////////////////////////
  384. // LADSPA Buffers
  385. for(vector<LADSPA_Data*>::iterator i=m_LADSPABufVec.begin();
  386. i!=m_LADSPABufVec.end(); i++)
  387. {
  388. if (*i) delete[] (*i);
  389. }
  390. m_LADSPABufVec.clear();
  391. unsigned long c=0;
  392. for (unsigned int n=0; n<PlugDesc->PortCount; n++)
  393. {
  394. if (LADSPA_IS_PORT_INPUT(PlugDesc->PortDescriptors[n]))
  395. {
  396. LADSPA_Data *NewPort = new LADSPA_Data[m_HostInfo->BUFSIZE];
  397. m_LADSPABufVec.push_back(NewPort);
  398. PlugDesc->connect_port(PlugInstHandle, n, m_LADSPABufVec[c]);
  399. m_PortID.push_back(n);
  400. c++;
  401. }
  402. }
  403. for (unsigned int n=0; n<PlugDesc->PortCount; n++)
  404. {
  405. if (LADSPA_IS_PORT_OUTPUT(PlugDesc->PortDescriptors[n]))
  406. {
  407. LADSPA_Data *NewPort = new LADSPA_Data[m_HostInfo->BUFSIZE];
  408. m_LADSPABufVec.push_back(NewPort);
  409. PlugDesc->connect_port(PlugInstHandle, n, m_LADSPABufVec[c]);
  410. m_PortID.push_back(n);
  411. c++;
  412. }
  413. }
  414. // activate the plugin now
  415. if (PlugDesc->activate)
  416. PlugDesc->activate(PlugInstHandle);
  417. /////////////////////////////////
  418. // SSM Buffers
  419. // Clear i/o buffers
  420. RemoveAllInputs();
  421. RemoveAllOutputs();
  422. // Reallocate the i/o buffers required
  423. for (int n=0; n<m_PluginInfo.NumInputs; n++) AddInput();
  424. for (int n=0; n<m_PluginInfo.NumOutputs; n++) AddOutput();
  425. //////////////////////////////
  426. // Update the GUI stuff
  427. m_CurrentPlugin.Name=PlugDesc->Name;
  428. m_CurrentPlugin.Maker=PlugDesc->Maker;
  429. m_CurrentPlugin.Filename=filename;
  430. m_CurrentPlugin.Label=label;
  431. m_CurrentPlugin.Ports.clear();
  432. m_PluginInfo.PortTips.clear();
  433. string desc;
  434. c=0;
  435. for (unsigned int i = 0; i < PlugDesc->PortCount; i++)
  436. {
  437. if (LADSPA_IS_PORT_INPUT(PlugDesc->PortDescriptors[i]))
  438. {
  439. desc = string(PlugDesc->PortNames[i]) +
  440. (LADSPA_IS_PORT_CONTROL(PlugDesc->PortDescriptors[i]) ? " (CV)" : " (AU)");
  441. m_PluginInfo.PortTips.push_back(desc.c_str());
  442. LPluginInfo::LPortDetails PortDetails;
  443. PortDetails.Name=m_PluginInfo.PortTips[c].c_str();
  444. m_CurrentPlugin.Ports.push_back(PortDetails);
  445. c++;
  446. }
  447. }
  448. for (unsigned int i = 0; i < PlugDesc->PortCount; i++)
  449. {
  450. if (LADSPA_IS_PORT_OUTPUT(PlugDesc->PortDescriptors[i])) {
  451. desc = string(PlugDesc->PortNames[i]) +
  452. (LADSPA_IS_PORT_CONTROL(PlugDesc->PortDescriptors[i]) ? " (CV)" : " (AU)");
  453. m_PluginInfo.PortTips.push_back(desc.c_str());
  454. }
  455. }
  456. UpdatePluginInfoWithHost();
  457. if (PortClampReset)
  458. {
  459. m_PortMin.clear();
  460. m_PortMax.clear();
  461. m_PortClamp.clear();
  462. for (int n=0; n<m_PluginInfo.NumInputs; n++)
  463. {
  464. float Max=1.0f, Min=-1.0f;
  465. int Port=m_PortID[n];
  466. // Get the bounding hints for the port
  467. LADSPA_PortRangeHintDescriptor HintDesc=PlugDesc->PortRangeHints[Port].HintDescriptor;
  468. if (LADSPA_IS_HINT_BOUNDED_BELOW(HintDesc))
  469. {
  470. Min=PlugDesc->PortRangeHints[Port].LowerBound;
  471. if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc))
  472. {
  473. Min*=m_HostInfo->SAMPLERATE;
  474. }
  475. }
  476. if (LADSPA_IS_HINT_BOUNDED_ABOVE(HintDesc))
  477. {
  478. Max=PlugDesc->PortRangeHints[Port].UpperBound;
  479. if (LADSPA_IS_HINT_SAMPLE_RATE(HintDesc))
  480. {
  481. Max*=m_HostInfo->SAMPLERATE;
  482. }
  483. }
  484. m_PortMin.push_back(Min);
  485. m_PortMax.push_back(Max);
  486. // PortClamp defaults to true
  487. m_PortClamp.push_back(true);
  488. m_CurrentPlugin.Ports[n].Min=Min;
  489. m_CurrentPlugin.Ports[n].Max=Max;
  490. m_CurrentPlugin.Ports[n].Clamped=true;
  491. }
  492. }
  493. return true;
  494. }
  495. }
  496. cerr << "Error loading LADSPA Plugin.\n";
  497. return false;
  498. }