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.

926 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 <jack/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. if (str->new_ports)
  191. jack_ringbuffer_free(str->new_ports);
  192. }
  193. alsa_midi_t* alsa_seqmidi_new(jack_client_t *client, const char* alsa_name)
  194. {
  195. alsa_seqmidi_t *self = calloc(1, sizeof(alsa_seqmidi_t));
  196. debug_log("midi: new\n");
  197. if (!self)
  198. return NULL;
  199. self->jack = client;
  200. if (!alsa_name)
  201. alsa_name = "jack_midi";
  202. snprintf(self->alsa_name, sizeof(self->alsa_name), "%s", alsa_name);
  203. self->port_add = jack_ringbuffer_create(2*MAX_PORTS*sizeof(snd_seq_addr_t));
  204. self->port_del = jack_ringbuffer_create(2*MAX_PORTS*sizeof(port_t*));
  205. sem_init(&self->port_sem, 0, 0);
  206. stream_init(self, PORT_INPUT);
  207. stream_init(self, PORT_OUTPUT);
  208. self->ops.destroy = alsa_seqmidi_delete;
  209. self->ops.attach = alsa_seqmidi_attach;
  210. self->ops.detach = alsa_seqmidi_detach;
  211. self->ops.start = alsa_seqmidi_start;
  212. self->ops.stop = alsa_seqmidi_stop;
  213. self->ops.read = alsa_seqmidi_read;
  214. self->ops.write = alsa_seqmidi_write;
  215. return &self->ops;
  216. }
  217. static
  218. void alsa_seqmidi_delete(alsa_midi_t *m)
  219. {
  220. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  221. debug_log("midi: delete\n");
  222. alsa_seqmidi_detach(m);
  223. stream_close(self, PORT_OUTPUT);
  224. stream_close(self, PORT_INPUT);
  225. jack_ringbuffer_free(self->port_add);
  226. jack_ringbuffer_free(self->port_del);
  227. sem_close(&self->port_sem);
  228. free(self);
  229. }
  230. static
  231. int alsa_seqmidi_attach(alsa_midi_t *m)
  232. {
  233. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  234. int err;
  235. debug_log("midi: attach\n");
  236. if (self->seq)
  237. return -EALREADY;
  238. if ((err = snd_seq_open(&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0)) < 0) {
  239. error_log("failed to open alsa seq");
  240. return err;
  241. }
  242. snd_seq_set_client_name(self->seq, self->alsa_name);
  243. self->port_id = snd_seq_create_simple_port(self->seq, "port",
  244. SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_WRITE
  245. #ifndef JACK_MIDI_DEBUG
  246. |SND_SEQ_PORT_CAP_NO_EXPORT
  247. #endif
  248. ,SND_SEQ_PORT_TYPE_APPLICATION);
  249. self->client_id = snd_seq_client_id(self->seq);
  250. self->queue = snd_seq_alloc_queue(self->seq);
  251. snd_seq_start_queue(self->seq, self->queue, 0);
  252. stream_attach(self, PORT_INPUT);
  253. stream_attach(self, PORT_OUTPUT);
  254. snd_seq_nonblock(self->seq, 1);
  255. return 0;
  256. }
  257. static
  258. int alsa_seqmidi_detach(alsa_midi_t *m)
  259. {
  260. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  261. debug_log("midi: detach\n");
  262. if (!self->seq)
  263. return -EALREADY;
  264. alsa_seqmidi_stop(m);
  265. jack_ringbuffer_reset(self->port_add);
  266. free_ports(self, self->port_del);
  267. stream_detach(self, PORT_INPUT);
  268. stream_detach(self, PORT_OUTPUT);
  269. snd_seq_close(self->seq);
  270. self->seq = NULL;
  271. return 0;
  272. }
  273. static void* port_thread(void *);
  274. static void add_existing_ports(alsa_seqmidi_t *self);
  275. static void update_ports(alsa_seqmidi_t *self);
  276. static void add_ports(stream_t *str);
  277. static
  278. int alsa_seqmidi_start(alsa_midi_t *m)
  279. {
  280. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  281. int err;
  282. debug_log("midi: start\n");
  283. if (!self->seq)
  284. return -EBADF;
  285. if (self->keep_walking)
  286. return -EALREADY;
  287. snd_seq_connect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
  288. snd_seq_drop_input(self->seq);
  289. add_existing_ports(self);
  290. update_ports(self);
  291. add_ports(&self->stream[PORT_INPUT]);
  292. add_ports(&self->stream[PORT_OUTPUT]);
  293. self->keep_walking = 1;
  294. if ((err = pthread_create(&self->port_thread, NULL, port_thread, self))) {
  295. self->keep_walking = 0;
  296. return -errno;
  297. }
  298. return 0;
  299. }
  300. static
  301. int alsa_seqmidi_stop(alsa_midi_t *m)
  302. {
  303. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  304. debug_log("midi: stop\n");
  305. if (!self->keep_walking)
  306. return -EALREADY;
  307. snd_seq_disconnect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
  308. self->keep_walking = 0;
  309. sem_post(&self->port_sem);
  310. pthread_join(self->port_thread, NULL);
  311. self->port_thread = 0;
  312. return 0;
  313. }
  314. static
  315. int alsa_connect_from(alsa_seqmidi_t *self, int client, int port)
  316. {
  317. snd_seq_port_subscribe_t* sub;
  318. snd_seq_addr_t seq_addr;
  319. int err;
  320. snd_seq_port_subscribe_alloca(&sub);
  321. seq_addr.client = client;
  322. seq_addr.port = port;
  323. snd_seq_port_subscribe_set_sender(sub, &seq_addr);
  324. seq_addr.client = self->client_id;
  325. seq_addr.port = self->port_id;
  326. snd_seq_port_subscribe_set_dest(sub, &seq_addr);
  327. snd_seq_port_subscribe_set_time_update(sub, 1);
  328. snd_seq_port_subscribe_set_queue(sub, self->queue);
  329. snd_seq_port_subscribe_set_time_real(sub, 1);
  330. if ((err=snd_seq_subscribe_port(self->seq, sub)))
  331. error_log("can't subscribe to %d:%d - %s\n", client, port, snd_strerror(err));
  332. return err;
  333. }
  334. /*
  335. * ==================== Port routines =============================
  336. */
  337. static inline
  338. int port_hash(snd_seq_addr_t addr)
  339. {
  340. return (addr.client + addr.port) % PORT_HASH_SIZE;
  341. }
  342. static
  343. port_t* port_get(port_hash_t hash, snd_seq_addr_t addr)
  344. {
  345. port_t **pport = &hash[port_hash(addr)];
  346. while (*pport) {
  347. port_t *port = *pport;
  348. if (port->remote.client == addr.client && port->remote.port == addr.port)
  349. return port;
  350. pport = &port->next;
  351. }
  352. return NULL;
  353. }
  354. static
  355. void port_insert(port_hash_t hash, port_t *port)
  356. {
  357. port_t **pport = &hash[port_hash(port->remote)];
  358. port->next = *pport;
  359. *pport = port;
  360. }
  361. static
  362. void port_setdead(port_hash_t hash, snd_seq_addr_t addr)
  363. {
  364. port_t *port = port_get(hash, addr);
  365. if (port)
  366. port->is_dead = 1; // see jack_process
  367. else
  368. debug_log("port_setdead: not found (%d:%d)\n", addr.client, addr.port);
  369. }
  370. static
  371. void port_free(alsa_seqmidi_t *self, port_t *port)
  372. {
  373. //snd_seq_disconnect_from(self->seq, self->port_id, port->remote.client, port->remote.port);
  374. //snd_seq_disconnect_to(self->seq, self->port_id, port->remote.client, port->remote.port);
  375. if (port->early_events)
  376. jack_ringbuffer_free(port->early_events);
  377. if (port->jack_port)
  378. jack_port_unregister(self->jack, port->jack_port);
  379. // info_log("port deleted: %s\n", port->name);
  380. free(port);
  381. }
  382. static
  383. port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const snd_seq_port_info_t *info)
  384. {
  385. snd_seq_client_info_t* client_info;
  386. port_t *port;
  387. char *c;
  388. int err;
  389. int jack_caps;
  390. port = calloc(1, sizeof(port_t));
  391. if (!port)
  392. return NULL;
  393. port->remote = addr;
  394. snd_seq_client_info_alloca (&client_info);
  395. snd_seq_get_any_client_info (self->seq, addr.client, client_info);
  396. snprintf(port->name, sizeof(port->name), "%s/midi_%s_%d",
  397. snd_seq_client_info_get_name(client_info), port_type[type].name, addr.port+1);
  398. // replace all offending characters by -
  399. for (c = port->name; *c; ++c)
  400. if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')')
  401. *c = '-';
  402. jack_caps = port_type[type].jack_caps;
  403. /* mark anything that looks like a hardware port as physical&terminal */
  404. if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE|SND_SEQ_PORT_TYPE_PORT|SND_SEQ_PORT_TYPE_SPECIFIC)) {
  405. jack_caps |= (JackPortIsPhysical|JackPortIsTerminal);
  406. }
  407. port->jack_port = jack_port_register(self->jack,
  408. port->name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0);
  409. if (!port->jack_port)
  410. goto failed;
  411. /* generate an alias */
  412. snprintf(port->name, sizeof(port->name), "%s:midi/%s_%d",
  413. snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port+1);
  414. // replace all offending characters by -
  415. for (c = port->name; *c; ++c)
  416. if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')')
  417. *c = '-';
  418. jack_port_set_alias (port->jack_port, port->name);
  419. if (type == PORT_INPUT)
  420. err = alsa_connect_from(self, port->remote.client, port->remote.port);
  421. else
  422. err = snd_seq_connect_to(self->seq, self->port_id, port->remote.client, port->remote.port);
  423. if (err)
  424. goto failed;
  425. port->early_events = jack_ringbuffer_create(MAX_EVENT_SIZE*16);
  426. // info_log("port created: %s\n", port->name);
  427. return port;
  428. failed:
  429. port_free(self, port);
  430. return NULL;
  431. }
  432. /*
  433. * ==================== Port add/del handling thread ==============================
  434. */
  435. static
  436. void update_port_type(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t *info)
  437. {
  438. stream_t *str = &self->stream[type];
  439. int alsa_mask = port_type[type].alsa_mask;
  440. port_t *port = port_get(str->ports, addr);
  441. debug_log("update_port_type(%d:%d)\n", addr.client, addr.port);
  442. if (port && (caps & alsa_mask)!=alsa_mask) {
  443. debug_log("setdead: %s\n", port->name);
  444. port->is_dead = 1;
  445. }
  446. if (!port && (caps & alsa_mask)==alsa_mask) {
  447. assert (jack_ringbuffer_write_space(str->new_ports) >= sizeof(port));
  448. port = port_create(self, type, addr, info);
  449. if (port)
  450. jack_ringbuffer_write(str->new_ports, (char*)&port, sizeof(port));
  451. }
  452. }
  453. static
  454. void update_port(alsa_seqmidi_t *self, snd_seq_addr_t addr, const snd_seq_port_info_t *info)
  455. {
  456. unsigned int port_caps = snd_seq_port_info_get_capability(info);
  457. if (port_caps & SND_SEQ_PORT_CAP_NO_EXPORT)
  458. return;
  459. update_port_type(self, PORT_INPUT, addr, port_caps, info);
  460. update_port_type(self, PORT_OUTPUT,addr, port_caps, info);
  461. }
  462. static
  463. void free_ports(alsa_seqmidi_t *self, jack_ringbuffer_t *ports)
  464. {
  465. port_t *port;
  466. int sz;
  467. while ((sz = jack_ringbuffer_read(ports, (char*)&port, sizeof(port)))) {
  468. assert (sz == sizeof(port));
  469. port_free(self, port);
  470. }
  471. }
  472. static
  473. void update_ports(alsa_seqmidi_t *self)
  474. {
  475. snd_seq_addr_t addr;
  476. snd_seq_port_info_t *info;
  477. int size;
  478. snd_seq_port_info_alloca(&info);
  479. while ((size = jack_ringbuffer_read(self->port_add, (char*)&addr, sizeof(addr)))) {
  480. int err;
  481. assert (size == sizeof(addr));
  482. assert (addr.client != self->client_id);
  483. if ((err=snd_seq_get_any_port_info(self->seq, addr.client, addr.port, info))>=0) {
  484. update_port(self, addr, info);
  485. } else {
  486. //port_setdead(self->stream[PORT_INPUT].ports, addr);
  487. //port_setdead(self->stream[PORT_OUTPUT].ports, addr);
  488. }
  489. }
  490. }
  491. static
  492. void* port_thread(void *arg)
  493. {
  494. alsa_seqmidi_t *self = arg;
  495. while (self->keep_walking) {
  496. sem_wait(&self->port_sem);
  497. free_ports(self, self->port_del);
  498. update_ports(self);
  499. }
  500. debug_log("port_thread exited\n");
  501. return NULL;
  502. }
  503. static
  504. void add_existing_ports(alsa_seqmidi_t *self)
  505. {
  506. snd_seq_addr_t addr;
  507. snd_seq_client_info_t *client_info;
  508. snd_seq_port_info_t *port_info;
  509. snd_seq_client_info_alloca(&client_info);
  510. snd_seq_port_info_alloca(&port_info);
  511. snd_seq_client_info_set_client(client_info, -1);
  512. while (snd_seq_query_next_client(self->seq, client_info) >= 0)
  513. {
  514. addr.client = snd_seq_client_info_get_client(client_info);
  515. if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id)
  516. continue;
  517. snd_seq_port_info_set_client(port_info, addr.client);
  518. snd_seq_port_info_set_port(port_info, -1);
  519. while (snd_seq_query_next_port(self->seq, port_info) >= 0)
  520. {
  521. addr.port = snd_seq_port_info_get_port(port_info);
  522. update_port(self, addr, port_info);
  523. }
  524. }
  525. }
  526. /*
  527. * =================== Input/output port handling =========================
  528. */
  529. static
  530. void set_process_info(struct process_info *info, alsa_seqmidi_t *self, int dir, jack_nframes_t nframes)
  531. {
  532. const snd_seq_real_time_t* alsa_time;
  533. snd_seq_queue_status_t *status;
  534. snd_seq_queue_status_alloca(&status);
  535. info->dir = dir;
  536. info->period_start = jack_last_frame_time(self->jack);
  537. info->nframes = nframes;
  538. info->sample_rate = jack_get_sample_rate(self->jack);
  539. info->cur_frames = jack_frame_time(self->jack);
  540. // immediately get alsa'a real time (uhh, why everybody has their on 'real' time)
  541. snd_seq_get_queue_status(self->seq, self->queue, status);
  542. alsa_time = snd_seq_queue_status_get_real_time(status);
  543. info->alsa_time = alsa_time->tv_sec * NSEC_PER_SEC + alsa_time->tv_nsec;
  544. if (info->period_start + info->nframes < info->cur_frames) {
  545. int periods_lost = (info->cur_frames - info->period_start) / info->nframes;
  546. info->period_start += periods_lost * info->nframes;
  547. debug_log("xrun detected: %d periods lost\n", periods_lost);
  548. }
  549. }
  550. static
  551. void add_ports(stream_t *str)
  552. {
  553. port_t *port;
  554. while (jack_ringbuffer_read(str->new_ports, (char*)&port, sizeof(port))) {
  555. debug_log("jack: inserted port %s\n", port->name);
  556. port_insert(str->ports, port);
  557. }
  558. }
  559. static
  560. void jack_process(alsa_seqmidi_t *self, struct process_info *info)
  561. {
  562. stream_t *str = &self->stream[info->dir];
  563. port_jack_func process = port_type[info->dir].jack_func;
  564. int i, del=0;
  565. add_ports(str);
  566. // process ports
  567. for (i=0; i<PORT_HASH_SIZE; ++i) {
  568. port_t **pport = &str->ports[i];
  569. while (*pport) {
  570. port_t *port = *pport;
  571. port->jack_buf = jack_port_get_buffer(port->jack_port, info->nframes);
  572. if (info->dir == PORT_INPUT)
  573. jack_midi_clear_buffer(port->jack_buf);
  574. if (!port->is_dead)
  575. (*process)(self, port, info);
  576. else if (jack_ringbuffer_write_space(self->port_del) >= sizeof(port)) {
  577. debug_log("jack: removed port %s\n", port->name);
  578. *pport = port->next;
  579. jack_ringbuffer_write(self->port_del, (char*)&port, sizeof(port));
  580. del++;
  581. continue;
  582. }
  583. pport = &port->next;
  584. }
  585. }
  586. if (del)
  587. sem_post(&self->port_sem);
  588. }
  589. /*
  590. * ============================ Input ==============================
  591. */
  592. static
  593. void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info *info)
  594. {
  595. // process port->early_events
  596. alsa_midi_event_t ev;
  597. while (jack_ringbuffer_read(port->early_events, (char*)&ev, sizeof(ev))) {
  598. jack_midi_data_t* buf;
  599. jack_nframes_t time = ev.time - info->period_start;
  600. if (time < 0)
  601. time = 0;
  602. else if (time >= info->nframes)
  603. time = info->nframes - 1;
  604. buf = jack_midi_event_reserve(port->jack_buf, time, ev.size);
  605. if (buf)
  606. jack_ringbuffer_read(port->early_events, (char*)buf, ev.size);
  607. else
  608. jack_ringbuffer_read_advance(port->early_events, ev.size);
  609. debug_log("input: it's time for %d bytes at %d\n", ev.size, time);
  610. }
  611. }
  612. static
  613. void port_event(alsa_seqmidi_t *self, snd_seq_event_t *ev)
  614. {
  615. const snd_seq_addr_t addr = ev->data.addr;
  616. if (addr.client == self->client_id)
  617. return;
  618. if (ev->type == SND_SEQ_EVENT_PORT_START || ev->type == SND_SEQ_EVENT_PORT_CHANGE) {
  619. assert (jack_ringbuffer_write_space(self->port_add) >= sizeof(addr));
  620. debug_log("port_event: add/change %d:%d\n", addr.client, addr.port);
  621. jack_ringbuffer_write(self->port_add, (char*)&addr, sizeof(addr));
  622. sem_post(&self->port_sem);
  623. } else if (ev->type == SND_SEQ_EVENT_PORT_EXIT) {
  624. debug_log("port_event: del %d:%d\n", addr.client, addr.port);
  625. port_setdead(self->stream[PORT_INPUT].ports, addr);
  626. port_setdead(self->stream[PORT_OUTPUT].ports, addr);
  627. }
  628. }
  629. static
  630. void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct process_info* info)
  631. {
  632. jack_midi_data_t data[MAX_EVENT_SIZE];
  633. stream_t *str = &self->stream[PORT_INPUT];
  634. long size;
  635. int64_t alsa_time, time_offset;
  636. int64_t frame_offset, event_frame;
  637. port_t *port;
  638. port = port_get(str->ports, alsa_event->source);
  639. if (!port)
  640. return;
  641. /*
  642. * RPNs, NRPNs, Bank Change, etc. need special handling
  643. * but seems, ALSA does it for us already.
  644. */
  645. snd_midi_event_reset_decode(str->codec);
  646. if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0)
  647. return;
  648. // fixup NoteOn with vel 0
  649. if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) {
  650. data[0] = 0x80 + (data[0] & 0x0F);
  651. data[2] = 0x40;
  652. }
  653. alsa_time = alsa_event->time.time.tv_sec * NSEC_PER_SEC + alsa_event->time.time.tv_nsec;
  654. time_offset = info->alsa_time - alsa_time;
  655. frame_offset = (info->sample_rate * time_offset) / NSEC_PER_SEC;
  656. event_frame = (int64_t)info->cur_frames - info->period_start - frame_offset + info->nframes;
  657. debug_log("input: %d bytes at event_frame=%d\n", (int)size, (int)event_frame);
  658. if (event_frame >= info->nframes &&
  659. jack_ringbuffer_write_space(port->early_events) >= (sizeof(alsa_midi_event_t) + size)) {
  660. alsa_midi_event_t ev;
  661. ev.time = event_frame + info->period_start;
  662. ev.size = size;
  663. jack_ringbuffer_write(port->early_events, (char*)&ev, sizeof(ev));
  664. jack_ringbuffer_write(port->early_events, (char*)data, size);
  665. debug_log("postponed to next frame +%d\n", (int) (event_frame - info->nframes));
  666. return;
  667. }
  668. if (event_frame < 0)
  669. event_frame = 0;
  670. else if (event_frame >= info->nframes)
  671. event_frame = info->nframes - 1;
  672. jack_midi_event_write(port->jack_buf, event_frame, data, size);
  673. }
  674. static
  675. void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes)
  676. {
  677. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  678. int res;
  679. snd_seq_event_t *event;
  680. struct process_info info;
  681. if (!self->keep_walking)
  682. return;
  683. set_process_info(&info, self, PORT_INPUT, nframes);
  684. jack_process(self, &info);
  685. while ((res = snd_seq_event_input(self->seq, &event))>0) {
  686. if (event->source.client == SND_SEQ_CLIENT_SYSTEM)
  687. port_event(self, event);
  688. else
  689. input_event(self, event, &info);
  690. }
  691. }
  692. /*
  693. * ============================ Output ==============================
  694. */
  695. static
  696. void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* info)
  697. {
  698. stream_t *str = &self->stream[info->dir];
  699. int nevents = jack_midi_get_event_count(port->jack_buf);
  700. int i;
  701. for (i=0; i<nevents; ++i) {
  702. jack_midi_event_t jack_event;
  703. snd_seq_event_t alsa_event;
  704. int64_t frame_offset;
  705. int64_t out_time;
  706. snd_seq_real_time_t out_rt;
  707. int err;
  708. jack_midi_event_get(&jack_event, port->jack_buf, i);
  709. snd_seq_ev_clear(&alsa_event);
  710. snd_midi_event_reset_encode(str->codec);
  711. if (!snd_midi_event_encode(str->codec, jack_event.buffer, jack_event.size, &alsa_event))
  712. continue; // invalid event
  713. snd_seq_ev_set_source(&alsa_event, self->port_id);
  714. snd_seq_ev_set_dest(&alsa_event, port->remote.client, port->remote.port);
  715. /* NOTE: in case of xrun it could become negative, so it is essential to use signed type! */
  716. frame_offset = (int64_t)jack_event.time + info->period_start + info->nframes - info->cur_frames;
  717. if (frame_offset < 0) {
  718. frame_offset = info->nframes + jack_event.time;
  719. error_log("internal xrun detected: frame_offset = %"PRId64"\n", frame_offset);
  720. }
  721. /* Ken Ellinwood reported problems with this assert.
  722. * Seems, magic 2 should be replaced with nperiods. */
  723. //FIXME: assert (frame_offset < info->nframes*2);
  724. //if (frame_offset < info->nframes * info->nperiods)
  725. // debug_log("alsa_out: BLAH-BLAH-BLAH");
  726. out_time = info->alsa_time + (frame_offset * NSEC_PER_SEC) / info->sample_rate;
  727. // we should use absolute time to prevent reordering caused by rounding errors
  728. if (out_time < port->last_out_time) {
  729. debug_log("alsa_out: limiting out_time %lld at %lld\n", out_time, port->last_out_time);
  730. out_time = port->last_out_time;
  731. } else
  732. port->last_out_time = out_time;
  733. out_rt.tv_nsec = out_time % NSEC_PER_SEC;
  734. out_rt.tv_sec = out_time / NSEC_PER_SEC;
  735. snd_seq_ev_schedule_real(&alsa_event, self->queue, 0, &out_rt);
  736. err = snd_seq_event_output(self->seq, &alsa_event);
  737. debug_log("alsa_out: written %d bytes to %s at %d (%lld): %d %s\n",
  738. jack_event.size, port->name, (int)frame_offset, out_time - info->alsa_time, err, err < 0 ? snd_strerror(err) : "bytes queued");
  739. }
  740. }
  741. static
  742. void alsa_seqmidi_write(alsa_midi_t *m, jack_nframes_t nframes)
  743. {
  744. alsa_seqmidi_t *self = (alsa_seqmidi_t*) m;
  745. struct process_info info;
  746. if (!self->keep_walking)
  747. return;
  748. set_process_info(&info, self, PORT_OUTPUT, nframes);
  749. jack_process(self, &info);
  750. snd_seq_drain_output(self->seq);
  751. }