| @@ -55,8 +55,6 @@ JackClient::~JackClient() | |||
| bool JackClient::Attach() | |||
| { | |||
| if (m_Attached) return true; | |||
| cerr<<"Attach"<<endl; | |||
| if (!(m_Client = jack_client_new("SSM"))) | |||
| { | |||
| @@ -64,15 +62,11 @@ bool JackClient::Attach() | |||
| return false; | |||
| } | |||
| cerr<<"Register"<<endl; | |||
| jack_set_process_callback(m_Client, JackClient::Process, 0); | |||
| jack_set_buffer_size_callback(m_Client, JackClient::OnBufSizeChange, 0); | |||
| jack_set_sample_rate_callback (m_Client, JackClient::OnSRateChange, 0); | |||
| jack_on_shutdown (m_Client, JackClient::OnJackShutdown, this); | |||
| printf ("engine sample rate: %lu\n", jack_get_sample_rate(m_Client)); | |||
| m_InputPortMap.clear(); | |||
| m_OutputPortMap.clear(); | |||
| @@ -80,7 +74,7 @@ bool JackClient::Attach() | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| { | |||
| char Name[256]; | |||
| sprintf(Name,"Out %d",n); | |||
| sprintf(Name,"In %d",n); | |||
| JackPort *NewPort = new JackPort; | |||
| NewPort->Name=Name; | |||
| @@ -92,7 +86,7 @@ bool JackClient::Attach() | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| char Name[256]; | |||
| sprintf(Name,"In %d",n); | |||
| sprintf(Name,"Out %d",n); | |||
| JackPort *NewPort = new JackPort; | |||
| NewPort->Name=Name; | |||
| @@ -111,10 +105,7 @@ bool JackClient::Attach() | |||
| m_Attached=true; | |||
| cerr<<"connected to jack..."<<endl; | |||
| ConnectOutput(0,"alsa_pcm:out_1"); | |||
| ConnectOutput(1,"alsa_pcm:out_2"); | |||
| return true; | |||
| } | |||
| @@ -140,15 +131,11 @@ int JackClient::Process(jack_nframes_t nframes, void *o) | |||
| { | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| { | |||
| if (m_InputPortMap[n]->Connected) | |||
| if (jack_port_connected(m_InputPortMap[n]->Port)) | |||
| { | |||
| if (m_InputPortMap[n]->Buf) | |||
| { | |||
| 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); | |||
| //cerr<<"got "<<m_InputPortMap[n]->Buf[0]<<" from "<<m_InputPortMap[n]->Name<<endl; | |||
| } | |||
| } | |||
| 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++) | |||
| @@ -156,19 +143,18 @@ int JackClient::Process(jack_nframes_t nframes, void *o) | |||
| //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 | |||
| @@ -243,6 +229,8 @@ void JackClient::GetPortNames(vector<string> &InputNames, vector<string> &Output | |||
| // Input means input of SSM, so this connects jack sources to the plugin outputs | |||
| void JackClient::ConnectInput(int n, const string &JackPort) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::ConnectInput: connecting source ["<<JackPort<<"] to dest ["<<m_InputPortMap[n]->Name<<"]"<<endl; | |||
| if (m_InputPortMap[n]->ConnectedTo!="") | |||
| @@ -265,6 +253,7 @@ void JackClient::ConnectInput(int n, const string &JackPort) | |||
| // Output means output of SSM, so this connects plugin inputs to a jack destination | |||
| void JackClient::ConnectOutput(int n, const string &JackPort) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::ConnectOutput: connecting source ["<<m_OutputPortMap[n]->Name<<"] to dest ["<<JackPort<<"]"<<endl; | |||
| if (m_OutputPortMap[n]->ConnectedTo!="") | |||
| @@ -275,14 +264,45 @@ void JackClient::ConnectOutput(int n, const string &JackPort) | |||
| } | |||
| m_OutputPortMap[n]->ConnectedTo = JackPort; | |||
| if (jack_connect (m_Client, jack_port_name(m_OutputPortMap[n]->Port), JackPort.c_str())) | |||
| cerr<<"JackClient::ConnectOutput: cannot connect output port [" | |||
| <<m_OutputPortMap[n]->Name<<"] to ["<<JackPort<<"]"<<endl; | |||
| m_OutputPortMap[n]->Connected=true; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| // Input means input of SSM, so this connects jack sources to the plugin outputs | |||
| void JackClient::DisconnectInput(int n) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl; | |||
| if (m_InputPortMap[n]->ConnectedTo!="") | |||
| { | |||
| if (jack_disconnect (m_Client, m_InputPortMap[n]->ConnectedTo.c_str(), jack_port_name(m_InputPortMap[n]->Port))) | |||
| cerr<<"JackClient::ConnectInput: cannot disconnect input port [" | |||
| <<m_InputPortMap[n]->ConnectedTo<<"] from ["<<m_InputPortMap[n]->Name<<"]"<<endl; | |||
| } | |||
| m_InputPortMap[n]->Connected=false; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| // Output means output of SSM, so this connects plugin inputs to a jack destination | |||
| void JackClient::DisconnectOutput(int n) | |||
| { | |||
| if (!IsAttached()) return; | |||
| cerr<<"JackClient::DisconnectInput: Disconnecting input "<<n<<endl; | |||
| if (m_OutputPortMap[n]->ConnectedTo!="") | |||
| { | |||
| if (jack_disconnect (m_Client, jack_port_name(m_OutputPortMap[n]->Port), m_OutputPortMap[n]->ConnectedTo.c_str())) | |||
| cerr<<"JackClient::ConnectOutput: cannot disconnect output port [" | |||
| <<m_OutputPortMap[n]->ConnectedTo<<"] from ["<<m_OutputPortMap[n]->Name<<"]"<<endl; | |||
| } | |||
| m_OutputPortMap[n]->Connected=false; | |||
| } | |||
| ///////////////////////////////////////////////////////////////////////////////////////////// | |||
| void JackClient::SetInputBuf(int ID, float* s) | |||
| @@ -327,7 +347,7 @@ m_Connected(false) | |||
| m_PluginInfo.Name="Jack"; | |||
| m_PluginInfo.Width=200; | |||
| m_PluginInfo.Height=415; | |||
| m_PluginInfo.Height=325; | |||
| m_PluginInfo.NumInputs=NUM_OUTPUTS; | |||
| m_PluginInfo.NumOutputs=NUM_INPUTS; | |||
| @@ -390,28 +410,21 @@ void JackPlugin::Execute() | |||
| void JackPlugin::ExecuteCommands() | |||
| { | |||
| // we want to process this whether we are connected to stuff or not | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| GetOutputBuf(n)->Zero(); | |||
| } | |||
| JackClient* pJack=JackClient::Get(); | |||
| // connect the buffers up if we are plugged into something | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| if (InputExists(n)) | |||
| { | |||
| JackClient::Get()->SetOutputBuf(n,(float*)GetInput(n)->GetBuffer()); | |||
| pJack->SetOutputBuf(n,(float*)GetInput(n)->GetBuffer()); | |||
| } | |||
| else | |||
| { | |||
| JackClient::Get()->SetOutputBuf(n,NULL); | |||
| pJack->SetOutputBuf(n,NULL); | |||
| } | |||
| } | |||
| // don't really want to do this all the time, as it only needs to | |||
| // be done once per attach. | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| { | |||
| pJack->SetInputBuf(n,(float*)GetOutputBuf(n)->GetBuffer()); | |||
| @@ -421,10 +434,10 @@ void JackPlugin::ExecuteCommands() | |||
| { | |||
| switch (m_AudioCH->GetCommand()) | |||
| { | |||
| case ATTACH : Attach(); break; | |||
| /*case ATTACH : Attach(); break; | |||
| case DETACH : Detach(); break; | |||
| case CONNECTINPUT : ConnectInput(m_GUIArgs.Num,m_GUIArgs.Port); break; | |||
| case CONNECTOUTPUT : ConnectOutput(m_GUIArgs.Num,m_GUIArgs.Port); 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; | |||
| @@ -451,6 +464,7 @@ void JackPlugin::ExecuteCommands() | |||
| m_NumOutputPortNames=OutputNames.size(); | |||
| } | |||
| break; | |||
| default : break; | |||
| } | |||
| } | |||
| m_Connected=JackClient::Get()->IsAttached(); | |||
| @@ -46,6 +46,8 @@ public: | |||
| void GetPortNames(vector<string> &InputNames,vector<string> &OutputNames); | |||
| void ConnectInput(int n, const string &JackPort); | |||
| void ConnectOutput(int n, const string &JackPort); | |||
| void DisconnectInput(int n); | |||
| void DisconnectOutput(int n); | |||
| string GetInputName(int ID) { return m_InputPortMap[ID]->Name; } | |||
| string GetOutputName(int ID) { return m_OutputPortMap[ID]->Name; } | |||
| void SetInputBuf(int ID, float* s); | |||
| @@ -16,6 +16,7 @@ | |||
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "JackPlugin.h" | |||
| #include "JackPluginGUI.h" | |||
| #include <FL/fl_draw.h> | |||
| #include <FL/fl_file_chooser.H> | |||
| @@ -80,41 +81,43 @@ SpiralPluginGUI(w,h,o,ch) | |||
| { | |||
| for (int n=0; n<255; n++) Numbers[n]=n; | |||
| m_Indicator = new Fl_LED_Button(85,17,30,30,""); | |||
| m_Indicator = new Fl_LED_Button(85,15,30,30,""); | |||
| m_Indicator->value(0); | |||
| m_Indicator->color(FL_RED); | |||
| m_Attach = new Fl_Button(5,50,190,20,"Attach"); | |||
| m_Attach = new Fl_Button(5,40,190,20,"Attach"); | |||
| m_Attach->type(0); | |||
| m_Attach->labelsize(10); | |||
| m_Attach->callback((Fl_Callback*)cb_Attach); | |||
| m_Detach = new Fl_Button(5,70,190,20,"Detach"); | |||
| m_Detach = new Fl_Button(5,60,190,20,"Detach"); | |||
| m_Detach->type(0); | |||
| m_Detach->labelsize(10); | |||
| m_Detach->callback((Fl_Callback*)cb_Detach); | |||
| int yoff=90; | |||
| int yoff=80; | |||
| for (int n=0; n<NUM_OUTPUTS; n++) | |||
| { | |||
| sprintf(m_OutputName[n],"Output %d",n); | |||
| m_OutputLabel[n] = new Fl_Box(5,n*40+yoff,95,20,m_OutputName[n]); | |||
| m_OutputLabel[n]->labelsize(10); | |||
| m_OutputLabel[n]->labeltype(FL_ENGRAVED_LABEL); | |||
| m_OutputButton[n] = new Fl_Button(5,n*40+yoff+20,95,20,"None yet"); | |||
| m_OutputButton[n]->labelsize(10); | |||
| 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]); | |||
| } | |||
| for (int n=0; n<NUM_INPUTS; n++) | |||
| { | |||
| sprintf(m_InputName[n],"Input %d",n); | |||
| m_InputLabel[n] = new Fl_Box(100,n*40+yoff,95,20,m_InputName[n]); | |||
| m_InputLabel[n]->labelsize(10); | |||
| m_InputLabel[n]->labeltype(FL_ENGRAVED_LABEL); | |||
| m_InputButton[n] = new Fl_Button(100,n*40+yoff+20,95,20,"None yet"); | |||
| m_InputButton[n]->labelsize(10); | |||
| 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]); | |||
| } | |||
| @@ -126,48 +129,62 @@ void JackPluginGUI::UpdateValues(SpiralPlugin *o) | |||
| } | |||
| void JackPluginGUI::draw() | |||
| { | |||
| SpiralPluginGUI::draw(); | |||
| void JackPluginGUI::Update() | |||
| { | |||
| m_Indicator->value(m_GUICH->GetBool("Connected")); | |||
| }; | |||
| redraw(); | |||
| } | |||
| //// Callbacks //// | |||
| inline void JackPluginGUI::cb_Attach_i(Fl_Button* o, void* v) | |||
| { | |||
| m_GUICH->SetCommand(JackPlugin::ATTACH); | |||
| //m_GUICH->SetCommand(JackPlugin::ATTACH); | |||
| JackClient::Get()->Attach(); | |||
| } | |||
| 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) | |||
| { | |||
| m_GUICH->SetCommand(JackPlugin::DETACH); | |||
| //m_GUICH->SetCommand(JackPlugin::DETACH); | |||
| JackClient::Get()->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) | |||
| { | |||
| 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]; | |||
| m_GUICH->GetData("InputPortNames",inputs); | |||
| if (o->value()) | |||
| { | |||
| m_GUICH->SetCommand(JackPlugin::UPDATE_NAMES); | |||
| m_GUICH->Wait(); | |||
| vector<string> Inputs; | |||
| for (int n=0; n<ninputs; n++) Inputs.push_back(inputs[n]); | |||
| int choice=OptionsList(Inputs); | |||
| // bit of a hack for multithreaded safety | |||
| int ninputs=m_GUICH->GetInt("NumOutputPortNames"); | |||
| char inputs[MAX_INPUTPORTS][256]; | |||
| m_GUICH->GetData("InputPortNames",inputs); | |||
| // connect this plugin's output to a jack input | |||
| if (choice>0) | |||
| vector<string> Inputs; | |||
| for (int n=0; n<ninputs; n++) Inputs.push_back(inputs[n]); | |||
| int choice=OptionsList(Inputs); | |||
| // 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]); | |||
| o->label(inputs[choice-1]); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| m_GUICH->Set("Num",(*(int*)v)); | |||
| m_GUICH->SetData("Port",inputs[choice-1]); | |||
| m_GUICH->SetCommand(JackPlugin::CONNECTOUTPUT); | |||
| o->label(inputs[choice-1]); | |||
| JackClient::Get()->DisconnectOutput((*(int*)v)); | |||
| o->label("None"); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| @@ -176,25 +193,37 @@ void JackPluginGUI::cb_OutputConnect(Fl_Button* o, void* v) | |||
| inline void JackPluginGUI::cb_InputConnect_i(Fl_Button* o, void* v) | |||
| { | |||
| 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]; | |||
| m_GUICH->GetData("OutputPortNames",outputs); | |||
| if (o->value()) | |||
| { | |||
| m_GUICH->SetCommand(JackPlugin::UPDATE_NAMES); | |||
| m_GUICH->Wait(); | |||
| vector<string> Outputs; | |||
| for (int n=0; n<noutputs; n++) Outputs.push_back(outputs[n]); | |||
| int choice=OptionsList(Outputs); | |||
| // connect this plugin's input to a jack output | |||
| if (choice>0) | |||
| // bit of a hack for multithreaded safety | |||
| int noutputs=m_GUICH->GetInt("NumOutputPortNames"); | |||
| char outputs[MAX_OUTPUTPORTS][256]; | |||
| m_GUICH->GetData("OutputPortNames",outputs); | |||
| vector<string> Outputs; | |||
| for (int n=0; n<noutputs; n++) Outputs.push_back(outputs[n]); | |||
| int choice=OptionsList(Outputs); | |||
| // 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]); | |||
| o->label(outputs[choice-1]); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| m_GUICH->Set("Num",(*(int*)v)); | |||
| m_GUICH->SetData("Port",outputs[choice-1]); | |||
| m_GUICH->SetCommand(JackPlugin::CONNECTINPUT); | |||
| o->label(outputs[choice-1]); | |||
| JackClient::Get()->DisconnectInput((*(int*)v)); | |||
| o->label("None"); | |||
| o->redraw(); | |||
| } | |||
| } | |||
| @@ -38,7 +38,7 @@ public: | |||
| JackPluginGUI(int w, int h, JackPlugin *o,ChannelHandler *ch,const HostInfo *Info); | |||
| virtual void UpdateValues(SpiralPlugin *o); | |||
| virtual void draw(); | |||
| virtual void Update(); | |||
| private: | |||