Fix crash with clap plugins without MIDI input
[carla.git] / source / libjack / libjack.hpp
blob5f1f5d49dbf63546e69042e3947881528e61d7f0
1 /*
2 * Carla JACK API for external applications
3 * Copyright (C) 2016-2022 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_LIBJACK_HPP_INCLUDED
19 #define CARLA_LIBJACK_HPP_INCLUDED
21 // need to include this first
22 #include "CarlaDefines.h"
24 // now define as bridge
25 #define BUILD_BRIDGE 1
27 // now include a bunch of stuff
28 #include "CarlaBackendUtils.hpp"
29 #include "CarlaBridgeUtils.hpp"
30 #include "CarlaMIDI.h"
31 #include "CarlaMutex.hpp"
32 #include "LinkedList.hpp"
34 #if 0
35 #include <jack/jack.h>
36 #include <jack/midiport.h>
37 #include <jack/transport.h>
38 #include <jack/session.h>
39 #include <jack/metadata.h>
40 #endif
42 #include <cerrno>
43 #include <map>
44 #include <string>
46 #ifdef __SSE2_MATH__
47 # include <xmmintrin.h>
48 #endif
50 // must be last include
51 #include "api.hpp"
53 // small check to not hurt myself
54 #ifdef JACKBRIDGE_DIRECT
55 # error "Cannot create custom jack server while linking to libjack directly"
56 #endif
58 CARLA_BACKEND_START_NAMESPACE
60 // --------------------------------------------------------------------------------------------------------------------
62 class CarlaJackAppClient;
63 struct JackClientState;
64 struct JackServerState;
66 struct JackMidiPortBufferBase {
67 static const uint8_t kMaxEventSize = 128;
68 static const size_t kMaxEventCount = 512;
69 static const size_t kBufferPoolSize = kMaxEventCount*8;
71 bool isInput;
72 bool isDummy;
75 struct JackMidiPortBufferOnStack : JackMidiPortBufferBase {
76 size_t bufferPoolPos;
77 uint16_t count;
79 jack_midi_event_t events[kMaxEventCount];
80 jack_midi_data_t bufferPool[kBufferPoolSize];
82 JackMidiPortBufferOnStack()
83 : bufferPoolPos(0),
84 count(0),
85 events(),
86 bufferPool()
88 isInput = true;
89 isDummy = false;
92 CARLA_DECLARE_NON_COPYABLE(JackMidiPortBufferOnStack)
95 struct JackMidiPortBufferDummy : JackMidiPortBufferBase {
96 JackMidiPortBufferDummy(const bool input)
98 isInput = input;
99 isDummy = true;
102 CARLA_DECLARE_NON_COPYABLE(JackMidiPortBufferDummy)
105 struct JackPortState {
106 enum Offsets {
107 kPortIdOffsetAudioIn = 100,
108 kPortIdOffsetMidiIn = 300,
109 kPortIdOffsetAudioOut = 500,
110 kPortIdOffsetMidiOut = 700,
111 kPortIdOffsetUser = 1000,
114 char* name;
115 char* fullname;
116 void* buffer;
117 uint index;
118 int flags;
119 uint gid;
120 jack_uuid_t uuid;
121 bool isMidi : 1;
122 bool isSystem : 1;
123 bool isConnected : 1;
124 bool unused : 1;
126 JackPortState(const char* const fullPortName,
127 const char* const portName,
128 const uint i, const int f, const uint id,
129 const bool midi, const bool con)
130 : name(portName != nullptr ? strdup(portName) : nullptr),
131 fullname(fullPortName != nullptr ? strdup(fullPortName) : nullptr),
132 buffer(nullptr),
133 index(i),
134 flags(f),
135 gid(id),
136 uuid(jack_port_uuid_generate(id)),
137 isMidi(midi),
138 isSystem(true),
139 isConnected(con),
140 unused(false) {}
142 JackPortState(const char* const clientName,
143 const char* const portName,
144 const uint i, const int f, const uint id,
145 const bool midi, const bool sys, const bool con)
146 : name(portName != nullptr ? strdup(portName) : nullptr),
147 fullname(nullptr),
148 buffer(nullptr),
149 index(i),
150 flags(f),
151 gid(id),
152 uuid(jack_port_uuid_generate(id)),
153 isMidi(midi),
154 isSystem(sys),
155 isConnected(con),
156 unused(false)
158 if (clientName != nullptr && portName != nullptr)
160 char strBuf[STR_MAX+1];
161 snprintf(strBuf, STR_MAX, "%s:%s", clientName, portName);
162 strBuf[STR_MAX] = '\0';
164 fullname = strdup(strBuf);
168 ~JackPortState()
170 std::free(name);
171 name = nullptr;
173 std::free(fullname);
174 fullname = nullptr;
177 CARLA_DECLARE_NON_COPYABLE(JackPortState)
180 struct JackClientState {
181 const JackServerState& server;
182 CarlaMutex mutex;
184 bool activated;
185 bool deactivated; // activated once, then deactivated
187 char* name;
188 jack_uuid_t uuid;
190 LinkedList<JackPortState*> audioIns;
191 LinkedList<JackPortState*> audioOuts;
192 LinkedList<JackPortState*> midiIns;
193 LinkedList<JackPortState*> midiOuts;
195 std::map<uint, JackPortState*> portIdMapping;
196 std::map<std::string, JackPortState*> portNameMapping;
198 JackShutdownCallback shutdownCb;
199 void* shutdownCbPtr;
201 JackInfoShutdownCallback infoShutdownCb;
202 void* infoShutdownCbPtr;
204 JackProcessCallback processCb;
205 void* processCbPtr;
207 JackFreewheelCallback freewheelCb;
208 void* freewheelCbPtr;
210 JackBufferSizeCallback bufferSizeCb;
211 void* bufferSizeCbPtr;
213 JackSampleRateCallback sampleRateCb;
214 void* sampleRateCbPtr;
216 JackSyncCallback syncCb;
217 void* syncCbPtr;
219 JackThreadInitCallback threadInitCb;
220 void* threadInitCbPtr;
222 JackClientState(const JackServerState& s, const char* const n)
223 : server(s),
224 mutex(),
225 activated(false),
226 deactivated(false),
227 name(strdup(n)),
228 uuid(jack_client_uuid_generate()),
229 audioIns(),
230 audioOuts(),
231 midiIns(),
232 midiOuts(),
233 portIdMapping(),
234 portNameMapping(),
235 shutdownCb(nullptr),
236 shutdownCbPtr(nullptr),
237 infoShutdownCb(nullptr),
238 infoShutdownCbPtr(nullptr),
239 processCb(nullptr),
240 processCbPtr(nullptr),
241 freewheelCb(nullptr),
242 freewheelCbPtr(nullptr),
243 bufferSizeCb(nullptr),
244 bufferSizeCbPtr(nullptr),
245 sampleRateCb(nullptr),
246 sampleRateCbPtr(nullptr),
247 syncCb(nullptr),
248 syncCbPtr(nullptr),
249 threadInitCb(nullptr),
250 threadInitCbPtr(nullptr) {}
252 ~JackClientState()
254 const CarlaMutexLocker cms(mutex);
256 for (LinkedList<JackPortState*>::Itenerator it = audioIns.begin2(); it.valid(); it.next())
258 if (JackPortState* const jport = it.getValue(nullptr))
259 delete jport;
262 for (LinkedList<JackPortState*>::Itenerator it = audioOuts.begin2(); it.valid(); it.next())
264 if (JackPortState* const jport = it.getValue(nullptr))
265 delete jport;
268 for (LinkedList<JackPortState*>::Itenerator it = midiIns.begin2(); it.valid(); it.next())
270 if (JackPortState* const jport = it.getValue(nullptr))
271 delete jport;
274 for (LinkedList<JackPortState*>::Itenerator it = midiOuts.begin2(); it.valid(); it.next())
276 if (JackPortState* const jport = it.getValue(nullptr))
277 delete jport;
280 std::free(name);
281 name = nullptr;
283 audioIns.clear();
284 audioOuts.clear();
285 midiIns.clear();
286 midiOuts.clear();
288 portIdMapping.clear();
289 portNameMapping.clear();
292 CARLA_DECLARE_NON_COPYABLE(JackClientState)
295 struct JackServerState {
296 CarlaJackAppClient* jackAppPtr;
298 uint32_t bufferSize;
299 double sampleRate;
301 jack_uuid_t uuid;
303 uint8_t numAudioIns;
304 uint8_t numAudioOuts;
305 uint8_t numMidiIns;
306 uint8_t numMidiOuts;
308 bool playing;
309 jack_position_t position;
310 jack_nframes_t monotonic_frame;
312 JackServerState(CarlaJackAppClient* const app)
313 : jackAppPtr(app),
314 bufferSize(0),
315 sampleRate(0.0),
316 uuid(jack_client_uuid_generate()),
317 numAudioIns(0),
318 numAudioOuts(0),
319 numMidiIns(0),
320 numMidiOuts(0),
321 playing(false),
322 position(),
323 monotonic_frame(0)
325 carla_zeroStruct(position);
328 CARLA_DECLARE_NON_COPYABLE(JackServerState)
331 CARLA_BACKEND_END_NAMESPACE
333 // --------------------------------------------------------------------------------------------------------------------
335 #endif // CARLA_LIBJACK_HPP_INCLUDED