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