| @@ -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 | |||
| New GUI - less cluttered and more "traditional" toolbars. | |||
| @@ -14,7 +14,7 @@ | |||
| * You should have received a copy of the GNU General Public License | |||
| * along with this program; if not, write to the Free Software | |||
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| */ | |||
| #include <FL/Fl_Group.h> | |||
| #include <FL/Fl_Output.h> | |||
| @@ -36,8 +36,8 @@ class CanvasWire | |||
| { | |||
| public: | |||
| CanvasWire() { Clear(); } | |||
| void Clear() | |||
| void Clear() | |||
| { | |||
| OutputPort=-1; | |||
| OutputID=-1; | |||
| @@ -97,9 +97,9 @@ public: | |||
| void ClearConnections(Fl_DeviceGUI* Device); | |||
| void RemoveDevice(Fl_DeviceGUI* Device); | |||
| 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(); | |||
| @@ -131,10 +131,7 @@ public: | |||
| 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; } | |||
| CanvasGroup Selection() { return m_Selection; } | |||
| @@ -146,102 +143,43 @@ public: | |||
| } | |||
| private: | |||
| void PopupEditMenu (Fl_Group *group); | |||
| void DrawSelection(); | |||
| void CalculateSelection(); | |||
| void DrawWires(); | |||
| void ClearIncompleteWire(); | |||
| void DrawIncompleteWire(); | |||
| bool UserMakingConnection(); | |||
| 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_Unconnect)(Fl_Widget*, void*); | |||
| void (*cb_AddDevice)(Fl_Widget*, void*); | |||
| void (*cb_Rename)(Fl_Widget*, void*); | |||
| void (*cb_CutDeviceGroup)(Fl_Widget*, void*); | |||
| void (*cb_CopyDeviceGroup)(Fl_Widget*, void*); | |||
| void (*cb_PasteDeviceGroup)(Fl_Widget*, void*); | |||
| void (*cb_MergePatch)(Fl_Widget*, void*); | |||
| map<int,int> MapNewDeviceIds; | |||
| map<int,int> MapNewDeviceIds; | |||
| 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; | |||
| 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 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); | |||
| @@ -132,9 +132,9 @@ void DiskWriterPluginGUI::UpdateValues (SpiralPlugin *o) | |||
| m_32bits->value(0); | |||
| m_24bits->value(0); | |||
| m_16bits->value(1); | |||
| } | |||
| } | |||
| } | |||
| m_Stereo->value(Plugin->GetStereo()); | |||
| redraw(); | |||
| @@ -143,13 +143,28 @@ void DiskWriterPluginGUI::UpdateValues (SpiralPlugin *o) | |||
| //// Callbacks //// | |||
| inline void DiskWriterPluginGUI::cb_Open_i(Fl_Button* o) | |||
| { | |||
| { | |||
| if (o->value()) | |||
| { | |||
| 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!="") | |||
| { | |||
| 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) | |||
| { | |||
| if (o->value()) | |||
| { | |||
| if (o->value()) | |||
| { | |||
| m_GUICH->SetCommand(DiskWriterPlugin::RECORD); | |||
| } | |||
| else | |||
| } | |||
| else | |||
| { | |||
| m_GUICH->SetCommand(DiskWriterPlugin::STOP); | |||
| } | |||
| } | |||
| } | |||
| inline void DiskWriterPluginGUI::cb_16bits_i(Fl_Button* o) | |||
| { | |||
| { | |||
| m_GUICH->Set("BitsPerSample",16); | |||
| } | |||
| inline void DiskWriterPluginGUI::cb_24bits_i(Fl_Button* o) | |||
| { | |||
| { | |||
| m_GUICH->Set("BitsPerSample",24); | |||
| } | |||
| inline void DiskWriterPluginGUI::cb_32bits_i(Fl_Button* o) | |||
| { | |||
| { | |||
| m_GUICH->Set("BitsPerSample",32); | |||
| } | |||
| inline void DiskWriterPluginGUI::cb_Stereo_i(Fl_Button* o) | |||
| { | |||
| { | |||
| m_GUICH->Set("Stereo",o->value()); | |||
| } | |||
| @@ -460,7 +460,6 @@ SpiralWindowType *SynthModular::CreateWindow() | |||
| m_TopWindow->resizable(m_CanvasScroll); | |||
| m_Canvas = new Fl_Canvas(-5000, -5000, 10000, 10000, ""); | |||
| m_Canvas->user_data ((void*)(this)); | |||
| m_Canvas->type(1); | |||
| m_Canvas->box(FL_FLAT_BOX); | |||
| m_Canvas->labeltype(FL_ENGRAVED_LABEL); | |||
| @@ -596,39 +595,43 @@ void SynthModular::LoadPlugins (string pluginPath) { | |||
| //NewButton->color(SpiralInfo::GUICOL_Button); | |||
| //NewButton->selection_color(SpiralInfo::GUICOL_Button); | |||
| 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 | |||
| 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 | |||
| 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 | |||
| while ((p = GroupName.find ('/')) < PluginName.length()) | |||
| while ((p = GroupName.find ('/')) < PluginName->length()) | |||
| 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); | |||
| //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 | |||
| // so we can't use it for other purposes | |||
| NewButton->callback ((Fl_Callback*)cb_NewDevice, &Numbers[ID]); | |||
| NewButton->show(); | |||
| // Nothing else ever touches m_DeviceVec - is this right??? (andy) | |||
| m_DeviceVec.push_back (NewButton); | |||
| the_group->redraw(); | |||
| // m_NextPluginButton++; | |||
| Fl::check(); | |||
| splashtext->label (PluginName.c_str()); | |||
| splashtext->label (PluginName->c_str()); | |||
| Splash->redraw(); | |||
| } | |||
| } | |||
| @@ -1415,12 +1418,13 @@ void SynthModular::cb_NewDevice (Fl_Button *o, void *v) { | |||
| // (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 | |||
| { | |||
| 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) {} | |||
| virtual void draw() { draw_label(); } | |||
| }; | |||
| @@ -72,7 +72,7 @@ class DeviceGroup | |||
| { | |||
| public: | |||
| DeviceGroup() { devicecount = 0; } | |||
| int devicecount; | |||
| fstream devices; | |||
| map<int,int> m_DeviceIds;//old ID, new ID | |||
| @@ -98,13 +98,13 @@ public: | |||
| void FreezeAll() | |||
| { | |||
| m_CH.Set("Frozen",true); | |||
| m_CH.Set("Frozen",true); | |||
| m_CH.Wait(); | |||
| } | |||
| void ThawAll() | |||
| { | |||
| m_CH.Set("Frozen",false); | |||
| m_CH.Set("Frozen",false); | |||
| } | |||
| void PauseAudio() | |||
| @@ -121,7 +121,7 @@ public: | |||
| { | |||
| if (! m_ResetingAudioThread) | |||
| { | |||
| FreezeAll(); | |||
| FreezeAll(); | |||
| m_ResetingAudioThread = true; | |||
| @@ -175,7 +175,6 @@ private: | |||
| inline void cb_NewComment_i(Fl_Button* o, void* v); | |||
| static void cb_NewComment(Fl_Button* o, void* v); | |||
| // File menu - and associated buttons, etc. | |||
| inline void cb_New_i (Fl_Widget *o, void *v); | |||
| static void cb_New (Fl_Widget *o, void *v); | |||