allow changing of port count improve the gui to fit ports in smaller space auto update when ports are changed for eg from another appmaster
| @@ -25,76 +25,182 @@ | |||
| using namespace std; | |||
| static const HostInfo* host; | |||
| JackClient* JackClient::m_Singleton = NULL; | |||
| bool JackClient::m_Attached = false; | |||
| long unsigned int JackClient::m_BufferSize = 0; | |||
| long unsigned int JackClient::m_SampleRate = 0; | |||
| void (*JackClient::RunCallback)(void*, bool m)=NULL; | |||
| void *JackClient::RunContext = NULL; | |||
| jack_client_t *JackClient::m_Client = NULL; | |||
| map<int,JackClient::JackPort*> JackClient::m_InputPortMap; | |||
| map<int,JackClient::JackPort*> JackClient::m_OutputPortMap; | |||
| int JackPlugin::m_RefCount = 0; | |||
| int JackPlugin::m_NoExecuted = 0; | |||
| static int JackInstances = 0; | |||
| static int JackProcessInstance = -1; | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| inline void JackClient::JackProcess_i(jack_nframes_t nframes) | |||
| { | |||
| SetBufferSize(nframes); | |||
| for (int n=0; n<GetJackInputCount(); n++) | |||
| { | |||
| if (jack_port_connected(m_InputPortMap[n]->Port)) | |||
| { | |||
| sample_t *in = (sample_t *) jack_port_get_buffer(m_InputPortMap[n]->Port, nframes); | |||
| memcpy (m_InputPortMap[n]->Buf, in, sizeof (sample_t) * GetBufferSize()); | |||
| } | |||
| } | |||
| for (int n=0; n<GetJackOutputCount(); n++) | |||
| { | |||
| if (jack_port_connected(m_OutputPortMap[n]->Port)) | |||
| { | |||
| if (m_OutputPortMap[n]->Buf) | |||
| { | |||
| sample_t *out = (sample_t *) jack_port_get_buffer(m_OutputPortMap[n]->Port, nframes); | |||
| memcpy (out, m_OutputPortMap[n]->Buf, sizeof (sample_t) * GetBufferSize()); | |||
| } | |||
| else // no output availible, clear | |||
| { | |||
| sample_t *out = (sample_t *) jack_port_get_buffer(m_OutputPortMap[n]->Port, nframes); | |||
| memset (out, 0, sizeof (sample_t) * GetBufferSize()); | |||
| } | |||
| } | |||
| } | |||
| if (RunCallback&&RunContext) | |||
| { | |||
| if (JackProcessInstance==-1) | |||
| JackProcessInstance = m_JackInstanceID; | |||
| if (JackProcessInstance==m_JackInstanceID) | |||
| RunCallback(RunContext,true); | |||
| } | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| inline void JackClient::SampleRateChange_i(jack_nframes_t nframes) | |||
| { | |||
| SetSampleRate(nframes); | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| inline void JackClient::JackShutdown_i() | |||
| { | |||
| cerr<<"Shutdown"<<endl; | |||
| SetAttached(false); | |||
| if (JackProcessInstance==m_JackInstanceID) | |||
| JackProcessInstance = -1; | |||
| // tells ssm to go back to non callback mode | |||
| RunCallback(RunContext, false); | |||
| } | |||
| /////////////////////////////////////////////////////// | |||
| JackClient::JackClient() | |||
| { | |||
| m_JackInstanceID = 0; | |||
| m_Attached = false; | |||
| m_SampleRate = 0; | |||
| m_BufferSize = 0; | |||
| m_JackInputCount = 8; | |||
| m_JackOutputCount = 8; | |||
| m_Client=NULL; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| JackClient::~JackClient() | |||
| { | |||
| Detach(); | |||
| if (IsAttached()) Detach(); | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| void JackClient::AddInputPort(int NewPortNumber) | |||
| { | |||
| char Name[256]; | |||
| JackPort *NewPort; | |||
| if (!(m_Client)) return; | |||
| NewPort = new JackPort; | |||
| sprintf(Name,"In%d", NewPortNumber); | |||
| NewPort->PortNo = NewPortNumber; | |||
| NewPort->Name=Name; | |||
| NewPort->Buf=NULL; | |||
| NewPort->Port = jack_port_register (m_Client, Name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| m_InputPortMap[NewPortNumber]=NewPort; | |||
| } | |||
| void JackClient::AddOutputPort(int NewPortNumber) | |||
| { | |||
| char Name[256]; | |||
| JackPort *NewPort; | |||
| if (!(m_Client)) return; | |||
| NewPort = new JackPort; | |||
| sprintf(Name,"Out%d", NewPortNumber); | |||
| NewPort->PortNo = NewPortNumber; | |||
| NewPort->Name=Name; | |||
| NewPort->Buf=NULL; | |||
| NewPort->Port = jack_port_register (m_Client, Name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| m_OutputPortMap[NewPortNumber]=NewPort; | |||
| } | |||
| void JackClient::RemoveInputPort(int PortNumber) | |||
| { | |||
| char Name[256]; | |||
| JackPort *OldPort; | |||
| if (!(m_Client)) return; | |||
| OldPort = m_InputPortMap[PortNumber]; | |||
| m_InputPortMap[PortNumber] = NULL; | |||
| jack_port_unregister (m_Client, OldPort->Port); | |||
| delete OldPort; | |||
| } | |||
| void JackClient::RemoveOutputPort(int PortNumber) | |||
| { | |||
| char Name[256]; | |||
| JackPort *OldPort; | |||
| if (!(m_Client)) return; | |||
| OldPort = m_OutputPortMap[PortNumber]; | |||
| m_OutputPortMap[PortNumber] = NULL; | |||
| jack_port_unregister (m_Client, OldPort->Port); | |||
| delete OldPort; | |||
| } | |||
| bool JackClient::Attach() | |||
| { | |||
| char JackClientName[256]; | |||
| if (m_Attached) return true; | |||
| if (!(m_Client = jack_client_new("SSM"))) | |||
| sprintf(JackClientName,"SSM%d",GetJackInstanceID()); | |||
| if (!(m_Client = jack_client_new(JackClientName))) | |||
| { | |||
| cerr<<"jack server not running?"<<endl; | |||
| return false; | |||
| } | |||
| jack_set_process_callback(m_Client, JackClient::Process, 0); | |||
| jack_set_sample_rate_callback (m_Client, JackClient::OnSRateChange, 0); | |||
| jack_on_shutdown (m_Client, JackClient::OnJackShutdown, this); | |||
| m_InputPortMap.clear(); | |||
| m_OutputPortMap.clear(); | |||
| jack_set_process_callback(m_Client, JackProcess, this); | |||
| jack_set_sample_rate_callback (m_Client, SampleRateChange, this); | |||
| jack_on_shutdown (m_Client, JackShutdown, this); | |||
| // create the ports | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| { | |||
| char Name[256]; | |||
| sprintf(Name,"In%d",n); | |||
| JackPort *NewPort = new JackPort; | |||
| NewPort->Name=Name; | |||
| NewPort->Buf=NULL; | |||
| NewPort->Port = jack_port_register (m_Client, Name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| m_InputPortMap[n]=NewPort; | |||
| } | |||
| m_InputPortMap.clear(); | |||
| for (int n=0; n<GetJackInputCount(); n++) | |||
| AddInputPort(n); | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| char Name[256]; | |||
| sprintf(Name,"Out%d",n); | |||
| JackPort *NewPort = new JackPort; | |||
| NewPort->Name=Name; | |||
| NewPort->Buf=NULL; | |||
| NewPort->Port = jack_port_register (m_Client, Name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| m_OutputPortMap[n]=NewPort; | |||
| } | |||
| m_OutputPortMap.clear(); | |||
| for (int n=0; n<GetJackOutputCount(); n++) | |||
| AddOutputPort(n); | |||
| // tell the JACK server that we are ready to roll | |||
| if (jack_activate (m_Client)) | |||
| @@ -122,68 +228,11 @@ void JackClient::Detach() | |||
| m_Attached=false; | |||
| } | |||
| // tells ssm to go back to non callback mode | |||
| RunCallback(RunContext, false); | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| int JackClient::Process(jack_nframes_t nframes, void *o) | |||
| { | |||
| m_BufferSize=nframes; | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| { | |||
| if (jack_port_connected(m_InputPortMap[n]->Port)) | |||
| { | |||
| sample_t *in = (sample_t *) jack_port_get_buffer(m_InputPortMap[n]->Port, nframes); | |||
| memcpy (m_InputPortMap[n]->Buf, in, sizeof (sample_t) * m_BufferSize); | |||
| } | |||
| } | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| //if (m_OutputPortMap[n]->Connected) | |||
| { | |||
| if (m_OutputPortMap[n]->Buf) | |||
| { | |||
| sample_t *out = (sample_t *) jack_port_get_buffer(m_OutputPortMap[n]->Port, nframes); | |||
| memcpy (out, m_OutputPortMap[n]->Buf, sizeof (sample_t) * m_BufferSize); | |||
| } | |||
| else // no output availible, clear | |||
| { | |||
| sample_t *out = (sample_t *) jack_port_get_buffer(m_OutputPortMap[n]->Port, nframes); | |||
| memset (out, 0, sizeof (sample_t) * m_BufferSize); | |||
| } | |||
| } | |||
| } | |||
| if(RunCallback&&RunContext) | |||
| { | |||
| // do the work | |||
| RunCallback(RunContext, true); | |||
| } | |||
| return 0; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| int JackClient::OnSRateChange(long unsigned int n, void *o) | |||
| { | |||
| m_SampleRate=n; | |||
| return 0; | |||
| } | |||
| if (JackProcessInstance==m_JackInstanceID) | |||
| JackProcessInstance = -1; | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| void JackClient::OnJackShutdown(void *o) | |||
| { | |||
| cerr<<"Shutdown"<<endl; | |||
| m_Attached=false; | |||
| // tells ssm to go back to non callback mode | |||
| RunCallback(RunContext, false); | |||
| return; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -226,7 +275,7 @@ void JackClient::ConnectInput(int n, const string &JackPort) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::ConnectInput: connecting source ["<<JackPort<<"] to dest ["<<m_InputPortMap[n]->Name<<"]"<<endl; | |||
| // cerr<<"JackClient::ConnectInput: connecting source ["<<JackPort<<"] to dest ["<<m_InputPortMap[n]->Name<<"]"<<endl; | |||
| if (m_InputPortMap[n]->ConnectedTo!="") | |||
| { | |||
| @@ -249,7 +298,7 @@ void JackClient::ConnectInput(int n, const string &JackPort) | |||
| void JackClient::ConnectOutput(int n, const string &JackPort) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::ConnectOutput: connecting source ["<<m_OutputPortMap[n]->Name<<"] to dest ["<<JackPort<<"]"<<endl; | |||
| // cerr<<"JackClient::ConnectOutput: connecting source ["<<m_OutputPortMap[n]->Name<<"] to dest ["<<JackPort<<"]"<<endl; | |||
| if (m_OutputPortMap[n]->ConnectedTo!="") | |||
| { | |||
| @@ -270,7 +319,7 @@ void JackClient::ConnectOutput(int n, const string &JackPort) | |||
| void JackClient::DisconnectInput(int n) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl; | |||
| // cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl; | |||
| if (m_InputPortMap[n]->ConnectedTo!="") | |||
| { | |||
| @@ -287,7 +336,7 @@ void JackClient::DisconnectInput(int n) | |||
| void JackClient::DisconnectOutput(int n) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl; | |||
| // cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl; | |||
| if (m_OutputPortMap[n]->ConnectedTo!="") | |||
| { | |||
| @@ -312,7 +361,6 @@ void JackClient::SetOutputBuf(int ID, float* s) | |||
| if(m_OutputPortMap.find(ID)!=m_OutputPortMap.end()) m_OutputPortMap[ID]->Buf=s; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| extern "C" { | |||
| @@ -343,32 +391,44 @@ JackPlugin::JackPlugin() : | |||
| m_UpdateNames(false), | |||
| m_Connected(false) | |||
| { | |||
| m_RefCount++; | |||
| m_JackClient=new JackClient; | |||
| m_JackInstanceID = JackInstances ; | |||
| JackInstances++; | |||
| m_JackClient->SetJackInstanceID(m_JackInstanceID); | |||
| // we are an output | |||
| m_IsTerminal = true; | |||
| m_PluginInfo.Name="Jack"; | |||
| m_PluginInfo.Width=200; | |||
| m_PluginInfo.Height=325; | |||
| m_PluginInfo.NumInputs=NUM_OUTPUTS; | |||
| m_PluginInfo.NumOutputs=NUM_INPUTS; | |||
| m_PluginInfo.Width=225; | |||
| m_PluginInfo.Height=230; | |||
| m_PluginInfo.NumInputs=0; | |||
| m_PluginInfo.NumOutputs=0; | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| m_PluginInfo.PortTips.clear(); | |||
| m_PluginInfo.NumInputs = m_JackClient->GetJackOutputCount(); | |||
| for (int n=0; n<m_JackClient->GetJackInputCount(); n++) | |||
| { | |||
| char Temp[256]; | |||
| sprintf(Temp,"SSM Output %d",n); | |||
| sprintf(Temp,"SSM Input %d",n); | |||
| m_PluginInfo.PortTips.push_back(Temp); | |||
| } | |||
| } | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| m_PluginInfo.NumOutputs = m_JackClient->GetJackOutputCount(); | |||
| for (int n=0; n<m_JackClient->GetJackOutputCount(); n++) | |||
| { | |||
| char Temp[256]; | |||
| sprintf(Temp,"SSM Input %d",n); | |||
| sprintf(Temp,"SSM Output %d",n); | |||
| m_PluginInfo.PortTips.push_back(Temp); | |||
| } | |||
| m_AudioCH->Register("Num",&m_GUIArgs.Num); | |||
| } | |||
| m_AudioCH->Register("NumInputs",&m_GUIArgs.NumInputs); | |||
| m_AudioCH->Register("NumOutputs",&m_GUIArgs.NumOutputs); | |||
| m_AudioCH->RegisterData("Port",ChannelHandler::INPUT,&m_GUIArgs.Port,sizeof(m_GUIArgs.Port)); | |||
| m_AudioCH->Register("NumInputPortNames",&m_NumInputPortNames,ChannelHandler::OUTPUT); | |||
| m_AudioCH->Register("NumOutputPortNames",&m_NumOutputPortNames,ChannelHandler::OUTPUT); | |||
| @@ -380,12 +440,9 @@ m_Connected(false) | |||
| JackPlugin::~JackPlugin() | |||
| { | |||
| m_RefCount--; | |||
| if (m_RefCount==0) | |||
| { | |||
| JackClient::Get()->Detach(); | |||
| JackClient::PackUpAndGoHome(); | |||
| } | |||
| m_JackClient->Detach(); | |||
| delete m_JackClient; | |||
| m_JackClient=NULL; | |||
| } | |||
| PluginInfo &JackPlugin::Initialise(const HostInfo *Host) | |||
| @@ -393,7 +450,7 @@ PluginInfo &JackPlugin::Initialise(const HostInfo *Host) | |||
| PluginInfo& Info= SpiralPlugin::Initialise(Host); | |||
| host=Host; | |||
| if (m_RefCount==1) JackClient::Get()->SetCallback(cb_Update,m_Parent); | |||
| m_JackClient->SetCallback(cb_Update,m_Parent); | |||
| return Info; | |||
| } | |||
| @@ -405,23 +462,70 @@ 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() | |||
| { | |||
| } | |||
| void JackPlugin::ExecuteCommands() | |||
| { | |||
| // only do this once per set of plugins | |||
| m_NoExecuted++; | |||
| if (m_NoExecuted!=m_RefCount) return; | |||
| m_NoExecuted=0; | |||
| bool commandwaiting = m_AudioCH->IsCommandWaiting(); | |||
| int command = (commandwaiting)?(int)m_AudioCH->GetCommand():0; | |||
| if (commandwaiting) | |||
| { | |||
| switch (command) { | |||
| case SET_PORT_COUNT : | |||
| SetNumberPorts (m_GUIArgs.NumInputs, m_GUIArgs.NumOutputs); | |||
| } | |||
| } | |||
| // we want to process this whether we are connected to stuff or not | |||
| JackClient* pJack=JackClient::Get(); | |||
| JackClient* pJack=m_JackClient; | |||
| // connect the buffers up if we are plugged into something | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| for (int n=0; n<pJack->GetJackOutputCount(); n++) | |||
| { | |||
| if (InputExists(n)) | |||
| { | |||
| @@ -433,24 +537,27 @@ void JackPlugin::ExecuteCommands() | |||
| } | |||
| } | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| for (int n=0; n<pJack->GetJackInputCount(); n++) | |||
| { | |||
| pJack->SetInputBuf(n,(float*)GetOutputBuf(n)->GetBuffer()); | |||
| } | |||
| if (m_AudioCH->IsCommandWaiting()) | |||
| if (OutputExists(n)) | |||
| { | |||
| pJack->SetInputBuf(n,(float*)GetOutputBuf(n)->GetBuffer()); | |||
| } | |||
| else | |||
| { | |||
| pJack->SetInputBuf(n,NULL); | |||
| } | |||
| } | |||
| if (commandwaiting) | |||
| { | |||
| switch (m_AudioCH->GetCommand()) | |||
| switch (command) | |||
| { | |||
| //case ATTACH : Attach(); break; | |||
| //case DETACH : Detach(); break; | |||
| //case CONNECTINPUT : pJack->ConnectInput(m_GUIArgs.Num,m_GUIArgs.Port); break; | |||
| //case CONNECTOUTPUT : pJack->ConnectOutput(m_GUIArgs.Num,m_GUIArgs.Port); break; | |||
| case UPDATE_NAMES : | |||
| { | |||
| int c=0; | |||
| vector<string> InputNames,OutputNames; | |||
| std::vector<string> InputNames,OutputNames; | |||
| GetPortNames(InputNames,OutputNames); | |||
| for (vector<string>::iterator i=InputNames.begin(); | |||
| i!=InputNames.end(); ++i) | |||
| @@ -461,7 +568,7 @@ void JackPlugin::ExecuteCommands() | |||
| c=0; | |||
| for (vector<string>::iterator i=OutputNames.begin(); | |||
| for (std::vector<string>::iterator i=OutputNames.begin(); | |||
| i!=OutputNames.end(); ++i) | |||
| { | |||
| strcpy(m_OutputPortNames[c],i->c_str()); | |||
| @@ -472,8 +579,25 @@ void JackPlugin::ExecuteCommands() | |||
| m_NumOutputPortNames=OutputNames.size(); | |||
| } | |||
| break; | |||
| case CHECK_PORT_CHANGES : | |||
| if ((m_JackClient->IsAttached()) && (!m_JackClient->CheckingPortChanges)) { | |||
| m_JackClient->CheckingPortChanges = true; | |||
| for (int n=0; n<m_PluginInfo.NumInputs; n++) { | |||
| if (jack_port_connected(m_JackClient->m_OutputPortMap[n]->Port)!=m_JackClient->m_OutputPortMap[n]->Connected) | |||
| m_JackClient->m_OutputPortsChanged.push_back(m_JackClient->m_OutputPortMap[n]); | |||
| if (jack_port_connected(m_JackClient->m_InputPortMap[n]->Port)!=m_JackClient->m_InputPortMap[n]->Connected) | |||
| m_JackClient->m_InputPortsChanged.push_back(m_JackClient->m_InputPortMap[n]); | |||
| } | |||
| m_JackClient->CheckingPortChanges = false; | |||
| } | |||
| break; | |||
| default : break; | |||
| } | |||
| } | |||
| m_Connected=JackClient::Get()->IsAttached(); | |||
| m_Connected=m_JackClient->IsAttached(); | |||
| } | |||
| @@ -19,28 +19,34 @@ | |||
| #include "../SpiralPlugin.h" | |||
| #include "../../RiffWav.h" | |||
| #include <FL/Fl_Pixmap.H> | |||
| #include <map> | |||
| #include <jack/jack.h> | |||
| using namespace std; | |||
| typedef jack_default_audio_sample_t sample_t; | |||
| #ifndef JackPLUGIN | |||
| #define JackPLUGIN | |||
| const int NUM_INPUTS = 8; | |||
| const int NUM_OUTPUTS = 8; | |||
| const int MAX_INPUTPORTS = 256; | |||
| const int MAX_OUTPUTPORTS = 256; | |||
| const int MAX_PORTS = 64; | |||
| const int MIN_PORTS = 2; | |||
| class JackClient | |||
| { | |||
| public: | |||
| static JackClient *Get() { if(!m_Singleton) m_Singleton=new JackClient; return m_Singleton; } | |||
| static void PackUpAndGoHome() { if(m_Singleton) { delete m_Singleton; m_Singleton=NULL; } } | |||
| JackClient(); | |||
| virtual ~JackClient(); | |||
| void AddInputPort(int NewPortNumber); | |||
| void AddOutputPort(int NewPortNumber); | |||
| void RemoveInputPort(int PortNumber); | |||
| void RemoveOutputPort(int PortNumber); | |||
| bool Attach(); | |||
| void Detach(); | |||
| bool IsAttached() { return m_Attached; } | |||
| void SetAttached(bool Attached) { m_Attached = Attached; } | |||
| void SetCallback(void(*Run)(void*, bool m),void *Context) { RunCallback=Run; RunContext=Context; } | |||
| void GetPortNames(std::vector<std::string> &InputNames,std::vector<std::string> &OutputNames); | |||
| void ConnectInput(int n, const std::string &JackPort); | |||
| @@ -51,17 +57,16 @@ public: | |||
| std::string GetOutputName(int ID) { return m_OutputPortMap[ID]->Name; } | |||
| void SetInputBuf(int ID, float* s); | |||
| void SetOutputBuf(int ID, float* s); | |||
| protected: | |||
| JackClient(); | |||
| ~JackClient(); | |||
| static int Process(jack_nframes_t nframes, void *o); | |||
| static int OnBufSizeChange(long unsigned int n, void *o); | |||
| static int OnSRateChange(long unsigned int n, void *o); | |||
| static void OnJackShutdown(void *o); | |||
| private: | |||
| int GetJackInstanceID() { return m_JackInstanceID; } | |||
| void SetJackInstanceID(int JackInstanceID) { m_JackInstanceID=JackInstanceID; } | |||
| int GetBufferSize() { return m_BufferSize; } | |||
| void SetBufferSize(jack_nframes_t BufferSize) { m_BufferSize=BufferSize; } | |||
| int GetSampleRate() { return m_BufferSize; } | |||
| void SetSampleRate(jack_nframes_t SampleRate) { m_SampleRate=SampleRate; } | |||
| int GetJackInputCount() { return m_JackInputCount; } | |||
| void SetJackInputCount(int JackInputCount) { m_JackInputCount=JackInputCount; } | |||
| int GetJackOutputCount() { return m_JackOutputCount; } | |||
| void SetJackOutputCount(int JackOutputCount) { m_JackOutputCount=JackOutputCount; } | |||
| class JackPort | |||
| { | |||
| @@ -69,23 +74,42 @@ private: | |||
| JackPort::JackPort() : | |||
| Connected(false),Buf(NULL),Port(NULL) {} | |||
| std::string Name; | |||
| int PortNo; | |||
| std::string Name; | |||
| bool Connected; | |||
| float* Buf; | |||
| jack_port_t* Port; | |||
| std::string ConnectedTo; | |||
| }; | |||
| static JackClient* m_Singleton; | |||
| static jack_client_t* m_Client; | |||
| static std::map<int,JackPort*> m_InputPortMap; | |||
| static std::map<int,JackPort*> m_OutputPortMap; | |||
| static long unsigned int m_BufferSize; | |||
| static long unsigned int m_SampleRate; | |||
| static bool m_Attached; | |||
| jack_client_t* m_Client; | |||
| std::map<int,JackPort*> m_InputPortMap; | |||
| std::map<int,JackPort*> m_OutputPortMap; | |||
| //// Kludge for GUI //// | |||
| bool CheckingPortChanges; | |||
| std::vector<JackPort*> m_OutputPortsChanged; | |||
| std::vector<JackPort*> m_InputPortsChanged; | |||
| static void(*RunCallback)(void*, bool m); | |||
| static void *RunContext; | |||
| //// inline Callbacks //// | |||
| inline void JackProcess_i(jack_nframes_t nframes); | |||
| inline void SampleRateChange_i(jack_nframes_t nframes); | |||
| inline void JackShutdown_i(); | |||
| //// static Callbacks //// | |||
| static int JackProcess(jack_nframes_t nframes, void *jack_client) { ((JackClient *)jack_client)->JackProcess_i(nframes); return 0;} | |||
| static int SampleRateChange(jack_nframes_t nframes, void *jack_client) { ((JackClient *)jack_client)->SampleRateChange_i(nframes); return 0;} | |||
| static void JackShutdown(void *jack_client) { ((JackClient *)jack_client)->JackShutdown_i();} | |||
| private: | |||
| jack_nframes_t m_BufferSize; | |||
| jack_nframes_t m_SampleRate; | |||
| bool m_Attached; | |||
| int m_JackInputCount; | |||
| int m_JackOutputCount; | |||
| int m_JackInstanceID; | |||
| void(*RunCallback)(void*, bool m); | |||
| void *RunContext; | |||
| }; | |||
| /////////////////////////////////////////////////// | |||
| @@ -103,32 +127,42 @@ public: | |||
| virtual void StreamOut(std::ostream &s) {} | |||
| virtual void StreamIn(std::istream &s) {} | |||
| enum GUICommands{NONE,ATTACH,DETACH,CONNECTINPUT,CONNECTOUTPUT,UPDATE_NAMES}; | |||
| JackClient *GetJackClient() { return m_JackClient; } | |||
| void SetNumberPorts (int nInputs, int nOutputs); | |||
| enum GUICommands{NONE,UPDATE_NAMES,SET_PORT_COUNT,CHECK_PORT_CHANGES}; | |||
| struct GUIArgs | |||
| { | |||
| int NumInputs; | |||
| int NumOutputs; | |||
| int Num; | |||
| char Port[256]; | |||
| }; | |||
| void Attach() { m_JackClient->Attach(); } | |||
| void Detach() { m_JackClient->Detach(); } | |||
| private: | |||
| const HostInfo* host; | |||
| GUIArgs m_GUIArgs; | |||
| // slightly clumsy, but we have to share this data with the gui | |||
| int m_NumInputPortNames; | |||
| char m_InputPortNames[MAX_INPUTPORTS][256]; | |||
| char m_InputPortNames[MAX_PORTS][256]; | |||
| int m_NumOutputPortNames; | |||
| char m_OutputPortNames[MAX_OUTPUTPORTS][256]; | |||
| void Attach() { JackClient::Get()->Attach(); } | |||
| void Detach() { JackClient::Get()->Detach(); } | |||
| void GetPortNames(std::vector<std::string> &InputNames,std::vector<std::string> &OutputNames) { JackClient::Get()->GetPortNames(InputNames,OutputNames); } | |||
| void ConnectInput(int n, const std::string &JackPort) { JackClient::Get()->ConnectInput(n,JackPort); } | |||
| void ConnectOutput(int n, const std::string &JackPort) { JackClient::Get()->ConnectOutput(n,JackPort); } | |||
| static int m_RefCount; | |||
| static int m_NoExecuted; | |||
| bool m_UpdateNames; | |||
| bool m_Connected; | |||
| char m_OutputPortNames[MAX_PORTS][256]; | |||
| void GetPortNames(std::vector<std::string> &InputNames,std::vector<std::string> &OutputNames) { m_JackClient->GetPortNames(InputNames,OutputNames); } | |||
| void ConnectInput(int n, const std::string &JackPort) { m_JackClient->ConnectInput(n,JackPort); } | |||
| void ConnectOutput(int n, const std::string &JackPort) { m_JackClient->ConnectOutput(n,JackPort); } | |||
| void CreatePorts (int nInputs, int nOutputs, bool ); | |||
| bool m_UpdateNames; | |||
| bool m_Connected; | |||
| JackClient *m_JackClient; | |||
| int m_JackInstanceID; | |||
| }; | |||
| #endif | |||
| @@ -24,11 +24,9 @@ | |||
| using namespace std; | |||
| static int Numbers[255]; | |||
| //////////////////////////////////////////////////////////////////////// | |||
| int OptionsList(const vector<string> &List) | |||
| int OptionsList(const std::vector<string> &List) | |||
| { | |||
| Fl_Double_Window *Win = new Fl_Double_Window(300,300); | |||
| Fl_Button *Ok = new Fl_Button(10,275,40,20,"Ok"); | |||
| @@ -37,7 +35,7 @@ int OptionsList(const vector<string> &List) | |||
| Cancel->labelsize(10); | |||
| Fl_Hold_Browser* Browser = new Fl_Hold_Browser(5,5,290,265,""); | |||
| for (vector<string>::const_iterator i = List.begin(); | |||
| for (std::vector<string>::const_iterator i = List.begin(); | |||
| i!=List.end(); i++) | |||
| { | |||
| Browser->add(i->c_str()); | |||
| @@ -77,102 +75,357 @@ int OptionsList(const vector<string> &List) | |||
| JackPluginGUI::JackPluginGUI(int w, int h,JackPlugin *o,ChannelHandler *ch,const HostInfo *Info) : | |||
| SpiralPluginGUI(w,h,o,ch) | |||
| { | |||
| for (int n=0; n<255; n++) Numbers[n]=n; | |||
| m_GUIColour = (Fl_Color)Info->GUI_COLOUR; | |||
| m_JackPlugin =o; | |||
| m_JackClient = o->GetJackClient(); | |||
| m_Indicator = new Fl_LED_Button(85,15,30,30,""); | |||
| m_Indicator = new Fl_LED_Button(w/2 - 15,15,30,30,""); | |||
| m_Indicator->value(0); | |||
| m_Indicator->color(FL_RED); | |||
| add(m_Indicator); | |||
| m_Remove = new Fl_Button(5,15,25,25,"-"); | |||
| m_Remove->box (FL_PLASTIC_UP_BOX); | |||
| m_Remove->color (m_GUIColour); | |||
| m_Remove->type(0); | |||
| m_Remove->labelsize(2); | |||
| m_Remove->selection_color (m_GUIColour); | |||
| m_Remove->callback((Fl_Callback*)cb_Remove, this); | |||
| add(m_Remove); | |||
| m_Attach = new Fl_Button(5,40,190,20,"Attach"); | |||
| m_Add = new Fl_Button(30,15,25,25,"+"); | |||
| m_Add->box (FL_PLASTIC_UP_BOX); | |||
| m_Add->color (m_GUIColour); | |||
| m_Add->type(0); | |||
| m_Add->labelsize(2); | |||
| m_Add->selection_color (m_GUIColour); | |||
| m_Add->callback((Fl_Callback*)cb_Add, this); | |||
| add(m_Add); | |||
| m_Attach = new Fl_Button(5,45,w - 10,20,"Attach"); | |||
| m_Attach->box (FL_PLASTIC_UP_BOX); | |||
| m_Attach->color (m_GUIColour); | |||
| m_Attach->type(0); | |||
| m_Attach->labelsize(10); | |||
| m_Attach->callback((Fl_Callback*)cb_Attach); | |||
| m_Attach->selection_color (m_GUIColour); | |||
| m_Attach->callback((Fl_Callback*)cb_Attach, this); | |||
| add(m_Attach); | |||
| m_Detach = new Fl_Button(5,60,190,20,"Detach"); | |||
| m_Detach = new Fl_Button(5,65,w - 10,20,"Detach"); | |||
| m_Detach->box (FL_PLASTIC_UP_BOX); | |||
| m_Detach->color (m_GUIColour); | |||
| m_Detach->type(0); | |||
| m_Detach->labelsize(10); | |||
| m_Detach->callback((Fl_Callback*)cb_Detach); | |||
| m_Detach->selection_color (m_GUIColour); | |||
| m_Detach->callback((Fl_Callback*)cb_Detach, this); | |||
| add(m_Detach); | |||
| int yoff=80; | |||
| m_Scroll = new Fl_Scroll(5, 90, w - 10, h - 102); | |||
| m_Scroll->box(FL_PLASTIC_DOWN_BOX); | |||
| m_Scroll->type(Fl_Scroll::VERTICAL_ALWAYS); | |||
| m_Scroll->position(0, 0); | |||
| add(m_Scroll); | |||
| m_OutputPack = new Fl_Pack(15, 90, 85, h - 102); | |||
| m_Scroll->add(m_OutputPack); | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| sprintf(m_OutputName[n],"Output %d",n); | |||
| m_OutputLabel[n] = new Fl_Box(5,n*30+yoff,95,10,m_OutputName[n]); | |||
| m_OutputLabel[n]->labelsize(8); | |||
| //m_OutputLabel[n]->labeltype(FL_ENGRAVED_LABEL); | |||
| m_OutputButton[n] = new Fl_Button(5,n*30+yoff+10,95,20,"None"); | |||
| m_OutputButton[n]->type(1); | |||
| m_OutputButton[n]->labelsize(8); | |||
| m_OutputButton[n]->callback((Fl_Callback*)cb_OutputConnect,&Numbers[n]); | |||
| } | |||
| m_InputPack = new Fl_Pack(110, 90, 85, h - 102); | |||
| m_Scroll->add(m_InputPack); | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| for (int n=0; n<m_JackClient->GetJackInputCount(); n++) | |||
| { | |||
| sprintf(m_InputName[n],"Input %d",n); | |||
| m_InputLabel[n] = new Fl_Box(100,n*30+yoff,95,10,m_InputName[n]); | |||
| m_InputLabel[n]->labelsize(8); | |||
| //m_InputLabel[n]->labeltype(FL_ENGRAVED_LABEL); | |||
| m_InputButton[n] = new Fl_Button(100,n*30+yoff+10,95,20,"None"); | |||
| m_InputButton[n]->type(1); | |||
| m_InputButton[n]->labelsize(8); | |||
| m_InputButton[n]->callback((Fl_Callback*)cb_InputConnect,&Numbers[n]); | |||
| AddOutput(); | |||
| AddInput(); | |||
| } | |||
| end(); | |||
| } | |||
| void JackPluginGUI::UpdateValues(SpiralPlugin *o) | |||
| { | |||
| } | |||
| void JackPluginGUI::Update() | |||
| { | |||
| if (m_GUICH->GetBool("Connected")) { | |||
| m_JackClient->CheckingPortChanges = true; | |||
| for (unsigned int n=0; n<m_JackClient->m_OutputPortsChanged.size(); n++) { | |||
| m_JackClient->m_OutputPortsChanged[n]->Connected = jack_port_connected(m_JackClient->m_OutputPortsChanged[n]->Port); | |||
| if (jack_port_connected(m_JackClient->m_OutputPortsChanged[n]->Port)) { | |||
| if (m_JackClient->m_OutputPortsChanged[n]->ConnectedTo!="") { | |||
| m_OutputButton[n]->label(m_JackClient->m_OutputPortsChanged[n]->ConnectedTo.c_str()); | |||
| } | |||
| else | |||
| { | |||
| const char** connections = jack_port_get_all_connections(m_JackClient->m_Client,m_JackClient->m_OutputPortsChanged[n]->Port); | |||
| if (connections) { | |||
| m_OutputButton[m_JackClient->m_OutputPortsChanged[n]->PortNo]->label(connections[0]); | |||
| free(connections); | |||
| } | |||
| } | |||
| m_OutputButton[m_JackClient->m_OutputPortsChanged[n]->PortNo]->value(1); | |||
| } | |||
| else | |||
| { | |||
| m_OutputButton[m_JackClient->m_OutputPortsChanged[n]->PortNo]->value(0); | |||
| m_OutputButton[m_JackClient->m_OutputPortsChanged[n]->PortNo]->label("None"); | |||
| } | |||
| } | |||
| m_JackClient->m_OutputPortsChanged.clear(); | |||
| for (unsigned int n=0; n<m_JackClient->m_InputPortsChanged.size(); n++) { | |||
| m_JackClient->m_InputPortsChanged[n]->Connected = jack_port_connected(m_JackClient->m_InputPortsChanged[n]->Port); | |||
| if (m_JackClient->m_InputPortsChanged[n]->Connected) { | |||
| if (m_JackClient->m_InputPortsChanged[n]->ConnectedTo!="") { | |||
| m_InputButton[n]->label(m_JackClient->m_InputPortsChanged[n]->ConnectedTo.c_str()); | |||
| } | |||
| else | |||
| { | |||
| const char** connections = jack_port_get_all_connections(m_JackClient->m_Client,m_JackClient->m_InputPortsChanged[n]->Port); | |||
| if (connections) { | |||
| m_InputButton[m_JackClient->m_InputPortsChanged[n]->PortNo]->label(connections[0]); | |||
| free(connections); | |||
| } | |||
| } | |||
| m_InputButton[m_JackClient->m_InputPortsChanged[n]->PortNo]->value(1); | |||
| } | |||
| else | |||
| { | |||
| m_InputButton[m_JackClient->m_InputPortsChanged[n]->PortNo]->value(0); | |||
| m_InputButton[m_JackClient->m_InputPortsChanged[n]->PortNo]->label("None"); | |||
| } | |||
| } | |||
| m_JackClient->m_InputPortsChanged.clear(); | |||
| m_JackClient->CheckingPortChanges = false; | |||
| } | |||
| m_GUICH->SetCommand (JackPlugin::CHECK_PORT_CHANGES); | |||
| m_Indicator->value(m_GUICH->GetBool("Connected")); | |||
| redraw(); | |||
| } | |||
| //// Callbacks //// | |||
| inline void JackPluginGUI::cb_Attach_i(Fl_Button* o, void* v) | |||
| void JackPluginGUI::RemoveOutput() { | |||
| int n =(int) m_InputName.size() - 1; | |||
| if (m_OutputName[n]) | |||
| { | |||
| delete(m_OutputName[n]); | |||
| m_OutputName[n] = NULL; | |||
| m_OutputName.pop_back(); | |||
| } | |||
| if (m_OutputLabel[n]) | |||
| { | |||
| m_OutputPack->remove(m_OutputLabel[n]); | |||
| delete(m_OutputLabel[n]); | |||
| m_OutputLabel[n] = NULL; | |||
| m_OutputLabel.pop_back(); | |||
| m_OutputPack->redraw(); | |||
| m_Scroll->redraw(); | |||
| } | |||
| if (m_OutputButton[n]) | |||
| { | |||
| m_OutputPack->remove(m_OutputButton[n]); | |||
| delete(m_OutputButton[n]); | |||
| m_OutputButton[n] = NULL; | |||
| m_OutputButton.pop_back(); | |||
| m_OutputPack->redraw(); | |||
| m_Scroll->redraw(); | |||
| } | |||
| } | |||
| void JackPluginGUI::RemoveInput() { | |||
| int n = (int) m_InputName.size() - 1; | |||
| if (m_InputName[n]) | |||
| { | |||
| delete(m_InputName[n]); | |||
| m_InputName[n] = NULL; | |||
| m_InputName.pop_back(); | |||
| } | |||
| if (m_InputLabel[n]) | |||
| { | |||
| m_InputPack->remove(m_InputLabel[n]); | |||
| delete(m_InputLabel[n]); | |||
| m_InputLabel[n] = NULL; | |||
| m_InputLabel.pop_back(); | |||
| m_InputPack->redraw(); | |||
| m_Scroll->redraw(); | |||
| } | |||
| if (m_InputButton[n]) | |||
| { | |||
| m_InputPack->remove(m_InputButton[n]); | |||
| delete(m_InputButton[n]); | |||
| m_InputButton[n] = NULL; | |||
| m_InputButton.pop_back(); | |||
| m_InputPack->redraw(); | |||
| m_Scroll->redraw(); | |||
| } | |||
| } | |||
| void JackPluginGUI::AddOutput() { | |||
| int n = (int) m_OutputName.size(); | |||
| char *NewName = new char [256]; | |||
| sprintf(NewName,"Output %d",n); | |||
| m_OutputName.push_back(NewName); | |||
| m_OutputLabel.push_back(new Fl_Box(0,n*30,90,10,m_OutputName[n])); | |||
| m_OutputLabel[n]->labelsize(8); | |||
| m_OutputPack->add(m_OutputLabel[n]); | |||
| m_OutputButton.push_back(new Fl_Button(0,n*30+10,90,20,"None")); | |||
| m_OutputButton[n]->type(1); | |||
| m_OutputButton[n]->labelsize(8); | |||
| m_OutputButton[n]->callback((Fl_Callback*)cb_OutputConnect,this); | |||
| m_OutputPack->add(m_OutputButton[n]); | |||
| redraw(); | |||
| Fl::check(); | |||
| } | |||
| void JackPluginGUI::AddInput() { | |||
| int n = (int) m_InputName.size(); | |||
| char *NewName = new char [256]; | |||
| sprintf(NewName,"Input %d",n); | |||
| m_InputName.push_back(NewName); | |||
| m_InputLabel.push_back(new Fl_Box(95,n*30,90,10, m_InputName[n])); | |||
| m_InputLabel[n]->labelsize(8); | |||
| m_InputPack->add(m_InputLabel[n]); | |||
| m_InputButton.push_back(new Fl_Button(95,n*30+10,90,20,"None")); | |||
| m_InputButton[n]->type(1); | |||
| m_InputButton[n]->labelsize(8); | |||
| m_InputButton[n]->callback((Fl_Callback*)cb_InputConnect,this); | |||
| m_InputPack->add(m_InputButton[n]); | |||
| redraw(); | |||
| Fl::check(); | |||
| } | |||
| inline void JackPluginGUI::cb_Remove_i(Fl_Button* o) | |||
| { | |||
| //m_GUICH->SetCommand(JackPlugin::ATTACH); | |||
| JackClient::Get()->Attach(); | |||
| int n = (int) m_InputName.size(); | |||
| if (n > MIN_PORTS) | |||
| { | |||
| RemoveOutput() ; | |||
| RemoveInput() ; | |||
| m_GUICH->Set ("NumInputs", n-1); | |||
| m_GUICH->Set ("NumOutputs", n-1); | |||
| m_GUICH->SetCommand (JackPlugin::SET_PORT_COUNT); | |||
| m_GUICH->Wait (); | |||
| /* removing connections live must be called directly from here in the GUI thread */ | |||
| if (m_GUICH->GetBool("Connected")) { | |||
| m_JackClient->RemoveInputPort(n-1); | |||
| m_JackClient->RemoveOutputPort(n-1); | |||
| } | |||
| if (n > 19) { | |||
| resize (x(), y(), w(), h()-7); | |||
| m_Indicator->resize (x()+w()/2 - 15,y()+15,30,30); | |||
| m_Remove->resize (x()+5,y()+15,25,25); | |||
| m_Add->resize (x()+30,y()+15,25,25); | |||
| m_Attach->resize (x()+5,y()+45,w() - 10,20); | |||
| m_Detach->resize (x()+5,y()+65,w() - 10,20); | |||
| m_Scroll->resize (x()+5, y()+90, w() - 10, h() - 102); | |||
| m_OutputPack->resize (x()+15, y()+90, 85, h() - 102); | |||
| m_InputPack->resize (x()+110, y()+90, 85, h() - 102); | |||
| } | |||
| } | |||
| } | |||
| void JackPluginGUI::cb_Attach(Fl_Button* o, void* v) | |||
| { ((JackPluginGUI*)(o->parent()))->cb_Attach_i(o,v);} | |||
| inline void JackPluginGUI::cb_Detach_i(Fl_Button* o, void* v) | |||
| inline void JackPluginGUI::cb_Add_i(Fl_Button* o) | |||
| { | |||
| //m_GUICH->SetCommand(JackPlugin::DETACH); | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| int n = (int) m_OutputName.size(); | |||
| if (n <= MAX_PORTS) | |||
| { | |||
| /* Adding connections live must be called directly from here in the GUI thread */ | |||
| if (m_GUICH->GetBool("Connected")) { | |||
| m_JackClient->AddInputPort(n); | |||
| m_JackClient->AddOutputPort(n); | |||
| } | |||
| m_GUICH->Set ("NumInputs", n+1); | |||
| m_GUICH->Set ("NumOutputs", n+1); | |||
| m_GUICH->SetCommand (JackPlugin::SET_PORT_COUNT); | |||
| m_GUICH->Wait (); | |||
| AddOutput() ; | |||
| AddInput() ; | |||
| if (n > 20) { | |||
| resize (x(), y(), w(), h()+12); | |||
| m_Indicator->resize (x()+w()/2 - 15,y()+15,30,30); | |||
| m_Remove->resize (x()+5,y()+15,25,25); | |||
| m_Add->resize (x()+30,y()+15,25,25); | |||
| m_Attach->resize (x()+5,y()+45,w() - 10,20); | |||
| m_Detach->resize (x()+5,y()+65,w() - 10,20); | |||
| m_Scroll->resize (x()+5, y()+90, w() - 10, h() - 102); | |||
| m_OutputPack->resize (x()+15, y()+90, 85, h() - 102); | |||
| m_InputPack->resize (x()+110, y()+90, 85, h() - 102); | |||
| } | |||
| } | |||
| } | |||
| inline void JackPluginGUI::cb_Attach_i(Fl_Button* o) | |||
| { | |||
| m_JackPlugin->Attach(); | |||
| } | |||
| inline void JackPluginGUI::cb_Detach_i(Fl_Button* o) | |||
| { | |||
| for (int n=0; n<(int)m_OutputName.size(); n++) | |||
| { | |||
| m_OutputButton[n]->value(false); | |||
| m_OutputButton[n]->label("None"); | |||
| } | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| for (int n=0; n<(int)m_InputName.size(); n++) | |||
| { | |||
| m_InputButton[n]->value(false); | |||
| m_InputButton[n]->label("None"); | |||
| } | |||
| JackClient::Get()->Detach(); | |||
| m_JackPlugin->Detach(); | |||
| } | |||
| void JackPluginGUI::cb_Detach(Fl_Button* o, void* v) | |||
| { ((JackPluginGUI*)(o->parent()))->cb_Detach_i(o,v);} | |||
| inline void JackPluginGUI::cb_OutputConnect_i(Fl_Button* o, void* v) | |||
| inline void JackPluginGUI::cb_OutputConnect_i(Fl_Button* o) | |||
| { | |||
| if (o->value()) | |||
| int index=0; | |||
| std::vector<Fl_Button *>::iterator it = std::find( m_OutputButton.begin(), m_OutputButton.end(), o ); | |||
| if ( it != m_OutputButton.end() ) | |||
| index = std::distance( m_OutputButton.begin(), it ); | |||
| if ((o->value()) && m_GUICH->GetBool("Connected")) | |||
| { | |||
| m_GUICH->SetCommand(JackPlugin::UPDATE_NAMES); | |||
| m_GUICH->Wait(); | |||
| // bit of a hack for multithreaded safety | |||
| int ninputs=m_GUICH->GetInt("NumOutputPortNames"); | |||
| char inputs[MAX_INPUTPORTS][256]; | |||
| char inputs[MAX_PORTS][256]; | |||
| m_GUICH->GetData("InputPortNames",inputs); | |||
| vector<string> Inputs; | |||
| @@ -181,37 +434,43 @@ inline void JackPluginGUI::cb_OutputConnect_i(Fl_Button* o, void* v) | |||
| // connect this plugin's output to a jack input | |||
| if (choice>0) | |||
| { | |||
| //m_GUICH->Set("Num",(*(int*)v)); | |||
| //m_GUICH->SetData("Port",inputs[choice-1]); | |||
| //m_GUICH->SetCommand(JackPlugin::CONNECTOUTPUT); | |||
| JackClient::Get()->ConnectOutput((*(int*)v),inputs[choice-1]); | |||
| { | |||
| m_JackClient->ConnectOutput(index,inputs[choice-1]); | |||
| o->label(inputs[choice-1]); | |||
| o->redraw(); | |||
| } | |||
| else { | |||
| o->label("None"); | |||
| o->value(0); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| JackClient::Get()->DisconnectOutput((*(int*)v)); | |||
| m_JackClient->DisconnectOutput(index); | |||
| o->label("None"); | |||
| o->value(0); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| void JackPluginGUI::cb_OutputConnect(Fl_Button* o, void* v) | |||
| { ((JackPluginGUI*)(o->parent()))->cb_OutputConnect_i(o,v);} | |||
| inline void JackPluginGUI::cb_InputConnect_i(Fl_Button* o, void* v) | |||
| inline void JackPluginGUI::cb_InputConnect_i(Fl_Button* o) | |||
| { | |||
| if (o->value()) | |||
| int index=0; | |||
| std::vector<Fl_Button *>::iterator it = std::find( m_InputButton.begin(), m_InputButton.end(), o ); | |||
| if ( it != m_InputButton.end() ) | |||
| index = std::distance( m_InputButton.begin(), it ); | |||
| if ((o->value()) && (m_JackClient) && (m_JackClient->IsAttached())) | |||
| { | |||
| m_GUICH->SetCommand(JackPlugin::UPDATE_NAMES); | |||
| m_GUICH->Wait(); | |||
| // bit of a hack for multithreaded safety | |||
| int noutputs=m_GUICH->GetInt("NumOutputPortNames"); | |||
| char outputs[MAX_OUTPUTPORTS][256]; | |||
| char outputs[MAX_PORTS][256]; | |||
| m_GUICH->GetData("OutputPortNames",outputs); | |||
| vector<string> Outputs; | |||
| @@ -220,40 +479,36 @@ inline void JackPluginGUI::cb_InputConnect_i(Fl_Button* o, void* v) | |||
| // connect this plugin's input to a jack output | |||
| if (choice>0) | |||
| { | |||
| //m_GUICH->Set("Num",(*(int*)v)); | |||
| //m_GUICH->SetData("Port",outputs[choice-1]); | |||
| //m_GUICH->SetCommand(JackPlugin::CONNECTINPUT); | |||
| JackClient::Get()->ConnectInput((*(int*)v),outputs[choice-1]); | |||
| { | |||
| m_JackClient->ConnectInput(index,outputs[choice-1]); | |||
| o->label(outputs[choice-1]); | |||
| o->redraw(); | |||
| } | |||
| else { | |||
| o->label("None"); | |||
| o->value(0); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| JackClient::Get()->DisconnectInput((*(int*)v)); | |||
| m_JackClient->DisconnectInput(index); | |||
| o->label("None"); | |||
| o->value(0); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| void JackPluginGUI::cb_InputConnect(Fl_Button* o, void* v) | |||
| { ((JackPluginGUI*)(o->parent()))->cb_InputConnect_i(o,v);} | |||
| const string JackPluginGUI::GetHelpText(const string &loc){ | |||
| return string("") | |||
| + "JACK is the Jack Audio Connection Kit, and allows multiple Linux audio\n" | |||
| + "apps to be connected together and run simultaneously in a low latency.\n" | |||
| + "environment.\n\n" | |||
| + "This plugin allows you to connect up to 8 inputs and outputs to other\n" | |||
| + "JACK apps (providing a server is running)\n" | |||
| + "You can use the JackPlugin to connect the ports, or a external program\n" | |||
| + "such as the excellent qjackconnect app. Be aware however that if you\n" | |||
| + "connect from an external app, the port GUI does not update itself yet.\n" | |||
| + "Another problem yet to be fixed is that ssm will get confused if more\n" | |||
| + "than one JackPlugin is being used. It's best to use one central\n" | |||
| + "JackPlugin at this time.\n\n" | |||
| + "This plugin allows you to connect up to 64 inputs and outputs to other\n" | |||
| + "JACK apps (providing a server is running and your system can handle it)\n" | |||
| + "You can use the JackPlugin to connect the ports, or an external program\n" | |||
| + "such as the excellent qjackconnect app.\n\n" | |||
| + "When using JACK, make sure the buffer size and samplerate are set to\n" | |||
| + "match the JACK server, otherwise glitchy playback, and/or crashes may\n" | |||
| + "result"; | |||
| @@ -22,6 +22,8 @@ | |||
| #include <FL/Fl_Button.H> | |||
| #include <FL/Fl_Pixmap.H> | |||
| #include <FL/Fl_Box.H> | |||
| #include <FL/Fl_Scroll.H> | |||
| #include <FL/Fl_Pack.H> | |||
| #include "../Widgets/Fl_Knob.H" | |||
| #include "../Widgets/Fl_LED_Button.H" | |||
| #include "JackPlugin.h" | |||
| @@ -30,6 +32,8 @@ | |||
| #ifndef JACK_GUI_H | |||
| #define JACK_GUI_H | |||
| using namespace std; | |||
| class JackPluginGUI : public SpiralPluginGUI | |||
| { | |||
| public: | |||
| @@ -42,28 +46,52 @@ protected: | |||
| const std::string GetHelpText(const std::string &loc); | |||
| private: | |||
| JackClient *m_JackClient; | |||
| JackPlugin *m_JackPlugin; | |||
| Fl_Color m_GUIColour; | |||
| Fl_LED_Button *m_Indicator; | |||
| Fl_Button *m_Remove; | |||
| Fl_Button *m_Add; | |||
| Fl_Button *m_Attach; | |||
| Fl_Button *m_Detach; | |||
| char m_InputName[NUM_INPUTS][256]; | |||
| Fl_Box *m_InputLabel[NUM_INPUTS]; | |||
| Fl_Button *m_InputButton[NUM_INPUTS]; | |||
| Fl_Scroll *m_Scroll; | |||
| Fl_Pack *m_InputPack; | |||
| Fl_Pack *m_OutputPack; | |||
| std::vector<char*> m_InputName; | |||
| std::vector<Fl_Box*> m_InputLabel; | |||
| std::vector<Fl_Button*> m_InputButton; | |||
| char m_OutputName[NUM_INPUTS][256]; | |||
| Fl_Box *m_OutputLabel[NUM_OUTPUTS]; | |||
| Fl_Button *m_OutputButton[NUM_OUTPUTS]; | |||
| //// Callbacks //// | |||
| inline void cb_Attach_i(Fl_Button* o, void* v); | |||
| static void cb_Attach(Fl_Button* o, void* v); | |||
| inline void cb_Detach_i(Fl_Button* o, void* v); | |||
| static void cb_Detach(Fl_Button* o, void* v); | |||
| inline void cb_OutputConnect_i(Fl_Button* o, void* v); | |||
| static void cb_OutputConnect(Fl_Button* o, void* v); | |||
| inline void cb_InputConnect_i(Fl_Button* o, void* v); | |||
| static void cb_InputConnect(Fl_Button* o, void* v); | |||
| std::vector<char*> m_OutputName; | |||
| std::vector<Fl_Box*> m_OutputLabel; | |||
| std::vector<Fl_Button*> m_OutputButton; | |||
| void RemoveInput() ; | |||
| void RemoveOutput() ; | |||
| void AddInput() ; | |||
| void AddOutput() ; | |||
| //// inline Callbacks //// | |||
| inline void cb_Add_i(Fl_Button* o); | |||
| inline void cb_Remove_i(Fl_Button* o); | |||
| inline void cb_Attach_i(Fl_Button* o); | |||
| inline void cb_Detach_i(Fl_Button* o); | |||
| inline void cb_OutputConnect_i(Fl_Button* o); | |||
| inline void cb_InputConnect_i(Fl_Button* o); | |||
| //// Static Callbacks //// | |||
| static void cb_Add(Fl_Button* o, JackPluginGUI* v) {v->cb_Add_i(o);} | |||
| static void cb_Remove(Fl_Button* o, JackPluginGUI* v) {v->cb_Remove_i(o);} | |||
| static void cb_Attach(Fl_Button* o, JackPluginGUI* v) {v->cb_Attach_i(o);} | |||
| static void cb_Detach(Fl_Button* o, JackPluginGUI* v) {v->cb_Detach_i(o);} | |||
| static void cb_OutputConnect(Fl_Button* o, JackPluginGUI* v) {v->cb_OutputConnect_i(o);} | |||
| static void cb_InputConnect(Fl_Button* o, JackPluginGUI* v) {v->cb_InputConnect_i(o);} | |||
| }; | |||
| #endif | |||