Browse Source

Started AudioDriver framework, switched Jack and OSS for basic differences,

as a result SSM will now always try and follow Jack settings while attached.
master
aj_genius 21 years ago
parent
commit
325e98a5a3
8 changed files with 380 additions and 201 deletions
  1. +134
    -104
      SpiralSound/Plugins/JackPlugin/JackPlugin.C
  2. +24
    -12
      SpiralSound/Plugins/JackPlugin/JackPlugin.h
  3. +44
    -46
      SpiralSound/Plugins/OutputPlugin/OutputPlugin.C
  4. +23
    -16
      SpiralSound/Plugins/OutputPlugin/OutputPlugin.h
  5. +1
    -1
      SpiralSound/Plugins/OutputPlugin/OutputPluginGUI.C
  6. +41
    -4
      SpiralSound/Plugins/SpiralPlugin.h
  7. +101
    -17
      SpiralSynthModular.C
  8. +12
    -1
      SpiralSynthModular.h

+ 134
- 104
SpiralSound/Plugins/JackPlugin/JackPlugin.C View File

@@ -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..."<<endl;
@@ -228,13 +236,13 @@ void JackClient::Detach()
jack_client_close(m_Client);
m_Client=NULL;
m_Attached=false;
}
if (JackProcessInstanceID==m_JackInstanceID)
JackProcessInstanceID = -1;

// tells ssm to go back to non callback mode
RunCallback(RunContext, false);
if (JackProcessInstanceID==m_JackInstanceID)
JackProcessInstanceID = -1;

// tells ssm to go back to non callback mode
RunCallback(RunContext, false);
}
}

/////////////////////////////////////////////////////////////////////////////////////////////
@@ -458,28 +466,12 @@ JackPlugin::~JackPlugin()
}
}

bool JackPlugin::Kill()
{
m_IsDead=true;

UpdatePluginInfoWithHost();
RemoveAllInputs ();
RemoveAllOutputs ();
UpdatePluginInfoWithHost();

m_JackClient->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; n<nInputs; n++)
{
char Temp[256];
sprintf(Temp,"SSM Input %d",n);
m_PluginInfo.PortTips.push_back(Temp);
}
m_PluginInfo.NumOutputs = nOutputs;
m_JackClient->SetJackOutputCount(nOutputs);

for (int n=0; n<nOutputs; n++)
{
char Temp[256];
sprintf(Temp,"SSM Output %d",n);
m_PluginInfo.PortTips.push_back(Temp);
}

if (AddPorts) {
for (int n=0; n<nInputs; n++) AddInput();
for (int n=0; n<nOutputs; n++) AddOutput();
}

}

void JackPlugin::Execute()
{
}
@@ -539,50 +490,13 @@ void JackPlugin::ExecuteCommands()
{
if (m_IsDead) return;
bool commandwaiting = m_AudioCH->IsCommandWaiting();
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; n<pJack->GetJackOutputCount(); n++)
{
if (InputExists(n))
{
pJack->SetOutputBuf(n,(float*)GetInput(n)->GetBuffer());
}
else
{
pJack->SetOutputBuf(n,NULL);
}
}
for (int n=0; n<pJack->GetJackInputCount(); 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; n<pJack->GetJackOutputCount(); n++)
{
pJack->SetOutputBuf(n,NULL);
}
for (int n=0; n<pJack->GetJackInputCount(); 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; n<m_JackClient->GetJackOutputCount(); n++)
{
if (InputExists(n))
{
m_JackClient->SetOutputBuf(n,(float*)GetInput(n)->GetBuffer());
}
else
{
m_JackClient->SetOutputBuf(n,NULL);
}
}
for (int n=0; n<m_JackClient->GetJackInputCount(); 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; n<nInputs; n++)
{
char Temp[256];
sprintf(Temp,"SSM Input %d",n);
m_PluginInfo.PortTips.push_back(Temp);
}
m_PluginInfo.NumOutputs = nOutputs;
m_JackClient->SetJackOutputCount(nOutputs);

for (int n=0; n<nOutputs; n++)
{
char Temp[256];
sprintf(Temp,"SSM Output %d",n);
m_PluginInfo.PortTips.push_back(Temp);
}

if (AddPorts) {
for (int n=0; n<nInputs; n++) AddInput();
for (int n=0; n<nOutputs; n++) AddOutput();
}

}

void JackPlugin::StreamOut (ostream &s)
{
s << m_Version << " " << m_GUIArgs.NumInputs << " " << m_GUIArgs.NumOutputs << " ";


+ 24
- 12
SpiralSound/Plugins/JackPlugin/JackPlugin.h View File

@@ -66,6 +66,8 @@ public:
void SetJackInputCount(int JackInputCount) { m_JackInputCount=JackInputCount; }
int GetJackOutputCount() { return m_JackOutputCount; }
void SetJackOutputCount(int JackOutputCount) { m_JackOutputCount=JackOutputCount; }
long int JackSampleRate() { return m_JackSampleRate; }
long int JackBufferSize() { return m_JackBufferSize; }

class JackPort
{
@@ -107,6 +109,9 @@ private:
int m_JackOutputCount;
int m_JackInstanceID;

long int m_JackSampleRate;
long int m_JackBufferSize;

static int JackProcessInstanceID;

void(*RunCallback)(void*, bool m);
@@ -115,7 +120,7 @@ private:

///////////////////////////////////////////////////

class JackPlugin : public SpiralPlugin
class JackPlugin : public AudioDriver
{
public:
JackPlugin();
@@ -124,16 +129,21 @@ public:
virtual PluginInfo& Initialise(const HostInfo *Host);
virtual SpiralGUIType* CreateGUI();
virtual void Execute();
virtual void ExecuteCommands();
/* General Plugin Function */
virtual void Execute();
virtual void ExecuteCommands();

virtual bool Kill();
virtual void StreamOut(std::ostream &s);
virtual void StreamIn(std::istream &s);
virtual bool Kill();
virtual void Reset();
/* Audio Driver Specific Functions */
virtual bool IsAudioDriver() { return true; }
virtual AudioProcessType ProcessType() { return AudioDriver::ALWAYS; }
virtual void ProcessAudio();

/* Jack Plugin Specific Functions */
JackClient *GetJackClient() { return m_JackClient; }
void SetNumberPorts (int nInputs, int nOutputs);

enum GUICommands{NONE,UPDATE_NAMES,SET_PORT_COUNT,CHECK_PORT_CHANGES};
@@ -145,10 +155,12 @@ public:
};

void Attach() { m_JackClient->Attach(); }
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;
};


+ 44
- 46
SpiralSound/Plugins/OutputPlugin/OutputPlugin.C View File

@@ -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"<<endl;
close(m_Dspfd);
@@ -425,7 +423,7 @@ bool OSSOutput::Close()

//////////////////////////////////////////////////////////////////////

bool OSSOutput::OpenWrite()
bool OSSClient::OpenWrite()
{
int result,val;
cerr<<"Opening dsp output"<<endl;
@@ -489,7 +487,7 @@ bool OSSOutput::OpenWrite()

//////////////////////////////////////////////////////////////////////

bool OSSOutput::OpenRead()
bool OSSClient::OpenRead()
{
int result,val;
@@ -524,7 +522,7 @@ bool OSSOutput::OpenRead()

//////////////////////////////////////////////////////////////////////

bool OSSOutput::OpenReadWrite()
bool OSSClient::OpenReadWrite()
{
int result,val;
cerr<<"Opening dsp output (duplex)"<<endl;


+ 23
- 16
SpiralSound/Plugins/OutputPlugin/OutputPlugin.h View File

@@ -23,12 +23,12 @@
#ifndef OutputPLUGIN
#define OutputPLUGIN

class OSSOutput
class OSSClient
{
public:
static OSSOutput *Get() { if(!m_Singleton) m_Singleton=new OSSOutput; return m_Singleton; }
static OSSClient *Get() { if(!m_Singleton) m_Singleton=new OSSClient; return m_Singleton; }
static void PackUpAndGoHome() { if(m_Singleton) { delete m_Singleton; m_Singleton=NULL; } }
~OSSOutput();
~OSSClient();

void AllocateBuffer();
void DeallocateBuffer();
@@ -39,8 +39,7 @@ public:
float GetVolume() {return m_Amp;}
void Play();
void Read();
void WavOpen(char* name) {m_Wav.Open(name,WavFile::WRITE, WavFile::STEREO);}
void WavClose() {m_Wav.Close();}

short *GetBuffer() {return m_Buffer[m_WriteBufferNum];}

bool OpenReadWrite();
@@ -49,9 +48,9 @@ public:
bool Close();
void Kill() { m_IsDead = true; m_OutputOk=false; PackUpAndGoHome(); }
private:
static OSSOutput* m_Singleton;
static OSSClient* m_Singleton;

OSSOutput();
OSSClient();

short *m_Buffer[2];
short *m_InBuffer[2];
@@ -59,7 +58,7 @@ private:
int m_Dspfd;
float m_Amp;
int m_Channels;
WavFile m_Wav;
int m_ReadBufferNum;
int m_WriteBufferNum;
bool m_OutputOk;
@@ -67,7 +66,7 @@ private:
};


class OutputPlugin : public SpiralPlugin
class OutputPlugin : public AudioDriver
{
public:
enum Mode {NO_MODE,INPUT,OUTPUT,DUPLEX,CLOSED};
@@ -77,26 +76,34 @@ public:

virtual PluginInfo& Initialise(const HostInfo *Host);
virtual SpiralGUIType* CreateGUI();
virtual void Execute();
virtual bool Kill();
virtual void Reset();

virtual void ExecuteCommands();
virtual void StreamOut(std::ostream &s) {}
virtual void StreamIn(std::istream &s) {}
/* General Plugin Function */
virtual void Execute();
virtual void ExecuteCommands();

virtual bool Kill();
virtual void Reset();
/* Audio Driver Specific Functions */
virtual bool IsAudioDriver() { return true; }
virtual AudioProcessType ProcessType() { return AudioDriver::ALWAYS; }
virtual void ProcessAudio();

/* OSS Plugin Specific Functions */
enum GUICommands {NONE, OPENREAD, OPENWRITE, OPENDUPLEX, CLOSE, SET_VOLUME, CLEAR_NOTIFY};
float m_Volume;

Mode GetMode() { return m_Mode; }

/* OSS Plugin Streaming - soon to be obsolete and for backward compatibility only*/
virtual void StreamOut(std::ostream &s) {}
virtual void StreamIn(std::istream &s) {}
private:
static int m_RefCount;
static int m_NoExecuted;
static Mode m_Mode;
bool m_NotifyOpenOut;
bool m_CheckedAlready;
bool m_Recmode;
};

#endif

+ 1
- 1
SpiralSound/Plugins/OutputPlugin/OutputPluginGUI.C View File

@@ -73,7 +73,7 @@ void OutputPluginGUI::Update()

void OutputPluginGUI::UpdateValues(SpiralPlugin *o)
{
Volume->value(OSSOutput::Get()->GetVolume());
Volume->value(OSSClient::Get()->GetVolume());
}

//// Callbacks ////


+ 41
- 4
SpiralSound/Plugins/SpiralPlugin.h View File

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

+ 101
- 17
SpiralSynthModular.C View File

@@ -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<int,DeviceWin*>::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 "<<i->second->m_PluginID<<endl;
#endif
if ((!m_ResetingAudioThread) && (!m_PauseAudio))
{
#ifdef DEBUG_PLUGINS
cerr<<"Updating channelhandler of plugin "<<i->second->m_PluginID<<endl;
#endif

// updates the data from the gui thread, if it's not blocking
i->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"<<endl;
#endif
#ifdef DEBUG_PLUGINS
cerr<<"Finished updating"<<endl;
#endif

// run any commands we've received from the GUI's
i->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<int,DeviceWin*>::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 "<<di->second->m_PluginID<<endl;
@@ -198,6 +215,17 @@ void SynthModular::Update()
else
{
di->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<AudioDriver*>(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();


+ 12
- 1
SpiralSynthModular.h View File

@@ -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();


Loading…
Cancel
Save