| @@ -1,6 +1,6 @@ | |||
| /* Graph Sort | |||
| * Copyleft (C) 2002 David Griffiths <dave@pawfal.org> | |||
| * | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| @@ -23,8 +23,9 @@ | |||
| ////////////////////////////////////////////////////////// | |||
| GraphSort::GraphSort() | |||
| GraphSort::GraphSort(bool UseTestSort) | |||
| { | |||
| m_UseTestSort=UseTestSort; | |||
| } | |||
| GraphSort::~GraphSort() | |||
| @@ -37,13 +38,118 @@ void GraphSort::Clear() | |||
| m_Graph.clear(); | |||
| } | |||
| const list<int> &GraphSort::GetSortedList() | |||
| { | |||
| return m_Sorted; | |||
| } | |||
| void GraphSort::Sort() | |||
| { | |||
| m_UseTestSort?TestSort():OrigSort(); | |||
| } | |||
| void GraphSort::TestSort() | |||
| { | |||
| m_Sorted.clear(); | |||
| list<int> Candidates; | |||
| #ifdef GRAPHSORT_TRACE | |||
| cerr<<"finding seed candidates"<<endl; | |||
| #endif | |||
| for (map<int,Node>::iterator i=m_Graph.begin(); | |||
| i!=m_Graph.end(); i++) | |||
| { | |||
| // all nodes need these vars reset | |||
| i->second.UnsatisfiedOutputs = i->second.Outputs.size(); | |||
| i->second.IsSorted = false; | |||
| if (i->second.Outputs.empty() || i->second.IsTerminal) | |||
| { | |||
| // terminals and roots are seed candidates | |||
| Candidates.push_back(i->first); | |||
| i->second.IsCandidate=true; | |||
| #ifdef GRAPHSORT_TRACE | |||
| cerr<<i->first<<" is seed candidate"<<endl; | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| i->second.IsCandidate = false; | |||
| } | |||
| } | |||
| while (!Candidates.empty()) | |||
| { | |||
| int NodeToSort; | |||
| bool FoundNodeToSort=false; | |||
| // look for an ideal candidate | |||
| for (list<int>::iterator i = Candidates.begin(); | |||
| i!=Candidates.end() && !FoundNodeToSort; i++) | |||
| { | |||
| if (!m_Graph[*i].UnsatisfiedOutputs) | |||
| { | |||
| NodeToSort=*i; | |||
| FoundNodeToSort=true; | |||
| #ifdef GRAPHSORT_TRACE | |||
| cerr<<"sorted "<<NodeToSort<<" (ideal)"<<endl; | |||
| #endif | |||
| } | |||
| } | |||
| if (!FoundNodeToSort) | |||
| { | |||
| // The latest, ie closest to the outputs, feedback source is | |||
| // first on the candidate list. (There may be several equally | |||
| // late candidates, but the first will do fine in that case). | |||
| NodeToSort=*Candidates.begin(); | |||
| #ifdef GRAPHSORT_TRACE | |||
| cerr<<"sorted "<<NodeToSort<<" (feedback)"<<endl; | |||
| #endif | |||
| } | |||
| // put the chosen candidate on the sort list | |||
| Candidates.remove(NodeToSort); | |||
| m_Sorted.push_back(NodeToSort); | |||
| m_Graph[NodeToSort].IsCandidate=false; | |||
| m_Graph[NodeToSort].IsSorted=true; | |||
| // all nodes which fed the candidate... | |||
| for (list<int>::iterator i=m_Graph[NodeToSort].Inputs.begin(); | |||
| i!=m_Graph[NodeToSort].Inputs.end(); i++) | |||
| { | |||
| // ...have another satisfied output... | |||
| m_Graph[*i].UnsatisfiedOutputs--; | |||
| if(!m_Graph[*i].IsCandidate && !m_Graph[*i].IsSorted) | |||
| { | |||
| // ..and are promoted to candidate if they haven't been already | |||
| Candidates.push_back(*i); | |||
| m_Graph[*i].IsCandidate=true; | |||
| #ifdef GRAPHSORT_TRACE | |||
| cerr<<*i<<" is now a candidate"<<endl; | |||
| #endif | |||
| } | |||
| } | |||
| } | |||
| #ifdef GRAPHSORT_TRACE | |||
| for(list<int>::iterator i=m_Sorted.begin(); | |||
| i!=m_Sorted.end(); i++) | |||
| { | |||
| cerr<<*i<<" "; | |||
| } | |||
| cerr<<endl; | |||
| #endif | |||
| } | |||
| void GraphSort::OrigSort() | |||
| { | |||
| // walk back from all the roots | |||
| m_Sorted.clear(); | |||
| @@ -207,6 +313,7 @@ void GraphSort::RemoveConnection(int SID, int DID) | |||
| cerr<<"removed "<<DID<<endl; | |||
| #endif | |||
| } | |||
| Sort(); | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| /* Graph sort | |||
| * Copyleft (C) 2002 David Griffiths <dave@pawfal.org> | |||
| * | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| @@ -25,15 +25,26 @@ | |||
| #ifndef GRAPH_SORT | |||
| #define GRAPH_SORT | |||
| #define GRAPHSORT_USE_TEST_SORT_BY_DEFAULT | |||
| using namespace std; | |||
| class GraphSort | |||
| { | |||
| public: | |||
| GraphSort(); | |||
| #ifdef GRAPHSORT_USE_TEST_SORT_BY_DEFAULT | |||
| GraphSort(bool UseTestSort=true); | |||
| #else | |||
| GraphSort(bool UseTestSort=false); | |||
| #endif | |||
| ~GraphSort(); | |||
| const list<int> &GetSortedList(); | |||
| void Sort(); | |||
| void TestSort(); | |||
| void OrigSort(); | |||
| void AddConnection(int SID, bool STerminal, int DID, bool DTerminal); | |||
| void RemoveConnection(int SID, int DID); | |||
| void Clear(); | |||
| @@ -44,13 +55,19 @@ public: | |||
| list<int> Inputs; | |||
| list<int> Outputs; | |||
| bool IsTerminal; | |||
| // temporaries used during sort | |||
| int UnsatisfiedOutputs; | |||
| bool IsCandidate; | |||
| bool IsSorted; | |||
| }; | |||
| private: | |||
| void RecursiveWalk(int node); | |||
| bool m_UseTestSort; | |||
| map<int,Node> m_Graph; | |||
| list<int> m_Sorted; | |||
| list<int> m_Sorted; | |||
| }; | |||
| #endif | |||
| @@ -58,7 +58,8 @@ m_Move(0), | |||
| m_LastMove(0), | |||
| m_Snap(false), | |||
| m_SnapDegrees(45), | |||
| m_PosMarkerCount(0) | |||
| m_PosMarkerCount(0), | |||
| cb_Move(NULL) | |||
| { | |||
| box(FL_NO_BOX); | |||
| m_MidX=(w/2)+x; | |||
| @@ -352,7 +353,7 @@ int Fl_Loop::handle(int event) | |||
| while (m_Move > m_Length) m_Move -= m_Length; | |||
| // do the move | |||
| cb_Move(this,m_LastMove-m_Move); | |||
| if (cb_Move) cb_Move(this,m_LastMove-m_Move); | |||
| m_LastMove=m_Move; | |||
| } | |||
| @@ -48,6 +48,7 @@ public: | |||
| bool Completed() {return (m_Count==m_Passes); } | |||
| float GetAngle() {return m_Angle;} | |||
| void SetAngle(float s) {m_Angle=s;} | |||
| int GetLoop() {return m_Loop;} | |||
| int GetPass() {return m_Passes;} | |||
| void SetSnap(bool s) {m_Snap=s;} | |||
| @@ -45,6 +45,13 @@ public: | |||
| SpiralLoopPlugin(); | |||
| virtual ~SpiralLoopPlugin(); | |||
| struct TriggerInfo | |||
| { | |||
| int Channel; | |||
| float Time; | |||
| bool Triggered; | |||
| }; | |||
| virtual PluginInfo &Initialise(const HostInfo *Host); | |||
| virtual SpiralGUIType *CreateGUI(); | |||
| virtual void Execute(); | |||
| @@ -92,6 +99,7 @@ public: | |||
| const float GetVolume() { return m_Volume; } | |||
| const float GetCurrentAngle() { return m_LoopPoint?(m_Pos/m_LoopPoint)*360.0f:0; } | |||
| const string& GetSampleName() { return m_Sample; } | |||
| vector<TriggerInfo> *GetTriggerVec() { return &m_TriggerVec; } | |||
| void Cut(int Start, int End); | |||
| void Copy(int Start, int End); | |||
| @@ -151,13 +159,6 @@ private: | |||
| char m_SampleBuffer[TRANSBUF_SIZE]; | |||
| long m_SampleSize; | |||
| struct TriggerInfo | |||
| { | |||
| int Channel; | |||
| float Time; | |||
| bool Triggered; | |||
| }; | |||
| vector<TriggerInfo> m_TriggerVec; | |||
| @@ -229,8 +229,36 @@ void SpiralLoopPluginGUI::UpdateValues(SpiralPlugin *o) | |||
| m_Volume->value(Plugin->GetVolume()); | |||
| m_Speed->value(Plugin->GetSpeed()); | |||
| m_Length->value(Plugin->GetLoopLength()/m_SampleSize); | |||
| m_LoopGUI->SetLength(Plugin->GetLoopLength()); | |||
| if(m_SampleSize!=0) | |||
| { | |||
| m_Length->value(Plugin->GetLoopLength()/m_SampleSize); | |||
| m_LoopGUI->SetLength(Plugin->GetLoopLength()); | |||
| } | |||
| else | |||
| { | |||
| m_LoopGUI->SetLength(0); | |||
| } | |||
| vector<SpiralLoopPlugin::TriggerInfo> *TrigVec=Plugin->GetTriggerVec(); | |||
| int ID=0; | |||
| for (vector<SpiralLoopPlugin::TriggerInfo>::iterator i=TrigVec->begin(); | |||
| i!=TrigVec->end(); i++) | |||
| { | |||
| Fl_Trigger *NewTrigger = new Fl_Trigger(parent()->x(), parent()->y(), 20, 20); | |||
| NewTrigger->SetCentreX(150); | |||
| NewTrigger->SetCentreY(150); | |||
| NewTrigger->SetCentreRadius(125); | |||
| if(m_SampleSize!=0) NewTrigger->SetAngle(i->Time*360.0f); | |||
| NewTrigger->SetID(ID); | |||
| NewTrigger->SetChannel(i->Channel); | |||
| NewTrigger->callback((Fl_Callback*)cb_Trigger); | |||
| m_LoopGUI->add(NewTrigger); | |||
| m_TriggerVec.push_back(NewTrigger); | |||
| NewTrigger->redraw(); | |||
| m_LoopGUI->redraw(); | |||
| ID++; | |||
| } | |||
| } | |||
| void SpiralLoopPluginGUI::Update() | |||
| @@ -360,7 +388,8 @@ inline void SpiralLoopPluginGUI::cb_Trig_i(Fl_Button* o, void* v) | |||
| m_LoopGUI->add(NewTrigger); | |||
| m_TriggerVec.push_back(NewTrigger); | |||
| NewTrigger->redraw(); | |||
| m_LoopGUI->redraw(); | |||
| m_GUICH->Set("Start",NewTrigger->GetID()); | |||
| m_GUICH->Set("End",NewTrigger->GetChannel()); | |||
| m_GUICH->Set("Length",0); | |||
| @@ -104,6 +104,8 @@ void audioloop(void* o) | |||
| #include <libgen.h> | |||
| #endif | |||
| #include "GraphSort.h" | |||
| int main(int argc, char **argv) | |||
| { | |||
| #if __APPLE__ | |||
| @@ -211,6 +213,7 @@ int main(int argc, char **argv) | |||
| //pthread_cancel(loopthread); | |||
| delete synth; | |||
| return 1; | |||
| } | |||