You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

421 lines
8.4KB

  1. #include "bridge.hpp"
  2. #include "util/common.hpp"
  3. #include "dsp/ringbuffer.hpp"
  4. #include <unistd.h>
  5. #ifdef ARCH_WIN
  6. #include <winsock2.h>
  7. #else
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <netinet/tcp.h>
  12. #include <fcntl.h>
  13. #endif
  14. #include <thread>
  15. namespace rack {
  16. struct BridgeClientConnection;
  17. static BridgeClientConnection *connections[BRIDGE_NUM_PORTS] = {};
  18. static AudioIO *audioListeners[BRIDGE_NUM_PORTS] = {};
  19. static MidiIO *midiListeners[BRIDGE_NUM_PORTS] = {};
  20. static std::thread serverThread;
  21. static bool serverRunning = false;
  22. struct BridgeClientConnection {
  23. int client;
  24. bool ready = false;
  25. int port = -1;
  26. int sampleRate = 0;
  27. int audioChannels = 0;
  28. bool audioActive = false;
  29. ~BridgeClientConnection() {
  30. setPort(-1);
  31. }
  32. /** Returns true if successful */
  33. bool send(const void *buffer, int length) {
  34. if (length <= 0)
  35. return false;
  36. #ifdef ARCH_LIN
  37. int flags = MSG_NOSIGNAL;
  38. #else
  39. int flags = 0;
  40. #endif
  41. ssize_t actual = ::send(client, (const char*) buffer, length, flags);
  42. if (actual != length) {
  43. ready = false;
  44. return false;
  45. }
  46. return true;
  47. }
  48. template <typename T>
  49. bool send(T x) {
  50. return send(&x, sizeof(x));
  51. }
  52. /** Returns true if successful */
  53. bool recv(void *buffer, int length) {
  54. if (length <= 0)
  55. return false;
  56. #ifdef ARCH_LIN
  57. int flags = MSG_NOSIGNAL;
  58. #else
  59. int flags = 0;
  60. #endif
  61. ssize_t actual = ::recv(client, (char*) buffer, length, flags);
  62. if (actual != length) {
  63. ready = false;
  64. return false;
  65. }
  66. return true;
  67. }
  68. template <typename T>
  69. bool recv(T *x) {
  70. return recv(x, sizeof(*x));
  71. }
  72. void flush() {
  73. int err;
  74. // Turn off Nagle
  75. int flag = 1;
  76. err = setsockopt(client, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(int));
  77. // Turn on Nagle
  78. flag = 0;
  79. err = setsockopt(client, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(int));
  80. (void) err;
  81. }
  82. void run() {
  83. info("Bridge client connected");
  84. // Check hello key
  85. uint32_t hello = -1;
  86. recv<uint32_t>(&hello);
  87. if (hello != BRIDGE_HELLO) {
  88. info("Bridge client protocol mismatch %x %x", hello, BRIDGE_HELLO);
  89. return;
  90. }
  91. // Process commands until no longer ready
  92. ready = true;
  93. while (ready) {
  94. step();
  95. }
  96. info("Bridge client closed");
  97. }
  98. /** Accepts a command from the client */
  99. void step() {
  100. uint8_t command = NO_COMMAND;
  101. if (!recv<uint8_t>(&command)) {
  102. ready = false;
  103. return;
  104. }
  105. switch (command) {
  106. default:
  107. case NO_COMMAND: {
  108. warn("Bridge client: bad command %d detected, closing", command);
  109. ready = false;
  110. } break;
  111. case QUIT_COMMAND: {
  112. debug("Bridge client quitting");
  113. ready = false;
  114. } break;
  115. case PORT_SET_COMMAND: {
  116. uint8_t port = -1;
  117. recv<uint8_t>(&port);
  118. setPort(port);
  119. } break;
  120. case MIDI_MESSAGE_SEND_COMMAND: {
  121. MidiMessage message;
  122. if (!recv(&message, 3)) {
  123. ready = false;
  124. return;
  125. }
  126. processMidi(message);
  127. } break;
  128. case AUDIO_SAMPLE_RATE_SET_COMMAND: {
  129. uint32_t sampleRate = 0;
  130. recv<uint32_t>(&sampleRate);
  131. setSampleRate(sampleRate);
  132. } break;
  133. case AUDIO_CHANNELS_SET_COMMAND: {
  134. uint8_t channels = 0;
  135. recv<uint8_t>(&channels);
  136. // TODO
  137. } break;
  138. case AUDIO_PROCESS_COMMAND: {
  139. uint32_t length = 0;
  140. recv<uint32_t>(&length);
  141. if (length == 0) {
  142. ready = false;
  143. return;
  144. }
  145. float input[length];
  146. if (!recv(&input, length * sizeof(float))) {
  147. ready = false;
  148. return;
  149. }
  150. float output[length];
  151. int frames = length / 2;
  152. memset(&output, 0, sizeof(output));
  153. processStream(input, output, frames);
  154. send(&output, length * sizeof(float));
  155. flush();
  156. } break;
  157. case AUDIO_ACTIVATE: {
  158. audioActive = true;
  159. refreshAudio();
  160. } break;
  161. case AUDIO_DEACTIVATE: {
  162. audioActive = false;
  163. refreshAudio();
  164. } break;
  165. }
  166. }
  167. void setPort(int port) {
  168. // Unbind from existing port
  169. if (this->port >= 0 && connections[this->port] == this) {
  170. if (audioListeners[this->port])
  171. audioListeners[this->port]->setChannels(0, 0);
  172. connections[this->port] = NULL;
  173. }
  174. // Bind to new port
  175. if ((0 <= port && port < BRIDGE_NUM_PORTS) && !connections[port]) {
  176. this->port = port;
  177. connections[this->port] = this;
  178. refreshAudio();
  179. }
  180. else {
  181. this->port = -1;
  182. }
  183. }
  184. void processMidi(MidiMessage message) {
  185. if (!(0 <= port && port < BRIDGE_NUM_PORTS))
  186. return;
  187. if (!midiListeners[port])
  188. return;
  189. midiListeners[port]->onMessage(message);
  190. }
  191. void setSampleRate(int sampleRate) {
  192. this->sampleRate = sampleRate;
  193. refreshAudio();
  194. }
  195. void processStream(const float *input, float *output, int frames) {
  196. if (!(0 <= port && port < BRIDGE_NUM_PORTS))
  197. return;
  198. if (!audioListeners[port])
  199. return;
  200. audioListeners[port]->setBlockSize(frames);
  201. audioListeners[port]->processStream(input, output, frames);
  202. }
  203. void refreshAudio() {
  204. if (!(0 <= port && port < BRIDGE_NUM_PORTS))
  205. return;
  206. if (connections[port] != this)
  207. return;
  208. if (!audioListeners[port])
  209. return;
  210. if (audioActive)
  211. audioListeners[port]->setChannels(2, 2);
  212. else
  213. audioListeners[port]->setChannels(0, 0);
  214. audioListeners[port]->setSampleRate(sampleRate);
  215. }
  216. };
  217. static void clientRun(int client) {
  218. defer({
  219. close(client);
  220. });
  221. int err;
  222. (void) err;
  223. #ifdef ARCH_MAC
  224. // Avoid SIGPIPE
  225. int flag = 1;
  226. setsockopt(client, SOL_SOCKET, SO_NOSIGPIPE, &flag, sizeof(int));
  227. #endif
  228. // Disable non-blocking
  229. #ifdef ARCH_WIN
  230. unsigned long blockingMode = 0;
  231. ioctlsocket(client, FIONBIO, &blockingMode);
  232. #else
  233. err = fcntl(client, F_SETFL, fcntl(client, F_GETFL, 0) & ~O_NONBLOCK);
  234. #endif
  235. BridgeClientConnection connection;
  236. connection.client = client;
  237. connection.run();
  238. }
  239. static void serverConnect() {
  240. int err;
  241. // Initialize sockets
  242. #ifdef ARCH_WIN
  243. WSADATA wsaData;
  244. err = WSAStartup(MAKEWORD(2, 2), &wsaData);
  245. defer({
  246. WSACleanup();
  247. });
  248. if (err) {
  249. warn("Could not initialize Winsock");
  250. return;
  251. }
  252. #endif
  253. // Get address
  254. struct sockaddr_in addr;
  255. memset(&addr, 0, sizeof(addr));
  256. addr.sin_family = AF_INET;
  257. addr.sin_port = htons(BRIDGE_PORT);
  258. #ifdef ARCH_WIN
  259. addr.sin_addr.s_addr = inet_addr(BRIDGE_HOST);
  260. #else
  261. inet_pton(AF_INET, BRIDGE_HOST, &addr.sin_addr);
  262. #endif
  263. // Open socket
  264. int server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  265. if (server < 0) {
  266. warn("Bridge server socket() failed");
  267. return;
  268. }
  269. defer({
  270. close(server);
  271. });
  272. // Bind socket to address
  273. err = bind(server, (struct sockaddr*) &addr, sizeof(addr));
  274. if (err) {
  275. warn("Bridge server bind() failed");
  276. return;
  277. }
  278. // Listen for clients
  279. err = listen(server, 20);
  280. if (err) {
  281. warn("Bridge server listen() failed");
  282. return;
  283. }
  284. info("Bridge server started");
  285. // Enable non-blocking
  286. #ifdef ARCH_WIN
  287. unsigned long blockingMode = 1;
  288. ioctlsocket(server, FIONBIO, &blockingMode);
  289. #else
  290. int flags = fcntl(server, F_GETFL, 0);
  291. err = fcntl(server, F_SETFL, flags | O_NONBLOCK);
  292. #endif
  293. // Accept clients
  294. while (serverRunning) {
  295. int client = accept(server, NULL, NULL);
  296. if (client < 0) {
  297. // Wait a bit before attempting to accept another client
  298. std::this_thread::sleep_for(std::chrono::duration<double>(0.1));
  299. continue;
  300. }
  301. // Launch client thread
  302. std::thread clientThread(clientRun, client);
  303. clientThread.detach();
  304. }
  305. info("Bridge server closed");
  306. }
  307. static void serverRun() {
  308. while (serverRunning) {
  309. std::this_thread::sleep_for(std::chrono::duration<double>(0.1));
  310. serverConnect();
  311. }
  312. }
  313. void bridgeInit() {
  314. serverRunning = true;
  315. serverThread = std::thread(serverRun);
  316. }
  317. void bridgeDestroy() {
  318. serverRunning = false;
  319. serverThread.join();
  320. }
  321. void bridgeMidiSubscribe(int port, MidiIO *midi) {
  322. if (!(0 <= port && port < BRIDGE_NUM_PORTS))
  323. return;
  324. // Check if a Midi is already subscribed on the port
  325. if (midiListeners[port])
  326. return;
  327. midiListeners[port] = midi;
  328. if (connections[port])
  329. connections[port]->refreshAudio();
  330. }
  331. void bridgeMidiUnsubscribe(int port, MidiIO *midi) {
  332. if (!(0 <= port && port < BRIDGE_NUM_PORTS))
  333. return;
  334. if (midiListeners[port] != midi)
  335. return;
  336. midiListeners[port] = NULL;
  337. }
  338. void bridgeAudioSubscribe(int port, AudioIO *audio) {
  339. if (!(0 <= port && port < BRIDGE_NUM_PORTS))
  340. return;
  341. // Check if an Audio is already subscribed on the port
  342. if (audioListeners[port])
  343. return;
  344. audioListeners[port] = audio;
  345. if (connections[port])
  346. connections[port]->refreshAudio();
  347. }
  348. void bridgeAudioUnsubscribe(int port, AudioIO *audio) {
  349. if (!(0 <= port && port < BRIDGE_NUM_PORTS))
  350. return;
  351. if (audioListeners[port] != audio)
  352. return;
  353. audioListeners[port] = NULL;
  354. audio->setChannels(0, 0);
  355. }
  356. } // namespace rack