diff --git a/SpiralSound/Plugins/JackPlugin/JackPlugin.C b/SpiralSound/Plugins/JackPlugin/JackPlugin.C index 3420925..32ba67f 100644 --- a/SpiralSound/Plugins/JackPlugin/JackPlugin.C +++ b/SpiralSound/Plugins/JackPlugin/JackPlugin.C @@ -103,6 +103,8 @@ JackClient::JackClient() m_JackInputCount = 4; m_JackOutputCount = 4; m_Client=NULL; + m_JackSampleRate = -1; + m_JackBufferSize = -1; } ///////////////////////////////////////////////////////////////////////////////////////////// @@ -191,6 +193,9 @@ bool JackClient::Attach() return false; } + m_JackSampleRate = jack_get_sample_rate(m_Client); + m_JackBufferSize = jack_get_buffer_size(m_Client); + jack_set_process_callback(m_Client, JackProcess, this); jack_set_sample_rate_callback (m_Client, SampleRateChange, this); jack_on_shutdown (m_Client, JackShutdown, this); @@ -211,6 +216,9 @@ bool JackClient::Attach() return false; } + // tells ssm to go back to callback mode + RunCallback(RunContext, true); + m_Attached=true; cerr<<"connected to jack..."<Detach(); - delete m_JackClient; - m_JackClient=NULL; - return true; -} - PluginInfo &JackPlugin::Initialise(const HostInfo *Host) { PluginInfo& Info= SpiralPlugin::Initialise(Host); - host=Host; m_JackClient->SetCallback(cb_Update,m_Parent); - + return Info; } @@ -490,47 +482,6 @@ SpiralGUIType *JackPlugin::CreateGUI() this,m_AudioCH,m_HostInfo); } -void JackPlugin::SetNumberPorts (int nInputs, int nOutputs) { - UpdatePluginInfoWithHost(); - RemoveAllInputs (); - RemoveAllOutputs (); - m_PluginInfo.NumInputs = 0; - m_PluginInfo.NumOutputs = 0; - m_PluginInfo.PortTips.clear (); - CreatePorts (nInputs, nOutputs, true); - UpdatePluginInfoWithHost (); -} - -void JackPlugin::CreatePorts (int nInputs, int nOutputs, bool AddPorts) { - m_PluginInfo.PortTips.clear(); - - m_PluginInfo.NumInputs = nInputs; - m_JackClient->SetJackInputCount(nInputs); - - for (int n=0; nSetJackOutputCount(nOutputs); - - for (int n=0; nIsCommandWaiting(); - int command = (commandwaiting)?(int)m_AudioCH->GetCommand():0; - - if (commandwaiting) + if (m_AudioCH->IsCommandWaiting()) { - switch (command) { + switch (m_AudioCH->GetCommand()) { case SET_PORT_COUNT : SetNumberPorts (m_GUIArgs.NumInputs, m_GUIArgs.NumOutputs); - } - } - + break; - // we want to process this whether we are connected to stuff or not - JackClient* pJack=m_JackClient; - - // connect the buffers up if we are plugged into something - for (int n=0; nGetJackOutputCount(); n++) - { - if (InputExists(n)) - { - pJack->SetOutputBuf(n,(float*)GetInput(n)->GetBuffer()); - } - else - { - pJack->SetOutputBuf(n,NULL); - } - } - - for (int n=0; nGetJackInputCount(); n++) - { - if (OutputExists(n)) - { - pJack->SetInputBuf(n,(float*)GetOutputBuf(n)->GetBuffer()); - } - else - { - pJack->SetInputBuf(n,NULL); - } - } - - if (commandwaiting) - { - switch (command) - { case UPDATE_NAMES : { int c=0; @@ -626,12 +540,128 @@ void JackPlugin::ExecuteCommands() } break; + default : break; } } m_Connected=m_JackClient->IsAttached(); } +bool JackPlugin::Kill() +{ + m_IsDead=true; + + UpdatePluginInfoWithHost(); + RemoveAllInputs (); + RemoveAllOutputs (); + UpdatePluginInfoWithHost(); + + if (m_JackClient) + { + m_JackClient->Detach(); + delete m_JackClient; + m_JackClient=NULL; + } + + return true; +} + +void JackPlugin::Reset() +{ + // we want to process this whether we are connected to stuff or not + JackClient* pJack=m_JackClient; + + // connect the buffers up if we are plugged into something + for (int n=0; nGetJackOutputCount(); n++) + { + pJack->SetOutputBuf(n,NULL); + } + + for (int n=0; nGetJackInputCount(); n++) + { + pJack->SetInputBuf(n,NULL); + } + + ResetPorts(); +} + +void JackPlugin::ProcessAudio() +{ + if (m_IsDead) return; + + // Make sure all plugins match Jack's SampleRate and Buffersize + if ((m_JackClient->JackSampleRate() != -1) && (m_JackClient->JackBufferSize() != -1)) + { + ChangeBufferAndSampleRate(m_JackClient->JackBufferSize(), m_JackClient->JackSampleRate(), m_Parent); + } + + // connect the buffers up if we are plugged into something + for (int n=0; nGetJackOutputCount(); n++) + { + if (InputExists(n)) + { + m_JackClient->SetOutputBuf(n,(float*)GetInput(n)->GetBuffer()); + } + else + { + m_JackClient->SetOutputBuf(n,NULL); + } + } + + for (int n=0; nGetJackInputCount(); n++) + { + if (OutputExists(n)) + { + m_JackClient->SetInputBuf(n,(float*)GetOutputBuf(n)->GetBuffer()); + } + else + { + m_JackClient->SetInputBuf(n,NULL); + } + } +} + +void JackPlugin::SetNumberPorts (int nInputs, int nOutputs) { + UpdatePluginInfoWithHost(); + RemoveAllInputs (); + RemoveAllOutputs (); + m_PluginInfo.NumInputs = 0; + m_PluginInfo.NumOutputs = 0; + m_PluginInfo.PortTips.clear (); + CreatePorts (nInputs, nOutputs, true); + UpdatePluginInfoWithHost (); +} + +void JackPlugin::CreatePorts (int nInputs, int nOutputs, bool AddPorts) { + m_PluginInfo.PortTips.clear(); + + m_PluginInfo.NumInputs = nInputs; + m_JackClient->SetJackInputCount(nInputs); + + for (int n=0; nSetJackOutputCount(nOutputs); + + for (int n=0; nAttach(); } - void Detach() { m_JackClient->Detach(); } -private: - const HostInfo* host; + void Detach() { m_JackClient->Detach(); } + /* Jack Plugin Streaming - soon to be obsolete and for backward compatibility only*/ + virtual void StreamOut(std::ostream &s); + virtual void StreamIn(std::istream &s); +private: GUIArgs m_GUIArgs; int m_Version; @@ -169,7 +181,7 @@ private: bool m_Connected; JackClient *m_JackClient; int m_JackInstanceID; - + //clunky work-around for unique ID static int JackInstanceCount; }; diff --git a/SpiralSound/Plugins/OutputPlugin/OutputPlugin.C b/SpiralSound/Plugins/OutputPlugin/OutputPlugin.C index 38e10fd..21dc791 100644 --- a/SpiralSound/Plugins/OutputPlugin/OutputPlugin.C +++ b/SpiralSound/Plugins/OutputPlugin/OutputPlugin.C @@ -53,7 +53,7 @@ static const int IN_SHLEN = 2; static const int OUT_MAIN = 0; static const HostInfo* host; -OSSOutput* OSSOutput::m_Singleton = NULL; +OSSClient* OSSClient::m_Singleton = NULL; int OutputPlugin::m_RefCount=0; int OutputPlugin::m_NoExecuted=0; OutputPlugin::Mode OutputPlugin::m_Mode=NO_MODE; @@ -117,7 +117,7 @@ OutputPlugin::~OutputPlugin() if (m_RefCount==0) { cb_Blocking(m_Parent,false); - OSSOutput::PackUpAndGoHome(); + OSSClient::PackUpAndGoHome(); m_Mode=NO_MODE; } } @@ -126,7 +126,7 @@ PluginInfo &OutputPlugin::Initialise(const HostInfo *Host) { PluginInfo& Info= SpiralPlugin::Initialise(Host); host=Host; - OSSOutput::Get()->AllocateBuffer(); + OSSClient::Get()->AllocateBuffer(); return Info; } @@ -140,7 +140,7 @@ SpiralGUIType *OutputPlugin::CreateGUI() bool OutputPlugin::Kill() { m_IsDead=true; - OSSOutput::Get()->Kill(); + OSSClient::Get()->Kill(); m_Mode=CLOSED; cb_Blocking(m_Parent,false); return true; @@ -150,23 +150,23 @@ void OutputPlugin::Reset() { if (m_IsDead) return; m_IsDead=true; - OSSOutput::Get()->Kill(); + OSSClient::Get()->Kill(); cb_Blocking(m_Parent,false); ResetPorts(); - OSSOutput::Get()->AllocateBuffer(); + OSSClient::Get()->AllocateBuffer(); switch (m_Mode) { case INPUT : - OSSOutput::Get()->OpenRead(); + OSSClient::Get()->OpenRead(); cb_Blocking(m_Parent,true); break; case OUTPUT : - OSSOutput::Get()->OpenWrite(); + OSSClient::Get()->OpenWrite(); cb_Blocking(m_Parent,true); break; case DUPLEX : - OSSOutput::Get()->OpenReadWrite(); + OSSClient::Get()->OpenReadWrite(); cb_Blocking(m_Parent,true); break; @@ -183,7 +183,7 @@ void OutputPlugin::Execute() if (m_Mode==NO_MODE && m_RefCount==1) { - if (OSSOutput::Get()->OpenWrite()) + if (OSSClient::Get()->OpenWrite()) { cb_Blocking(m_Parent,true); m_Mode=OUTPUT; @@ -193,11 +193,11 @@ void OutputPlugin::Execute() if (m_Mode==OUTPUT || m_Mode==DUPLEX) { - OSSOutput::Get()->SendStereo(GetInput(0),GetInput(1)); + OSSClient::Get()->SendStereo(GetInput(0),GetInput(1)); } if (m_Mode==INPUT || m_Mode==DUPLEX) - OSSOutput::Get()->GetStereo(GetOutputBuf(0),GetOutputBuf(1)); + OSSClient::Get()->GetStereo(GetOutputBuf(0),GetOutputBuf(1)); } void OutputPlugin::ExecuteCommands() @@ -205,36 +205,26 @@ void OutputPlugin::ExecuteCommands() if (m_IsDead) return; - // Only Play() once per set of plugins - m_NoExecuted--; - if (m_NoExecuted<=0) - { - if (m_Mode==INPUT || m_Mode==DUPLEX) OSSOutput::Get()->Read(); - if (m_Mode==OUTPUT || m_Mode==DUPLEX) OSSOutput::Get()->Play(); - m_NoExecuted=m_RefCount; - } - - if (m_AudioCH->IsCommandWaiting()) { switch(m_AudioCH->GetCommand()) { case OPENREAD : - if (OSSOutput::Get()->OpenRead()) + if (OSSClient::Get()->OpenRead()) { m_Mode=INPUT; //cb_Blocking(m_Parent,true); } break; case OPENWRITE : - if (OSSOutput::Get()->OpenWrite()) + if (OSSClient::Get()->OpenWrite()) { m_Mode=OUTPUT; cb_Blocking(m_Parent,true); } break; case OPENDUPLEX : - if (OSSOutput::Get()->OpenReadWrite()) + if (OSSClient::Get()->OpenReadWrite()) { m_Mode=DUPLEX; cb_Blocking(m_Parent,true); @@ -243,10 +233,10 @@ void OutputPlugin::ExecuteCommands() case CLOSE : m_Mode=CLOSED; cb_Blocking(m_Parent,false); - OSSOutput::Get()->Close(); + OSSClient::Get()->Close(); break; case SET_VOLUME : - OSSOutput::Get()->SetVolume(m_Volume); + OSSClient::Get()->SetVolume(m_Volume); break; case CLEAR_NOTIFY: m_NotifyOpenOut=false; @@ -256,10 +246,25 @@ void OutputPlugin::ExecuteCommands() } } +void OutputPlugin::ProcessAudio() +{ + if (m_IsDead) + return; + + // Only Play() once per set of plugins + m_NoExecuted--; + if (m_NoExecuted<=0) + { + if (m_Mode==INPUT || m_Mode==DUPLEX) OSSClient::Get()->Read(); + if (m_Mode==OUTPUT || m_Mode==DUPLEX) OSSClient::Get()->Play(); + m_NoExecuted=m_RefCount; + } +} + ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// -OSSOutput::OSSOutput() : +OSSClient::OSSClient() : m_Amp(0.5), m_Channels(2), m_ReadBufferNum(0), @@ -276,7 +281,7 @@ m_IsDead(false) ////////////////////////////////////////////////////////////////////// -OSSOutput::~OSSOutput() +OSSClient::~OSSClient() { Close(); DeallocateBuffer(); @@ -284,7 +289,7 @@ OSSOutput::~OSSOutput() ////////////////////////////////////////////////////////////////////// -void OSSOutput::AllocateBuffer() +void OSSClient::AllocateBuffer() { if (m_Buffer[0]==NULL) { @@ -296,11 +301,9 @@ void OSSOutput::AllocateBuffer() m_InBuffer[0] = (short*) calloc(m_BufSizeBytes/2,m_BufSizeBytes); m_InBuffer[1] = (short*) calloc(m_BufSizeBytes/2,m_BufSizeBytes); } - - m_Wav.SetSamplerate(host->SAMPLERATE); } -void OSSOutput::DeallocateBuffer() +void OSSClient::DeallocateBuffer() { if (m_Buffer[0]!=NULL) { @@ -316,7 +319,7 @@ void OSSOutput::DeallocateBuffer() ////////////////////////////////////////////////////////////////////// -void OSSOutput::SendStereo(const Sample *ldata,const Sample *rdata) +void OSSClient::SendStereo(const Sample *ldata,const Sample *rdata) { if (m_Channels!=2) return; @@ -349,7 +352,7 @@ void OSSOutput::SendStereo(const Sample *ldata,const Sample *rdata) ////////////////////////////////////////////////////////////////////// -void OSSOutput::Play() +void OSSClient::Play() { int BufferToSend=!m_WriteBufferNum; @@ -365,18 +368,13 @@ void OSSOutput::Play() write(m_Dspfd,m_Buffer[BufferToSend],m_BufSizeBytes); } - if(m_Wav.Recording()) - { - m_Wav.Save(m_Buffer[BufferToSend],m_BufSizeBytes); - } - memset(m_Buffer[BufferToSend],0,m_BufSizeBytes); m_WriteBufferNum=BufferToSend; } ////////////////////////////////////////////////////////////////////// -void OSSOutput::GetStereo(Sample *ldata,Sample *rdata) +void OSSClient::GetStereo(Sample *ldata,Sample *rdata) { if (m_Channels!=2) return; @@ -395,7 +393,7 @@ void OSSOutput::GetStereo(Sample *ldata,Sample *rdata) ////////////////////////////////////////////////////////////////////// -void OSSOutput::Read() +void OSSClient::Read() { int BufferToRead=!m_ReadBufferNum; @@ -415,7 +413,7 @@ void OSSOutput::Read() ////////////////////////////////////////////////////////////////////// -bool OSSOutput::Close() +bool OSSClient::Close() { cerr<<"Closing dsp output"<value(OSSOutput::Get()->GetVolume()); + Volume->value(OSSClient::Get()->GetVolume()); } //// Callbacks //// diff --git a/SpiralSound/Plugins/SpiralPlugin.h b/SpiralSound/Plugins/SpiralPlugin.h index bd00d7f..02ca7bb 100644 --- a/SpiralSound/Plugins/SpiralPlugin.h +++ b/SpiralSound/Plugins/SpiralPlugin.h @@ -47,12 +47,15 @@ struct PluginInfo struct HostInfo { int BUFSIZE; + int SAMPLERATE; + + /* obsolete - REMOVE SOON */ int FRAGSIZE; int FRAGCOUNT; - int SAMPLERATE; std::string OUTPUTFILE; std::string MIDIFILE; int POLY; + unsigned GUI_COLOUR; unsigned SCOPE_BG_COLOUR; unsigned SCOPE_FG_COLOUR; @@ -102,7 +105,7 @@ public: void UpdatePluginInfoWithHost(); void SetInPortType(PluginInfo &pinfo, int port, Sample::SampleType type); - void SetOutPortType(PluginInfo &pinfo, int port, Sample::SampleType type); + void SetOutPortType(PluginInfo &pinfo, int port, Sample::SampleType type); // Callbacks to main engine. Should only called by plugin hosts. void SetUpdateInfoCallback(int ID, void(*s)(int, void *)); @@ -115,8 +118,9 @@ public: bool IsTerminal() { return m_IsTerminal; } bool IsDead() { return m_IsDead; } - ChannelHandler *GetChannelHandler() { return m_AudioCH; } - + ChannelHandler *GetChannelHandler() { return m_AudioCH; } + + virtual bool IsAudioDriver() { return false; } protected: ChannelHandler *m_AudioCH; @@ -178,4 +182,37 @@ private: int m_HostID; }; +class AudioDriver : public SpiralPlugin +{ +public: + /* if this is an ALWAYS process then ProcessAudio must + always be called regardless whether it has something to + process or not, so it is run along side GUI commands, + ala ExecuteCommands, and is run even if paused. + + If its MANUAL we are the ones doing the pushing of data + so we don't have to worry about it if we aren't hooked up, + and we do have to worry about synchronization with other + plugins, so ProcessAudio should be run along side of + regular audio updates, ala Execute. This is eg. for + a File Output driver. + + NEVER means we never need to run ProcessAudio, eg, + a dummy audio driver. + */ + enum AudioProcessType { ALWAYS, MANUAL, NEVER }; + + virtual bool IsAudioDriver() { return true; } + + virtual void ProcessAudio()=0; + + virtual AudioProcessType ProcessType() { return NEVER; } + + // Callbacks to main engine. Should only called by plugin hosts. + void SetChangeBufferAndSampleRateCallback(void(*s)(long unsigned int, long unsigned int, void *)) { ChangeBufferAndSampleRate = s; } ; + +protected: + void (*ChangeBufferAndSampleRate)(long unsigned int BufferSize, long unsigned int SampleRate, void *); +}; + #endif diff --git a/SpiralSynthModular.C b/SpiralSynthModular.C index 90c3d79..0333227 100644 --- a/SpiralSynthModular.C +++ b/SpiralSynthModular.C @@ -77,13 +77,18 @@ SynthModular::SynthModular(): m_NextID(0), m_PauseAudio(false) { + /* Shared Audio State Information */ m_Info.BUFSIZE = SpiralInfo::BUFSIZE; + m_Info.SAMPLERATE = SpiralInfo::SAMPLERATE; + + /* obsolete - REMOVE SOON */ m_Info.FRAGSIZE = SpiralInfo::FRAGSIZE; m_Info.FRAGCOUNT = SpiralInfo::FRAGCOUNT; - m_Info.SAMPLERATE = SpiralInfo::SAMPLERATE; m_Info.OUTPUTFILE = SpiralInfo::OUTPUTFILE; m_Info.MIDIFILE = SpiralInfo::MIDIFILE; m_Info.POLY = SpiralInfo::POLY; + + /* Shared GUI Preferences Information */ m_Info.GUI_COLOUR = SpiralInfo::GUI_COLOUR; m_Info.SCOPE_BG_COLOUR = SpiralInfo::SCOPE_BG_COLOUR; m_Info.SCOPE_FG_COLOUR = SpiralInfo::SCOPE_FG_COLOUR; @@ -145,8 +150,6 @@ void SynthModular::Update() { m_CH.UpdateDataNow(); - if (m_PauseAudio) return; - // for all the plugins for(map::iterator i=m_DeviceWinMap.begin(); i!=m_DeviceWinMap.end(); i++) @@ -160,21 +163,35 @@ void SynthModular::Update() //Erase Device from DeviceWinMap m_DeviceWinMap.erase(i); } - else if (i->second->m_Device && !m_ResetingAudioThread) // if it's not a comment and we aren't reseting + else if (i->second->m_Device) // if it's not a comment { - #ifdef DEBUG_PLUGINS - cerr<<"Updating channelhandler of plugin "<second->m_PluginID<second->m_PluginID<second->m_Device->UpdateChannelHandler(); + // updates the data from the gui thread, if it's not blocking + i->second->m_Device->UpdateChannelHandler(); - #ifdef DEBUG_PLUGINS - cerr<<"Finished updating"<second->m_Device->ExecuteCommands(); + // run any commands we've received from the GUI's + i->second->m_Device->ExecuteCommands(); + } + + // If this is an audio device see if we always need to ProcessAudio here + if (i->second->m_Device->IsAudioDriver()) + { + AudioDriver *driver = ((AudioDriver *)i->second->m_Device); + + if (driver->ProcessType() == AudioDriver::ALWAYS) + { + driver->ProcessAudio(); + } + } } } @@ -185,7 +202,7 @@ void SynthModular::Update() { // use the graphsort order to remove internal latency map::iterator di=m_DeviceWinMap.find(*i); - if (di!=m_DeviceWinMap.end() && di->second->m_Device && (! di->second->m_Device->IsDead())) + if (di!=m_DeviceWinMap.end() && di->second->m_Device && (! di->second->m_Device->IsDead()) && (!m_PauseAudio)) { #ifdef DEBUG_PLUGINS cerr<<"Executing plugin "<second->m_PluginID<second->m_Device->Execute(); + + // If this is an audio device see if we need to ProcessAudio here + if (di->second->m_Device->IsAudioDriver()) + { + AudioDriver *driver = ((AudioDriver *)di->second->m_Device); + + if (driver->ProcessType() == AudioDriver::MANUAL) + { + driver->ProcessAudio(); + } + } } #ifdef DEBUG_PLUGINS @@ -258,6 +286,13 @@ void SynthModular::UpdatePluginGUIs() } m_Canvas->Poll(); + + if (m_HostNeedsUpdate) + { + cout << "Updating SampleRate to: " << SpiralInfo::SAMPLERATE << " and Buffer Size to: " << SpiralInfo::BUFSIZE << " to match current Audio Driver." << endl; + UpdateHostInfo(); + m_HostNeedsUpdate = false; + } } ////////////////////////////////////////////////////////// @@ -353,6 +388,16 @@ SpiralWindowType *SynthModular::CreateWindow() m_NewComment->callback((Fl_Callback*)cb_NewComment); m_Toolbar->add(m_NewComment); + m_PlayPause = new Fl_Button(0, 0, but, but, "Play/Pause"); + m_PlayPause->type(0); + m_PlayPause->box(FL_PLASTIC_UP_BOX); + m_PlayPause->color(SpiralInfo::GUICOL_Button); + m_PlayPause->selection_color(SpiralInfo::GUICOL_Tool); + m_PlayPause->labelsize (1); + m_PlayPause->tooltip("Play/Pause"); + m_PlayPause->callback((Fl_Callback*)cb_PlayPause); + m_Toolbar->add(m_PlayPause); + m_GroupFiller = new Fl_Group (0, 0, 0, ToolbarHeight, ""); m_GroupFiller->color(SpiralInfo::GUICOL_Button); m_Topbar->add (m_GroupFiller); @@ -634,6 +679,11 @@ DeviceWin* SynthModular::NewDeviceWin(int n, int x, int y) nlw->m_Device->SetUpdateCallback(cb_Update); nlw->m_Device->SetParent((void*)this); + if ( AudioDriver *driver = dynamic_cast(nlw->m_Device) ) + { + driver->SetChangeBufferAndSampleRateCallback(cb_ChangeBufferAndSampleRate); + } + PluginInfo PInfo = nlw->m_Device->Initialise(&m_Info); SpiralGUIType *temp = nlw->m_Device->CreateGUI(); Fl_Pixmap *Pix = new Fl_Pixmap(Plugin->GetIcon()); @@ -728,16 +778,35 @@ void SynthModular::AddComment(int n) ////////////////////////////////////////////////////////// +void SynthModular::cb_ChangeBufferAndSampleRate_i(long int NewBufferSize, long int NewSamplerate) +{ + if (SpiralInfo::BUFSIZE != NewBufferSize) + { + // update the settings + SpiralInfo::BUFSIZE = NewBufferSize; + m_HostNeedsUpdate = true; + } + + if (SpiralInfo::SAMPLERATE != NewSamplerate) + { + SpiralInfo::SAMPLERATE = NewSamplerate; + m_HostNeedsUpdate = true; + } +} + + void SynthModular::UpdateHostInfo() { /* Pause Audio */ PauseAudio(); - // update the settings + /* update the settings */ m_Info.BUFSIZE = SpiralInfo::BUFSIZE; + m_Info.SAMPLERATE = SpiralInfo::SAMPLERATE; + + /* obsolete - REMOVE SOON */ m_Info.FRAGSIZE = SpiralInfo::FRAGSIZE; m_Info.FRAGCOUNT = SpiralInfo::FRAGCOUNT; - m_Info.SAMPLERATE = SpiralInfo::SAMPLERATE; m_Info.OUTPUTFILE = SpiralInfo::OUTPUTFILE; m_Info.MIDIFILE = SpiralInfo::MIDIFILE; m_Info.POLY = SpiralInfo::POLY; @@ -1334,6 +1403,21 @@ void SynthModular::cb_NewComment(Fl_Button* o, void* v) ////////////////////////////////////////////////////////// +inline void SynthModular::cb_PlayPause_i(Fl_Button* o, void* v) +{ + if (m_ResetingAudioThread) return; + + if (IsPaused()) + ResumeAudio(); + else + PauseAudio(); +} + +void SynthModular::cb_PlayPause(Fl_Button* o, void* v) +{((SynthModular*)(o->parent()->user_data()))->cb_PlayPause_i(o,v);} + +////////////////////////////////////////////////////////// + inline void SynthModular::cb_GroupTab_i(Fl_Tabs* o, void* v) { m_GroupTab->redraw(); diff --git a/SpiralSynthModular.h b/SpiralSynthModular.h index df5d8ed..feaab32 100644 --- a/SpiralSynthModular.h +++ b/SpiralSynthModular.h @@ -134,6 +134,7 @@ private: HostInfo m_Info; bool m_ResetingAudioThread; + bool m_HostNeedsUpdate; static DeviceGUIInfo BuildDeviceGUIInfo(PluginInfo &PInfo); @@ -158,6 +159,7 @@ private: Fl_Button *m_New; Fl_Button *m_Options; Fl_Button *m_NewComment; + Fl_Button *m_PlayPause; Fl_Tabs *m_GroupTab; Fl_Canvas *m_Canvas; @@ -187,7 +189,9 @@ private: static void cb_Save(Fl_Button* o, void* v); inline void cb_New_i(Fl_Button* o, void* v); static void cb_New(Fl_Button* o, void* v); - + inline void cb_PlayPause_i(Fl_Button* o, void* v); + static void cb_PlayPause(Fl_Button* o, void* v); + inline void cb_MergePatch_i(); static void cb_MergePatch(Fl_Canvas* o, SynthModular*v) { v->cb_MergePatch_i(); }; @@ -208,6 +212,13 @@ private: static void cb_Blocking(void* o, bool Mode); static void cb_UpdatePluginInfo(int ID, void *PluginInfo); + inline void cb_ChangeBufferAndSampleRate_i(long int NewBufferSize, long int NewSamplerate); + + static void cb_ChangeBufferAndSampleRate(long unsigned int NewBufferSize, long unsigned int NewSamplerate, void *o) + { + ((SynthModular*)o)->cb_ChangeBufferAndSampleRate_i(NewBufferSize, NewSamplerate); + } + DeviceGroup m_Copied; inline void cb_CutDeviceGroup_i();