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.

719 lines
18KB

  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 <stdio.h>
  19. #include <limits.h>
  20. #include <math.h>
  21. #include "JackPlugin.h"
  22. #include "JackPluginGUI.h"
  23. #include "SpiralIcon.xpm"
  24. using namespace std;
  25. int JackClient::JackProcessInstanceID = -1;
  26. int JackPlugin::JackInstanceCount = 0;
  27. const HostInfo *host = NULL;
  28. /////////////////////////////////////////////////////////////////////////////////////////////
  29. inline void JackClient::JackProcess_i(jack_nframes_t nframes)
  30. {
  31. SetBufferSize(nframes);
  32. for (int n=0; n<GetJackInputCount(); n++)
  33. {
  34. if (jack_port_connected(m_InputPortMap[n]->Port))
  35. {
  36. sample_t *in = (sample_t *) jack_port_get_buffer(m_InputPortMap[n]->Port, nframes);
  37. assert( m_InputPortMap[n]->Buf );
  38. memcpy( m_InputPortMap[n]->Buf, in, sizeof (sample_t) * GetBufferSize());
  39. }
  40. }
  41. for (int n=0; n<GetJackOutputCount(); n++)
  42. {
  43. if (jack_port_connected(m_OutputPortMap[n]->Port))
  44. {
  45. if ((m_OutputPortMap[n]->Buf) && (!host->PAUSED))
  46. {
  47. sample_t *out = (sample_t *) jack_port_get_buffer(m_OutputPortMap[n]->Port, nframes);
  48. assert( m_OutputPortMap[n]->Buf );
  49. memcpy (out, m_OutputPortMap[n]->Buf, sizeof (sample_t) * GetBufferSize());
  50. }
  51. else // no output availible, clear
  52. {
  53. sample_t *out = (sample_t *) jack_port_get_buffer(m_OutputPortMap[n]->Port, nframes);
  54. memset(out, 0, sizeof (sample_t) * GetBufferSize());
  55. }
  56. }
  57. }
  58. if (RunCallback&&RunContext)
  59. {
  60. if (JackProcessInstanceID==-1)
  61. JackProcessInstanceID = m_JackInstanceID;
  62. if (JackProcessInstanceID==m_JackInstanceID)
  63. RunCallback(RunContext,true);
  64. }
  65. }
  66. /////////////////////////////////////////////////////////////////////////////////////////////
  67. inline void JackClient::SampleRateChange_i(jack_nframes_t nframes)
  68. {
  69. SetSampleRate(nframes);
  70. }
  71. /////////////////////////////////////////////////////////////////////////////////////////////
  72. inline void JackClient::JackShutdown_i()
  73. {
  74. cerr<<"Shutdown"<<endl;
  75. SetAttached(false);
  76. if (JackProcessInstanceID==m_JackInstanceID)
  77. JackProcessInstanceID = -1;
  78. // tells ssm to go back to non callback mode
  79. RunCallback(RunContext, false);
  80. }
  81. ///////////////////////////////////////////////////////
  82. JackClient::JackClient()
  83. {
  84. m_JackInstanceID = 0;
  85. m_Attached = false;
  86. m_SampleRate = 0;
  87. m_BufferSize = 0;
  88. m_JackInputCount = 4;
  89. m_JackOutputCount = 4;
  90. m_Client=NULL;
  91. m_JackSampleRate = -1;
  92. m_JackBufferSize = -1;
  93. }
  94. /////////////////////////////////////////////////////////////////////////////////////////////
  95. JackClient::~JackClient()
  96. {
  97. if (IsAttached()) Detach();
  98. }
  99. /////////////////////////////////////////////////////////////////////////////////////////////
  100. void JackClient::AddInputPort(int NewPortNumber)
  101. {
  102. char Name[256];
  103. JackPort *NewPort;
  104. if (!(m_Client)) return;
  105. NewPort = new JackPort;
  106. sprintf(Name,"In%d", NewPortNumber);
  107. NewPort->PortNo = NewPortNumber;
  108. NewPort->Name=Name;
  109. NewPort->Buf=NULL;
  110. NewPort->Port = jack_port_register (m_Client, Name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
  111. m_InputPortMap[NewPortNumber]=NewPort;
  112. }
  113. void JackClient::AddOutputPort(int NewPortNumber)
  114. {
  115. char Name[256];
  116. JackPort *NewPort;
  117. if (!(m_Client)) return;
  118. NewPort = new JackPort;
  119. sprintf(Name,"Out%d", NewPortNumber);
  120. NewPort->PortNo = NewPortNumber;
  121. NewPort->Name=Name;
  122. NewPort->Buf=NULL;
  123. NewPort->Port = jack_port_register (m_Client, Name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  124. m_OutputPortMap[NewPortNumber]=NewPort;
  125. }
  126. void JackClient::RemoveInputPort(int PortNumber)
  127. {
  128. char Name[256];
  129. JackPort *OldPort;
  130. if (!(m_Client)) return;
  131. OldPort = m_InputPortMap[PortNumber];
  132. m_InputPortMap[PortNumber] = NULL;
  133. jack_port_unregister (m_Client, OldPort->Port);
  134. delete OldPort;
  135. }
  136. void JackClient::RemoveOutputPort(int PortNumber)
  137. {
  138. char Name[256];
  139. JackPort *OldPort;
  140. if (!(m_Client)) return;
  141. OldPort = m_OutputPortMap[PortNumber];
  142. m_OutputPortMap[PortNumber] = NULL;
  143. jack_port_unregister (m_Client, OldPort->Port);
  144. delete OldPort;
  145. }
  146. bool JackClient::Attach()
  147. {
  148. char JackClientName[256];
  149. if (m_Attached) return true;
  150. sprintf(JackClientName,"SSM%d",GetJackInstanceID());
  151. if (!(m_Client = jack_client_new(JackClientName)))
  152. {
  153. cerr<<"jack server not running?"<<endl;
  154. return false;
  155. }
  156. m_JackSampleRate = jack_get_sample_rate(m_Client);
  157. m_JackBufferSize = jack_get_buffer_size(m_Client);
  158. jack_set_process_callback(m_Client, JackProcess, this);
  159. jack_set_sample_rate_callback (m_Client, SampleRateChange, this);
  160. jack_on_shutdown (m_Client, JackShutdown, this);
  161. // create the ports
  162. m_InputPortMap.clear();
  163. for (int n=0; n<GetJackInputCount(); n++)
  164. AddInputPort(n);
  165. m_OutputPortMap.clear();
  166. for (int n=0; n<GetJackOutputCount(); n++)
  167. AddOutputPort(n);
  168. // ProcessAudio();
  169. // tell the JACK server that we are ready to roll
  170. if (jack_activate (m_Client))
  171. {
  172. cerr<<"cannot activate client"<<endl;
  173. return false;
  174. }
  175. // tells ssm to go back to callback mode
  176. RunCallback(RunContext, true);
  177. m_Attached=true;
  178. cerr<<"connected to jack..."<<endl;
  179. return true;
  180. }
  181. /////////////////////////////////////////////////////////////////////////////////////////////
  182. void JackClient::Detach()
  183. {
  184. if (m_Client)
  185. {
  186. cerr<<"Detaching from JACK"<<endl;
  187. jack_client_close(m_Client);
  188. m_Client=NULL;
  189. m_Attached=false;
  190. if (JackProcessInstanceID==m_JackInstanceID)
  191. JackProcessInstanceID = -1;
  192. // tells ssm to go back to non callback mode
  193. RunCallback(RunContext, false);
  194. }
  195. }
  196. /////////////////////////////////////////////////////////////////////////////////////////////
  197. void JackClient::GetPortNames(vector<string> &InputNames, vector<string> &OutputNames)
  198. {
  199. InputNames.clear();
  200. OutputNames.clear();
  201. if (!m_Attached) return;
  202. //Outputs first
  203. const char **PortNameList=jack_get_ports(m_Client,NULL,NULL,JackPortIsOutput);
  204. int n=0;
  205. while(PortNameList[n]!=NULL)
  206. {
  207. OutputNames.push_back(PortNameList[n]);
  208. n++;
  209. }
  210. delete PortNameList;
  211. //Inputs second
  212. PortNameList=jack_get_ports(m_Client,NULL,NULL,JackPortIsInput);
  213. n=0;
  214. while(PortNameList[n]!=NULL)
  215. {
  216. InputNames.push_back(PortNameList[n]);
  217. n++;
  218. }
  219. delete PortNameList;
  220. }
  221. /////////////////////////////////////////////////////////////////////////////////////////////
  222. // Input means input of SSM, so this connects jack sources to the plugin outputs
  223. void JackClient::ConnectInput(int n, const string &JackPort)
  224. {
  225. if (!IsAttached()) return;
  226. cerr<<"JackClient::ConnectInput: connecting source ["<<JackPort<<"] to dest ["<<m_InputPortMap[n]->Name<<"]"<<endl;
  227. if (m_InputPortMap[n]->ConnectedTo!="")
  228. {
  229. if (jack_disconnect (m_Client, m_InputPortMap[n]->ConnectedTo.c_str(), jack_port_name(m_InputPortMap[n]->Port)))
  230. cerr<<"JackClient::ConnectInput: cannot disconnect input port ["
  231. <<m_InputPortMap[n]->ConnectedTo<<"] from ["<<m_InputPortMap[n]->Name<<"]"<<endl;
  232. }
  233. m_InputPortMap[n]->ConnectedTo = JackPort;
  234. if (jack_connect (m_Client, JackPort.c_str(), jack_port_name(m_InputPortMap[n]->Port)))
  235. cerr<<"JackClient::ConnectInput: cannot connect input port ["
  236. <<JackPort<<"] to ["<<m_InputPortMap[n]->Name<<"]"<<endl;
  237. m_InputPortMap[n]->Connected=true;
  238. }
  239. /////////////////////////////////////////////////////////////////////////////////////////////
  240. // Output means output of SSM, so this connects plugin inputs to a jack destination
  241. void JackClient::ConnectOutput(int n, const string &JackPort)
  242. {
  243. if (!IsAttached()) return;
  244. cerr<<"JackClient::ConnectOutput: connecting source ["<<m_OutputPortMap[n]->Name<<"] to dest ["<<JackPort<<"]"<<endl;
  245. if (m_OutputPortMap[n]->ConnectedTo!="")
  246. {
  247. if (jack_disconnect (m_Client, jack_port_name(m_OutputPortMap[n]->Port), m_OutputPortMap[n]->ConnectedTo.c_str()))
  248. cerr<<"JackClient::ConnectOutput: cannot disconnect output port ["
  249. <<m_OutputPortMap[n]->ConnectedTo<<"] from ["<<m_OutputPortMap[n]->Name<<"]"<<endl;
  250. }
  251. m_OutputPortMap[n]->ConnectedTo = JackPort;
  252. if (jack_connect (m_Client, jack_port_name(m_OutputPortMap[n]->Port), JackPort.c_str()))
  253. cerr<<"JackClient::ConnectOutput: cannot connect output port ["
  254. <<m_OutputPortMap[n]->Name<<"] to ["<<JackPort<<"]"<<endl;
  255. m_OutputPortMap[n]->Connected=true;
  256. }
  257. /////////////////////////////////////////////////////////////////////////////////////////////
  258. // Input means input of SSM, so this connects jack sources to the plugin outputs
  259. void JackClient::DisconnectInput(int n)
  260. {
  261. if (!IsAttached()) return;
  262. cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl;
  263. if (m_InputPortMap[n]->ConnectedTo!="")
  264. {
  265. if (jack_disconnect (m_Client, m_InputPortMap[n]->ConnectedTo.c_str(), jack_port_name(m_InputPortMap[n]->Port)))
  266. cerr<<"JackClient::ConnectInput: cannot disconnect input port ["
  267. <<m_InputPortMap[n]->ConnectedTo<<"] from ["<<m_InputPortMap[n]->Name<<"]"<<endl;
  268. }
  269. m_InputPortMap[n]->Connected=false;
  270. }
  271. /////////////////////////////////////////////////////////////////////////////////////////////
  272. // Output means output of SSM, so this connects plugin inputs to a jack destination
  273. void JackClient::DisconnectOutput(int n)
  274. {
  275. if (!IsAttached()) return;
  276. cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl;
  277. if (m_OutputPortMap[n]->ConnectedTo!="")
  278. {
  279. if (jack_disconnect (m_Client, jack_port_name(m_OutputPortMap[n]->Port), m_OutputPortMap[n]->ConnectedTo.c_str()))
  280. cerr<<"JackClient::ConnectOutput: cannot disconnect output port ["
  281. <<m_OutputPortMap[n]->ConnectedTo<<"] from ["<<m_OutputPortMap[n]->Name<<"]"<<endl;
  282. }
  283. m_OutputPortMap[n]->Connected=false;
  284. }
  285. /////////////////////////////////////////////////////////////////////////////////////////////
  286. void JackClient::SetInputBuf(int ID, float* s)
  287. {
  288. if(m_InputPortMap.find(ID)!=m_InputPortMap.end()) m_InputPortMap[ID]->Buf=s;
  289. }
  290. /////////////////////////////////////////////////////////////////////////////////////////////
  291. void JackClient::SetOutputBuf(int ID, float* s)
  292. {
  293. if(m_OutputPortMap.find(ID)!=m_OutputPortMap.end()) m_OutputPortMap[ID]->Buf=s;
  294. }
  295. /////////////////////////////////////////////////////////////////////////////////////////////
  296. extern "C" {
  297. SpiralPlugin* SpiralPlugin_CreateInstance()
  298. {
  299. return new JackPlugin;
  300. }
  301. char** SpiralPlugin_GetIcon()
  302. {
  303. return SpiralIcon_xpm;
  304. }
  305. int SpiralPlugin_GetID()
  306. {
  307. return 31;
  308. }
  309. string SpiralPlugin_GetGroupName()
  310. {
  311. return "InputOutput";
  312. }
  313. }
  314. ///////////////////////////////////////////////////////
  315. JackPlugin::JackPlugin() :
  316. m_UpdateNames(false),
  317. m_Connected(false)
  318. {
  319. m_JackClient=new JackClient;
  320. //clunky way to ensure unique JackID - JackInstanceCount is never dec
  321. //so new JackInstances per session always get a higher number even on
  322. //reload and new Patch
  323. m_JackInstanceID = JackInstanceCount;
  324. JackInstanceCount++;
  325. m_JackClient->SetJackInstanceID(m_JackInstanceID);
  326. // we are an output
  327. m_IsTerminal = true;
  328. m_Version = 2;
  329. m_PluginInfo.Name="Jack";
  330. m_PluginInfo.Width=225;
  331. m_PluginInfo.Height=230;
  332. m_PluginInfo.NumInputs=0;
  333. m_PluginInfo.NumOutputs=0;
  334. m_PluginInfo.PortTips.clear();
  335. m_PluginInfo.NumInputs = m_JackClient->GetJackOutputCount();
  336. m_GUIArgs.NumInputs = m_PluginInfo.NumInputs;
  337. for (int n=0; n<m_JackClient->GetJackInputCount(); n++)
  338. {
  339. char Temp[256];
  340. sprintf(Temp,"SSM Input %d",n);
  341. m_PluginInfo.PortTips.push_back(Temp);
  342. }
  343. m_PluginInfo.NumOutputs = m_JackClient->GetJackOutputCount();
  344. m_GUIArgs.NumOutputs = m_PluginInfo.NumOutputs;
  345. for (int n=0; n<m_JackClient->GetJackOutputCount(); n++)
  346. {
  347. char Temp[256];
  348. sprintf(Temp,"SSM Output %d",n);
  349. m_PluginInfo.PortTips.push_back(Temp);
  350. }
  351. m_AudioCH->Register("NumInputs",&m_GUIArgs.NumInputs);
  352. m_AudioCH->Register("NumOutputs",&m_GUIArgs.NumOutputs);
  353. m_AudioCH->RegisterData("Port",ChannelHandler::INPUT,&m_GUIArgs.Port,sizeof(m_GUIArgs.Port));
  354. m_AudioCH->Register("NumInputPortNames",&m_NumInputPortNames,ChannelHandler::OUTPUT);
  355. m_AudioCH->Register("NumOutputPortNames",&m_NumOutputPortNames,ChannelHandler::OUTPUT);
  356. m_AudioCH->RegisterData("InputPortNames",ChannelHandler::OUTPUT,&m_InputPortNames,sizeof(m_InputPortNames));
  357. m_AudioCH->RegisterData("OutputPortNames",ChannelHandler::OUTPUT,&m_OutputPortNames,sizeof(m_OutputPortNames));
  358. m_AudioCH->Register("UpdateNames",&m_UpdateNames,ChannelHandler::OUTPUT);
  359. m_AudioCH->Register("Connected",&m_Connected,ChannelHandler::OUTPUT);
  360. }
  361. JackPlugin::~JackPlugin()
  362. {
  363. if (m_JackClient)
  364. {
  365. m_JackClient->Detach();
  366. delete m_JackClient;
  367. m_JackClient=NULL;
  368. }
  369. }
  370. PluginInfo &JackPlugin::Initialise(const HostInfo *Host)
  371. {
  372. PluginInfo& Info= SpiralPlugin::Initialise(Host);
  373. host = Host;
  374. m_JackClient->SetCallback(cb_Update,m_Parent);
  375. return Info;
  376. }
  377. SpiralGUIType *JackPlugin::CreateGUI()
  378. {
  379. return new JackPluginGUI(m_PluginInfo.Width,
  380. m_PluginInfo.Height,
  381. this,m_AudioCH,m_HostInfo);
  382. }
  383. void JackPlugin::Execute()
  384. {
  385. }
  386. void JackPlugin::ExecuteCommands()
  387. {
  388. if (m_IsDead) return;
  389. if (m_AudioCH->IsCommandWaiting())
  390. {
  391. switch (m_AudioCH->GetCommand()) {
  392. case SET_PORT_COUNT :
  393. SetNumberPorts (m_GUIArgs.NumInputs, m_GUIArgs.NumOutputs);
  394. break;
  395. case UPDATE_NAMES :
  396. {
  397. int c=0;
  398. std::vector<string> InputNames,OutputNames;
  399. GetPortNames(InputNames,OutputNames);
  400. for (vector<string>::iterator i=InputNames.begin();
  401. i!=InputNames.end(); ++i)
  402. {
  403. strcpy(m_InputPortNames[c],i->c_str());
  404. c++;
  405. }
  406. c=0;
  407. for (std::vector<string>::iterator i=OutputNames.begin();
  408. i!=OutputNames.end(); ++i)
  409. {
  410. strcpy(m_OutputPortNames[c],i->c_str());
  411. c++;
  412. }
  413. m_NumInputPortNames=InputNames.size();
  414. m_NumOutputPortNames=OutputNames.size();
  415. }
  416. break;
  417. case CHECK_PORT_CHANGES :
  418. if ((m_JackClient->IsAttached()) && (!m_JackClient->CheckingPortChanges)) {
  419. m_JackClient->CheckingPortChanges = true;
  420. for (int n=0; n<m_PluginInfo.NumInputs; n++) {
  421. if (jack_port_connected(m_JackClient->m_OutputPortMap[n]->Port)!=m_JackClient->m_OutputPortMap[n]->Connected)
  422. m_JackClient->m_OutputPortsChanged.push_back(m_JackClient->m_OutputPortMap[n]);
  423. if (jack_port_connected(m_JackClient->m_InputPortMap[n]->Port)!=m_JackClient->m_InputPortMap[n]->Connected)
  424. m_JackClient->m_InputPortsChanged.push_back(m_JackClient->m_InputPortMap[n]);
  425. }
  426. m_JackClient->CheckingPortChanges = false;
  427. }
  428. break;
  429. default : break;
  430. }
  431. }
  432. m_Connected=m_JackClient->IsAttached();
  433. }
  434. bool JackPlugin::Kill()
  435. {
  436. m_IsDead=true;
  437. UpdatePluginInfoWithHost();
  438. RemoveAllInputs ();
  439. RemoveAllOutputs ();
  440. UpdatePluginInfoWithHost();
  441. if (m_JackClient)
  442. {
  443. m_JackClient->Detach();
  444. delete m_JackClient;
  445. m_JackClient=NULL;
  446. }
  447. return true;
  448. }
  449. void JackPlugin::Reset()
  450. {
  451. // connect the buffers up if we are plugged into something
  452. for (int n=0; n<m_JackClient->GetJackOutputCount(); n++)
  453. {
  454. m_JackClient->SetOutputBuf(n,NULL);
  455. }
  456. for (int n=0; n<m_JackClient->GetJackInputCount(); n++)
  457. {
  458. m_JackClient->SetInputBuf(n,NULL);
  459. }
  460. ResetPorts();
  461. }
  462. void JackPlugin::ProcessAudio()
  463. {
  464. if (m_IsDead) return;
  465. // Make sure all plugins match Jack's SampleRate and Buffersize
  466. if ((m_JackClient->JackSampleRate() != -1) && (m_JackClient->JackBufferSize() != -1))
  467. {
  468. ChangeBufferAndSampleRate(m_JackClient->JackBufferSize(), m_JackClient->JackSampleRate(), m_Parent);
  469. }
  470. // connect the buffers up if we are plugged into something
  471. for (int n=0; n<m_JackClient->GetJackOutputCount(); n++)
  472. {
  473. if (InputExists(n) && !m_HostInfo->PAUSED)
  474. {
  475. m_JackClient->SetOutputBuf(n,(float*)GetInput(n)->GetBuffer());
  476. }
  477. else
  478. {
  479. m_JackClient->SetOutputBuf(n,NULL);
  480. }
  481. }
  482. for (int n=0; n<m_JackClient->GetJackInputCount(); n++)
  483. {
  484. if (OutputExists(n) && !m_HostInfo->PAUSED)
  485. {
  486. m_JackClient->SetInputBuf(n,(float*)GetOutputBuf(n)->GetBuffer());
  487. }
  488. else
  489. {
  490. m_JackClient->SetInputBuf(n,NULL);
  491. }
  492. }
  493. }
  494. void JackPlugin::SetNumberPorts (int nInputs, int nOutputs) {
  495. UpdatePluginInfoWithHost();
  496. RemoveAllInputs ();
  497. RemoveAllOutputs ();
  498. m_PluginInfo.NumInputs = 0;
  499. m_PluginInfo.NumOutputs = 0;
  500. m_PluginInfo.PortTips.clear ();
  501. CreatePorts (nInputs, nOutputs, true);
  502. UpdatePluginInfoWithHost ();
  503. }
  504. void JackPlugin::CreatePorts (int nInputs, int nOutputs, bool AddPorts) {
  505. m_PluginInfo.PortTips.clear();
  506. m_PluginInfo.NumInputs = nInputs;
  507. m_JackClient->SetJackInputCount(nInputs);
  508. for (int n=0; n<nInputs; n++)
  509. {
  510. char Temp[256];
  511. sprintf(Temp,"SSM Input %d",n);
  512. m_PluginInfo.PortTips.push_back(Temp);
  513. }
  514. m_PluginInfo.NumOutputs = nOutputs;
  515. m_JackClient->SetJackOutputCount(nOutputs);
  516. for (int n=0; n<nOutputs; n++)
  517. {
  518. char Temp[256];
  519. sprintf(Temp,"SSM Output %d",n);
  520. m_PluginInfo.PortTips.push_back(Temp);
  521. }
  522. if (AddPorts) {
  523. for (int n=0; n<nInputs; n++) AddInput();
  524. for (int n=0; n<nOutputs; n++) AddOutput();
  525. }
  526. }
  527. void JackPlugin::StreamOut (ostream &s)
  528. {
  529. s << m_Version << " " << m_GUIArgs.NumInputs << " " << m_GUIArgs.NumOutputs << " ";
  530. }
  531. void JackPlugin::StreamIn (istream &s)
  532. {
  533. char Test;
  534. int Version, NumInputs, NumOutputs;
  535. s.seekg (2, ios::cur ); //skip to next line
  536. Test = s.peek(); //peek first char
  537. s.seekg (-2, ios::cur ); //jump back to prior line
  538. if ( (Test >= '0') && (Test <= '9') )
  539. {
  540. s >> Version;
  541. }
  542. else
  543. {
  544. //No Version, so use Version 1
  545. Version = 1;
  546. }
  547. switch (Version)
  548. {
  549. case 2:
  550. {
  551. s >> NumInputs >> NumOutputs;
  552. m_GUIArgs.NumOutputs = min(max(NumOutputs, MIN_PORTS), MAX_PORTS);
  553. m_GUIArgs.NumInputs = min(max(NumInputs, MIN_PORTS), MAX_PORTS);
  554. SetNumberPorts (m_GUIArgs.NumInputs, m_GUIArgs.NumOutputs);
  555. }
  556. break;
  557. case 1:
  558. {
  559. //use original fixed defaults
  560. m_GUIArgs.NumInputs = 16;
  561. m_GUIArgs.NumOutputs = 16;
  562. SetNumberPorts (m_GUIArgs.NumInputs, m_GUIArgs.NumOutputs);
  563. }
  564. break;
  565. }
  566. }