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.

772 lines
19KB

  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 "SequencerPlugin.h"
  19. #include "SequencerPluginGUI.h"
  20. #include <FL/Fl_Button.h>
  21. #include "SpiralIcon.xpm"
  22. #include "../../RiffWav.h"
  23. #include "../../NoteTable.h"
  24. // for note on's
  25. static const float TRIGGER_LEV=0.1;
  26. //////////////////////////////////////////////////////////////////////////
  27. // base sequencing stuff
  28. Note::Note(float t=0, float l=0.1f, int n=0, float v=1.0f)
  29. {
  30. Time = t;
  31. Length = l;
  32. MidiNote = n;
  33. Vol = v;
  34. }
  35. Note::~Note()
  36. {
  37. }
  38. istream &operator>>(istream &s, Note &o)
  39. {
  40. int version=1;
  41. string dummy;
  42. s>>version>>dummy>>o.Time>>o.Length>>o.MidiNote>>o.Vol;
  43. return s;
  44. }
  45. ostream &operator<<(ostream &s, Note &o)
  46. {
  47. int version=1;
  48. s<<version<<" note "<<o.Time<<" "<<o.Length<<" "<<o.MidiNote<<" "<<o.Vol<<" ";
  49. return s;
  50. }
  51. /////////////////////////////////////////////////////////////////////////
  52. Pattern::Pattern()
  53. {
  54. }
  55. Pattern::~Pattern()
  56. {
  57. }
  58. void Pattern::Copy(const Pattern *o)
  59. {
  60. // can't do this as we don't want to preserve the id numbers
  61. //m_NoteMap=o->m_NoteMap;
  62. int c=0;
  63. for (map<int,Note>::const_iterator i = o->m_NoteMap.begin();
  64. i!=o->m_NoteMap.end(); i++)
  65. {
  66. m_NoteMap[c++]=i->second;
  67. }
  68. }
  69. void Pattern::AddNote(int ID, float t, float l, int n, float v)
  70. {
  71. map<int,Note>::iterator i = m_NoteMap.find(ID);
  72. if (i != m_NoteMap.end())
  73. {
  74. cerr<<"duplicate note "<<ID<<" not added"<<endl;
  75. return;
  76. }
  77. Note newnote(t,l,n,v);
  78. m_NoteMap[ID]=newnote;
  79. }
  80. void Pattern::RemoveNote(int ID)
  81. {
  82. map<int,Note>::iterator i = m_NoteMap.find(ID);
  83. if (i == m_NoteMap.end())
  84. {
  85. cerr<<"couldn't find note "<<ID<<" not removed"<<endl;
  86. return;
  87. }
  88. m_NoteMap.erase(i);
  89. }
  90. Note *Pattern::GetNote(int ID)
  91. {
  92. map<int,Note>::iterator i = m_NoteMap.find(ID);
  93. if (i == m_NoteMap.end())
  94. {
  95. cerr<<"couldn't find note "<<ID<<endl;
  96. return NULL;
  97. }
  98. return &i->second;
  99. }
  100. istream &operator>>(istream &s, Pattern &o)
  101. {
  102. int version=1,Num;
  103. string dummy;
  104. int id=0;
  105. s>>version>>dummy>>Num;
  106. for (int n=0; n<Num; n++)
  107. {
  108. Note t;
  109. s>>t;
  110. o.m_NoteMap[id++]=t;
  111. }
  112. return s;
  113. }
  114. ostream &operator<<(ostream &s, Pattern &o)
  115. {
  116. int version=1;
  117. s<<version<<" pattern "<<o.m_NoteMap.size()<<" ";
  118. for (map<int,Note>::iterator i = o.m_NoteMap.begin();
  119. i!=o.m_NoteMap.end(); i++)
  120. {
  121. s<<i->second;
  122. }
  123. s<<endl;
  124. return s;
  125. }
  126. //////////////////////////////////////////////////////////////////////////
  127. Sequence::Sequence(float st=0, int pat=0)
  128. {
  129. m_StartTime=st;
  130. m_Pattern=pat;
  131. }
  132. Sequence::~Sequence()
  133. {
  134. }
  135. istream &operator>>(istream &s, Sequence &o)
  136. {
  137. int version=1;
  138. string dummy;
  139. s>>version>>dummy>>o.m_StartTime>>o.m_Pattern>>o.m_Colour>>o.m_YPos>>o.m_Length>>o.m_Channel;
  140. char Buf[4096];
  141. int size;
  142. s>>size;
  143. s.ignore(1);
  144. s.get(Buf,size+1);
  145. o.m_Name=Buf;
  146. return s;
  147. }
  148. ostream &operator<<(ostream &s, Sequence &o)
  149. {
  150. int version=1;
  151. s<<version<<" sequence"<<" "<<o.m_StartTime<<" "<<o.m_Pattern<<" "<<o.m_Colour<<" "<<o.m_YPos<<" "<<o.m_Length<<" "<<o.m_Channel<<" ";
  152. s<<o.m_Name.size()<<" "<<o.m_Name<<endl;
  153. return s;
  154. }
  155. //////////////////////////////////////////////////////////////////////////
  156. Track::Track()
  157. {
  158. m_NextPatternID=0;
  159. }
  160. Track::~Track()
  161. {
  162. }
  163. void Track::AddSequence(int ID)
  164. {
  165. map<int,Sequence>::iterator i = m_SequenceMap.find(ID);
  166. if (i != m_SequenceMap.end())
  167. {
  168. cerr<<"duplicate sequence "<<ID<<" not added"<<endl;
  169. return;
  170. }
  171. Sequence newsequence;
  172. AddPattern(m_NextPatternID);
  173. newsequence.SetPatternID(m_NextPatternID);
  174. newsequence.SetColour(0);
  175. newsequence.SetName("noname");
  176. newsequence.SetLength(10.0f);
  177. newsequence.SetYPos(1);
  178. newsequence.SetChannel(0);
  179. m_NextPatternID++;
  180. m_SequenceMap[ID]=newsequence;
  181. }
  182. // duplicate the sequence, but reference the same pattern
  183. void Track::CloneSequence(int ID, int nID)
  184. {
  185. AddSequence(nID);
  186. Sequence *s=GetSequence(nID);
  187. s->SetColour(GetSequence(ID)->GetColour());
  188. s->SetName(GetSequence(ID)->GetName());
  189. s->SetLength(GetSequence(ID)->GetLength());
  190. s->SetYPos(GetSequence(ID)->GetYPos());
  191. s->SetPatternID(GetSequence(ID)->GetPatternID());
  192. s->SetStartTime(GetSequence(ID)->GetStartTime());
  193. s->SetChannel(GetSequence(ID)->GetChannel());
  194. }
  195. // duplicate the sequence, and copy the pattern to it's own version
  196. void Track::CopySequence(int ID, int nID)
  197. {
  198. AddSequence(nID);
  199. Sequence *s=GetSequence(nID);
  200. s->SetColour(GetSequence(ID)->GetColour());
  201. s->SetName(GetSequence(ID)->GetName());
  202. s->SetLength(GetSequence(ID)->GetLength());
  203. s->SetYPos(GetSequence(ID)->GetYPos());
  204. s->SetStartTime(GetSequence(ID)->GetStartTime());
  205. s->SetChannel(GetSequence(ID)->GetChannel());
  206. AddPattern(m_NextPatternID);
  207. GetPattern(m_NextPatternID)->Copy(GetPattern(GetSequence(ID)->GetPatternID()));
  208. GetSequence(nID)->SetPatternID(m_NextPatternID);
  209. m_NextPatternID++;
  210. }
  211. // copy the sequences pattern, so it's got it's own version
  212. void Track::InstanceSequence(int ID)
  213. {
  214. AddPattern(m_NextPatternID);
  215. GetPattern(m_NextPatternID)->Copy(GetPattern(GetSequence(ID)->GetPatternID()));
  216. GetSequence(ID)->SetPatternID(m_NextPatternID);
  217. m_NextPatternID++;
  218. }
  219. void Track::RemoveSequence(int ID)
  220. {
  221. map<int,Sequence>::iterator i = m_SequenceMap.find(ID);
  222. if (i == m_SequenceMap.end())
  223. {
  224. cerr<<"couldn't find sequence "<<ID<<" not removed"<<endl;
  225. return;
  226. }
  227. // todo - refcount the patterns
  228. m_SequenceMap.erase(i);
  229. }
  230. Sequence *Track::GetSequence(int ID)
  231. {
  232. map<int, Sequence>::iterator i = m_SequenceMap.find(ID);
  233. if (i == m_SequenceMap.end())
  234. {
  235. cerr<<"couldn't find sequence "<<ID<<endl;
  236. return NULL;
  237. }
  238. return &i->second;
  239. }
  240. void Track::AddNote(int ID, int Sequence, float t, float l, int n, float v)
  241. {
  242. GetPattern(GetSequence(Sequence)->GetPatternID())->AddNote(ID,t,l,n,v);
  243. }
  244. void Track::RemoveNote(int ID, int Sequence)
  245. {
  246. GetPattern(GetSequence(Sequence)->GetPatternID())->RemoveNote(ID);
  247. }
  248. void Track::ChangeNote(int ID, int Sequence, float t, float l, int n, float v)
  249. {
  250. Note *note = GetPattern(GetSequence(Sequence)->GetPatternID())->GetNote(ID);
  251. note->Time = t;
  252. note->Length = l;
  253. note->MidiNote = n;
  254. note->Vol = v;
  255. }
  256. void Track::ReadTrack(float t, int channel, vector<Note> &NoteVec)
  257. {
  258. // for every sequence
  259. for (map<int, Sequence>::iterator i = m_SequenceMap.begin();
  260. i!=m_SequenceMap.end(); i++)
  261. {
  262. if (i->second.GetChannel()==channel)
  263. {
  264. Pattern *p=GetPattern(i->second.GetPatternID());
  265. float SeqTime=i->second.GetStartTime();
  266. // for every note in the pattern
  267. for (map<int, Note>::iterator n = p->m_NoteMap.begin();
  268. n!=p->m_NoteMap.end(); n++)
  269. {
  270. if (n->second.Time+SeqTime<t && n->second.Time+n->second.Length+SeqTime>t)
  271. {
  272. NoteVec.push_back(n->second);
  273. }
  274. }
  275. }
  276. }
  277. }
  278. //// private //////
  279. void Track::AddPattern(int ID)
  280. {
  281. map<int,Pattern>::iterator i = m_PatternMap.find(ID);
  282. if (i != m_PatternMap.end())
  283. {
  284. cerr<<"duplicate pattern "<<ID<<" not added"<<endl;
  285. return;
  286. }
  287. Pattern newpattern;
  288. m_PatternMap[ID]=newpattern;
  289. }
  290. void Track::RemovePattern(int ID)
  291. {
  292. map<int,Pattern>::iterator i = m_PatternMap.find(ID);
  293. if (i == m_PatternMap.end())
  294. {
  295. cerr<<"couldn't find pattern "<<ID<<" not removed"<<endl;
  296. return;
  297. }
  298. m_PatternMap.erase(i);
  299. }
  300. Pattern *Track::GetPattern(int ID)
  301. {
  302. map<int,Pattern>::iterator i = m_PatternMap.find(ID);
  303. if (i == m_PatternMap.end())
  304. {
  305. cerr<<"couldn't find pattern "<<ID<<endl;
  306. return NULL;
  307. }
  308. return &i->second;
  309. }
  310. istream &operator>>(istream &s, Track &o)
  311. {
  312. int version=1,Num,id=0;
  313. string dummy;
  314. s>>version>>dummy;
  315. s>>Num;
  316. for (int n=0; n<Num; n++)
  317. {
  318. Pattern t;
  319. s>>t;
  320. o.m_PatternMap[id++]=t;
  321. }
  322. s>>Num;
  323. id=0;
  324. for (int n=0; n<Num; n++)
  325. {
  326. Sequence t;
  327. s>>t;
  328. o.m_SequenceMap[id++]=t;
  329. cerr<<"Loaded sequence "<<t.GetName()<<endl;
  330. }
  331. s>>o.m_NextPatternID;
  332. o.m_NextPatternID=o.m_PatternMap.size();
  333. return s;
  334. }
  335. ostream &operator<<(ostream &s, Track &o)
  336. {
  337. int version=1;
  338. s<<version<<" "<<"track"<<" ";
  339. s<<o.m_PatternMap.size()<<endl;
  340. for (map<int,Pattern>::iterator i = o.m_PatternMap.begin();
  341. i!=o.m_PatternMap.end(); i++)
  342. {
  343. s<<i->second;
  344. }
  345. s<<o.m_SequenceMap.size()<<endl;
  346. for (map<int,Sequence>::iterator i = o.m_SequenceMap.begin();
  347. i!=o.m_SequenceMap.end(); i++)
  348. {
  349. s<<i->second;
  350. }
  351. s<<o.m_NextPatternID<<" "<<endl;
  352. return s;
  353. }
  354. ////////////////////////////////////////////////////////////////////////////////////
  355. ////////////////////////////////////////////////////////////////////////////////////
  356. extern "C" {
  357. SpiralPlugin* CreateInstance()
  358. {
  359. return new SequencerPlugin;
  360. }
  361. char** GetIcon()
  362. {
  363. return SpiralIcon_xpm;
  364. }
  365. int GetID()
  366. {
  367. return 0x0011;
  368. }
  369. }
  370. ///////////////////////////////////////////////////////
  371. SequencerPlugin::SequencerPlugin() :
  372. m_TransferPattern(-1),
  373. m_Time(0.0f),
  374. m_Length(4),
  375. m_BarLength(1.0f),
  376. m_BeatsPerBar(4),
  377. m_NextBeatTime(0.0f),
  378. m_BeatLevel(-1.0f),
  379. m_BeatCount(0),
  380. m_BarCount(0),
  381. m_SpeedMod(1.0f),
  382. m_InNoteDown(false),
  383. m_InNoteID(0),
  384. m_CurrentPattern(0),
  385. m_Triggered(false)
  386. {
  387. m_Version=1;
  388. m_PluginInfo.Name="Sequencer";
  389. m_PluginInfo.Width=540;
  390. m_PluginInfo.Height=290;
  391. m_PluginInfo.NumInputs=4;
  392. m_PluginInfo.NumOutputs=17;
  393. m_PluginInfo.PortTips.push_back("Play Trigger");
  394. m_PluginInfo.PortTips.push_back("Speed CV");
  395. m_PluginInfo.PortTips.push_back("Input Pitch CV");
  396. m_PluginInfo.PortTips.push_back("Input Trigger CV");
  397. m_PluginInfo.PortTips.push_back("Channel 0 Pitch");
  398. m_PluginInfo.PortTips.push_back("Channel 0 Trigger");
  399. m_PluginInfo.PortTips.push_back("Channel 1 Pitch");
  400. m_PluginInfo.PortTips.push_back("Channel 1 Trigger");
  401. m_PluginInfo.PortTips.push_back("Channel 2 Pitch");
  402. m_PluginInfo.PortTips.push_back("Channel 2 Trigger");
  403. m_PluginInfo.PortTips.push_back("Channel 3 Pitch");
  404. m_PluginInfo.PortTips.push_back("Channel 3 Trigger");
  405. m_PluginInfo.PortTips.push_back("Channel 4 Pitch");
  406. m_PluginInfo.PortTips.push_back("Channel 4 Trigger");
  407. m_PluginInfo.PortTips.push_back("Channel 5 Pitch");
  408. m_PluginInfo.PortTips.push_back("Channel 5 Trigger");
  409. m_PluginInfo.PortTips.push_back("Channel 6 Pitch");
  410. m_PluginInfo.PortTips.push_back("Channel 6 Trigger");
  411. m_PluginInfo.PortTips.push_back("Channel 7 Pitch");
  412. m_PluginInfo.PortTips.push_back("Channel 7 Trigger");
  413. /*m_PluginInfo.PortTips.push_back("Channel 8 Pitch");
  414. m_PluginInfo.PortTips.push_back("Channel 8 Trigger");
  415. m_PluginInfo.PortTips.push_back("Channel 9 Pitch");
  416. m_PluginInfo.PortTips.push_back("Channel 9 Trigger");
  417. m_PluginInfo.PortTips.push_back("Channel 10 Pitch");
  418. m_PluginInfo.PortTips.push_back("Channel 10 Trigger");
  419. m_PluginInfo.PortTips.push_back("Channel 11 Pitch");
  420. m_PluginInfo.PortTips.push_back("Channel 11 Trigger");
  421. m_PluginInfo.PortTips.push_back("Channel 12 Pitch");
  422. m_PluginInfo.PortTips.push_back("Channel 12 Trigger");
  423. m_PluginInfo.PortTips.push_back("Channel 13 Pitch");
  424. m_PluginInfo.PortTips.push_back("Channel 13 Trigger");
  425. m_PluginInfo.PortTips.push_back("Channel 14 Pitch");
  426. m_PluginInfo.PortTips.push_back("Channel 14 Trigger");
  427. m_PluginInfo.PortTips.push_back("Channel 15 Pitch");
  428. m_PluginInfo.PortTips.push_back("Channel 15 Trigger");*/
  429. m_PluginInfo.PortTips.push_back("Beat");
  430. m_AudioCH->Register("ID",&m_GUIArgs.Num);
  431. m_AudioCH->Register("ID2",&m_GUIArgs.Num2);
  432. m_AudioCH->Register("Channel",&m_GUIArgs.Channel);
  433. m_AudioCH->Register("Sequence",&m_GUIArgs.Sequence);
  434. m_AudioCH->Register("Time",&m_GUIArgs.t);
  435. m_AudioCH->Register("Length",&m_GUIArgs.l);
  436. m_AudioCH->Register("Vol",&m_GUIArgs.v);
  437. m_AudioCH->Register("Note",&m_GUIArgs.n);
  438. m_AudioCH->Register("CurrentTime",&m_Time,ChannelHandler::OUTPUT);
  439. m_AudioCH->Register("TotalLength",&m_Length);
  440. m_AudioCH->Register("BeatsPerBar",&m_BeatsPerBar);
  441. m_AudioCH->Register("BarLength",&m_BarLength);
  442. m_AudioCH->RegisterData("Name",ChannelHandler::INPUT,m_GUIArgs.Name,sizeof(m_GUIArgs.Name));
  443. // use OUTPUT_REQUEST for these, as we don't have to copy them constantly (and the gui can request them)
  444. m_AudioCH->Register("TransCount",&m_TransferCount,ChannelHandler::OUTPUT_REQUEST);
  445. m_AudioCH->RegisterData("TransNote",ChannelHandler::OUTPUT_REQUEST,&m_Transfer,sizeof(m_Transfer));
  446. }
  447. SequencerPlugin::~SequencerPlugin()
  448. {
  449. }
  450. PluginInfo &SequencerPlugin::Initialise(const HostInfo *Host)
  451. {
  452. return SpiralPlugin::Initialise(Host);
  453. }
  454. SpiralGUIType *SequencerPlugin::CreateGUI()
  455. {
  456. return new SequencerPluginGUI(m_PluginInfo.Width,
  457. m_PluginInfo.Height,
  458. this,m_AudioCH,m_HostInfo);
  459. }
  460. void SequencerPlugin::SetPattern(int s)
  461. {
  462. //m_Eventmap[m_CurrentPattern]->hide();
  463. m_CurrentPattern=s;
  464. //m_Eventmap[m_CurrentPattern]->show();
  465. }
  466. void SequencerPlugin::Execute()
  467. {
  468. float Speed;
  469. for (int n=0; n<m_HostInfo->BUFSIZE; n++)
  470. {
  471. if (GetInputPitch(0,n)>0)
  472. {
  473. if (!m_Triggered)
  474. {
  475. float Freq=GetInputPitch(0,n);
  476. // Notes 0 to 16 trigger patterns 0 to 16
  477. // No other notes catered for
  478. for (int i=0; i<NUM_PATTERNS; i++)
  479. {
  480. if (feq(Freq,NoteTable[i],0.01f))
  481. {
  482. SetPattern(i);
  483. break;
  484. }
  485. }
  486. m_Time=0;
  487. m_Triggered=true;
  488. }
  489. }
  490. else
  491. {
  492. m_Triggered=false;
  493. }
  494. if (InputExists(1))
  495. Speed =(1.1025f/m_HostInfo->SAMPLERATE) * (GetInput(1,n)+1.0f);
  496. else
  497. Speed =1.1025f/m_HostInfo->SAMPLERATE;
  498. if (!m_InNoteDown)
  499. {
  500. // Check trigger
  501. if (GetInput(3,n)>TRIGGER_LEV)
  502. {
  503. m_InNoteDown=true;
  504. float Freq=GetInputPitch(2,n);
  505. int NoteNum=0;
  506. for (int i=0; i<131; i++)
  507. {
  508. if (feq(Freq,NoteTable[i],0.01f))
  509. {
  510. NoteNum=i;
  511. break;
  512. }
  513. }
  514. /*cerr<<"note recieved ="<<NoteNum<<" f="<<Freq
  515. <<" t-1="<<NoteTable[NoteNum-1]
  516. <<" t="<<NoteTable[NoteNum]
  517. <<" t+1="<<NoteTable[NoteNum+1]<<endl;
  518. */
  519. //m_InNoteID=m_Eventmap[m_CurrentPattern]->AddEventTime(m_Time, NoteNum, 0.5, Fl_SEvent::MELODY, false);
  520. m_InNoteTime=m_Time;
  521. }
  522. }
  523. else
  524. {
  525. // Check trigger
  526. if (GetInput(3,n)<TRIGGER_LEV)
  527. {
  528. //m_Eventmap[m_CurrentPattern]->SetEventLength(m_InNoteID, m_Time-m_InNoteTime);
  529. m_InNoteDown=false;
  530. }
  531. }
  532. for (int channel=0; channel<NUM_CHANNELS; channel++)
  533. {
  534. // Get the notes from the map
  535. vector<Note> NoteVec;
  536. m_Track.ReadTrack(m_Time,channel,NoteVec);
  537. m_CurrentTriggerCV[channel]=0;
  538. //m_CurrentNoteCV=0;
  539. // play all the notes found
  540. for (vector<Note>::iterator i=NoteVec.begin();
  541. i!=NoteVec.end(); i++)
  542. {
  543. //cerr<<"time = "<<m_Time<<endl;
  544. //cerr<<"found note "<<i->Time<<" "<<i->Length<<endl;
  545. m_CurrentNoteCV[channel]=NoteTable[i->MidiNote];
  546. m_CurrentTriggerCV[channel]=1;
  547. }
  548. SetOutputPitch(channel*2,n,m_CurrentNoteCV[channel]);
  549. SetOutput(channel*2+1,n,m_CurrentTriggerCV[channel]);
  550. }
  551. m_Time+=Speed*m_SpeedMod;
  552. // deal with the beat calculation
  553. if (m_Time>m_NextBeatTime)
  554. {
  555. float BeatTime=m_BarLength/m_BeatsPerBar;
  556. m_NextBeatTime=m_Time+BeatTime;
  557. if (m_BeatLevel!=1.0f) m_BeatLevel=1.0f;
  558. else m_BeatLevel=-1.0f;
  559. m_BeatCount++;
  560. }
  561. SetOutput(NUM_CHANNELS*2,n,m_BeatLevel);
  562. if (m_BeatCount>=m_BeatsPerBar)
  563. {
  564. m_BeatCount=0;
  565. m_BarCount++;
  566. }
  567. if (m_BarCount>=m_Length)
  568. {
  569. m_Time=0;
  570. m_BeatCount=-1;
  571. m_BarCount=0;
  572. m_NextBeatTime=0;
  573. }
  574. if (m_Time<0)
  575. {
  576. m_Time=m_Length;
  577. }
  578. }
  579. }
  580. void SequencerPlugin::ExecuteCommands()
  581. {
  582. if (m_AudioCH->IsCommandWaiting())
  583. {
  584. switch (m_AudioCH->GetCommand())
  585. {
  586. case NEW_NOTE : m_Track.AddNote(m_GUIArgs.Num,m_GUIArgs.Sequence,m_GUIArgs.t,m_GUIArgs.l,m_GUIArgs.n,m_GUIArgs.v); break;
  587. case CHG_NOTE : m_Track.ChangeNote(m_GUIArgs.Num,m_GUIArgs.Sequence,m_GUIArgs.t,m_GUIArgs.l,m_GUIArgs.n,m_GUIArgs.v); break;
  588. case REM_NOTE : m_Track.RemoveNote(m_GUIArgs.Num,m_GUIArgs.Sequence); break;
  589. case NEW_SEQ :
  590. {
  591. m_Track.AddSequence(m_GUIArgs.Num);
  592. m_Track.GetSequence(m_GUIArgs.Num)->SetColour(m_GUIArgs.Num2);
  593. m_Track.GetSequence(m_GUIArgs.Num)->SetName(m_GUIArgs.Name);
  594. m_Track.GetSequence(m_GUIArgs.Num)->SetLength(m_GUIArgs.l);
  595. m_Track.GetSequence(m_GUIArgs.Num)->SetYPos(m_GUIArgs.n);
  596. m_Track.GetSequence(m_GUIArgs.Num)->SetChannel(m_GUIArgs.Channel);
  597. } break;
  598. case COPY_SEQ : m_Track.CopySequence(m_GUIArgs.Num,m_GUIArgs.Num2); break;
  599. case INST_SEQ : m_Track.InstanceSequence(m_GUIArgs.Num); break;
  600. case CLONE_SEQ : m_Track.CloneSequence(m_GUIArgs.Num,m_GUIArgs.Num2); break;
  601. case REM_SEQ : m_Track.RemoveSequence(m_GUIArgs.Num); break;
  602. case CHG_SEQ :
  603. {
  604. m_Track.GetSequence(m_GUIArgs.Num)->SetColour(m_GUIArgs.Num2);
  605. m_Track.GetSequence(m_GUIArgs.Num)->SetName(m_GUIArgs.Name);
  606. m_Track.GetSequence(m_GUIArgs.Num)->SetLength(m_GUIArgs.l);
  607. m_Track.GetSequence(m_GUIArgs.Num)->SetYPos(m_GUIArgs.n);
  608. m_Track.GetSequence(m_GUIArgs.Num)->SetChannel(m_GUIArgs.Channel);
  609. m_Track.GetSequence(m_GUIArgs.Num)->SetStartTime(m_GUIArgs.t);
  610. } break;
  611. case GET_PATTERN :
  612. {
  613. // start of transfer
  614. if (m_TransferPattern==-1)
  615. {
  616. m_TransferPattern=m_Track.GetSequence(m_GUIArgs.Num)->GetPatternID();
  617. m_TransferNote=m_Track.GetPattern(m_TransferPattern)->m_NoteMap.begin();
  618. m_TransferCount=m_Track.GetPattern(m_TransferPattern)->GetNoteCount();
  619. cerr<<"going to transfer "<<m_TransferCount<<" notes"<<endl;
  620. }
  621. else
  622. {
  623. // last note gone
  624. if (m_TransferNote==m_Track.GetPattern(m_TransferPattern)->m_NoteMap.end())
  625. {
  626. m_TransferPattern=-1;
  627. }
  628. else
  629. {
  630. // copy this note over
  631. m_Transfer.Time = m_TransferNote->second.Time;
  632. m_Transfer.Length = m_TransferNote->second.Length;
  633. m_Transfer.MidiNote = m_TransferNote->second.MidiNote;
  634. m_Transfer.Vol = m_TransferNote->second.Vol;
  635. m_TransferNote++;
  636. }
  637. }
  638. } break;
  639. default: break;
  640. }
  641. }
  642. }
  643. void SequencerPlugin::StreamOut(ostream &s)
  644. {
  645. s<<m_Version<<" ";
  646. switch (m_Version)
  647. {
  648. case 1:
  649. {
  650. s<<m_Time<<" "<<m_Length<<" "<<m_BarLength<<" "<<m_BeatsPerBar<<" ";
  651. s<<m_Track;
  652. } break;
  653. }
  654. }
  655. void SequencerPlugin::StreamIn(istream &s)
  656. {
  657. int version;
  658. s>>version;
  659. switch (version)
  660. {
  661. case 1:
  662. {
  663. s>>m_Time>>m_Length>>m_BarLength>>m_BeatsPerBar;
  664. s>>m_Track;
  665. } break;
  666. }
  667. }