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.

245 lines
6.2KB

  1. /* -*- Mode: C ; c-basic-offset: 2 -*- */
  2. /*
  3. * ALSA SEQ < - > JACK MIDI bridge
  4. *
  5. * Copyright (c) 2006,2007 Dmitry S. Baikov <c0ff@konstruktiv.org>
  6. * Copyright (c) 2007,2008,2009 Nedko Arnaudov <nedko@arnaudov.name>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; version 2 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include <stdbool.h>
  22. #include <semaphore.h>
  23. #include <alsa/asoundlib.h>
  24. #include <jack/jack.h>
  25. #include <jack/ringbuffer.h>
  26. #include "list.h"
  27. #include "a2j.h"
  28. #include "port.h"
  29. #include "port_hash.h"
  30. #include "port_thread.h"
  31. struct a2j_port *
  32. a2j_find_port_by_addr (
  33. struct a2j_stream * stream_ptr,
  34. snd_seq_addr_t addr)
  35. {
  36. struct list_head * node_ptr;
  37. struct a2j_port * port_ptr;
  38. list_for_each (node_ptr, &stream_ptr->list){
  39. port_ptr = list_entry (node_ptr, struct a2j_port, siblings);
  40. if (port_ptr->remote.client == addr.client && port_ptr->remote.port == addr.port) {
  41. return port_ptr;
  42. }
  43. }
  44. return NULL;
  45. }
  46. struct a2j_port *
  47. a2j_find_port_by_jack_port_name (
  48. struct a2j_stream * stream_ptr,
  49. const char * jack_port)
  50. {
  51. struct list_head * node_ptr;
  52. struct a2j_port * port_ptr;
  53. list_for_each (node_ptr, &stream_ptr->list){
  54. port_ptr = list_entry (node_ptr, struct a2j_port, siblings);
  55. if (strcmp (port_ptr->name, jack_port) == 0) {
  56. return port_ptr;
  57. }
  58. }
  59. return NULL;
  60. }
  61. /*
  62. * ==================== Port add/del handling thread ==============================
  63. */
  64. static
  65. void
  66. a2j_update_port_type (alsa_midi_driver_t * driver, int dir, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t * info)
  67. {
  68. struct a2j_stream * stream_ptr;
  69. int alsa_mask;
  70. struct a2j_port * port_ptr;
  71. a2j_debug ("update_port_type(%d:%d)", addr.client, addr.port);
  72. stream_ptr = &driver->stream[dir];
  73. port_ptr = a2j_find_port_by_addr (stream_ptr, addr);
  74. if (dir == A2J_PORT_CAPTURE) {
  75. alsa_mask = SND_SEQ_PORT_CAP_SUBS_READ;
  76. } else {
  77. alsa_mask = SND_SEQ_PORT_CAP_SUBS_WRITE;
  78. }
  79. if (port_ptr != NULL && (caps & alsa_mask) != alsa_mask) {
  80. a2j_debug ("setdead: %s", port_ptr->name);
  81. port_ptr->is_dead = true;
  82. }
  83. if (port_ptr == NULL && (caps & alsa_mask) == alsa_mask) {
  84. if (jack_ringbuffer_write_space (stream_ptr->new_ports) >= sizeof(port_ptr)) {
  85. port_ptr = a2j_port_create (driver, dir, addr, info);
  86. if (port_ptr != NULL) {
  87. jack_ringbuffer_write (stream_ptr->new_ports, (char*)&port_ptr, sizeof(port_ptr));
  88. }
  89. } else {
  90. a2j_error ( "dropping new port event... increase MAX_PORTS" );
  91. }
  92. }
  93. }
  94. void
  95. a2j_update_port (alsa_midi_driver_t * driver, snd_seq_addr_t addr, const snd_seq_port_info_t * info)
  96. {
  97. unsigned int port_caps = snd_seq_port_info_get_capability (info);
  98. unsigned int port_type = snd_seq_port_info_get_type (info);
  99. a2j_debug ("port %u:%u", addr.client, addr.port);
  100. a2j_debug ("port type: 0x%08X", port_type);
  101. a2j_debug ("port caps: 0x%08X", port_caps);
  102. if (port_type & SND_SEQ_PORT_TYPE_SPECIFIC) {
  103. a2j_debug ("SPECIFIC");
  104. }
  105. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GENERIC) {
  106. a2j_debug ("MIDI_GENERIC");
  107. }
  108. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GM) {
  109. a2j_debug ("MIDI_GM");
  110. }
  111. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GS) {
  112. a2j_debug ("MIDI_GS");
  113. }
  114. if (port_type & SND_SEQ_PORT_TYPE_MIDI_XG) {
  115. a2j_debug ("MIDI_XG");
  116. }
  117. if (port_type & SND_SEQ_PORT_TYPE_MIDI_MT32) {
  118. a2j_debug ("MIDI_MT32");
  119. }
  120. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GM2) {
  121. a2j_debug ("MIDI_GM2");
  122. }
  123. if (port_type & SND_SEQ_PORT_TYPE_SYNTH) {
  124. a2j_debug ("SYNTH");
  125. }
  126. if (port_type & SND_SEQ_PORT_TYPE_DIRECT_SAMPLE) {
  127. a2j_debug ("DIRECT_SAMPLE");
  128. }
  129. if (port_type & SND_SEQ_PORT_TYPE_SAMPLE) {
  130. a2j_debug ("SAMPLE");
  131. }
  132. if (port_type & SND_SEQ_PORT_TYPE_HARDWARE) {
  133. a2j_debug ("HARDWARE");
  134. }
  135. if (port_type & SND_SEQ_PORT_TYPE_SOFTWARE) {
  136. a2j_debug ("SOFTWARE");
  137. }
  138. if (port_type & SND_SEQ_PORT_TYPE_SYNTHESIZER) {
  139. a2j_debug ("SYNTHESIZER");
  140. }
  141. if (port_type & SND_SEQ_PORT_TYPE_PORT) {
  142. a2j_debug ("PORT");
  143. }
  144. if (port_type & SND_SEQ_PORT_TYPE_APPLICATION) {
  145. a2j_debug ("APPLICATION");
  146. }
  147. if (port_type == 0) {
  148. a2j_debug ("Ignoring port of type 0");
  149. return;
  150. }
  151. if (port_caps & SND_SEQ_PORT_CAP_NO_EXPORT) {
  152. a2j_debug ("Ignoring no-export port");
  153. return;
  154. }
  155. a2j_update_port_type (driver, A2J_PORT_CAPTURE, addr, port_caps, info);
  156. a2j_update_port_type (driver, A2J_PORT_PLAYBACK, addr, port_caps, info);
  157. }
  158. void
  159. a2j_free_ports (alsa_midi_driver_t * driver)
  160. {
  161. struct a2j_port *port;
  162. int sz;
  163. while ((sz = jack_ringbuffer_read (driver->port_del, (char*)&port, sizeof(port)))) {
  164. assert (sz == sizeof(port));
  165. a2j_debug ("port deleted: %s", port->name);
  166. list_del (&port->siblings);
  167. a2j_port_free (port);
  168. }
  169. }
  170. void
  171. a2j_update_ports (alsa_midi_driver_t * driver, snd_seq_addr_t addr)
  172. {
  173. snd_seq_port_info_t * info;
  174. int err;
  175. assert (addr.client != driver->client_id);
  176. snd_seq_port_info_alloca (&info);
  177. if ((err = snd_seq_get_any_port_info (driver->seq, addr.client, addr.port, info)) >= 0) {
  178. a2j_debug ("updating: %d:%d", addr.client, addr.port);
  179. a2j_update_port (driver, addr, info);
  180. } else {
  181. a2j_debug ("setting dead: %d:%d", addr.client, addr.port);
  182. a2j_port_setdead (driver->stream[A2J_PORT_CAPTURE].port_hash, addr);
  183. a2j_port_setdead (driver->stream[A2J_PORT_PLAYBACK].port_hash, addr);
  184. }
  185. }
  186. void
  187. a2j_new_ports (alsa_midi_driver_t * driver, snd_seq_addr_t addr)
  188. {
  189. snd_seq_port_info_t * port_info;
  190. assert (addr.client != driver->client_id);
  191. snd_seq_port_info_alloca (&port_info);
  192. a2j_debug ("adding new port: %d:%d", addr.client, addr.port);
  193. snd_seq_port_info_set_client (port_info, addr.client);
  194. snd_seq_port_info_set_port (port_info, -1);
  195. while (snd_seq_query_next_port (driver->seq, port_info) >= 0) {
  196. addr.port = snd_seq_port_info_get_port (port_info);
  197. a2j_update_port (driver, addr, port_info);
  198. }
  199. }