jack2 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.

856 lines
22KB

  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/midiport.h>
  41. #include <jack/ringbuffer.h>
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <signal.h>
  45. #include <semaphore.h>
  46. #include <pthread.h>
  47. #include <time.h>
  48. #include <ctype.h>
  49. #include "alsa_midi_impl.h"
  50. #define NSEC_PER_SEC ((int64_t)1000*1000*1000)
  51. enum {
  52. MAX_PORTS = 64,
  53. MAX_EVENT_SIZE = 1024,
  54. };
  55. typedef struct port_t port_t;
  56. enum {
  57. PORT_HASH_BITS = 4,
  58. PORT_HASH_SIZE = 1 << PORT_HASH_BITS
  59. };
  60. typedef port_t* port_hash_t[PORT_HASH_SIZE];
  61. struct port_t {
  62. port_t *next;
  63. int is_dead;
  64. char name[64];
  65. snd_seq_addr_t remote;
  66. jack_port_t *jack_port;
  67. jack_ringbuffer_t *early_events; // alsa_midi_event_t + data
  68. int64_t last_out_time;
  69. void *jack_buf;
  70. };
  71. typedef struct {
  72. snd_midi_event_t *codec;
  73. jack_ringbuffer_t *new_ports;
  74. port_t *ports[MAX_PORTS];
  75. } stream_t;
  76. typedef struct alsa_seqmidi {
  77. alsa_midi_t ops;
  78. jack_client_t *jack;
  79. snd_seq_t *seq;
  80. int client_id;
  81. int port_id;
  82. int queue;
  83. int keep_walking;
  84. pthread_t port_thread;
  85. sem_t port_sem;
  86. jack_ringbuffer_t *port_add; // snd_seq_addr_t
  87. jack_ringbuffer_t *port_del; // port_t*
  88. stream_t stream[2];
  89. char alsa_name[32];
  90. } alsa_seqmidi_t;
  91. struct alsa_midi_event {
  92. int64_t time;
  93. int size;
  94. };
  95. typedef struct alsa_midi_event alsa_midi_event_t;
  96. struct process_info {
  97. int dir;
  98. int64_t nframes;
  99. int64_t period_start;
  100. uint32_t sample_rate;
  101. int64_t cur_frames;
  102. int64_t alsa_time;
  103. };
  104. enum PortType { PORT_INPUT = 0, PORT_OUTPUT = 1 };
  105. typedef void (*port_jack_func)(alsa_seqmidi_t *self, port_t *port,struct process_info* info);
  106. static void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info* info);
  107. static void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* info);
  108. typedef struct {
  109. int alsa_mask;
  110. int jack_caps;
  111. char name[4];
  112. port_jack_func jack_func;
  113. } port_type_t;
  114. static port_type_t port_type[2] = {
  115. {
  116. SND_SEQ_PORT_CAP_SUBS_READ,
  117. JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal,
  118. "in",
  119. do_jack_input
  120. },
  121. {
  122. SND_SEQ_PORT_CAP_SUBS_WRITE,
  123. JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal,
  124. "out",
  125. do_jack_output
  126. }
  127. };
  128. static void alsa_seqmidi_delete(alsa_midi_t *m);
  129. static int alsa_seqmidi_attach(alsa_midi_t *m);
  130. static int alsa_seqmidi_detach(alsa_midi_t *m);
  131. static int alsa_seqmidi_start(alsa_midi_t *m);
  132. static int alsa_seqmidi_stop(alsa_midi_t *m);
  133. static void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes);
  134. static void alsa_seqmidi_write(alsa_midi_t *m, jack_nframes_t nframes);
  135. static
  136. void stream_init(alsa_seqmidi_t *self, int dir)
  137. {
  138. stream_t *str = &self->stream[dir];
  139. str->new_ports = jack_ringbuffer_create(MAX_PORTS*sizeof(port_t*));
  140. snd_midi_event_new(MAX_EVENT_SIZE, &str->codec);
  141. }
  142. static void port_free(alsa_seqmidi_t *self, port_t *port);
  143. static void free_ports(alsa_seqmidi_t *self, jack_ringbuffer_t *ports);
  144. static
  145. void stream_attach(alsa_seqmidi_t *self, int dir)
  146. {
  147. }
  148. static
  149. void stream_detach(alsa_seqmidi_t *self, int dir)
  150. {
  151. stream_t *str = &self->stream[dir];
  152. int i;
  153. free_ports(self, str->new_ports);
  154. // delete all ports from hash
  155. for (i=0; i<PORT_HASH_SIZE; ++i) {
  156. port_t *port = str->ports[i];
  157. while (port) {
  158. port_t *next = port->next;
  159. port_free(self, port);
  160. port = next;
  161. }
  162. str->ports[i] = NULL;
  163. }
  164. }
  165. static
  166. void stream_close(alsa_seqmidi_t *self, int dir)
  167. {
  168. stream_t *str = &self->stream[dir];
  169. if (str->codec)
  170. snd_midi_event_free(str->codec);
  171. if (str->new_ports)
  172. jack_ringbuffer_free(str->new_ports);
  173. }
  174. alsa_midi_t* alsa_seqmidi_new(jack_client_t *client, const char* alsa_name)
  175. {
  176. alsa_seqmidi_t *self = calloc(1, sizeof(alsa_seqmidi_t));
  177. debug_log("midi: new\n");
  178. if (!self)
  179. return NULL;
  180. self->jack = client;
  181. if (!alsa_name)
  182. alsa_name = "jack_midi";
  183. snprintf(self->alsa_name, sizeof(self->alsa_name), "%s", alsa_name);
  184. self->port_add = jack_ringbuffer_create(2*MAX_PORTS*sizeof(snd_seq_addr_t));
  185. self->port_del = jack_ringbuffer_create(2*MAX_PORTS*sizeof(port_t*));
  186. sem_init(&self->port_sem, 0, 0);
  187. stream_init(self, PORT_INPUT);
  188. stream_init(self, PORT_OUTPUT);
  189. self->ops.destroy = alsa_seqmidi_delete;
  190. self->ops.attach = alsa_seqmidi_attach;
  191. self->ops.detach = alsa_seqmidi_detach;
  192. self->ops.start = alsa_seqmidi_start;
  193. self->ops.stop = alsa_seqmidi_stop;
  194. self->ops.read = alsa_seqmidi_read;
  195. self->ops.write = alsa_seqmidi_write;
  196. return &self->ops;
  197. }
  198. static
  199. void alsa_seqmidi_delete(alsa_midi_t *m)
  200. {
  201. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  202. debug_log("midi: delete\n");
  203. alsa_seqmidi_detach(m);
  204. stream_close(self, PORT_OUTPUT);
  205. stream_close(self, PORT_INPUT);
  206. jack_ringbuffer_free(self->port_add);
  207. jack_ringbuffer_free(self->port_del);
  208. sem_close(&self->port_sem);
  209. free(self);
  210. }
  211. static
  212. int alsa_seqmidi_attach(alsa_midi_t *m)
  213. {
  214. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  215. int err;
  216. debug_log("midi: attach\n");
  217. if (self->seq)
  218. return -EALREADY;
  219. if ((err = snd_seq_open(&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0)) < 0) {
  220. error_log("failed to open alsa seq");
  221. return err;
  222. }
  223. snd_seq_set_client_name(self->seq, self->alsa_name);
  224. self->port_id = snd_seq_create_simple_port(self->seq, "port",
  225. SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_WRITE
  226. #ifndef DEBUG
  227. |SND_SEQ_PORT_CAP_NO_EXPORT
  228. #endif
  229. ,SND_SEQ_PORT_TYPE_APPLICATION);
  230. self->client_id = snd_seq_client_id(self->seq);
  231. self->queue = snd_seq_alloc_queue(self->seq);
  232. snd_seq_start_queue(self->seq, self->queue, 0);
  233. stream_attach(self, PORT_INPUT);
  234. stream_attach(self, PORT_OUTPUT);
  235. snd_seq_nonblock(self->seq, 1);
  236. return 0;
  237. }
  238. static
  239. int alsa_seqmidi_detach(alsa_midi_t *m)
  240. {
  241. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  242. debug_log("midi: detach\n");
  243. if (!self->seq)
  244. return -EALREADY;
  245. alsa_seqmidi_stop(m);
  246. jack_ringbuffer_reset(self->port_add);
  247. free_ports(self, self->port_del);
  248. stream_detach(self, PORT_INPUT);
  249. stream_detach(self, PORT_OUTPUT);
  250. snd_seq_close(self->seq);
  251. self->seq = NULL;
  252. return 0;
  253. }
  254. static void* port_thread(void *);
  255. static void add_existing_ports(alsa_seqmidi_t *self);
  256. static void update_ports(alsa_seqmidi_t *self);
  257. static void add_ports(stream_t *str);
  258. static
  259. int alsa_seqmidi_start(alsa_midi_t *m)
  260. {
  261. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  262. int err;
  263. debug_log("midi: start\n");
  264. if (!self->seq)
  265. return -EBADF;
  266. if (self->keep_walking)
  267. return -EALREADY;
  268. snd_seq_connect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
  269. snd_seq_drop_input(self->seq);
  270. add_existing_ports(self);
  271. update_ports(self);
  272. add_ports(&self->stream[PORT_INPUT]);
  273. add_ports(&self->stream[PORT_OUTPUT]);
  274. self->keep_walking = 1;
  275. if ((err = pthread_create(&self->port_thread, NULL, port_thread, self))) {
  276. self->keep_walking = 0;
  277. return -errno;
  278. }
  279. return 0;
  280. }
  281. static
  282. int alsa_seqmidi_stop(alsa_midi_t *m)
  283. {
  284. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  285. debug_log("midi: stop\n");
  286. if (!self->keep_walking)
  287. return -EALREADY;
  288. snd_seq_disconnect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
  289. self->keep_walking = 0;
  290. sem_post(&self->port_sem);
  291. pthread_join(self->port_thread, NULL);
  292. self->port_thread = 0;
  293. return 0;
  294. }
  295. static
  296. int alsa_connect_from(alsa_seqmidi_t *self, int client, int port)
  297. {
  298. snd_seq_port_subscribe_t* sub;
  299. snd_seq_addr_t seq_addr;
  300. int err;
  301. snd_seq_port_subscribe_alloca(&sub);
  302. seq_addr.client = client;
  303. seq_addr.port = port;
  304. snd_seq_port_subscribe_set_sender(sub, &seq_addr);
  305. seq_addr.client = self->client_id;
  306. seq_addr.port = self->port_id;
  307. snd_seq_port_subscribe_set_dest(sub, &seq_addr);
  308. snd_seq_port_subscribe_set_time_update(sub, 1);
  309. snd_seq_port_subscribe_set_queue(sub, self->queue);
  310. snd_seq_port_subscribe_set_time_real(sub, 1);
  311. if ((err=snd_seq_subscribe_port(self->seq, sub)))
  312. error_log("can't subscribe to %d:%d - %s\n", client, port, snd_strerror(err));
  313. return err;
  314. }
  315. /*
  316. * ==================== Port routines =============================
  317. */
  318. static inline
  319. int port_hash(snd_seq_addr_t addr)
  320. {
  321. return (addr.client + addr.port) % PORT_HASH_SIZE;
  322. }
  323. static
  324. port_t* port_get(port_hash_t hash, snd_seq_addr_t addr)
  325. {
  326. port_t **pport = &hash[port_hash(addr)];
  327. while (*pport) {
  328. port_t *port = *pport;
  329. if (port->remote.client == addr.client && port->remote.port == addr.port)
  330. return port;
  331. pport = &port->next;
  332. }
  333. return NULL;
  334. }
  335. static
  336. void port_insert(port_hash_t hash, port_t *port)
  337. {
  338. port_t **pport = &hash[port_hash(port->remote)];
  339. port->next = *pport;
  340. *pport = port;
  341. }
  342. static
  343. void port_setdead(port_hash_t hash, snd_seq_addr_t addr)
  344. {
  345. port_t *port = port_get(hash, addr);
  346. if (port)
  347. port->is_dead = 1; // see jack_process
  348. else
  349. debug_log("port_setdead: not found (%d:%d)\n", addr.client, addr.port);
  350. }
  351. static
  352. void port_free(alsa_seqmidi_t *self, port_t *port)
  353. {
  354. //snd_seq_disconnect_from(self->seq, self->port_id, port->remote.client, port->remote.port);
  355. //snd_seq_disconnect_to(self->seq, self->port_id, port->remote.client, port->remote.port);
  356. if (port->early_events)
  357. jack_ringbuffer_free(port->early_events);
  358. if (port->jack_port)
  359. jack_port_unregister(self->jack, port->jack_port);
  360. info_log("port deleted: %s\n", port->name);
  361. free(port);
  362. }
  363. static
  364. port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const snd_seq_port_info_t *info)
  365. {
  366. port_t *port;
  367. char *c;
  368. int err;
  369. port = calloc(1, sizeof(port_t));
  370. if (!port)
  371. return NULL;
  372. port->remote = addr;
  373. snprintf(port->name, sizeof(port->name), "%s-%d-%d-%s",
  374. port_type[type].name, addr.client, addr.port, snd_seq_port_info_get_name(info));
  375. // replace all offending characters by -
  376. for (c = port->name; *c; ++c)
  377. if (!isalnum(*c))
  378. *c = '-';
  379. port->jack_port = jack_port_register(self->jack,
  380. port->name, JACK_DEFAULT_MIDI_TYPE, port_type[type].jack_caps, 0);
  381. if (!port->jack_port)
  382. goto failed;
  383. if (type == PORT_INPUT)
  384. err = alsa_connect_from(self, port->remote.client, port->remote.port);
  385. else
  386. err = snd_seq_connect_to(self->seq, self->port_id, port->remote.client, port->remote.port);
  387. if (err)
  388. goto failed;
  389. port->early_events = jack_ringbuffer_create(MAX_EVENT_SIZE*16);
  390. info_log("port created: %s\n", port->name);
  391. return port;
  392. failed:
  393. port_free(self, port);
  394. return NULL;
  395. }
  396. /*
  397. * ==================== Port add/del handling thread ==============================
  398. */
  399. static
  400. void update_port_type(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t *info)
  401. {
  402. stream_t *str = &self->stream[type];
  403. int alsa_mask = port_type[type].alsa_mask;
  404. port_t *port = port_get(str->ports, addr);
  405. debug_log("update_port_type(%d:%d)\n", addr.client, addr.port);
  406. if (port && (caps & alsa_mask)!=alsa_mask) {
  407. debug_log("setdead: %s\n", port->name);
  408. port->is_dead = 1;
  409. }
  410. if (!port && (caps & alsa_mask)==alsa_mask) {
  411. assert (jack_ringbuffer_write_space(str->new_ports) >= sizeof(port));
  412. port = port_create(self, type, addr, info);
  413. if (port)
  414. jack_ringbuffer_write(str->new_ports, (char*)&port, sizeof(port));
  415. }
  416. }
  417. static
  418. void update_port(alsa_seqmidi_t *self, snd_seq_addr_t addr, const snd_seq_port_info_t *info)
  419. {
  420. unsigned int port_caps = snd_seq_port_info_get_capability(info);
  421. if (port_caps & SND_SEQ_PORT_CAP_NO_EXPORT)
  422. return;
  423. update_port_type(self, PORT_INPUT, addr, port_caps, info);
  424. update_port_type(self, PORT_OUTPUT, addr, port_caps, info);
  425. }
  426. static
  427. void free_ports(alsa_seqmidi_t *self, jack_ringbuffer_t *ports)
  428. {
  429. port_t *port;
  430. int sz;
  431. while ((sz = jack_ringbuffer_read(ports, (char*)&port, sizeof(port)))) {
  432. assert (sz == sizeof(port));
  433. port_free(self, port);
  434. }
  435. }
  436. static
  437. void update_ports(alsa_seqmidi_t *self)
  438. {
  439. snd_seq_addr_t addr;
  440. int size;
  441. while ((size = jack_ringbuffer_read(self->port_add, (char*)&addr, sizeof(addr)))) {
  442. snd_seq_port_info_t *info;
  443. int err;
  444. snd_seq_port_info_alloca(&info);
  445. assert (size == sizeof(addr));
  446. assert (addr.client != self->client_id);
  447. if ((err=snd_seq_get_any_port_info(self->seq, addr.client, addr.port, info))>=0) {
  448. update_port(self, addr, info);
  449. } else {
  450. //port_setdead(self->stream[PORT_INPUT].ports, addr);
  451. //port_setdead(self->stream[PORT_OUTPUT].ports, addr);
  452. }
  453. }
  454. }
  455. static
  456. void* port_thread(void *arg)
  457. {
  458. alsa_seqmidi_t *self = arg;
  459. while (self->keep_walking) {
  460. sem_wait(&self->port_sem);
  461. free_ports(self, self->port_del);
  462. update_ports(self);
  463. }
  464. debug_log("port_thread exited\n");
  465. return NULL;
  466. }
  467. static
  468. void add_existing_ports(alsa_seqmidi_t *self)
  469. {
  470. snd_seq_addr_t addr;
  471. snd_seq_client_info_t *client_info;
  472. snd_seq_port_info_t *port_info;
  473. snd_seq_client_info_alloca(&client_info);
  474. snd_seq_port_info_alloca(&port_info);
  475. snd_seq_client_info_set_client(client_info, -1);
  476. while (snd_seq_query_next_client(self->seq, client_info) >= 0)
  477. {
  478. addr.client = snd_seq_client_info_get_client(client_info);
  479. if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id)
  480. continue;
  481. snd_seq_port_info_set_client(port_info, addr.client);
  482. snd_seq_port_info_set_port(port_info, -1);
  483. while (snd_seq_query_next_port(self->seq, port_info) >= 0)
  484. {
  485. addr.port = snd_seq_port_info_get_port(port_info);
  486. update_port(self, addr, port_info);
  487. }
  488. }
  489. }
  490. /*
  491. * =================== Input/output port handling =========================
  492. */
  493. static
  494. void set_process_info(struct process_info *info, alsa_seqmidi_t *self, int dir, jack_nframes_t nframes)
  495. {
  496. const snd_seq_real_time_t* alsa_time;
  497. snd_seq_queue_status_t *status;
  498. snd_seq_queue_status_alloca(&status);
  499. info->dir = dir;
  500. info->period_start = jack_last_frame_time(self->jack);
  501. info->nframes = nframes;
  502. info->sample_rate = jack_get_sample_rate(self->jack);
  503. info->cur_frames = jack_frame_time(self->jack);
  504. // immediately get alsa'a real time (uhh, why everybody has their own 'real' time)
  505. snd_seq_get_queue_status(self->seq, self->queue, status);
  506. alsa_time = snd_seq_queue_status_get_real_time(status);
  507. info->alsa_time = alsa_time->tv_sec * NSEC_PER_SEC + alsa_time->tv_nsec;
  508. }
  509. static
  510. void add_ports(stream_t *str)
  511. {
  512. port_t *port;
  513. while (jack_ringbuffer_read(str->new_ports, (char*)&port, sizeof(port))) {
  514. debug_log("jack: inserted port %s\n", port->name);
  515. port_insert(str->ports, port);
  516. }
  517. }
  518. static
  519. void jack_process(alsa_seqmidi_t *self, struct process_info *info)
  520. {
  521. stream_t *str = &self->stream[info->dir];
  522. port_jack_func process = port_type[info->dir].jack_func;
  523. int i, del=0;
  524. add_ports(str);
  525. // process ports
  526. for (i=0; i<PORT_HASH_SIZE; ++i) {
  527. port_t **pport = &str->ports[i];
  528. while (*pport) {
  529. port_t *port = *pport;
  530. port->jack_buf = jack_port_get_buffer(port->jack_port, info->nframes);
  531. if (info->dir == PORT_INPUT)
  532. jack_midi_clear_buffer(port->jack_buf);
  533. if (!port->is_dead)
  534. (*process)(self, port, info);
  535. else if (jack_ringbuffer_write_space(self->port_del) >= sizeof(port)) {
  536. debug_log("jack: removed port %s\n", port->name);
  537. *pport = port->next;
  538. jack_ringbuffer_write(self->port_del, (char*)&port, sizeof(port));
  539. del++;
  540. continue;
  541. }
  542. pport = &port->next;
  543. }
  544. }
  545. if (del)
  546. sem_post(&self->port_sem);
  547. }
  548. /*
  549. * ============================ Input ==============================
  550. */
  551. static
  552. void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info *info)
  553. {
  554. // process port->early_events
  555. alsa_midi_event_t ev;
  556. while (jack_ringbuffer_read(port->early_events, (char*)&ev, sizeof(ev))) {
  557. jack_midi_data_t* buf;
  558. int64_t time = ev.time - info->period_start;
  559. if (time < 0)
  560. time = 0;
  561. else if (time >= info->nframes)
  562. time = info->nframes - 1;
  563. buf = jack_midi_event_reserve(port->jack_buf, (jack_nframes_t)time, ev.size);
  564. if (buf)
  565. jack_ringbuffer_read(port->early_events, (char*)buf, ev.size);
  566. else
  567. jack_ringbuffer_read_advance(port->early_events, ev.size);
  568. debug_log("input: it's time for %d bytes at %lld\n", ev.size, time);
  569. }
  570. }
  571. static
  572. void port_event(alsa_seqmidi_t *self, snd_seq_event_t *ev)
  573. {
  574. const snd_seq_addr_t addr = ev->data.addr;
  575. if (addr.client == self->client_id)
  576. return;
  577. if (ev->type == SND_SEQ_EVENT_PORT_START || ev->type == SND_SEQ_EVENT_PORT_CHANGE) {
  578. assert (jack_ringbuffer_write_space(self->port_add) >= sizeof(addr));
  579. debug_log("port_event: add/change %d:%d\n", addr.client, addr.port);
  580. jack_ringbuffer_write(self->port_add, (char*)&addr, sizeof(addr));
  581. sem_post(&self->port_sem);
  582. } else if (ev->type == SND_SEQ_EVENT_PORT_EXIT) {
  583. debug_log("port_event: del %d:%d\n", addr.client, addr.port);
  584. port_setdead(self->stream[PORT_INPUT].ports, addr);
  585. port_setdead(self->stream[PORT_OUTPUT].ports, addr);
  586. }
  587. }
  588. static
  589. void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct process_info* info)
  590. {
  591. jack_midi_data_t data[MAX_EVENT_SIZE];
  592. stream_t *str = &self->stream[PORT_INPUT];
  593. long size;
  594. int64_t alsa_time, time_offset;
  595. int64_t frame_offset, event_frame;
  596. port_t *port;
  597. port = port_get(str->ports, alsa_event->source);
  598. if (!port)
  599. return;
  600. /*
  601. * RPNs, NRPNs, Bank Change, etc. need special handling
  602. * but seems, ALSA does it for us already.
  603. */
  604. snd_midi_event_reset_decode(str->codec);
  605. if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0)
  606. return;
  607. // fixup NoteOn with vel 0
  608. if (data[0] == 0x90 && data[2] == 0x00) {
  609. data[0] = 0x80;
  610. data[2] = 0x40;
  611. }
  612. alsa_time = alsa_event->time.time.tv_sec * NSEC_PER_SEC + alsa_event->time.time.tv_nsec;
  613. time_offset = info->alsa_time - alsa_time;
  614. frame_offset = (info->sample_rate * time_offset) / NSEC_PER_SEC;
  615. event_frame = info->cur_frames - info->period_start - frame_offset + info->nframes;
  616. debug_log("input: %d bytes at event_frame=%d\n", (int)size, (int)event_frame);
  617. if (event_frame >= info->nframes &&
  618. jack_ringbuffer_write_space(port->early_events) >= (sizeof(alsa_midi_event_t) + size)) {
  619. alsa_midi_event_t ev;
  620. ev.time = event_frame + info->period_start;
  621. ev.size = size;
  622. jack_ringbuffer_write(port->early_events, (char*)&ev, sizeof(ev));
  623. jack_ringbuffer_write(port->early_events, (char*)data, size);
  624. debug_log("postponed to next frame +%d\n", (int) (event_frame - info->nframes));
  625. return;
  626. }
  627. if (event_frame < 0)
  628. event_frame = 0;
  629. else if (event_frame >= info->nframes)
  630. event_frame = info->nframes - 1;
  631. jack_midi_event_write(port->jack_buf, event_frame, data, size);
  632. }
  633. static
  634. void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes)
  635. {
  636. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  637. int res;
  638. snd_seq_event_t *event;
  639. struct process_info info;
  640. if (!self->keep_walking)
  641. return;
  642. set_process_info(&info, self, PORT_INPUT, nframes);
  643. jack_process(self, &info);
  644. while ((res = snd_seq_event_input(self->seq, &event))>0) {
  645. if (event->source.client == SND_SEQ_CLIENT_SYSTEM)
  646. port_event(self, event);
  647. else
  648. input_event(self, event, &info);
  649. }
  650. }
  651. /*
  652. * ============================ Output ==============================
  653. */
  654. static
  655. void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* info)
  656. {
  657. stream_t *str = &self->stream[info->dir];
  658. int nevents = jack_midi_get_event_count(port->jack_buf);
  659. int i;
  660. for (i=0; i<nevents; ++i) {
  661. jack_midi_event_t jack_event;
  662. snd_seq_event_t alsa_event;
  663. int64_t frame_offset;
  664. int64_t out_time;
  665. snd_seq_real_time_t out_rt;
  666. int err;
  667. jack_midi_event_get(&jack_event, port->jack_buf, i);
  668. snd_seq_ev_clear(&alsa_event);
  669. snd_midi_event_reset_encode(str->codec);
  670. if (!snd_midi_event_encode(str->codec, jack_event.buffer, jack_event.size, &alsa_event))
  671. continue; // invalid event
  672. snd_seq_ev_set_source(&alsa_event, self->port_id);
  673. snd_seq_ev_set_dest(&alsa_event, port->remote.client, port->remote.port);
  674. frame_offset = jack_event.time + info->period_start + info->nframes - info->cur_frames;
  675. out_time = info->alsa_time + (frame_offset * NSEC_PER_SEC) / info->sample_rate;
  676. debug_log("alsa_out: frame_offset = %lld, info->alsa_time = %lld, out_time = %lld, port->last_out_time = %lld\n",
  677. frame_offset, info->alsa_time, out_time, port->last_out_time);
  678. // we should use absolute time to prevent reordering caused by rounding errors
  679. if (out_time < port->last_out_time)
  680. out_time = port->last_out_time;
  681. else
  682. port->last_out_time = out_time;
  683. out_rt.tv_nsec = out_time % NSEC_PER_SEC;
  684. out_rt.tv_sec = out_time / NSEC_PER_SEC;
  685. snd_seq_ev_schedule_real(&alsa_event, self->queue, 0, &out_rt);
  686. err = snd_seq_event_output(self->seq, &alsa_event);
  687. debug_log("alsa_out: written %d bytes to %s at %+d (%lld): %d\n", (int)jack_event.size, port->name, (int)frame_offset, out_time, err);
  688. }
  689. }
  690. static
  691. void alsa_seqmidi_write(alsa_midi_t *m, jack_nframes_t nframes)
  692. {
  693. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  694. struct process_info info;
  695. if (!self->keep_walking)
  696. return;
  697. set_process_info(&info, self, PORT_OUTPUT, nframes);
  698. jack_process(self, &info);
  699. snd_seq_drain_output(self->seq);
  700. }