jack1 codebase
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.

969 lines
24KB

  1. /*
  2. * ALSA SEQ < - > JACK MIDI bridge
  3. *
  4. * Copyright (c) 2006,2007 Dmitry S. Baikov <c0ff@konstruktiv.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. /*
  21. * alsa_seqmidi_read:
  22. * add new ports
  23. * reads queued snd_seq_event's
  24. * if PORT_EXIT: mark port as dead
  25. * if PORT_ADD, PORT_CHANGE: send addr to port_thread (it also may mark port as dead)
  26. * else process input event
  27. * remove dead ports and send them to port_thread
  28. *
  29. * alsa_seqmidi_write:
  30. * remove dead ports and send them to port_thread
  31. * add new ports
  32. * queue output events
  33. *
  34. * port_thread:
  35. * wait for port_sem
  36. * free deleted ports
  37. * create new ports or mark existing as dead
  38. */
  39. #include <alsa/asoundlib.h>
  40. #include <jack/jack.h>
  41. #include <jack/midiport.h>
  42. #include <jack/ringbuffer.h>
  43. #include <jack/thread.h>
  44. #include <stdlib.h>
  45. #include <stdio.h>
  46. #include <signal.h>
  47. #include <semaphore.h>
  48. #include <time.h>
  49. #include <ctype.h>
  50. #include "alsa_midi.h"
  51. #ifndef SND_SEQ_PORT_TYPE_PORT
  52. #define SND_SEQ_PORT_TYPE_PORT (1 << 19) /* Appears in version 1.0.12rc1 */
  53. #endif
  54. #ifndef SND_SEQ_PORT_TYPE_HARDWARE
  55. #define SND_SEQ_PORT_TYPE_HARDWARE (1 << 16) /* Appears in version 1.0.12rc1 */
  56. #endif
  57. #ifdef STANDALONE
  58. #define MESSAGE(...) fprintf (stderr, __VA_ARGS__)
  59. #else
  60. #include "messagebuffer.h"
  61. #endif
  62. #define info_log(...) MESSAGE (__VA_ARGS__)
  63. #define error_log(...) MESSAGE (__VA_ARGS__)
  64. #ifdef JACK_MIDI_DEBUG
  65. #define debug_log(...) MESSAGE (__VA_ARGS__)
  66. #else
  67. #define debug_log(...)
  68. #endif
  69. #define NSEC_PER_SEC ((int64_t)1000 * 1000 * 1000)
  70. enum {
  71. MAX_PORTS = 64,
  72. MAX_EVENT_SIZE = 1024,
  73. };
  74. typedef struct port_t port_t;
  75. enum {
  76. PORT_HASH_BITS = 4,
  77. PORT_HASH_SIZE = 1 << PORT_HASH_BITS
  78. };
  79. typedef port_t* port_hash_t[PORT_HASH_SIZE];
  80. struct port_t {
  81. port_t *next;
  82. int is_dead;
  83. char name[64];
  84. snd_seq_addr_t remote;
  85. jack_port_t *jack_port;
  86. jack_ringbuffer_t *early_events; // alsa_midi_event_t + data
  87. int64_t last_out_time;
  88. void *jack_buf;
  89. };
  90. typedef struct {
  91. snd_midi_event_t *codec;
  92. jack_ringbuffer_t *new_ports;
  93. port_t *ports[MAX_PORTS];
  94. } stream_t;
  95. typedef struct alsa_seqmidi {
  96. alsa_midi_t ops;
  97. jack_client_t *jack;
  98. snd_seq_t *seq;
  99. int client_id;
  100. int port_id;
  101. int queue;
  102. int keep_walking;
  103. pthread_t port_thread;
  104. sem_t port_sem;
  105. jack_ringbuffer_t *port_add; // snd_seq_addr_t
  106. jack_ringbuffer_t *port_del; // port_t*
  107. stream_t stream[2];
  108. char alsa_name[32];
  109. } alsa_seqmidi_t;
  110. struct alsa_midi_event {
  111. int64_t time;
  112. int size;
  113. };
  114. typedef struct alsa_midi_event alsa_midi_event_t;
  115. struct process_info {
  116. int dir;
  117. jack_nframes_t nframes;
  118. jack_nframes_t period_start;
  119. jack_nframes_t sample_rate;
  120. jack_nframes_t cur_frames;
  121. int64_t alsa_time;
  122. };
  123. enum PortType { PORT_INPUT = 0, PORT_OUTPUT = 1 };
  124. typedef void (*port_jack_func)(alsa_seqmidi_t *self, port_t *port, struct process_info* info);
  125. static void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info* info);
  126. static void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* info);
  127. typedef struct {
  128. int alsa_mask;
  129. int jack_caps;
  130. char name[9];
  131. port_jack_func jack_func;
  132. } port_type_t;
  133. static port_type_t port_type[2] = {
  134. {
  135. SND_SEQ_PORT_CAP_SUBS_READ,
  136. JackPortIsOutput,
  137. "capture",
  138. do_jack_input
  139. },
  140. {
  141. SND_SEQ_PORT_CAP_SUBS_WRITE,
  142. JackPortIsInput,
  143. "playback",
  144. do_jack_output
  145. }
  146. };
  147. static void alsa_seqmidi_delete(alsa_midi_t *m);
  148. static int alsa_seqmidi_attach(alsa_midi_t *m);
  149. static int alsa_seqmidi_detach(alsa_midi_t *m);
  150. static int alsa_seqmidi_start(alsa_midi_t *m);
  151. static int alsa_seqmidi_stop(alsa_midi_t *m);
  152. static void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes);
  153. static void alsa_seqmidi_write(alsa_midi_t *m, jack_nframes_t nframes);
  154. static
  155. void stream_init (alsa_seqmidi_t *self, int dir)
  156. {
  157. stream_t *str = &self->stream[dir];
  158. str->new_ports = jack_ringbuffer_create (MAX_PORTS * sizeof(port_t*));
  159. snd_midi_event_new (MAX_EVENT_SIZE, &str->codec);
  160. }
  161. static void port_free(alsa_seqmidi_t *self, port_t *port);
  162. static void free_ports(alsa_seqmidi_t *self, jack_ringbuffer_t *ports);
  163. static
  164. void stream_attach (alsa_seqmidi_t *self, int dir)
  165. {
  166. }
  167. static
  168. void stream_detach (alsa_seqmidi_t *self, int dir)
  169. {
  170. stream_t *str = &self->stream[dir];
  171. int i;
  172. free_ports (self, str->new_ports);
  173. // delete all ports from hash
  174. for (i = 0; i < PORT_HASH_SIZE; ++i) {
  175. port_t *port = str->ports[i];
  176. while (port) {
  177. port_t *next = port->next;
  178. port_free (self, port);
  179. port = next;
  180. }
  181. str->ports[i] = NULL;
  182. }
  183. }
  184. static
  185. void stream_close (alsa_seqmidi_t *self, int dir)
  186. {
  187. stream_t *str = &self->stream[dir];
  188. if (str->codec) {
  189. snd_midi_event_free (str->codec);
  190. }
  191. if (str->new_ports) {
  192. jack_ringbuffer_free (str->new_ports);
  193. }
  194. }
  195. alsa_midi_t* alsa_seqmidi_new (jack_client_t *client, const char* alsa_name)
  196. {
  197. alsa_seqmidi_t *self = calloc (1, sizeof(alsa_seqmidi_t));
  198. debug_log ("midi: new\n");
  199. if (!self) {
  200. return NULL;
  201. }
  202. self->jack = client;
  203. if (!alsa_name) {
  204. alsa_name = "jack_midi";
  205. }
  206. snprintf (self->alsa_name, sizeof(self->alsa_name), "%s", alsa_name);
  207. self->port_add = jack_ringbuffer_create (2 * MAX_PORTS * sizeof(snd_seq_addr_t));
  208. self->port_del = jack_ringbuffer_create (2 * MAX_PORTS * sizeof(port_t*));
  209. sem_init (&self->port_sem, 0, 0);
  210. stream_init (self, PORT_INPUT);
  211. stream_init (self, PORT_OUTPUT);
  212. self->ops.destroy = alsa_seqmidi_delete;
  213. self->ops.attach = alsa_seqmidi_attach;
  214. self->ops.detach = alsa_seqmidi_detach;
  215. self->ops.start = alsa_seqmidi_start;
  216. self->ops.stop = alsa_seqmidi_stop;
  217. self->ops.read = alsa_seqmidi_read;
  218. self->ops.write = alsa_seqmidi_write;
  219. return &self->ops;
  220. }
  221. static
  222. void alsa_seqmidi_delete (alsa_midi_t *m)
  223. {
  224. alsa_seqmidi_t *self = (alsa_seqmidi_t*)m;
  225. debug_log ("midi: delete\n");
  226. alsa_seqmidi_detach (m);
  227. stream_close (self, PORT_OUTPUT);
  228. stream_close (self, PORT_INPUT);
  229. jack_ringbuffer_free (self->port_add);
  230. jack_ringbuffer_free (self->port_del);
  231. sem_close (&self->port_sem);
  232. free (self);
  233. }
  234. static
  235. int alsa_seqmidi_attach (alsa_midi_t *m)
  236. {
  237. alsa_seqmidi_t *self = (alsa_seqmidi_t*)m;
  238. int err;
  239. debug_log ("midi: attach\n");
  240. if (self->seq) {
  241. return -EALREADY;
  242. }
  243. if ((err = snd_seq_open (&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0)) < 0) {
  244. error_log ("failed to open alsa seq");
  245. return err;
  246. }
  247. snd_seq_set_client_name (self->seq, self->alsa_name);
  248. self->port_id = snd_seq_create_simple_port (self->seq, "port",
  249. SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE
  250. #ifndef JACK_MIDI_DEBUG
  251. | SND_SEQ_PORT_CAP_NO_EXPORT
  252. #endif
  253. , SND_SEQ_PORT_TYPE_APPLICATION);
  254. self->client_id = snd_seq_client_id (self->seq);
  255. self->queue = snd_seq_alloc_queue (self->seq);
  256. snd_seq_start_queue (self->seq, self->queue, 0);
  257. stream_attach (self, PORT_INPUT);
  258. stream_attach (self, PORT_OUTPUT);
  259. snd_seq_nonblock (self->seq, 1);
  260. return 0;
  261. }
  262. static
  263. int alsa_seqmidi_detach (alsa_midi_t *m)
  264. {
  265. alsa_seqmidi_t *self = (alsa_seqmidi_t*)m;
  266. debug_log ("midi: detach\n");
  267. if (!self->seq) {
  268. return -EALREADY;
  269. }
  270. alsa_seqmidi_stop (m);
  271. jack_ringbuffer_reset (self->port_add);
  272. free_ports (self, self->port_del);
  273. stream_detach (self, PORT_INPUT);
  274. stream_detach (self, PORT_OUTPUT);
  275. snd_seq_close (self->seq);
  276. self->seq = NULL;
  277. return 0;
  278. }
  279. static void* port_thread(void *);
  280. static void add_existing_ports(alsa_seqmidi_t *self);
  281. static void update_ports(alsa_seqmidi_t *self);
  282. static void add_ports(stream_t *str);
  283. static
  284. int alsa_seqmidi_start (alsa_midi_t *m)
  285. {
  286. alsa_seqmidi_t *self = (alsa_seqmidi_t*)m;
  287. int err;
  288. debug_log ("midi: start\n");
  289. if (!self->seq) {
  290. return -EBADF;
  291. }
  292. if (self->keep_walking) {
  293. return -EALREADY;
  294. }
  295. snd_seq_connect_from (self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
  296. snd_seq_drop_input (self->seq);
  297. add_existing_ports (self);
  298. update_ports (self);
  299. add_ports (&self->stream[PORT_INPUT]);
  300. add_ports (&self->stream[PORT_OUTPUT]);
  301. self->keep_walking = 1;
  302. if ((err = pthread_create (&self->port_thread, NULL, port_thread, self))) {
  303. self->keep_walking = 0;
  304. return -errno;
  305. }
  306. return 0;
  307. }
  308. static
  309. int alsa_seqmidi_stop (alsa_midi_t *m)
  310. {
  311. alsa_seqmidi_t *self = (alsa_seqmidi_t*)m;
  312. debug_log ("midi: stop\n");
  313. if (!self->keep_walking) {
  314. return -EALREADY;
  315. }
  316. snd_seq_disconnect_from (self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
  317. self->keep_walking = 0;
  318. sem_post (&self->port_sem);
  319. pthread_join (self->port_thread, NULL);
  320. self->port_thread = 0;
  321. return 0;
  322. }
  323. static
  324. int alsa_connect_from (alsa_seqmidi_t *self, int client, int port)
  325. {
  326. snd_seq_port_subscribe_t* sub;
  327. snd_seq_addr_t seq_addr;
  328. int err;
  329. snd_seq_port_subscribe_alloca (&sub);
  330. seq_addr.client = client;
  331. seq_addr.port = port;
  332. snd_seq_port_subscribe_set_sender (sub, &seq_addr);
  333. seq_addr.client = self->client_id;
  334. seq_addr.port = self->port_id;
  335. snd_seq_port_subscribe_set_dest (sub, &seq_addr);
  336. snd_seq_port_subscribe_set_time_update (sub, 1);
  337. snd_seq_port_subscribe_set_queue (sub, self->queue);
  338. snd_seq_port_subscribe_set_time_real (sub, 1);
  339. if ((err = snd_seq_subscribe_port (self->seq, sub))) {
  340. error_log ("can't subscribe to %d:%d - %s\n", client, port, snd_strerror (err));
  341. }
  342. return err;
  343. }
  344. /*
  345. * ==================== Port routines =============================
  346. */
  347. static inline
  348. int port_hash (snd_seq_addr_t addr)
  349. {
  350. return (addr.client + addr.port) % PORT_HASH_SIZE;
  351. }
  352. static
  353. port_t* port_get (port_hash_t hash, snd_seq_addr_t addr)
  354. {
  355. port_t **pport = &hash[port_hash (addr)];
  356. while (*pport) {
  357. port_t *port = *pport;
  358. if (port->remote.client == addr.client && port->remote.port == addr.port) {
  359. return port;
  360. }
  361. pport = &port->next;
  362. }
  363. return NULL;
  364. }
  365. static
  366. void port_insert (port_hash_t hash, port_t *port)
  367. {
  368. port_t **pport = &hash[port_hash (port->remote)];
  369. port->next = *pport;
  370. *pport = port;
  371. }
  372. static
  373. void port_setdead (port_hash_t hash, snd_seq_addr_t addr)
  374. {
  375. port_t *port = port_get (hash, addr);
  376. if (port) {
  377. port->is_dead = 1; // see jack_process
  378. } else {
  379. debug_log ("port_setdead: not found (%d:%d)\n", addr.client, addr.port);
  380. }
  381. }
  382. static
  383. void port_free (alsa_seqmidi_t *self, port_t *port)
  384. {
  385. //snd_seq_disconnect_from(self->seq, self->port_id, port->remote.client, port->remote.port);
  386. //snd_seq_disconnect_to(self->seq, self->port_id, port->remote.client, port->remote.port);
  387. if (port->early_events) {
  388. jack_ringbuffer_free (port->early_events);
  389. }
  390. if (port->jack_port) {
  391. jack_port_unregister (self->jack, port->jack_port);
  392. }
  393. // info_log("port deleted: %s\n", port->name);
  394. free (port);
  395. }
  396. static
  397. port_t* port_create (alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const snd_seq_port_info_t *info)
  398. {
  399. snd_seq_client_info_t* client_info;
  400. port_t *port;
  401. char *c;
  402. int err;
  403. int jack_caps;
  404. port = calloc (1, sizeof(port_t));
  405. if (!port) {
  406. return NULL;
  407. }
  408. port->remote = addr;
  409. snd_seq_client_info_alloca (&client_info);
  410. snd_seq_get_any_client_info (self->seq, addr.client, client_info);
  411. snprintf (port->name, sizeof(port->name), "%s/midi_%s_%d",
  412. snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port + 1);
  413. // replace all offending characters by -
  414. for (c = port->name; *c; ++c)
  415. if (!isalnum (*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') {
  416. *c = '-';
  417. }
  418. jack_caps = port_type[type].jack_caps;
  419. /* mark anything that looks like a hardware port as physical&terminal */
  420. if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE | SND_SEQ_PORT_TYPE_PORT | SND_SEQ_PORT_TYPE_SPECIFIC)) {
  421. jack_caps |= (JackPortIsPhysical | JackPortIsTerminal);
  422. }
  423. port->jack_port = jack_port_register (self->jack,
  424. port->name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0);
  425. if (!port->jack_port) {
  426. goto failed;
  427. }
  428. /* generate an alias */
  429. snprintf (port->name, sizeof(port->name), "%s:midi/%s_%d",
  430. snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port + 1);
  431. // replace all offending characters by -
  432. for (c = port->name; *c; ++c)
  433. if (!isalnum (*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') {
  434. *c = '-';
  435. }
  436. jack_port_set_alias (port->jack_port, port->name);
  437. if (type == PORT_INPUT) {
  438. err = alsa_connect_from (self, port->remote.client, port->remote.port);
  439. } else {
  440. err = snd_seq_connect_to (self->seq, self->port_id, port->remote.client, port->remote.port);
  441. }
  442. if (err) {
  443. goto failed;
  444. }
  445. port->early_events = jack_ringbuffer_create (MAX_EVENT_SIZE * 16);
  446. // info_log("port created: %s\n", port->name);
  447. return port;
  448. failed:
  449. port_free (self, port);
  450. return NULL;
  451. }
  452. /*
  453. * ==================== Port add/del handling thread ==============================
  454. */
  455. static
  456. void update_port_type (alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t *info)
  457. {
  458. stream_t *str = &self->stream[type];
  459. int alsa_mask = port_type[type].alsa_mask;
  460. port_t *port = port_get (str->ports, addr);
  461. debug_log ("update_port_type(%d:%d)\n", addr.client, addr.port);
  462. if (port && (caps & alsa_mask) != alsa_mask) {
  463. debug_log ("setdead: %s\n", port->name);
  464. port->is_dead = 1;
  465. }
  466. if (!port && (caps & alsa_mask) == alsa_mask) {
  467. assert (jack_ringbuffer_write_space (str->new_ports) >= sizeof(port));
  468. port = port_create (self, type, addr, info);
  469. if (port) {
  470. jack_ringbuffer_write (str->new_ports, (char*)&port, sizeof(port));
  471. }
  472. }
  473. }
  474. static
  475. void update_port (alsa_seqmidi_t *self, snd_seq_addr_t addr, const snd_seq_port_info_t *info)
  476. {
  477. unsigned int port_caps = snd_seq_port_info_get_capability (info);
  478. if (port_caps & SND_SEQ_PORT_CAP_NO_EXPORT) {
  479. return;
  480. }
  481. update_port_type (self, PORT_INPUT, addr, port_caps, info);
  482. update_port_type (self, PORT_OUTPUT, addr, port_caps, info);
  483. }
  484. static
  485. void free_ports (alsa_seqmidi_t *self, jack_ringbuffer_t *ports)
  486. {
  487. port_t *port;
  488. int sz;
  489. while ((sz = jack_ringbuffer_read (ports, (char*)&port, sizeof(port)))) {
  490. assert (sz == sizeof(port));
  491. port_free (self, port);
  492. }
  493. }
  494. static
  495. void update_ports (alsa_seqmidi_t *self)
  496. {
  497. snd_seq_addr_t addr;
  498. snd_seq_port_info_t *info;
  499. int size;
  500. snd_seq_port_info_alloca (&info);
  501. while ((size = jack_ringbuffer_read (self->port_add, (char*)&addr, sizeof(addr)))) {
  502. int err;
  503. assert (size == sizeof(addr));
  504. assert (addr.client != self->client_id);
  505. if ((err = snd_seq_get_any_port_info (self->seq, addr.client, addr.port, info)) >= 0) {
  506. update_port (self, addr, info);
  507. } else {
  508. //port_setdead(self->stream[PORT_INPUT].ports, addr);
  509. //port_setdead(self->stream[PORT_OUTPUT].ports, addr);
  510. }
  511. }
  512. }
  513. static
  514. void* port_thread (void *arg)
  515. {
  516. alsa_seqmidi_t *self = arg;
  517. while (self->keep_walking) {
  518. sem_wait (&self->port_sem);
  519. free_ports (self, self->port_del);
  520. update_ports (self);
  521. }
  522. debug_log ("port_thread exited\n");
  523. return NULL;
  524. }
  525. static
  526. void add_existing_ports (alsa_seqmidi_t *self)
  527. {
  528. snd_seq_addr_t addr;
  529. snd_seq_client_info_t *client_info;
  530. snd_seq_port_info_t *port_info;
  531. snd_seq_client_info_alloca (&client_info);
  532. snd_seq_port_info_alloca (&port_info);
  533. snd_seq_client_info_set_client (client_info, -1);
  534. while (snd_seq_query_next_client (self->seq, client_info) >= 0) {
  535. addr.client = snd_seq_client_info_get_client (client_info);
  536. if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id) {
  537. continue;
  538. }
  539. snd_seq_port_info_set_client (port_info, addr.client);
  540. snd_seq_port_info_set_port (port_info, -1);
  541. while (snd_seq_query_next_port (self->seq, port_info) >= 0) {
  542. addr.port = snd_seq_port_info_get_port (port_info);
  543. update_port (self, addr, port_info);
  544. }
  545. }
  546. }
  547. /*
  548. * =================== Input/output port handling =========================
  549. */
  550. static
  551. void set_process_info (struct process_info *info, alsa_seqmidi_t *self, int dir, jack_nframes_t nframes)
  552. {
  553. const snd_seq_real_time_t* alsa_time;
  554. snd_seq_queue_status_t *status;
  555. snd_seq_queue_status_alloca (&status);
  556. info->dir = dir;
  557. info->period_start = jack_last_frame_time (self->jack);
  558. info->nframes = nframes;
  559. info->sample_rate = jack_get_sample_rate (self->jack);
  560. info->cur_frames = jack_frame_time (self->jack);
  561. // immediately get alsa'a real time (uhh, why everybody has their on 'real' time)
  562. snd_seq_get_queue_status (self->seq, self->queue, status);
  563. alsa_time = snd_seq_queue_status_get_real_time (status);
  564. info->alsa_time = alsa_time->tv_sec * NSEC_PER_SEC + alsa_time->tv_nsec;
  565. if (info->period_start + info->nframes < info->cur_frames) {
  566. int periods_lost = (info->cur_frames - info->period_start) / info->nframes;
  567. info->period_start += periods_lost * info->nframes;
  568. debug_log ("xrun detected: %d periods lost\n", periods_lost);
  569. }
  570. }
  571. static
  572. void add_ports (stream_t *str)
  573. {
  574. port_t *port;
  575. while (jack_ringbuffer_read (str->new_ports, (char*)&port, sizeof(port))) {
  576. debug_log ("jack: inserted port %s\n", port->name);
  577. port_insert (str->ports, port);
  578. }
  579. }
  580. static
  581. void jack_process (alsa_seqmidi_t *self, struct process_info *info)
  582. {
  583. stream_t *str = &self->stream[info->dir];
  584. port_jack_func process = port_type[info->dir].jack_func;
  585. int i, del = 0;
  586. add_ports (str);
  587. // process ports
  588. for (i = 0; i < PORT_HASH_SIZE; ++i) {
  589. port_t **pport = &str->ports[i];
  590. while (*pport) {
  591. port_t *port = *pport;
  592. port->jack_buf = jack_port_get_buffer (port->jack_port, info->nframes);
  593. if (info->dir == PORT_INPUT) {
  594. jack_midi_clear_buffer (port->jack_buf);
  595. }
  596. if (!port->is_dead) {
  597. (*process)(self, port, info);
  598. } else if (jack_ringbuffer_write_space (self->port_del) >= sizeof(port)) {
  599. debug_log ("jack: removed port %s\n", port->name);
  600. *pport = port->next;
  601. jack_ringbuffer_write (self->port_del, (char*)&port, sizeof(port));
  602. del++;
  603. continue;
  604. }
  605. pport = &port->next;
  606. }
  607. }
  608. if (del) {
  609. sem_post (&self->port_sem);
  610. }
  611. }
  612. /*
  613. * ============================ Input ==============================
  614. */
  615. static
  616. void do_jack_input (alsa_seqmidi_t *self, port_t *port, struct process_info *info)
  617. {
  618. // process port->early_events
  619. alsa_midi_event_t ev;
  620. while (jack_ringbuffer_read (port->early_events, (char*)&ev, sizeof(ev))) {
  621. jack_midi_data_t* buf;
  622. jack_nframes_t time = ev.time - info->period_start;
  623. if (time < 0) {
  624. time = 0;
  625. } else if (time >= info->nframes) {
  626. time = info->nframes - 1;
  627. }
  628. buf = jack_midi_event_reserve (port->jack_buf, time, ev.size);
  629. if (buf) {
  630. jack_ringbuffer_read (port->early_events, (char*)buf, ev.size);
  631. } else {
  632. jack_ringbuffer_read_advance (port->early_events, ev.size);
  633. }
  634. debug_log ("input: it's time for %d bytes at %d\n", ev.size, time);
  635. }
  636. }
  637. static
  638. void port_event (alsa_seqmidi_t *self, snd_seq_event_t *ev)
  639. {
  640. const snd_seq_addr_t addr = ev->data.addr;
  641. if (addr.client == self->client_id) {
  642. return;
  643. }
  644. if (ev->type == SND_SEQ_EVENT_PORT_START || ev->type == SND_SEQ_EVENT_PORT_CHANGE) {
  645. assert (jack_ringbuffer_write_space (self->port_add) >= sizeof(addr));
  646. debug_log ("port_event: add/change %d:%d\n", addr.client, addr.port);
  647. jack_ringbuffer_write (self->port_add, (char*)&addr, sizeof(addr));
  648. sem_post (&self->port_sem);
  649. } else if (ev->type == SND_SEQ_EVENT_PORT_EXIT) {
  650. debug_log ("port_event: del %d:%d\n", addr.client, addr.port);
  651. port_setdead (self->stream[PORT_INPUT].ports, addr);
  652. port_setdead (self->stream[PORT_OUTPUT].ports, addr);
  653. }
  654. }
  655. static
  656. void input_event (alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct process_info* info)
  657. {
  658. jack_midi_data_t data[MAX_EVENT_SIZE];
  659. stream_t *str = &self->stream[PORT_INPUT];
  660. long size;
  661. int64_t alsa_time, time_offset;
  662. int64_t frame_offset, event_frame;
  663. port_t *port;
  664. port = port_get (str->ports, alsa_event->source);
  665. if (!port) {
  666. return;
  667. }
  668. /*
  669. * RPNs, NRPNs, Bank Change, etc. need special handling
  670. * but seems, ALSA does it for us already.
  671. */
  672. snd_midi_event_reset_decode (str->codec);
  673. if ((size = snd_midi_event_decode (str->codec, data, sizeof(data), alsa_event)) < 0) {
  674. return;
  675. }
  676. // fixup NoteOn with vel 0
  677. if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) {
  678. data[0] = 0x80 + (data[0] & 0x0F);
  679. data[2] = 0x40;
  680. }
  681. alsa_time = alsa_event->time.time.tv_sec * NSEC_PER_SEC + alsa_event->time.time.tv_nsec;
  682. time_offset = info->alsa_time - alsa_time;
  683. frame_offset = (info->sample_rate * time_offset) / NSEC_PER_SEC;
  684. event_frame = (int64_t)info->cur_frames - info->period_start - frame_offset + info->nframes;
  685. debug_log ("input: %d bytes at event_frame=%d\n", (int)size, (int)event_frame);
  686. if (event_frame >= info->nframes &&
  687. jack_ringbuffer_write_space (port->early_events) >= (sizeof(alsa_midi_event_t) + size)) {
  688. alsa_midi_event_t ev;
  689. ev.time = event_frame + info->period_start;
  690. ev.size = size;
  691. jack_ringbuffer_write (port->early_events, (char*)&ev, sizeof(ev));
  692. jack_ringbuffer_write (port->early_events, (char*)data, size);
  693. debug_log ("postponed to next frame +%d\n", (int)(event_frame - info->nframes));
  694. return;
  695. }
  696. if (event_frame < 0) {
  697. event_frame = 0;
  698. } else if (event_frame >= info->nframes) {
  699. event_frame = info->nframes - 1;
  700. }
  701. jack_midi_event_write (port->jack_buf, event_frame, data, size);
  702. }
  703. static
  704. void alsa_seqmidi_read (alsa_midi_t *m, jack_nframes_t nframes)
  705. {
  706. alsa_seqmidi_t *self = (alsa_seqmidi_t*)m;
  707. int res;
  708. snd_seq_event_t *event;
  709. struct process_info info;
  710. if (!self->keep_walking) {
  711. return;
  712. }
  713. set_process_info (&info, self, PORT_INPUT, nframes);
  714. jack_process (self, &info);
  715. while ((res = snd_seq_event_input (self->seq, &event)) > 0) {
  716. if (event->source.client == SND_SEQ_CLIENT_SYSTEM) {
  717. port_event (self, event);
  718. } else {
  719. input_event (self, event, &info);
  720. }
  721. }
  722. }
  723. /*
  724. * ============================ Output ==============================
  725. */
  726. static
  727. void do_jack_output (alsa_seqmidi_t *self, port_t *port, struct process_info* info)
  728. {
  729. stream_t *str = &self->stream[info->dir];
  730. int nevents = jack_midi_get_event_count (port->jack_buf);
  731. int i;
  732. for (i = 0; i < nevents; ++i) {
  733. jack_midi_event_t jack_event;
  734. snd_seq_event_t alsa_event;
  735. int64_t frame_offset;
  736. int64_t out_time;
  737. snd_seq_real_time_t out_rt;
  738. int err;
  739. jack_midi_event_get (&jack_event, port->jack_buf, i);
  740. snd_seq_ev_clear (&alsa_event);
  741. snd_midi_event_reset_encode (str->codec);
  742. if (!snd_midi_event_encode (str->codec, jack_event.buffer, jack_event.size, &alsa_event)) {
  743. continue; // invalid event
  744. }
  745. snd_seq_ev_set_source (&alsa_event, self->port_id);
  746. snd_seq_ev_set_dest (&alsa_event, port->remote.client, port->remote.port);
  747. /* NOTE: in case of xrun it could become negative, so it is essential to use signed type! */
  748. frame_offset = (int64_t)jack_event.time + info->period_start + info->nframes - info->cur_frames;
  749. if (frame_offset < 0) {
  750. frame_offset = info->nframes + jack_event.time;
  751. error_log ("internal xrun detected: frame_offset = %" PRId64 "\n", frame_offset);
  752. }
  753. /* Ken Ellinwood reported problems with this assert.
  754. * Seems, magic 2 should be replaced with nperiods. */
  755. //FIXME: assert (frame_offset < info->nframes*2);
  756. //if (frame_offset < info->nframes * info->nperiods)
  757. // debug_log("alsa_out: BLAH-BLAH-BLAH");
  758. out_time = info->alsa_time + (frame_offset * NSEC_PER_SEC) / info->sample_rate;
  759. // we should use absolute time to prevent reordering caused by rounding errors
  760. if (out_time < port->last_out_time) {
  761. debug_log ("alsa_out: limiting out_time %lld at %lld\n", out_time, port->last_out_time);
  762. out_time = port->last_out_time;
  763. } else {
  764. port->last_out_time = out_time;
  765. }
  766. out_rt.tv_nsec = out_time % NSEC_PER_SEC;
  767. out_rt.tv_sec = out_time / NSEC_PER_SEC;
  768. snd_seq_ev_schedule_real (&alsa_event, self->queue, 0, &out_rt);
  769. err = snd_seq_event_output (self->seq, &alsa_event);
  770. debug_log ("alsa_out: written %d bytes to %s at %d (%lld): %d %s\n",
  771. jack_event.size, port->name, (int)frame_offset, out_time - info->alsa_time, err, err < 0 ? snd_strerror (err) : "bytes queued");
  772. }
  773. }
  774. static
  775. void alsa_seqmidi_write (alsa_midi_t *m, jack_nframes_t nframes)
  776. {
  777. alsa_seqmidi_t *self = (alsa_seqmidi_t*)m;
  778. struct process_info info;
  779. if (!self->keep_walking) {
  780. return;
  781. }
  782. set_process_info (&info, self, PORT_OUTPUT, nframes);
  783. jack_process (self, &info);
  784. snd_seq_drain_output (self->seq);
  785. }