@@ -1,3 +1,16 @@ | |||||
CVS 0.2.3 | |||||
New plugin menu on canvas | |||||
New mouse clicks Button 1 = Box select devices, Move devices | |||||
Button 2 (Shift Button 1) = Drag Canvas, Multi select | |||||
Button 3 (Ctrl Button 1) = Edit and Plugin menu, Multi Select | |||||
Updated streamer - Now shows file name. | |||||
New output CV that rises from 0 to 1 as stream plays | |||||
Envelope update - Added a filter to smooth out clicks on very fast attack levels | |||||
Scope and Meter have moved to the Input/Output group | |||||
PoshSampler now has a button - ReTrigger, when this button is OFF, a sample cannot | |||||
be retriggered until it has finished playing. | |||||
Release 0.2.2 | Release 0.2.2 | ||||
New GUI - less cluttered and more "traditional" toolbars. | New GUI - less cluttered and more "traditional" toolbars. | ||||
@@ -14,7 +14,7 @@ | |||||
* You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
* along with this program; if not, write to the Free Software | * along with this program; if not, write to the Free Software | ||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | |||||
*/ | |||||
#include <FL/Fl_Group.h> | #include <FL/Fl_Group.h> | ||||
#include <FL/Fl_Output.h> | #include <FL/Fl_Output.h> | ||||
@@ -36,8 +36,8 @@ class CanvasWire | |||||
{ | { | ||||
public: | public: | ||||
CanvasWire() { Clear(); } | CanvasWire() { Clear(); } | ||||
void Clear() | |||||
void Clear() | |||||
{ | { | ||||
OutputPort=-1; | OutputPort=-1; | ||||
OutputID=-1; | OutputID=-1; | ||||
@@ -97,9 +97,9 @@ public: | |||||
void ClearConnections(Fl_DeviceGUI* Device); | void ClearConnections(Fl_DeviceGUI* Device); | ||||
void RemoveDevice(Fl_DeviceGUI* Device); | void RemoveDevice(Fl_DeviceGUI* Device); | ||||
void Clear(); | void Clear(); | ||||
void AddPluginName(const string &s, int ID) | |||||
{ m_PluginNameList.push_back(pair<string,int>(s,ID)); } | |||||
GraphSort* GetGraph() { return &m_Graph; } | |||||
void AddPluginName(const string &s, int ID); | |||||
GraphSort* GetGraph() { return &m_Graph; } | |||||
void Poll(); | void Poll(); | ||||
@@ -131,10 +131,7 @@ public: | |||||
data->redraw(); | data->redraw(); | ||||
} | } | ||||
static void EnablePaste(Fl_Canvas *data) | |||||
{ | |||||
data->m_CanPaste=true; | |||||
} | |||||
static void EnablePaste(Fl_Canvas *data) { data->m_CanPaste=true; } | |||||
bool HaveSelection() {return m_HaveSelection; } | bool HaveSelection() {return m_HaveSelection; } | ||||
CanvasGroup Selection() { return m_Selection; } | CanvasGroup Selection() { return m_Selection; } | ||||
@@ -146,102 +143,43 @@ public: | |||||
} | } | ||||
private: | private: | ||||
void PopupEditMenu (Fl_Group *group); | |||||
void DrawSelection(); | void DrawSelection(); | ||||
void CalculateSelection(); | void CalculateSelection(); | ||||
void DrawWires(); | void DrawWires(); | ||||
void ClearIncompleteWire(); | void ClearIncompleteWire(); | ||||
void DrawIncompleteWire(); | void DrawIncompleteWire(); | ||||
bool UserMakingConnection(); | bool UserMakingConnection(); | ||||
Fl_DeviceGUI *FindDevice(int ID); | Fl_DeviceGUI *FindDevice(int ID); | ||||
Fl_Image *m_BG; | |||||
char *m_BGData; | |||||
Fl_Image *m_BG; | |||||
char *m_BGData; | |||||
void (*cb_Connection)(Fl_Widget*, void*); | void (*cb_Connection)(Fl_Widget*, void*); | ||||
void (*cb_Unconnect)(Fl_Widget*, void*); | void (*cb_Unconnect)(Fl_Widget*, void*); | ||||
void (*cb_AddDevice)(Fl_Widget*, void*); | void (*cb_AddDevice)(Fl_Widget*, void*); | ||||
void (*cb_Rename)(Fl_Widget*, void*); | void (*cb_Rename)(Fl_Widget*, void*); | ||||
void (*cb_CutDeviceGroup)(Fl_Widget*, void*); | void (*cb_CutDeviceGroup)(Fl_Widget*, void*); | ||||
void (*cb_CopyDeviceGroup)(Fl_Widget*, void*); | void (*cb_CopyDeviceGroup)(Fl_Widget*, void*); | ||||
void (*cb_PasteDeviceGroup)(Fl_Widget*, void*); | void (*cb_PasteDeviceGroup)(Fl_Widget*, void*); | ||||
void (*cb_MergePatch)(Fl_Widget*, void*); | void (*cb_MergePatch)(Fl_Widget*, void*); | ||||
map<int,int> MapNewDeviceIds; | |||||
map<int,int> MapNewDeviceIds; | |||||
vector<CanvasWire> m_WireVec; | vector<CanvasWire> m_WireVec; | ||||
CanvasWire m_IncompleteWire; | |||||
bool m_ToolMenu, m_ButtonDown; | |||||
int m_x,m_y,m_Selected; | |||||
vector< pair<string,int> > m_PluginNameList; | |||||
CanvasWire m_IncompleteWire; | |||||
GraphSort m_Graph; | GraphSort m_Graph; | ||||
int m_UpdateTimer; | |||||
int m_DragX,m_DragY; | |||||
bool m_HaveSelection, m_Selecting; | |||||
int m_StartSelectX,m_StartSelectY; | |||||
int m_EndSelectX,m_EndSelectY; | |||||
CanvasGroup m_Selection; | |||||
bool m_CanPaste; | |||||
CanvasGroup m_Selection; | |||||
bool m_CanPaste, m_HaveSelection, m_Selecting; | |||||
int m_x, m_y, m_UpdateTimer, m_DragX, m_DragY; | |||||
int m_StartSelectX, m_StartSelectY, m_EndSelectX,m_EndSelectY; | |||||
friend istream &operator>>(istream &s, Fl_Canvas &o); | friend istream &operator>>(istream &s, Fl_Canvas &o); | ||||
friend ostream &operator<<(ostream &s, Fl_Canvas &o); | friend ostream &operator<<(ostream &s, Fl_Canvas &o); | ||||
void PopupEditMenu(Fl_Group *group); | |||||
///Inline Callbacks/// | |||||
inline void cb_OnDrag_i(Fl_Widget* widget, int x,int y); | |||||
inline void cb_OnDragClick_i(Fl_Widget* widget, int button,int shift_state) | |||||
{ | |||||
if ((button==3) && ((shift_state & FL_CTRL) != 0)) | |||||
{ | |||||
PopupEditMenu(widget->parent()); | |||||
} | |||||
if ((widget) && (button==1)) | |||||
{ | |||||
int ID = ((Fl_DeviceGUI*)(widget->parent()))->GetID(); | |||||
std::vector<int>::iterator device_iter = std::find(m_Selection.m_DeviceIds.begin(), m_Selection.m_DeviceIds.end(), ID); | |||||
if (((shift_state & FL_SHIFT) != 0) || ((shift_state & FL_CTRL) != 0)) | |||||
{ | |||||
if (m_HaveSelection) | |||||
{ | |||||
if (device_iter != m_Selection.m_DeviceIds.end()) | |||||
m_Selection.m_DeviceIds.erase(device_iter); | |||||
else | |||||
m_Selection.m_DeviceIds.push_back(ID); | |||||
} | |||||
else | |||||
{ | |||||
m_Selection.Clear(); | |||||
m_HaveSelection = true; | |||||
m_Selection.m_DeviceIds.push_back(ID); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
m_Selection.Clear(); | |||||
m_HaveSelection = true; | |||||
m_Selection.m_DeviceIds.push_back(ID); | |||||
} | |||||
redraw(); | |||||
} | |||||
} | |||||
inline void cb_DeleteDeviceGroup_i(); | |||||
///Static Callbacks/// | |||||
static void cb_OnDrag_s(Fl_Widget* widget, int x,int y, void* data) { ((Fl_Canvas *)data)->cb_OnDrag_i(widget, x, y); } | |||||
static void cb_OnDragClick_s(Fl_Widget* widget, int button,int shift_state, void* data) { ((Fl_Canvas *)data)->cb_OnDragClick_i(widget, button, shift_state); } | |||||
static void cb_DeleteDeviceGroup(Fl_Widget* widget, void* data) { ((Fl_Canvas *)data)->cb_DeleteDeviceGroup_i(); } | |||||
// Callbacks | |||||
static void cb_OnDrag_s (Fl_Widget* widget, int x, int y, void* data); | |||||
inline void cb_OnDrag_i (Fl_Widget* widget, int x,int y); | |||||
static void cb_OnDragClick_s (Fl_Widget* widget, int button, int shift_state, void* data); | |||||
inline void cb_OnDragClick_i(Fl_Widget* widget, int button,int shift_state); | |||||
static void cb_DeleteDeviceGroup (Fl_Widget* widget, void* data); | |||||
inline void cb_DeleteDeviceGroup_i(); | |||||
static void cb_AddDeviceFromMenu (Fl_Widget* widget, void* data); | |||||
inline void cb_AddDeviceFromMenu_i (Fl_Widget* widget, void* data); | |||||
}; | }; | ||||
istream &operator>>(istream &s, Fl_Canvas &o); | istream &operator>>(istream &s, Fl_Canvas &o); | ||||
@@ -132,9 +132,9 @@ void DiskWriterPluginGUI::UpdateValues (SpiralPlugin *o) | |||||
m_32bits->value(0); | m_32bits->value(0); | ||||
m_24bits->value(0); | m_24bits->value(0); | ||||
m_16bits->value(1); | m_16bits->value(1); | ||||
} | |||||
} | |||||
} | } | ||||
m_Stereo->value(Plugin->GetStereo()); | m_Stereo->value(Plugin->GetStereo()); | ||||
redraw(); | redraw(); | ||||
@@ -143,13 +143,28 @@ void DiskWriterPluginGUI::UpdateValues (SpiralPlugin *o) | |||||
//// Callbacks //// | //// Callbacks //// | ||||
inline void DiskWriterPluginGUI::cb_Open_i(Fl_Button* o) | inline void DiskWriterPluginGUI::cb_Open_i(Fl_Button* o) | ||||
{ | |||||
{ | |||||
if (o->value()) | if (o->value()) | ||||
{ | { | ||||
char *fn=fl_file_chooser("Pick a Wav file to save to", "*.wav", NULL); | char *fn=fl_file_chooser("Pick a Wav file to save to", "*.wav", NULL); | ||||
char t[256]; | |||||
sprintf(t,"%s",fn); | |||||
// On Mon, 2004-05-17 at 20:53, Bernd Breitenbach wrote: | |||||
// When you click the open button and click cancel right afterwards it crashes. | |||||
// Attached you find a patch for it. | |||||
// I would call it a work around not a solution, because you can't have filenames that exceeds | |||||
// 256 chars. | |||||
// A real solution requires a more flexible implementation of ChannelHandler::RegisterData | |||||
// On Mon, 17 May 2004 13:59:23 Dave Griffiths wrote: | |||||
// That's a difficult one. We can't use new/malloc as it's for use on the realtime thread | |||||
// (although in practice, ssm breaks this rule quite a lot :/ ) | |||||
// A solution would be to use a custom allocator, with constant timing | |||||
// - or a ringbuffer mechanism I think... | |||||
char t[256]; | |||||
strcpy (t, fn); | |||||
//sprintf(t,"%s",fn); | |||||
if (fn && fn!="") | if (fn && fn!="") | ||||
{ | { | ||||
m_GUICH->SetData("Filename",(void*)t); | m_GUICH->SetData("Filename",(void*)t); | ||||
@@ -168,34 +183,34 @@ inline void DiskWriterPluginGUI::cb_Open_i(Fl_Button* o) | |||||
} | } | ||||
inline void DiskWriterPluginGUI::cb_Record_i(Fl_Button* o) | inline void DiskWriterPluginGUI::cb_Record_i(Fl_Button* o) | ||||
{ | |||||
if (o->value()) | |||||
{ | |||||
if (o->value()) | |||||
{ | { | ||||
m_GUICH->SetCommand(DiskWriterPlugin::RECORD); | m_GUICH->SetCommand(DiskWriterPlugin::RECORD); | ||||
} | |||||
else | |||||
} | |||||
else | |||||
{ | { | ||||
m_GUICH->SetCommand(DiskWriterPlugin::STOP); | m_GUICH->SetCommand(DiskWriterPlugin::STOP); | ||||
} | |||||
} | |||||
} | } | ||||
inline void DiskWriterPluginGUI::cb_16bits_i(Fl_Button* o) | inline void DiskWriterPluginGUI::cb_16bits_i(Fl_Button* o) | ||||
{ | |||||
{ | |||||
m_GUICH->Set("BitsPerSample",16); | m_GUICH->Set("BitsPerSample",16); | ||||
} | } | ||||
inline void DiskWriterPluginGUI::cb_24bits_i(Fl_Button* o) | inline void DiskWriterPluginGUI::cb_24bits_i(Fl_Button* o) | ||||
{ | |||||
{ | |||||
m_GUICH->Set("BitsPerSample",24); | m_GUICH->Set("BitsPerSample",24); | ||||
} | } | ||||
inline void DiskWriterPluginGUI::cb_32bits_i(Fl_Button* o) | inline void DiskWriterPluginGUI::cb_32bits_i(Fl_Button* o) | ||||
{ | |||||
{ | |||||
m_GUICH->Set("BitsPerSample",32); | m_GUICH->Set("BitsPerSample",32); | ||||
} | } | ||||
inline void DiskWriterPluginGUI::cb_Stereo_i(Fl_Button* o) | inline void DiskWriterPluginGUI::cb_Stereo_i(Fl_Button* o) | ||||
{ | |||||
{ | |||||
m_GUICH->Set("Stereo",o->value()); | m_GUICH->Set("Stereo",o->value()); | ||||
} | } | ||||
@@ -460,7 +460,6 @@ SpiralWindowType *SynthModular::CreateWindow() | |||||
m_TopWindow->resizable(m_CanvasScroll); | m_TopWindow->resizable(m_CanvasScroll); | ||||
m_Canvas = new Fl_Canvas(-5000, -5000, 10000, 10000, ""); | m_Canvas = new Fl_Canvas(-5000, -5000, 10000, 10000, ""); | ||||
m_Canvas->user_data ((void*)(this)); | |||||
m_Canvas->type(1); | m_Canvas->type(1); | ||||
m_Canvas->box(FL_FLAT_BOX); | m_Canvas->box(FL_FLAT_BOX); | ||||
m_Canvas->labeltype(FL_ENGRAVED_LABEL); | m_Canvas->labeltype(FL_ENGRAVED_LABEL); | ||||
@@ -596,39 +595,43 @@ void SynthModular::LoadPlugins (string pluginPath) { | |||||
//NewButton->color(SpiralInfo::GUICOL_Button); | //NewButton->color(SpiralInfo::GUICOL_Button); | ||||
//NewButton->selection_color(SpiralInfo::GUICOL_Button); | //NewButton->selection_color(SpiralInfo::GUICOL_Button); | ||||
the_group->add (NewButton); | the_group->add (NewButton); | ||||
string PluginName=*i; | |||||
// we need to keep tooltips stored outside their widgets - widgets just have a pointer | |||||
// I haven't done anything about cleaning up these strings - which may cause memory leaks? | |||||
// But m_DeviceVec - which, I assume, would be used to keep track of / clean up the dynamicly | |||||
// created NewButton widgets isn't cleaned up either, so we might have 2 memory leaks | |||||
// involved? - but then again, they might be automatically deallocated because they're | |||||
// in another widget, in which case there's just one memory leak to deal with. (andy) | |||||
string* PluginName = new string (*i); | |||||
// find the first slash, if there is one, and get rid of everything before and including it | // find the first slash, if there is one, and get rid of everything before and including it | ||||
unsigned int p = PluginName.find ('/'); | |||||
if (p < PluginName.length()) PluginName.erase (0, p); | |||||
unsigned int p = PluginName->find ('/'); | |||||
if (p < PluginName->length()) PluginName->erase (0, p); | |||||
// find last . and get rid of everything after and including it | // find last . and get rid of everything after and including it | ||||
p = PluginName.rfind ('.'); | |||||
unsigned int l = PluginName.length (); | |||||
if (p < l) PluginName.erase (p, l); | |||||
NewButton->tooltip (PluginName.c_str()); | |||||
p = PluginName->rfind ('.'); | |||||
unsigned int l = PluginName->length (); | |||||
if (p < l) PluginName->erase (p, l); | |||||
NewButton->tooltip (PluginName->c_str()); | |||||
// Slashes have significance to the menu widgets, remove them from the GroupName | // Slashes have significance to the menu widgets, remove them from the GroupName | ||||
while ((p = GroupName.find ('/')) < PluginName.length()) | |||||
while ((p = GroupName.find ('/')) < PluginName->length()) | |||||
GroupName = GroupName.replace (p, 1, " and "); | GroupName = GroupName.replace (p, 1, " and "); | ||||
string MenuEntry = "Plugins/" + GroupName + "/" + PluginName; | |||||
string MenuEntry = "Plugins/" + GroupName + "/" + *PluginName; | |||||
m_MainMenu->add (MenuEntry.c_str(), 0, cb_NewDeviceFromMenu, &Numbers[ID], 0); | m_MainMenu->add (MenuEntry.c_str(), 0, cb_NewDeviceFromMenu, &Numbers[ID], 0); | ||||
//MenuEntry = "Help/" + MenuEntry; | |||||
//m_MainMenu->add (MenuEntry.c_str(), 0, NULL, &Numbers[ID], 0); | |||||
// andy preston | |||||
// my next step would be to add the plugins to Andrew's right-click menu | |||||
// to free up the middle button | |||||
m_Canvas->AddPluginName (PluginName, PluginManager::Get()->GetPlugin(ID)->ID); | |||||
// when help is working better - this will put the plugins into the help menu | |||||
// MenuEntry = "Help/" + MenuEntry; | |||||
// m_MainMenu->add (MenuEntry.c_str(), 0, NULL, &Numbers[ID], 0); | |||||
// Add the plugins to the canvas menu | |||||
m_Canvas->AddPluginName (MenuEntry, PluginManager::Get()->GetPlugin(ID)->ID); | |||||
// this overwrites the widget's user_data with that specified for the callback | // this overwrites the widget's user_data with that specified for the callback | ||||
// so we can't use it for other purposes | // so we can't use it for other purposes | ||||
NewButton->callback ((Fl_Callback*)cb_NewDevice, &Numbers[ID]); | NewButton->callback ((Fl_Callback*)cb_NewDevice, &Numbers[ID]); | ||||
NewButton->show(); | NewButton->show(); | ||||
// Nothing else ever touches m_DeviceVec - is this right??? (andy) | |||||
m_DeviceVec.push_back (NewButton); | m_DeviceVec.push_back (NewButton); | ||||
the_group->redraw(); | the_group->redraw(); | ||||
// m_NextPluginButton++; | // m_NextPluginButton++; | ||||
Fl::check(); | Fl::check(); | ||||
splashtext->label (PluginName.c_str()); | |||||
splashtext->label (PluginName->c_str()); | |||||
Splash->redraw(); | Splash->redraw(); | ||||
} | } | ||||
} | } | ||||
@@ -1415,12 +1418,13 @@ void SynthModular::cb_NewDevice (Fl_Button *o, void *v) { | |||||
// (Plugin Canvas Menu) | // (Plugin Canvas Menu) | ||||
inline void SynthModular::cb_NewDeviceFromCanvasMenu_i(Fl_Canvas* o, void* v) | |||||
{ | |||||
AddDevice(*((int*)v),*((int*)v+1),*((int*)v+2)); | |||||
inline void SynthModular::cb_NewDeviceFromCanvasMenu_i (Fl_Canvas* o, void* v) { | |||||
AddDevice(*((int*)v),*((int*)v+1),*((int*)v+2)); | |||||
} | |||||
void SynthModular::cb_NewDeviceFromCanvasMenu(Fl_Canvas* o, void* v) { | |||||
((SynthModular*)(o->user_data()))->cb_NewDeviceFromCanvasMenu_i(o,v); | |||||
} | } | ||||
void SynthModular::cb_NewDeviceFromCanvasMenu(Fl_Canvas* o, void* v) | |||||
{((SynthModular*)(o->user_data()))->cb_NewDeviceFromCanvasMenu_i(o,v);} | |||||
///////////////////////////////// | ///////////////////////////////// | ||||
@@ -63,7 +63,7 @@ public: | |||||
class Fl_ToolButton : public Fl_Button | class Fl_ToolButton : public Fl_Button | ||||
{ | { | ||||
public: | public: | ||||
Fl_ToolButton(int x, int y, int w, int h, const char *n=NULL) : | |||||
Fl_ToolButton(int x, int y, int w, int h, const char *n=NULL) : | |||||
Fl_Button(x,y,w,h,n) {} | Fl_Button(x,y,w,h,n) {} | ||||
virtual void draw() { draw_label(); } | virtual void draw() { draw_label(); } | ||||
}; | }; | ||||
@@ -72,7 +72,7 @@ class DeviceGroup | |||||
{ | { | ||||
public: | public: | ||||
DeviceGroup() { devicecount = 0; } | DeviceGroup() { devicecount = 0; } | ||||
int devicecount; | int devicecount; | ||||
fstream devices; | fstream devices; | ||||
map<int,int> m_DeviceIds;//old ID, new ID | map<int,int> m_DeviceIds;//old ID, new ID | ||||
@@ -98,13 +98,13 @@ public: | |||||
void FreezeAll() | void FreezeAll() | ||||
{ | { | ||||
m_CH.Set("Frozen",true); | |||||
m_CH.Set("Frozen",true); | |||||
m_CH.Wait(); | m_CH.Wait(); | ||||
} | } | ||||
void ThawAll() | void ThawAll() | ||||
{ | { | ||||
m_CH.Set("Frozen",false); | |||||
m_CH.Set("Frozen",false); | |||||
} | } | ||||
void PauseAudio() | void PauseAudio() | ||||
@@ -121,7 +121,7 @@ public: | |||||
{ | { | ||||
if (! m_ResetingAudioThread) | if (! m_ResetingAudioThread) | ||||
{ | { | ||||
FreezeAll(); | |||||
FreezeAll(); | |||||
m_ResetingAudioThread = true; | m_ResetingAudioThread = true; | ||||
@@ -175,7 +175,6 @@ private: | |||||
inline void cb_NewComment_i(Fl_Button* o, void* v); | inline void cb_NewComment_i(Fl_Button* o, void* v); | ||||
static void cb_NewComment(Fl_Button* o, void* v); | static void cb_NewComment(Fl_Button* o, void* v); | ||||
// File menu - and associated buttons, etc. | // File menu - and associated buttons, etc. | ||||
inline void cb_New_i (Fl_Widget *o, void *v); | inline void cb_New_i (Fl_Widget *o, void *v); | ||||
static void cb_New (Fl_Widget *o, void *v); | static void cb_New (Fl_Widget *o, void *v); | ||||