1 /*  SpiralSound
2  *  Copyleft (C) 2001 David Griffiths <dave@pawfal.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 
19 #include "../SpiralPlugin.h"
20 #include <FL/Fl_Pixmap.H>
21 #include <jack/jack.h>
22 
23 using namespace std;
24 
25 typedef jack_default_audio_sample_t sample_t;
26 
27 #ifndef JackPLUGIN
28 #define JackPLUGIN
29 
30 const int MAX_PORTS = 64;
31 const int MIN_PORTS = 2;
32 
33 class JackClient
34 {
35 public:
36  	JackClient();
37 	virtual ~JackClient();
38 
39 	void   AddInputPort(int NewPortNumber);
40 	void   AddOutputPort(int NewPortNumber);
41 
42 	void   RemoveInputPort(int PortNumber);
43 	void   RemoveOutputPort(int PortNumber);
44 
45 	bool   Attach();
46 	void   Detach();
IsAttached()47 	bool   IsAttached()                   { return m_Attached; }
SetAttached(bool Attached)48 	void   SetAttached(bool Attached)                   { m_Attached = Attached; }
SetCallback(void (* Run)(void *,bool m),void * Context)49 	void   SetCallback(void(*Run)(void*, bool m),void *Context) { RunCallback=Run; RunContext=Context; }
50 	void   GetPortNames(std::vector<std::string> &InputNames,std::vector<std::string> &OutputNames);
51 	void   ConnectInput(int n, const std::string &JackPort);
52 	void   ConnectOutput(int n, const std::string &JackPort);
53 	void   DisconnectInput(int n);
54 	void   DisconnectOutput(int n);
GetInputName(int ID)55 	std::string GetInputName(int ID)           { return m_InputPortMap[ID]->Name; }
GetOutputName(int ID)56 	std::string GetOutputName(int ID)          { return m_OutputPortMap[ID]->Name; }
57 	void   SetInputBuf(int ID, float* s);
58 	void   SetOutputBuf(int ID, float* s);
GetJackInstanceID()59 	int    GetJackInstanceID()           { return m_JackInstanceID; }
SetJackInstanceID(int JackInstanceID)60 	void   SetJackInstanceID(int JackInstanceID)          { m_JackInstanceID=JackInstanceID; }
GetBufferSize()61 	int    GetBufferSize()           { return m_BufferSize; }
SetBufferSize(jack_nframes_t BufferSize)62 	void   SetBufferSize(jack_nframes_t BufferSize)          { m_BufferSize=BufferSize; }
GetSampleRate()63 	int    GetSampleRate()           { return m_BufferSize; }
SetSampleRate(jack_nframes_t SampleRate)64 	void   SetSampleRate(jack_nframes_t SampleRate)          { m_SampleRate=SampleRate; }
GetJackInputCount()65 	int    GetJackInputCount()           { return m_JackInputCount; }
SetJackInputCount(int JackInputCount)66 	void   SetJackInputCount(int JackInputCount)          { m_JackInputCount=JackInputCount; }
GetJackOutputCount()67 	int    GetJackOutputCount()           { return m_JackOutputCount; }
SetJackOutputCount(int JackOutputCount)68 	void   SetJackOutputCount(int JackOutputCount)          { m_JackOutputCount=JackOutputCount; }
69 
70 	class JackPort
71 	{
72 		public:
JackPort()73 		JackPort() :
74 			Connected(false),Buf(NULL),Port(NULL) {}
75 
76 		int            PortNo;
77 		std::string    Name;
78 		bool           Connected;
79 		float*         Buf;
80 		jack_port_t*   Port;
81 		std::string    ConnectedTo;
82 	};
83 
84 	jack_client_t*     m_Client;
85 	std::map<int,JackPort*> m_InputPortMap;
86 	std::map<int,JackPort*> m_OutputPortMap;
87 
88 	//// Kludge for GUI ////
89 	bool CheckingPortChanges;
90 	std::vector<JackPort*> m_OutputPortsChanged;
91 	std::vector<JackPort*> m_InputPortsChanged;
92 
93 	//// inline Callbacks ////
94         inline void JackProcess_i(jack_nframes_t nframes);
95 	inline void SampleRateChange_i(jack_nframes_t nframes);
96 	inline void JackShutdown_i();
97 
98 	//// static Callbacks ////
JackProcess(jack_nframes_t nframes,void * jack_client)99         static int JackProcess(jack_nframes_t nframes, void *jack_client) { ((JackClient *)jack_client)->JackProcess_i(nframes); return 0;}
SampleRateChange(jack_nframes_t nframes,void * jack_client)100 	static int SampleRateChange(jack_nframes_t nframes, void *jack_client) { ((JackClient *)jack_client)->SampleRateChange_i(nframes); return 0;}
JackShutdown(void * jack_client)101 	static void JackShutdown(void *jack_client) { ((JackClient *)jack_client)->JackShutdown_i();}
102 private:
103 	jack_nframes_t  m_BufferSize;
104 	jack_nframes_t  m_SampleRate;
105 	bool            m_Attached;
106         int             m_JackInputCount;
107         int             m_JackOutputCount;
108 	int		m_JackInstanceID;
109 
110 	static int JackProcessInstanceID;
111 
112 	void(*RunCallback)(void*, bool m);
113 	void *RunContext;
114 };
115 
116 ///////////////////////////////////////////////////
117 
118 class JackPlugin : public SpiralPlugin
119 {
120 public:
121  	JackPlugin();
122 	virtual ~JackPlugin();
123 
124 	virtual PluginInfo& Initialise(const HostInfo *Host);
125 	virtual SpiralGUIType*  CreateGUI();
126 
127 	virtual void 		Execute();
128 	virtual void 		ExecuteCommands();
129 
130 	virtual bool         	Kill();
131 
132 	virtual void	    StreamOut(std::ostream &s);
133 	virtual void	    StreamIn(std::istream &s);
134 
GetJackClient()135 	JackClient *GetJackClient()           { return m_JackClient; }
136 
137         void SetNumberPorts (int nInputs, int nOutputs);
138 
139 	enum GUICommands{NONE,UPDATE_NAMES,SET_PORT_COUNT,CHECK_PORT_CHANGES};
140 	struct GUIArgs
141 	{
142 		int NumInputs;
143 		int NumOutputs;
144 		char Port[256];
145 	};
146 
Attach()147 	void Attach() { m_JackClient->Attach(); }
Detach()148 	void Detach() { m_JackClient->Detach(); }
149 private:
150 	const HostInfo* host;
151 
152 	GUIArgs m_GUIArgs;
153 
154 	int m_Version;
155 
156 	// slightly clumsy, but we have to share this data with the gui
157 	int  m_NumInputPortNames;
158 	char m_InputPortNames[MAX_PORTS][256];
159 	int  m_NumOutputPortNames;
160 	char m_OutputPortNames[MAX_PORTS][256];
161 
GetPortNames(std::vector<std::string> & InputNames,std::vector<std::string> & OutputNames)162 	void GetPortNames(std::vector<std::string> &InputNames,std::vector<std::string> &OutputNames) { m_JackClient->GetPortNames(InputNames,OutputNames); }
ConnectInput(int n,const std::string & JackPort)163 	void ConnectInput(int n, const std::string &JackPort)  { m_JackClient->ConnectInput(n,JackPort); }
ConnectOutput(int n,const std::string & JackPort)164 	void ConnectOutput(int n, const std::string &JackPort) { m_JackClient->ConnectOutput(n,JackPort); }
165 
166         void CreatePorts (int nInputs, int nOutputs, bool );
167 
168 	bool		m_UpdateNames;
169 	bool		m_Connected;
170 	JackClient 	*m_JackClient;
171 	int		m_JackInstanceID;
172 
173 	//clunky work-around for unique ID
174 	static int JackInstanceCount;
175 };
176 
177 #endif
178