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.

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