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