| @@ -184,7 +184,7 @@ SequencerPlugin.o: SequencerPlugin.C \ | |||
| SequencerPluginGUI.o: SequencerPluginGUI.C \ | |||
| SequencerPluginGUI.h \ | |||
| SequencerPluginss.h \ | |||
| SequencerPlugin.h \ | |||
| ../SpiralPlugin.h \ | |||
| ../../Sample.h \ | |||
| ../../SpiralInfo.h \ | |||
| @@ -25,6 +25,398 @@ | |||
| // for note on's | |||
| static const float TRIGGER_LEV=0.1; | |||
| ////////////////////////////////////////////////////////////////////////// | |||
| // base sequencing stuff | |||
| Note::Note(float t=0, float l=0.1f, int n=0, float v=1.0f) | |||
| { | |||
| Time = t; | |||
| Length = l; | |||
| MidiNote = n; | |||
| Vol = v; | |||
| } | |||
| Note::~Note() | |||
| { | |||
| } | |||
| istream &operator>>(istream &s, Note &o) | |||
| { | |||
| int version=1; | |||
| string dummy; | |||
| s>>version>>dummy>>o.Time>>o.Length>>o.MidiNote>>o.Vol; | |||
| return s; | |||
| } | |||
| ostream &operator<<(ostream &s, Note &o) | |||
| { | |||
| int version=1; | |||
| s<<version<<" note "<<o.Time<<" "<<o.Length<<" "<<o.MidiNote<<" "<<o.Vol<<" "; | |||
| return s; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////// | |||
| Pattern::Pattern() | |||
| { | |||
| } | |||
| Pattern::~Pattern() | |||
| { | |||
| } | |||
| void Pattern::Copy(const Pattern *o) | |||
| { | |||
| // can't do this as we don't want to preserve the id numbers | |||
| //m_NoteMap=o->m_NoteMap; | |||
| int c=0; | |||
| for (map<int,Note>::const_iterator i = o->m_NoteMap.begin(); | |||
| i!=o->m_NoteMap.end(); i++) | |||
| { | |||
| m_NoteMap[c++]=i->second; | |||
| } | |||
| } | |||
| void Pattern::AddNote(int ID, float t, float l, int n, float v) | |||
| { | |||
| map<int,Note>::iterator i = m_NoteMap.find(ID); | |||
| if (i != m_NoteMap.end()) | |||
| { | |||
| cerr<<"duplicate note "<<ID<<" not added"<<endl; | |||
| return; | |||
| } | |||
| Note newnote(t,l,n,v); | |||
| m_NoteMap[ID]=newnote; | |||
| } | |||
| void Pattern::RemoveNote(int ID) | |||
| { | |||
| map<int,Note>::iterator i = m_NoteMap.find(ID); | |||
| if (i == m_NoteMap.end()) | |||
| { | |||
| cerr<<"couldn't find note "<<ID<<" not removed"<<endl; | |||
| return; | |||
| } | |||
| m_NoteMap.erase(i); | |||
| } | |||
| Note *Pattern::GetNote(int ID) | |||
| { | |||
| map<int,Note>::iterator i = m_NoteMap.find(ID); | |||
| if (i == m_NoteMap.end()) | |||
| { | |||
| cerr<<"couldn't find note "<<ID<<endl; | |||
| return NULL; | |||
| } | |||
| return &i->second; | |||
| } | |||
| istream &operator>>(istream &s, Pattern &o) | |||
| { | |||
| int version=1,Num; | |||
| string dummy; | |||
| int id=0; | |||
| s>>version>>dummy>>Num; | |||
| for (int n=0; n<Num; n++) | |||
| { | |||
| Note t; | |||
| s>>t; | |||
| o.m_NoteMap[id++]=t; | |||
| } | |||
| return s; | |||
| } | |||
| ostream &operator<<(ostream &s, Pattern &o) | |||
| { | |||
| int version=1; | |||
| s<<version<<" pattern "<<o.m_NoteMap.size()<<" "; | |||
| for (map<int,Note>::iterator i = o.m_NoteMap.begin(); | |||
| i!=o.m_NoteMap.end(); i++) | |||
| { | |||
| s<<i->second; | |||
| } | |||
| s<<endl; | |||
| return s; | |||
| } | |||
| ////////////////////////////////////////////////////////////////////////// | |||
| Sequence::Sequence(float st=0, int pat=0) | |||
| { | |||
| m_StartTime=st; | |||
| m_Pattern=pat; | |||
| } | |||
| Sequence::~Sequence() | |||
| { | |||
| } | |||
| istream &operator>>(istream &s, Sequence &o) | |||
| { | |||
| int version=1; | |||
| string dummy; | |||
| s>>version>>dummy>>o.m_StartTime>>o.m_Pattern>>o.m_Colour>>o.m_YPos>>o.m_Length>>o.m_Channel; | |||
| char Buf[4096]; | |||
| int size; | |||
| s>>size; | |||
| s.ignore(1); | |||
| s.get(Buf,size+1); | |||
| o.m_Name=Buf; | |||
| return s; | |||
| } | |||
| ostream &operator<<(ostream &s, Sequence &o) | |||
| { | |||
| int version=1; | |||
| s<<version<<" sequence"<<" "<<o.m_StartTime<<" "<<o.m_Pattern<<" "<<o.m_Colour<<" "<<o.m_YPos<<" "<<o.m_Length<<" "<<o.m_Channel<<" "; | |||
| s<<o.m_Name.size()<<" "<<o.m_Name<<endl; | |||
| return s; | |||
| } | |||
| ////////////////////////////////////////////////////////////////////////// | |||
| Track::Track() | |||
| { | |||
| m_NextPatternID=0; | |||
| } | |||
| Track::~Track() | |||
| { | |||
| } | |||
| void Track::AddSequence(int ID) | |||
| { | |||
| map<int,Sequence>::iterator i = m_SequenceMap.find(ID); | |||
| if (i != m_SequenceMap.end()) | |||
| { | |||
| cerr<<"duplicate sequence "<<ID<<" not added"<<endl; | |||
| return; | |||
| } | |||
| Sequence newsequence; | |||
| AddPattern(m_NextPatternID); | |||
| newsequence.SetPatternID(m_NextPatternID); | |||
| newsequence.SetColour(0); | |||
| newsequence.SetName("noname"); | |||
| newsequence.SetLength(10.0f); | |||
| newsequence.SetYPos(1); | |||
| newsequence.SetChannel(0); | |||
| m_NextPatternID++; | |||
| m_SequenceMap[ID]=newsequence; | |||
| } | |||
| // duplicate the sequence, but reference the same pattern | |||
| void Track::CloneSequence(int ID, int nID) | |||
| { | |||
| AddSequence(nID); | |||
| Sequence *s=GetSequence(nID); | |||
| s->SetColour(GetSequence(ID)->GetColour()); | |||
| s->SetName(GetSequence(ID)->GetName()); | |||
| s->SetLength(GetSequence(ID)->GetLength()); | |||
| s->SetYPos(GetSequence(ID)->GetYPos()); | |||
| s->SetPatternID(GetSequence(ID)->GetPatternID()); | |||
| s->SetStartTime(GetSequence(ID)->GetStartTime()); | |||
| s->SetChannel(GetSequence(ID)->GetChannel()); | |||
| } | |||
| // duplicate the sequence, and copy the pattern to it's own version | |||
| void Track::CopySequence(int ID, int nID) | |||
| { | |||
| AddSequence(nID); | |||
| Sequence *s=GetSequence(nID); | |||
| s->SetColour(GetSequence(ID)->GetColour()); | |||
| s->SetName(GetSequence(ID)->GetName()); | |||
| s->SetLength(GetSequence(ID)->GetLength()); | |||
| s->SetYPos(GetSequence(ID)->GetYPos()); | |||
| s->SetStartTime(GetSequence(ID)->GetStartTime()); | |||
| s->SetChannel(GetSequence(ID)->GetChannel()); | |||
| AddPattern(m_NextPatternID); | |||
| GetPattern(m_NextPatternID)->Copy(GetPattern(GetSequence(ID)->GetPatternID())); | |||
| GetSequence(nID)->SetPatternID(m_NextPatternID); | |||
| m_NextPatternID++; | |||
| } | |||
| // copy the sequences pattern, so it's got it's own version | |||
| void Track::InstanceSequence(int ID) | |||
| { | |||
| AddPattern(m_NextPatternID); | |||
| GetPattern(m_NextPatternID)->Copy(GetPattern(GetSequence(ID)->GetPatternID())); | |||
| GetSequence(ID)->SetPatternID(m_NextPatternID); | |||
| m_NextPatternID++; | |||
| } | |||
| void Track::RemoveSequence(int ID) | |||
| { | |||
| map<int,Sequence>::iterator i = m_SequenceMap.find(ID); | |||
| if (i == m_SequenceMap.end()) | |||
| { | |||
| cerr<<"couldn't find sequence "<<ID<<" not removed"<<endl; | |||
| return; | |||
| } | |||
| // todo - refcount the patterns | |||
| m_SequenceMap.erase(i); | |||
| } | |||
| Sequence *Track::GetSequence(int ID) | |||
| { | |||
| map<int, Sequence>::iterator i = m_SequenceMap.find(ID); | |||
| if (i == m_SequenceMap.end()) | |||
| { | |||
| cerr<<"couldn't find sequence "<<ID<<endl; | |||
| return NULL; | |||
| } | |||
| return &i->second; | |||
| } | |||
| void Track::AddNote(int ID, int Sequence, float t, float l, int n, float v) | |||
| { | |||
| GetPattern(GetSequence(Sequence)->GetPatternID())->AddNote(ID,t,l,n,v); | |||
| } | |||
| void Track::RemoveNote(int ID, int Sequence) | |||
| { | |||
| GetPattern(GetSequence(Sequence)->GetPatternID())->RemoveNote(ID); | |||
| } | |||
| void Track::ChangeNote(int ID, int Sequence, float t, float l, int n, float v) | |||
| { | |||
| Note *note = GetPattern(GetSequence(Sequence)->GetPatternID())->GetNote(ID); | |||
| note->Time = t; | |||
| note->Length = l; | |||
| note->MidiNote = n; | |||
| note->Vol = v; | |||
| } | |||
| void Track::ReadTrack(float t, int channel, vector<Note> &NoteVec) | |||
| { | |||
| // for every sequence | |||
| for (map<int, Sequence>::iterator i = m_SequenceMap.begin(); | |||
| i!=m_SequenceMap.end(); i++) | |||
| { | |||
| if (i->second.GetChannel()==channel) | |||
| { | |||
| Pattern *p=GetPattern(i->second.GetPatternID()); | |||
| float SeqTime=i->second.GetStartTime(); | |||
| // for every note in the pattern | |||
| for (map<int, Note>::iterator n = p->m_NoteMap.begin(); | |||
| n!=p->m_NoteMap.end(); n++) | |||
| { | |||
| if (n->second.Time+SeqTime<t && n->second.Time+n->second.Length+SeqTime>t) | |||
| { | |||
| NoteVec.push_back(n->second); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| //// private ////// | |||
| void Track::AddPattern(int ID) | |||
| { | |||
| map<int,Pattern>::iterator i = m_PatternMap.find(ID); | |||
| if (i != m_PatternMap.end()) | |||
| { | |||
| cerr<<"duplicate pattern "<<ID<<" not added"<<endl; | |||
| return; | |||
| } | |||
| Pattern newpattern; | |||
| m_PatternMap[ID]=newpattern; | |||
| } | |||
| void Track::RemovePattern(int ID) | |||
| { | |||
| map<int,Pattern>::iterator i = m_PatternMap.find(ID); | |||
| if (i == m_PatternMap.end()) | |||
| { | |||
| cerr<<"couldn't find pattern "<<ID<<" not removed"<<endl; | |||
| return; | |||
| } | |||
| m_PatternMap.erase(i); | |||
| } | |||
| Pattern *Track::GetPattern(int ID) | |||
| { | |||
| map<int,Pattern>::iterator i = m_PatternMap.find(ID); | |||
| if (i == m_PatternMap.end()) | |||
| { | |||
| cerr<<"couldn't find pattern "<<ID<<endl; | |||
| return NULL; | |||
| } | |||
| return &i->second; | |||
| } | |||
| istream &operator>>(istream &s, Track &o) | |||
| { | |||
| int version=1,Num,id=0; | |||
| string dummy; | |||
| s>>version>>dummy; | |||
| s>>Num; | |||
| for (int n=0; n<Num; n++) | |||
| { | |||
| Pattern t; | |||
| s>>t; | |||
| o.m_PatternMap[id++]=t; | |||
| } | |||
| s>>Num; | |||
| id=0; | |||
| for (int n=0; n<Num; n++) | |||
| { | |||
| Sequence t; | |||
| s>>t; | |||
| o.m_SequenceMap[id++]=t; | |||
| cerr<<"Loaded sequence "<<t.GetName()<<endl; | |||
| } | |||
| s>>o.m_NextPatternID; | |||
| o.m_NextPatternID=o.m_PatternMap.size(); | |||
| return s; | |||
| } | |||
| ostream &operator<<(ostream &s, Track &o) | |||
| { | |||
| int version=1; | |||
| s<<version<<" "<<"track"<<" "; | |||
| s<<o.m_PatternMap.size()<<endl; | |||
| for (map<int,Pattern>::iterator i = o.m_PatternMap.begin(); | |||
| i!=o.m_PatternMap.end(); i++) | |||
| { | |||
| s<<i->second; | |||
| } | |||
| s<<o.m_SequenceMap.size()<<endl; | |||
| for (map<int,Sequence>::iterator i = o.m_SequenceMap.begin(); | |||
| i!=o.m_SequenceMap.end(); i++) | |||
| { | |||
| s<<i->second; | |||
| } | |||
| s<<o.m_NextPatternID<<" "<<endl; | |||
| return s; | |||
| } | |||
| //////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////// | |||
| extern "C" { | |||
| SpiralPlugin* CreateInstance() | |||
| { | |||
| @@ -45,29 +437,83 @@ int GetID() | |||
| /////////////////////////////////////////////////////// | |||
| SequencerPlugin::SequencerPlugin() : | |||
| m_TransferPattern(-1), | |||
| m_Time(0.0f), | |||
| m_Length(10.0f), | |||
| m_Length(4), | |||
| m_BarLength(1.0f), | |||
| m_BeatsPerBar(4), | |||
| m_NextBeatTime(0.0f), | |||
| m_BeatLevel(-1.0f), | |||
| m_BeatCount(0), | |||
| m_BarCount(0), | |||
| m_SpeedMod(1.0f), | |||
| m_CurrentNoteCV(0), | |||
| m_CurrentTriggerCV(0), | |||
| m_InNoteDown(false), | |||
| m_InNoteID(0), | |||
| m_CurrentPattern(0), | |||
| m_Triggered(false) | |||
| { | |||
| m_Version=2; | |||
| m_Version=1; | |||
| m_PluginInfo.Name="Sequencer"; | |||
| m_PluginInfo.Width=540; | |||
| m_PluginInfo.Height=290; | |||
| m_PluginInfo.NumInputs=4; | |||
| m_PluginInfo.NumOutputs=2; | |||
| m_PluginInfo.NumOutputs=17; | |||
| m_PluginInfo.PortTips.push_back("Play Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Speed CV"); | |||
| m_PluginInfo.PortTips.push_back("Input Pitch CV"); | |||
| m_PluginInfo.PortTips.push_back("Input Trigger CV"); | |||
| m_PluginInfo.PortTips.push_back("Output Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Output Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 0 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 0 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 1 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 1 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 2 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 2 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 3 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 3 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 4 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 4 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 5 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 5 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 6 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 6 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 7 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 7 Trigger"); | |||
| /*m_PluginInfo.PortTips.push_back("Channel 8 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 8 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 9 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 9 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 10 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 10 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 11 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 11 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 12 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 12 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 13 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 13 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 14 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 14 Trigger"); | |||
| m_PluginInfo.PortTips.push_back("Channel 15 Pitch"); | |||
| m_PluginInfo.PortTips.push_back("Channel 15 Trigger");*/ | |||
| m_PluginInfo.PortTips.push_back("Beat"); | |||
| m_AudioCH->Register("ID",&m_GUIArgs.Num); | |||
| m_AudioCH->Register("ID2",&m_GUIArgs.Num2); | |||
| m_AudioCH->Register("Channel",&m_GUIArgs.Channel); | |||
| m_AudioCH->Register("Sequence",&m_GUIArgs.Sequence); | |||
| m_AudioCH->Register("Time",&m_GUIArgs.t); | |||
| m_AudioCH->Register("Length",&m_GUIArgs.l); | |||
| m_AudioCH->Register("Vol",&m_GUIArgs.v); | |||
| m_AudioCH->Register("Note",&m_GUIArgs.n); | |||
| m_AudioCH->Register("CurrentTime",&m_Time,ChannelHandler::OUTPUT); | |||
| m_AudioCH->Register("TotalLength",&m_Length); | |||
| m_AudioCH->Register("BeatsPerBar",&m_BeatsPerBar); | |||
| m_AudioCH->Register("BarLength",&m_BarLength); | |||
| m_AudioCH->RegisterData("Name",ChannelHandler::INPUT,m_GUIArgs.Name,sizeof(m_GUIArgs.Name)); | |||
| // use OUTPUT_REQUEST for these, as we don't have to copy them constantly (and the gui can request them) | |||
| m_AudioCH->Register("TransCount",&m_TransferCount,ChannelHandler::OUTPUT_REQUEST); | |||
| m_AudioCH->RegisterData("TransNote",ChannelHandler::OUTPUT_REQUEST,&m_Transfer,sizeof(m_Transfer)); | |||
| } | |||
| SequencerPlugin::~SequencerPlugin() | |||
| @@ -171,35 +617,55 @@ void SequencerPlugin::Execute() | |||
| } | |||
| } | |||
| // Get the notes from the map | |||
| /*vector<EventInfo> NoteVec=m_Eventmap[m_CurrentPattern]->GetEvents(m_Time); | |||
| // play all the notes found | |||
| for (vector<EventInfo>::iterator i=NoteVec.begin(); | |||
| i!=NoteVec.end(); i++) | |||
| for (int channel=0; channel<NUM_CHANNELS; channel++) | |||
| { | |||
| if (i->m_Type==EventInfo::START) | |||
| { | |||
| m_CurrentNoteCV=NoteTable[i->m_Group]; | |||
| m_CurrentTriggerCV=1; | |||
| } | |||
| if (i->m_Type==EventInfo::END) | |||
| { | |||
| m_CurrentTriggerCV=0; | |||
| if (m_NoteCut) m_CurrentNoteCV=0; | |||
| // Get the notes from the map | |||
| vector<Note> NoteVec; | |||
| m_Track.ReadTrack(m_Time,channel,NoteVec); | |||
| m_CurrentTriggerCV[channel]=0; | |||
| //m_CurrentNoteCV=0; | |||
| // play all the notes found | |||
| for (vector<Note>::iterator i=NoteVec.begin(); | |||
| i!=NoteVec.end(); i++) | |||
| { | |||
| //cerr<<"time = "<<m_Time<<endl; | |||
| //cerr<<"found note "<<i->Time<<" "<<i->Length<<endl; | |||
| m_CurrentNoteCV[channel]=NoteTable[i->MidiNote]; | |||
| m_CurrentTriggerCV[channel]=1; | |||
| } | |||
| SetOutputPitch(channel*2,n,m_CurrentNoteCV[channel]); | |||
| SetOutput(channel*2+1,n,m_CurrentTriggerCV[channel]); | |||
| } | |||
| */ | |||
| SetOutputPitch(0,n,m_CurrentNoteCV); | |||
| SetOutput(1,n,m_CurrentTriggerCV); | |||
| m_Time+=Speed*m_SpeedMod; | |||
| if (m_Time>m_Length) | |||
| // deal with the beat calculation | |||
| if (m_Time>m_NextBeatTime) | |||
| { | |||
| float BeatTime=m_BarLength/m_BeatsPerBar; | |||
| m_NextBeatTime=m_Time+BeatTime; | |||
| if (m_BeatLevel!=1.0f) m_BeatLevel=1.0f; | |||
| else m_BeatLevel=-1.0f; | |||
| m_BeatCount++; | |||
| } | |||
| SetOutput(NUM_CHANNELS*2,n,m_BeatLevel); | |||
| if (m_BeatCount>=m_BeatsPerBar) | |||
| { | |||
| m_BeatCount=0; | |||
| m_BarCount++; | |||
| } | |||
| if (m_BarCount>=m_Length) | |||
| { | |||
| m_Time=0; | |||
| m_BeatCount=-1; | |||
| m_BarCount=0; | |||
| m_NextBeatTime=0; | |||
| } | |||
| if (m_Time<0) | |||
| @@ -211,6 +677,68 @@ void SequencerPlugin::Execute() | |||
| void SequencerPlugin::ExecuteCommands() | |||
| { | |||
| if (m_AudioCH->IsCommandWaiting()) | |||
| { | |||
| switch (m_AudioCH->GetCommand()) | |||
| { | |||
| 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; | |||
| 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; | |||
| case REM_NOTE : m_Track.RemoveNote(m_GUIArgs.Num,m_GUIArgs.Sequence); break; | |||
| case NEW_SEQ : | |||
| { | |||
| m_Track.AddSequence(m_GUIArgs.Num); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetColour(m_GUIArgs.Num2); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetName(m_GUIArgs.Name); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetLength(m_GUIArgs.l); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetYPos(m_GUIArgs.n); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetChannel(m_GUIArgs.Channel); | |||
| } break; | |||
| case COPY_SEQ : m_Track.CopySequence(m_GUIArgs.Num,m_GUIArgs.Num2); break; | |||
| case INST_SEQ : m_Track.InstanceSequence(m_GUIArgs.Num); break; | |||
| case CLONE_SEQ : m_Track.CloneSequence(m_GUIArgs.Num,m_GUIArgs.Num2); break; | |||
| case REM_SEQ : m_Track.RemoveSequence(m_GUIArgs.Num); break; | |||
| case CHG_SEQ : | |||
| { | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetColour(m_GUIArgs.Num2); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetName(m_GUIArgs.Name); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetLength(m_GUIArgs.l); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetYPos(m_GUIArgs.n); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetChannel(m_GUIArgs.Channel); | |||
| m_Track.GetSequence(m_GUIArgs.Num)->SetStartTime(m_GUIArgs.t); | |||
| } break; | |||
| case GET_PATTERN : | |||
| { | |||
| // start of transfer | |||
| if (m_TransferPattern==-1) | |||
| { | |||
| m_TransferPattern=m_Track.GetSequence(m_GUIArgs.Num)->GetPatternID(); | |||
| m_TransferNote=m_Track.GetPattern(m_TransferPattern)->m_NoteMap.begin(); | |||
| m_TransferCount=m_Track.GetPattern(m_TransferPattern)->GetNoteCount(); | |||
| cerr<<"going to transfer "<<m_TransferCount<<" notes"<<endl; | |||
| } | |||
| else | |||
| { | |||
| // last note gone | |||
| if (m_TransferNote==m_Track.GetPattern(m_TransferPattern)->m_NoteMap.end()) | |||
| { | |||
| m_TransferPattern=-1; | |||
| } | |||
| else | |||
| { | |||
| // copy this note over | |||
| m_Transfer.Time = m_TransferNote->second.Time; | |||
| m_Transfer.Length = m_TransferNote->second.Length; | |||
| m_Transfer.MidiNote = m_TransferNote->second.MidiNote; | |||
| m_Transfer.Vol = m_TransferNote->second.Vol; | |||
| m_TransferNote++; | |||
| } | |||
| } | |||
| } break; | |||
| default: break; | |||
| } | |||
| } | |||
| } | |||
| void SequencerPlugin::StreamOut(ostream &s) | |||
| @@ -219,23 +747,10 @@ void SequencerPlugin::StreamOut(ostream &s) | |||
| switch (m_Version) | |||
| { | |||
| case 2: | |||
| { | |||
| s<<m_Time<<" "; | |||
| s<<m_Length<<" "; | |||
| s<<m_SpeedMod<<" "; | |||
| s<<m_Loop<<" "; | |||
| s<<m_NoteCut<<" "; | |||
| s<<m_CurrentPattern<<" "; | |||
| } | |||
| // fallthrough | |||
| case 1: | |||
| { | |||
| for(int n=0; n<NUM_PATTERNS; n++) | |||
| { | |||
| //s<<*m_Eventmap[n]<<" "; | |||
| } | |||
| s<<m_Time<<" "<<m_Length<<" "<<m_BarLength<<" "<<m_BeatsPerBar<<" "; | |||
| s<<m_Track; | |||
| } break; | |||
| } | |||
| } | |||
| @@ -247,23 +762,10 @@ void SequencerPlugin::StreamIn(istream &s) | |||
| switch (version) | |||
| { | |||
| case 2: | |||
| { | |||
| s>>m_Time; | |||
| s>>m_Length; | |||
| s>>m_SpeedMod; | |||
| s>>m_Loop; | |||
| s>>m_NoteCut; | |||
| s>>m_CurrentPattern; | |||
| } | |||
| // fallthrough | |||
| case 1: | |||
| { | |||
| for(int n=0; n<NUM_PATTERNS; n++) | |||
| { | |||
| //s>>*m_Eventmap[n]; | |||
| } | |||
| s>>m_Time>>m_Length>>m_BarLength>>m_BeatsPerBar; | |||
| s>>m_Track; | |||
| } break; | |||
| } | |||
| } | |||
| @@ -24,36 +24,127 @@ | |||
| #ifndef SequencerPLUGIN | |||
| #define SequencerPLUGIN | |||
| const int NUM_PATTERNS = 16; | |||
| const int NUM_PATTERNS = 8; | |||
| const int NUM_CHANNELS = 8; | |||
| ////////////////////////////////////////////////////////////////////////// | |||
| // base sequencing stuff | |||
| class Note | |||
| { | |||
| public: | |||
| Note(float t, float l, int n, float v); | |||
| virtual ~Note(); | |||
| float Time; | |||
| float Length; | |||
| int MidiNote; | |||
| float Vol; | |||
| friend istream &operator>>(istream &s, Note &o); | |||
| friend ostream &operator<<(ostream &s, Note &o); | |||
| }; | |||
| istream &operator>>(istream &s, Note &o); | |||
| ostream &operator<<(ostream &s, Note &o); | |||
| class Pattern | |||
| { | |||
| public: | |||
| Pattern(); | |||
| virtual ~Pattern(); | |||
| void Copy(const Pattern *o); | |||
| void AddNote(int ID, float t, float l, int n, float v); | |||
| void RemoveNote(int ID); | |||
| Note *GetNote(int ID); | |||
| int GetNoteCount() { return m_NoteMap.size(); } | |||
| map<int,Note> m_NoteMap; | |||
| friend istream &operator>>(istream &s, Pattern &o); | |||
| friend ostream &operator<<(ostream &s, Pattern &o); | |||
| }; | |||
| istream &operator>>(istream &s, Pattern &o); | |||
| ostream &operator<<(ostream &s, Pattern &o); | |||
| class Sequence | |||
| { | |||
| public: | |||
| Sequence(float st=0, int pat=0); | |||
| virtual ~Sequence(); | |||
| void SetStartTime(float t) { m_StartTime=t; } | |||
| float GetStartTime() { return m_StartTime; } | |||
| void SetPatternID(int p) { m_Pattern=p; } | |||
| int GetPatternID() { return m_Pattern; } | |||
| void SetName(string s) { m_Name=s; } | |||
| string GetName() { return m_Name; } | |||
| void SetColour(int s) { m_Colour=s; } | |||
| int GetColour() { return m_Colour; } | |||
| void SetYPos(int s) { m_YPos=s; } | |||
| int GetYPos() { return m_YPos; } | |||
| void SetLength(float t) { m_Length=t; } | |||
| float GetLength() { return m_Length; } | |||
| void SetChannel(int s) { m_Channel=s; } | |||
| int GetChannel() { return m_Channel; } | |||
| private: | |||
| float m_StartTime; | |||
| int m_Pattern; | |||
| string m_Name; | |||
| int m_Colour; | |||
| int m_YPos; | |||
| float m_Length; | |||
| int m_Channel; | |||
| friend istream &operator>>(istream &s, Sequence &o); | |||
| friend ostream &operator<<(ostream &s, Sequence &o); | |||
| }; | |||
| istream &operator>>(istream &s, Sequence &o); | |||
| ostream &operator<<(ostream &s, Sequence &o); | |||
| class Track | |||
| { | |||
| public: | |||
| class Sequence | |||
| { | |||
| public: | |||
| class Pattern | |||
| { | |||
| public: | |||
| class Note | |||
| { | |||
| public: | |||
| float time; | |||
| int note; | |||
| float vol; | |||
| }; | |||
| map<int,Note> m_NoteMap; | |||
| }; | |||
| Track(); | |||
| virtual ~Track(); | |||
| void AddSequence(int ID); | |||
| void CloneSequence(int ID, int nID); | |||
| void CopySequence(int ID, int nID); | |||
| void InstanceSequence(int ID); | |||
| void RemoveSequence(int ID); | |||
| Sequence *GetSequence(int ID); | |||
| float m_StartTime; | |||
| int m_Pattern; | |||
| }; | |||
| void AddNote(int ID, int Sequence, float t, float l, int n, float v); | |||
| void RemoveNote(int ID, int Sequence); | |||
| void ChangeNote(int ID, int Sequence, float t, float l, int n, float v); | |||
| void ReadTrack(float t, int channel, vector<Note> &NoteVec); | |||
| Pattern *GetPattern(int ID); | |||
| map<int,Sequence> *GetSequenceMap() { return &m_SequenceMap; } | |||
| private: | |||
| void AddPattern(int ID); | |||
| void RemovePattern(int ID); | |||
| map<int,Pattern> m_PatternMap; | |||
| map<int,Sequence> m_SequenceMap; | |||
| int m_NextPatternID; | |||
| map<int,Sequence::Pattern> m_PatternMap; | |||
| list<Sequence> m_SequenceList; | |||
| friend istream &operator>>(istream &s, Track &o); | |||
| friend ostream &operator<<(ostream &s, Track &o); | |||
| }; | |||
| istream &operator>>(istream &s, Track &o); | |||
| ostream &operator<<(ostream &s, Track &o); | |||
| /////////////////////////////////////////////////////////////////////////// | |||
| class SequencerPlugin : public SpiralPlugin | |||
| { | |||
| public: | |||
| @@ -70,26 +161,56 @@ public: | |||
| bool GetNoteCut() { return m_NoteCut; } | |||
| void ClearAll() { /*m_Eventmap[m_CurrentPattern]->RemoveAllEvents();*/ } | |||
| int GetCurrentPattern() { return m_CurrentPattern; } | |||
| Track *GetTrack() { return &m_Track; } | |||
| enum GUICommands {NONE,NEW_NOTE,REM_NOTE,CHG_NOTE,NEW_SEQ,CHG_SEQ,COPY_SEQ, | |||
| INST_SEQ,CLONE_SEQ,REM_SEQ,GET_PATTERN}; | |||
| struct GUIArgs | |||
| { | |||
| int Num,Num2; | |||
| int Sequence; | |||
| float t,l,v; | |||
| int n; | |||
| char Name[256]; | |||
| int Channel; | |||
| }; | |||
| private: | |||
| GUIArgs m_GUIArgs; | |||
| Track m_Track; | |||
| int m_TransferPattern; | |||
| //int m_TransferNote; | |||
| map<int,Note>::iterator m_TransferNote; | |||
| int m_TransferCount; | |||
| Note m_Transfer; | |||
| void SetEventMap(int n, Fl_EventMap* s) { /*m_Eventmap[n]=s;*/ } | |||
| void SetUpdate(bool s) { /*m_Eventmap[m_CurrentPattern]->SetUpdate(s);*/ } | |||
| void SetZoom(float s) { /*m_Eventmap[m_CurrentPattern]->SetZoomLevel(s);*/ } | |||
| void SetNoteCut(bool s) { m_NoteCut=s; } | |||
| void SetEndTime(float s) { /*m_Eventmap[m_CurrentPattern]->SetEndTime(s);*/ m_Length=s; } | |||
| //void SetEndTime(float s) { /*m_Eventmap[m_CurrentPattern]->SetEndTime(s);*/ m_Length=s; } | |||
| void SetSpeed(float s) { m_SpeedMod=s; } | |||
| void SetPattern(int s); | |||
| float m_Time; | |||
| float m_Length; | |||
| int m_Length; // in bars | |||
| float m_BarLength; | |||
| int m_BeatsPerBar; | |||
| float m_NextBeatTime; | |||
| float m_BeatLevel; | |||
| int m_BeatCount; | |||
| int m_BarCount; | |||
| bool m_Loop; | |||
| bool m_NoteCut; | |||
| float m_SpeedMod; | |||
| float m_CurrentNoteCV; | |||
| float m_CurrentTriggerCV; | |||
| float m_CurrentNoteCV[NUM_CHANNELS]; | |||
| float m_CurrentTriggerCV[NUM_CHANNELS]; | |||
| bool m_InNoteDown; | |||
| int m_InNoteID; | |||
| float m_InNoteTime; | |||
| @@ -21,6 +21,7 @@ | |||
| #include <FL/fl_draw.h> | |||
| #include <FL/fl_draw.H> | |||
| #include <FL/fl_file_chooser.h> | |||
| #include <FL/Fl_Color_Chooser.H> | |||
| static const int GUI_COLOUR = 179; | |||
| static const int GUIBG_COLOUR = 144; | |||
| @@ -34,14 +35,23 @@ Fl_Double_Window(w,h,n) | |||
| m_Scroll = new Fl_Scroll(0, 0, w, h, ""); | |||
| resizable(m_Scroll); | |||
| add(m_Scroll); | |||
| m_NextNoteID=0; | |||
| m_Melody = new Fl_EventMap(0, 0, 1000, 1000, ""); | |||
| m_Melody->SetType(Fl_EventMap::MELODY_MAP); | |||
| m_Scroll->add(m_Melody); | |||
| m_Scroll->position(0,350); | |||
| m_Melody->CreateWindow(); | |||
| m_Melody->SetUpdateLineClip(0, 18, w, h-38); | |||
| m_Melody->show(); | |||
| // callbacks for note events | |||
| Fl_EventMap::EventCallbacks cb; | |||
| cb.cb_NewEvent=(Fl_Callback*)cb_NewNote; | |||
| cb.cb_MoveEvent=(Fl_Callback*)cb_MoveNote; | |||
| cb.cb_DelEvent=(Fl_Callback*)cb_RemoveNote; | |||
| m_Melody->SetCallbacks(cb); | |||
| end(); | |||
| } | |||
| @@ -52,25 +62,56 @@ SpiralPluginGUI(w,h,o,ch) | |||
| { | |||
| m_Scroll = new Fl_Scroll(50, 20, w-57, h-26, ""); | |||
| add(m_Scroll); | |||
| m_ArrangementMap = new Fl_EventMap(0, 0, 1000, 1000, ""); | |||
| m_ArrangementMap = new Fl_EventMap(0, 0, 1000, 132*10, ""); | |||
| // num midi notes * gridsize y ^ | |||
| m_ArrangementMap->user_data((void*)this); | |||
| m_ArrangementMap->SetType(Fl_EventMap::ARRANGE_MAP); | |||
| m_Scroll->add(m_ArrangementMap); | |||
| m_Scroll->position(-50,350); | |||
| m_ArrangementMap->CreateWindow(); | |||
| m_ArrangementMap->SetUpdateLineClip(0, 18, w, h-38); | |||
| m_ArrangementMap->SetZoomLevel(3.0f); | |||
| m_ArrangementMap->show(); | |||
| m_Length = new Fl_Knob(5, 60, 40, 40, "Length"); | |||
| m_Length->color(GUI_COLOUR); | |||
| m_Length->type(Fl_Knob::DOTLIN); | |||
| m_Length->labelsize(10); | |||
| m_Length->maximum(30); | |||
| m_Length->step(0.01); | |||
| m_Length->value(1.0); | |||
| // callbacks for sequence events | |||
| Fl_EventMap::EventCallbacks cb; | |||
| cb.cb_EventDoubleClicked=(Fl_Callback*)cb_ArrangeRM; | |||
| cb.cb_MoveEvent=(Fl_Callback*)cb_MoveSequence; | |||
| cb.cb_RenameEvent=(Fl_Callback*)cb_Rename; | |||
| cb.cb_Recolour=(Fl_Callback*)cb_Recolour; | |||
| cb.cb_CopyEvent=(Fl_Callback*)cb_Copy; | |||
| cb.cb_DelEvent=(Fl_Callback*)cb_RemoveSequence; | |||
| cb.cb_EditEvent=(Fl_Callback*)cb_Edit; | |||
| m_ArrangementMap->SetCallbacks(cb); | |||
| m_Length = new Fl_Input(12, 15, 24, 12, "LengthBars"); | |||
| m_Length->color(GUI_COLOUR); | |||
| m_Length->labelsize(8); | |||
| m_Length->align(FL_ALIGN_BOTTOM|FL_ALIGN_CENTER); | |||
| m_Length->textsize(8); | |||
| m_Length->value("4"); | |||
| m_Length->callback((Fl_Callback*)cb_Length); | |||
| add(m_Length); | |||
| m_BeatsPerBar = new Fl_Input(12, 38, 24, 12, "BeatsPerBar"); | |||
| m_BeatsPerBar->color(GUI_COLOUR); | |||
| m_BeatsPerBar->labelsize(8); | |||
| m_BeatsPerBar->align(FL_ALIGN_BOTTOM|FL_ALIGN_CENTER); | |||
| m_BeatsPerBar->textsize(8); | |||
| m_BeatsPerBar->value("4"); | |||
| m_BeatsPerBar->callback((Fl_Callback*)cb_BeatsPerBar); | |||
| add(m_BeatsPerBar); | |||
| m_BarLength = new Fl_Knob(5, 60, 40, 40, "BarLength"); | |||
| m_BarLength->color(GUI_COLOUR); | |||
| m_BarLength->type(Fl_Knob::DOTLIN); | |||
| m_BarLength->labelsize(10); | |||
| m_BarLength->maximum(10); | |||
| m_BarLength->step(0.01); | |||
| m_BarLength->value(1.0); | |||
| m_BarLength->callback((Fl_Callback*)cb_BarLength); | |||
| add(m_BarLength); | |||
| m_Speed = new Fl_Knob(5, 115, 40, 40, "Speed"); | |||
| m_Speed->color(GUI_COLOUR); | |||
| m_Speed->type(Fl_Knob::DOTLIN); | |||
| @@ -85,9 +126,9 @@ SpiralPluginGUI(w,h,o,ch) | |||
| m_Zoom->color(GUI_COLOUR); | |||
| m_Zoom->type(Fl_Knob::DOTLIN); | |||
| m_Zoom->labelsize(10); | |||
| m_Zoom->maximum(2); | |||
| m_Zoom->maximum(6); | |||
| m_Zoom->step(0.01); | |||
| m_Zoom->value(1.0); | |||
| m_Zoom->value(3.0); | |||
| m_Zoom->callback((Fl_Callback*)cb_Zoom); | |||
| add(m_Zoom); | |||
| @@ -114,10 +155,94 @@ SpiralPluginGUI(w,h,o,ch) | |||
| end(); | |||
| } | |||
| void SequencerPluginGUI::LoadPatternData(int ID) | |||
| { | |||
| Note note(0,1.0f,0,0); | |||
| m_PatternWinMap[ID]->GetEventMap()->RemoveAllEvents(); | |||
| m_GUICH->Wait(); | |||
| m_GUICH->Set("ID",ID); | |||
| m_GUICH->SetCommand(SequencerPlugin::GET_PATTERN); | |||
| m_GUICH->Wait(); | |||
| m_GUICH->RequestChannelAndWait("TransCount"); | |||
| int c = m_GUICH->GetInt("TransCount"); | |||
| cerr<<"TransCount="<<c<<endl; | |||
| for (int n=0; n<c; n++) | |||
| { | |||
| m_GUICH->SetCommand(SequencerPlugin::GET_PATTERN); | |||
| m_GUICH->RequestChannelAndWait("TransNote"); | |||
| m_GUICH->GetData("TransNote",(void*)¬e); | |||
| cerr<<"Adding note "<<n<<" "<<note.Time<<" "<<note.MidiNote<<" "<<note.Length<<endl; | |||
| m_PatternWinMap[ID]->GetEventMap()->AddEventTime(note.Time,note.MidiNote,note.Length,Fl_SEvent::MELODY,false); | |||
| } | |||
| } | |||
| void SequencerPluginGUI::UpdateValues(SpiralPlugin *o) | |||
| { | |||
| SequencerPlugin *Plugin = (SequencerPlugin *)o; | |||
| Track *t = Plugin->GetTrack(); | |||
| map<int,Sequence> *seqmap=t->GetSequenceMap(); | |||
| map<int,Note>::iterator pi; | |||
| // for each sequence | |||
| for (map<int,Sequence>::iterator i=seqmap->begin(); | |||
| i!=seqmap->end(); i++) | |||
| { | |||
| int eid = m_ArrangementMap->AddEventTime(i->second.GetStartTime(),i->second.GetYPos(),i->second.GetLength(),Fl_SEvent::NO_TYPE,false); | |||
| m_ArrangementMap->GetEvent(eid)->SetName(i->second.GetName()); | |||
| m_ArrangementMap->GetEvent(eid)->SetColour(i->second.GetColour()); | |||
| m_ArrangementMap->GetEvent(eid)->SetChannel(i->second.GetChannel()); | |||
| m_ArrangementMap->GetEvent(eid)->SetLengthTime(i->second.GetLength()); | |||
| m_PatternWinMap[eid] = new PatternWin(400,200,m_ArrangementMap->GetEvent(eid)->GetName().c_str()); | |||
| Fl_EventMap *map = m_PatternWinMap[eid]->GetEventMap(); | |||
| map->user_data((void*)this); | |||
| map->SetID(eid); | |||
| // load the pattern data | |||
| Pattern *p = t->GetPattern(i->second.GetPatternID()); | |||
| for (pi=p->m_NoteMap.begin(); | |||
| pi!=p->m_NoteMap.end(); pi++) | |||
| { | |||
| map->AddEventTime(pi->second.Time,pi->second.MidiNote,pi->second.Length,Fl_SEvent::MELODY,false); | |||
| } | |||
| } | |||
| redraw(); | |||
| } | |||
| void SequencerPluginGUI::Update() | |||
| { | |||
| float Time=m_GUICH->GetFloat("CurrentTime"); | |||
| m_ArrangementMap->SetTime(Time); | |||
| for (map<int,PatternWin*>::iterator i=m_PatternWinMap.begin(); | |||
| i!=m_PatternWinMap.end(); i++) | |||
| { | |||
| i->second->GetEventMap()->SetTime(Time); | |||
| } | |||
| } | |||
| void SequencerPluginGUI::ChangeSequenceHelper(Fl_SEvent *event) | |||
| { | |||
| m_GUICH->Set("ID",event->GetID()); | |||
| m_GUICH->Set("ID2",event->GetColour()); | |||
| char t[256]; | |||
| sprintf(t,"%s",event->GetName().c_str()); | |||
| m_GUICH->SetData("Name",(void*)t); | |||
| m_GUICH->Set("Length",event->GetLengthTime()); | |||
| m_GUICH->Set("Note",event->GetGroup()); | |||
| m_GUICH->Set("Channel",event->GetChannel()); | |||
| m_GUICH->Set("Time",event->GetStartTime()); | |||
| m_GUICH->SetCommand(SequencerPlugin::CHG_SEQ); | |||
| } | |||
| inline void SequencerPluginGUI::cb_NoteCut_i(Fl_Button* o, void* v) | |||
| { | |||
| //m_Plugin->SetNoteCut(o->value()); | |||
| @@ -127,7 +252,7 @@ void SequencerPluginGUI::cb_NoteCut(Fl_Button* o, void* v) | |||
| inline void SequencerPluginGUI::cb_Zoom_i(Fl_Knob* o, void* v) | |||
| { | |||
| //m_Plugin->SetZoom(o->value()); | |||
| if (o->value()!=0) m_ArrangementMap->SetZoomLevel(o->value()); | |||
| } | |||
| void SequencerPluginGUI::cb_Zoom(Fl_Knob* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()))->cb_Zoom_i(o,v);} | |||
| @@ -144,13 +269,60 @@ inline void SequencerPluginGUI::cb_Pattern_i(Fl_Counter* o, void* v) | |||
| void SequencerPluginGUI::cb_Pattern(Fl_Counter* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()))->cb_Pattern_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_Length_i(Fl_Knob* o, void* v) | |||
| inline void SequencerPluginGUI::cb_Length_i(Fl_Input* o, void* v) | |||
| { | |||
| //m_Plugin->SetEndTime(o->value()); | |||
| int val=(int)strtod(o->value(),NULL); | |||
| if (val<1) o->value("error!"); | |||
| else | |||
| { | |||
| m_GUICH->Set("TotalLength",val); | |||
| } | |||
| } | |||
| void SequencerPluginGUI::cb_Length(Fl_Knob* o, void* v) | |||
| void SequencerPluginGUI::cb_Length(Fl_Input* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()))->cb_Length_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_BeatsPerBar_i(Fl_Input* o, void* v) | |||
| { | |||
| int val=(int)strtod(o->value(),NULL); | |||
| if (val<1) o->value("error!"); | |||
| else | |||
| { | |||
| m_GUICH->Set("BeatsPerBar",val); | |||
| m_ArrangementMap->SetBeatsBar(val); | |||
| m_ArrangementMap->redraw(); | |||
| for (map<int,PatternWin*>::iterator i=m_PatternWinMap.begin(); | |||
| i!=m_PatternWinMap.end(); i++) | |||
| { | |||
| i->second->GetEventMap()->SetBeatsBar(val); | |||
| i->second->GetEventMap()->redraw(); | |||
| } | |||
| } | |||
| } | |||
| void SequencerPluginGUI::cb_BeatsPerBar(Fl_Input* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()))->cb_BeatsPerBar_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_BarLength_i(Fl_Knob* o, void* v) | |||
| { | |||
| if (o->value()!=0) | |||
| { | |||
| m_GUICH->Set("BarLength",(float)o->value()); | |||
| m_ArrangementMap->SetBarLength(o->value()); | |||
| m_ArrangementMap->redraw(); | |||
| for (map<int,PatternWin*>::iterator i=m_PatternWinMap.begin(); | |||
| i!=m_PatternWinMap.end(); i++) | |||
| { | |||
| i->second->GetEventMap()->SetBarLength(o->value()); | |||
| i->second->GetEventMap()->redraw(); | |||
| } | |||
| redraw(); | |||
| } | |||
| } | |||
| void SequencerPluginGUI::cb_BarLength(Fl_Knob* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()))->cb_BarLength_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_Speed_i(Fl_Knob* o, void* v) | |||
| { | |||
| //m_Plugin->SetSpeed(o->value()-2.0f); | |||
| @@ -165,20 +337,110 @@ inline void SequencerPluginGUI::cb_Clear_i(Fl_Button* o, void* v) | |||
| void SequencerPluginGUI::cb_Clear(Fl_Button* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()))->cb_Clear_i(o,v);} | |||
| /// sequence callbacks ///////////////////////////////////////////////////////// | |||
| inline void SequencerPluginGUI::cb_NewPattern_i(Fl_Button* o, void* v) | |||
| { | |||
| int eid = m_ArrangementMap->AddEvent(300,100,100,Fl_SEvent::NO_TYPE); | |||
| int eid = m_ArrangementMap->AddEventTime(1,50,2,Fl_SEvent::NO_TYPE); | |||
| m_ArrangementMap->GetEvent(eid)->SetName("My Pattern"); | |||
| const char *name = fl_input("Name the new pattern:", "My Pattern"); | |||
| if (name) m_ArrangementMap->GetEvent(eid)->SetName(name); | |||
| m_PatternWinMap[eid] = new PatternWin(400,200,m_ArrangementMap->GetEvent(eid)->GetName().c_str()); | |||
| m_ArrangementMap->SetEventCallback((Fl_Callback*)cb_ArrangeRM); | |||
| Fl_EventMap *map = m_PatternWinMap[eid]->GetEventMap(); | |||
| Fl_SEvent *event = m_ArrangementMap->GetEvent(eid); | |||
| // setup the stuff needed by the callbacks | |||
| map->user_data((void*)this); | |||
| map->SetID(eid); | |||
| m_GUICH->Set("ID",eid); | |||
| m_GUICH->Set("ID2",event->GetColour()); | |||
| char t[256]; | |||
| sprintf(t,"%s",event->GetName().c_str()); | |||
| m_GUICH->SetData("Name",(void*)t); | |||
| m_GUICH->Set("Length",event->GetLengthTime()); | |||
| m_GUICH->Set("Channel",event->GetChannel()); | |||
| m_GUICH->Set("Note",event->GetGroup()); | |||
| m_GUICH->SetCommand(SequencerPlugin::NEW_SEQ); | |||
| redraw(); | |||
| } | |||
| void SequencerPluginGUI::cb_NewPattern(Fl_Button* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()))->cb_NewPattern_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_Rename_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)v); | |||
| const char *name = fl_input("Rename the sequence:", | |||
| m_ArrangementMap->GetEvent(event->GetID())->GetName().c_str()); | |||
| if (name) m_ArrangementMap->GetEvent(event->GetID())->SetName(name); | |||
| ChangeSequenceHelper(event); | |||
| redraw(); | |||
| } | |||
| void SequencerPluginGUI::cb_Rename(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->parent()->user_data()))->cb_Rename_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_Recolour_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)v); | |||
| unsigned char r=255,g=255,b=255; | |||
| if (fl_color_chooser("colour",r,g,b)) | |||
| { | |||
| fl_color(r,g,b); | |||
| Fl_Color col=fl_color(); | |||
| m_ArrangementMap->GetEvent(event->GetID())->SetColour(col); | |||
| ChangeSequenceHelper(event); | |||
| redraw(); | |||
| } | |||
| } | |||
| void SequencerPluginGUI::cb_Recolour(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->parent()->user_data()))->cb_Recolour_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_RemoveSequence_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)v); | |||
| Fl_EventMap *map = ((Fl_EventMap*)event->parent()); | |||
| event->KillMe(); | |||
| map->redraw(); | |||
| m_GUICH->Set("ID",event->GetID()); | |||
| m_GUICH->SetCommand(SequencerPlugin::REM_SEQ); | |||
| } | |||
| void SequencerPluginGUI::cb_RemoveSequence(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->parent()->user_data()))->cb_RemoveSequence_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_Copy_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)v); | |||
| int NewID = m_ArrangementMap->CopyEvent(event->x()+event->w(),event->y(),event->w(),event->GetID(), event->GetLengthTime()); | |||
| m_PatternWinMap[NewID] = new PatternWin(400,200,m_ArrangementMap->GetEvent(NewID)->GetName().c_str()); | |||
| m_PatternWinMap[NewID]->GetEventMap()->user_data((void*)this); | |||
| m_PatternWinMap[NewID]->GetEventMap()->SetID(NewID); | |||
| m_GUICH->Set("ID",event->GetID()); | |||
| m_GUICH->Set("ID2",NewID); | |||
| m_GUICH->SetCommand(SequencerPlugin::COPY_SEQ); | |||
| LoadPatternData(NewID); | |||
| } | |||
| void SequencerPluginGUI::cb_Copy(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->parent()->user_data()))->cb_Copy_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_MoveSequence_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)o); | |||
| m_PatternWinMap[event->GetID()]->GetEventMap()->SetTimeOffset(event->GetStartTime()); | |||
| ChangeSequenceHelper(event); | |||
| } | |||
| void SequencerPluginGUI::cb_MoveSequence(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->user_data()))->cb_MoveSequence_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_ArrangeRM_i(Fl_Button* o, void* v) | |||
| { | |||
| int ID=((Fl_SEvent*)o)->GetID(); | |||
| @@ -188,4 +450,83 @@ inline void SequencerPluginGUI::cb_ArrangeRM_i(Fl_Button* o, void* v) | |||
| } | |||
| void SequencerPluginGUI::cb_ArrangeRM(Fl_Button* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->user_data()))->cb_ArrangeRM_i(o,v);} | |||
| #include <unistd.h> | |||
| inline void SequencerPluginGUI::cb_Edit_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)v); | |||
| Fl_Double_Window *EditWin = new Fl_Double_Window(100,100,"Properties"); | |||
| Fl_Button *exit = new Fl_Button(10,80,80,10,"Exit"); | |||
| exit->labelsize(8); | |||
| Fl_Counter *channel = new Fl_Counter(5,10,90,20,"Channel"); | |||
| channel->labelsize(8); | |||
| channel->textsize(8); | |||
| channel->type(FL_SIMPLE_COUNTER); | |||
| channel->step(1); | |||
| channel->value(event->GetChannel()); | |||
| EditWin->show(); | |||
| while (!exit->value() || !EditWin->shown()) | |||
| { | |||
| Fl::check(); | |||
| usleep(10000); | |||
| } | |||
| event->SetChannel((int)channel->value()); | |||
| ChangeSequenceHelper(event); | |||
| redraw(); | |||
| EditWin->hide(); | |||
| } | |||
| void SequencerPluginGUI::cb_Edit(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->parent()->user_data()))->cb_Edit_i(o,v);} | |||
| /// note callbacks /////////////////////////////////////////////////////////////// | |||
| inline void SequencerPluginGUI::cb_NewNote_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)o); | |||
| Fl_EventMap *map = ((Fl_EventMap*)o->parent()); | |||
| m_GUICH->Set("ID",event->GetID()); | |||
| m_GUICH->Set("Sequence",map->GetID()); | |||
| m_GUICH->Set("Time",event->GetStartTime()); | |||
| m_GUICH->Set("Length",event->GetLengthTime()); | |||
| m_GUICH->Set("Note",event->GetGroup()); | |||
| m_GUICH->Set("Vol",1.0f); | |||
| m_GUICH->SetCommand(SequencerPlugin::NEW_NOTE); | |||
| } | |||
| void SequencerPluginGUI::cb_NewNote(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->user_data()))->cb_NewNote_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_MoveNote_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)o); | |||
| Fl_EventMap *map = ((Fl_EventMap*)o->parent()); | |||
| m_GUICH->Set("ID",event->GetID()); | |||
| m_GUICH->Set("Sequence",map->GetID()); | |||
| m_GUICH->Set("Time",event->GetStartTime()); | |||
| m_GUICH->Set("Length",event->GetLengthTime()); | |||
| m_GUICH->Set("Note",event->GetGroup()); | |||
| m_GUICH->Set("Vol",1.0f); | |||
| m_GUICH->SetCommand(SequencerPlugin::CHG_NOTE); | |||
| } | |||
| void SequencerPluginGUI::cb_MoveNote(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->user_data()))->cb_MoveNote_i(o,v);} | |||
| inline void SequencerPluginGUI::cb_RemoveNote_i(Fl_Widget* o, void* v) | |||
| { | |||
| Fl_SEvent *event = ((Fl_SEvent*)v); | |||
| Fl_EventMap *map = ((Fl_EventMap*)event->parent()); | |||
| event->KillMe(); | |||
| map->redraw(); | |||
| m_GUICH->Set("ID",event->GetID()); | |||
| m_GUICH->Set("Sequence",map->GetID()); | |||
| m_GUICH->SetCommand(SequencerPlugin::REM_NOTE); | |||
| } | |||
| void SequencerPluginGUI::cb_RemoveNote(Fl_Widget* o, void* v) | |||
| { ((SequencerPluginGUI*)(o->parent()->parent()->user_data()))->cb_RemoveNote_i(o,v);} | |||
| @@ -23,6 +23,7 @@ | |||
| #include <FL/Fl_Slider.H> | |||
| #include <FL/Fl_Counter.H> | |||
| #include <FL/Fl_Output.H> | |||
| #include <FL/Fl_Input.H> | |||
| #include "SequencerPlugin.h" | |||
| #include "../SpiralPluginGUI.h" | |||
| @@ -39,6 +40,7 @@ public: | |||
| SequencerPluginGUI(int w, int h, SequencerPlugin *o, ChannelHandler *ch,const HostInfo *Info); | |||
| virtual void UpdateValues(SpiralPlugin *o); | |||
| virtual void Update(); | |||
| private: | |||
| @@ -46,23 +48,34 @@ private: | |||
| Fl_Button* m_NewPattern; | |||
| Fl_Button* m_NoteCut; | |||
| Fl_Knob* m_Zoom; | |||
| Fl_Knob* m_Length; | |||
| Fl_Knob* m_Speed; | |||
| Fl_Button* m_Clear; | |||
| Fl_Input* m_Length; | |||
| Fl_Input* m_BeatsPerBar; | |||
| Fl_Knob* m_BarLength; | |||
| int m_NextPatternID; | |||
| class PatternWin : public Fl_Double_Window | |||
| { | |||
| public: | |||
| PatternWin(int w,int h,const char* n); | |||
| Fl_EventMap *GetEventMap() { return m_Melody; } | |||
| private: | |||
| Fl_Scroll* m_Scroll; | |||
| Fl_EventMap* m_Melody; | |||
| int m_NextNoteID; | |||
| }; | |||
| map<int,PatternWin*> m_PatternWinMap; | |||
| Fl_EventMap* m_ArrangementMap; | |||
| // get the notes from the audio thread | |||
| void LoadPatternData(int ID); | |||
| void ChangeSequenceHelper(Fl_SEvent *event); | |||
| //// Callbacks //// | |||
| inline void cb_Zoom_i(Fl_Knob* o, void* v); | |||
| static void cb_Zoom(Fl_Knob* o, void* v); | |||
| @@ -70,8 +83,12 @@ private: | |||
| static void cb_NoteCut(Fl_Button* o, void* v); | |||
| inline void cb_Pattern_i(Fl_Counter* o, void* v); | |||
| static void cb_Pattern(Fl_Counter* o, void* v); | |||
| inline void cb_Length_i(Fl_Knob* o, void* v); | |||
| static void cb_Length(Fl_Knob* o, void* v); | |||
| inline void cb_Length_i(Fl_Input* o, void* v); | |||
| static void cb_Length(Fl_Input* o, void* v); | |||
| inline void cb_BeatsPerBar_i(Fl_Input* o, void* v); | |||
| static void cb_BeatsPerBar(Fl_Input* o, void* v); | |||
| inline void cb_BarLength_i(Fl_Knob* o, void* v); | |||
| static void cb_BarLength(Fl_Knob* o, void* v); | |||
| inline void cb_Speed_i(Fl_Knob* o, void* v); | |||
| static void cb_Speed(Fl_Knob* o, void* v); | |||
| inline void cb_Clear_i(Fl_Button* o, void* v); | |||
| @@ -79,8 +96,29 @@ private: | |||
| inline void cb_NewPattern_i(Fl_Button* o, void* v); | |||
| static void cb_NewPattern(Fl_Button* o, void* v); | |||
| // sequence event callbacks | |||
| inline void cb_ArrangeRM_i(Fl_Button* o, void* v); | |||
| static void cb_ArrangeRM(Fl_Button* o, void* v); | |||
| inline void cb_MoveSequence_i(Fl_Widget* o, void* v); | |||
| static void cb_MoveSequence(Fl_Widget* o, void* v); | |||
| inline void cb_Rename_i(Fl_Widget* o, void* v); | |||
| static void cb_Rename(Fl_Widget* o, void* v); | |||
| inline void cb_Recolour_i(Fl_Widget* o, void* v); | |||
| static void cb_Recolour(Fl_Widget* o, void* v); | |||
| inline void cb_Copy_i(Fl_Widget* o, void* v); | |||
| static void cb_Copy(Fl_Widget* o, void* v); | |||
| inline void cb_RemoveSequence_i(Fl_Widget* o, void* v); | |||
| static void cb_RemoveSequence(Fl_Widget* o, void* v); | |||
| inline void cb_Edit_i(Fl_Widget* o, void* v); | |||
| static void cb_Edit(Fl_Widget* o, void* v); | |||
| // note event callbacks | |||
| inline void cb_NewNote_i(Fl_Widget* o, void* v); | |||
| static void cb_NewNote(Fl_Widget* o, void* v); | |||
| inline void cb_MoveNote_i(Fl_Widget* o, void* v); | |||
| static void cb_MoveNote(Fl_Widget* o, void* v); | |||
| inline void cb_RemoveNote_i(Fl_Widget* o, void* v); | |||
| static void cb_RemoveNote(Fl_Widget* o, void* v); | |||
| }; | |||
| #endif | |||