@@ -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 |