JACK tools
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.

236 lines
5.7KB

  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. {
  40. port_ptr = list_entry(node_ptr, struct a2j_port, siblings);
  41. if (port_ptr->remote.client == addr.client && port_ptr->remote.port == addr.port)
  42. {
  43. return port_ptr;
  44. }
  45. }
  46. return NULL;
  47. }
  48. struct a2j_port *
  49. a2j_find_port_by_jack_port_name(
  50. struct a2j_stream * stream_ptr,
  51. const char * jack_port)
  52. {
  53. struct list_head * node_ptr;
  54. struct a2j_port * port_ptr;
  55. list_for_each(node_ptr, &stream_ptr->list)
  56. {
  57. port_ptr = list_entry(node_ptr, struct a2j_port, siblings);
  58. if (strcmp(port_ptr->name, jack_port) == 0)
  59. {
  60. return port_ptr;
  61. }
  62. }
  63. return NULL;
  64. }
  65. /*
  66. * ==================== Port add/del handling thread ==============================
  67. */
  68. static
  69. void
  70. a2j_update_port_type (struct a2j * self, int dir, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t * info)
  71. {
  72. struct a2j_stream * stream_ptr;
  73. int alsa_mask;
  74. struct a2j_port * port_ptr;
  75. a2j_debug("update_port_type(%d:%d)", addr.client, addr.port);
  76. stream_ptr = &self->stream[dir];
  77. port_ptr = a2j_find_port_by_addr(stream_ptr, addr);
  78. if (dir == A2J_PORT_CAPTURE) {
  79. alsa_mask = SND_SEQ_PORT_CAP_SUBS_READ;
  80. } else {
  81. alsa_mask = SND_SEQ_PORT_CAP_SUBS_WRITE;
  82. }
  83. if (port_ptr != NULL && (caps & alsa_mask) != alsa_mask) {
  84. a2j_debug("setdead: %s", port_ptr->name);
  85. port_ptr->is_dead = true;
  86. }
  87. if (port_ptr == NULL && (caps & alsa_mask) == alsa_mask) {
  88. if(jack_ringbuffer_write_space(stream_ptr->new_ports) >= sizeof(port_ptr)) {
  89. port_ptr = a2j_port_create (self, dir, addr, info);
  90. if (port_ptr != NULL) {
  91. jack_ringbuffer_write(stream_ptr->new_ports, (char *)&port_ptr, sizeof(port_ptr));
  92. }
  93. } else {
  94. a2j_error( "dropping new port event... increase MAX_PORTS" );
  95. }
  96. }
  97. }
  98. void
  99. a2j_update_port (struct a2j * self, snd_seq_addr_t addr, const snd_seq_port_info_t * info)
  100. {
  101. unsigned int port_caps = snd_seq_port_info_get_capability(info);
  102. unsigned int port_type = snd_seq_port_info_get_type(info);
  103. a2j_debug("port %u:%u", addr.client, addr.port);
  104. a2j_debug("port type: 0x%08X", port_type);
  105. a2j_debug("port caps: 0x%08X", port_caps);
  106. if (port_type & SND_SEQ_PORT_TYPE_SPECIFIC) {
  107. a2j_debug("SPECIFIC");
  108. }
  109. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GENERIC) {
  110. a2j_debug("MIDI_GENERIC");
  111. }
  112. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GM) {
  113. a2j_debug("MIDI_GM");
  114. }
  115. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GS) {
  116. a2j_debug("MIDI_GS");
  117. }
  118. if (port_type & SND_SEQ_PORT_TYPE_MIDI_XG) {
  119. a2j_debug("MIDI_XG");
  120. }
  121. if (port_type & SND_SEQ_PORT_TYPE_MIDI_MT32) {
  122. a2j_debug("MIDI_MT32");
  123. }
  124. if (port_type & SND_SEQ_PORT_TYPE_MIDI_GM2) {
  125. a2j_debug("MIDI_GM2");
  126. }
  127. if (port_type & SND_SEQ_PORT_TYPE_SYNTH) {
  128. a2j_debug("SYNTH");
  129. }
  130. if (port_type & SND_SEQ_PORT_TYPE_DIRECT_SAMPLE) {
  131. a2j_debug("DIRECT_SAMPLE");
  132. }
  133. if (port_type & SND_SEQ_PORT_TYPE_SAMPLE) {
  134. a2j_debug("SAMPLE");
  135. }
  136. if (port_type & SND_SEQ_PORT_TYPE_HARDWARE) {
  137. a2j_debug("HARDWARE");
  138. }
  139. if (port_type & SND_SEQ_PORT_TYPE_SOFTWARE) {
  140. a2j_debug("SOFTWARE");
  141. }
  142. if (port_type & SND_SEQ_PORT_TYPE_SYNTHESIZER) {
  143. a2j_debug("SYNTHESIZER");
  144. }
  145. if (port_type & SND_SEQ_PORT_TYPE_PORT) {
  146. a2j_debug("PORT");
  147. }
  148. if (port_type & SND_SEQ_PORT_TYPE_APPLICATION) {
  149. a2j_debug("APPLICATION");
  150. }
  151. if (port_type == 0) {
  152. a2j_debug("Ignoring port of type 0");
  153. return;
  154. }
  155. if (port_caps & SND_SEQ_PORT_CAP_NO_EXPORT) {
  156. a2j_debug("Ignoring no-export port");
  157. return;
  158. }
  159. a2j_update_port_type (self, A2J_PORT_CAPTURE, addr, port_caps, info);
  160. a2j_update_port_type (self, A2J_PORT_PLAYBACK, addr, port_caps, info);
  161. }
  162. void
  163. a2j_free_ports (jack_ringbuffer_t * ports)
  164. {
  165. struct a2j_port *port;
  166. int sz;
  167. while ((sz = jack_ringbuffer_read (ports, (char*)&port, sizeof(port)))) {
  168. assert (sz == sizeof(port));
  169. a2j_debug("port deleted: %s", port->name);
  170. list_del (&port->siblings);
  171. a2j_port_free(port);
  172. }
  173. }
  174. void
  175. a2j_update_ports (struct a2j * self)
  176. {
  177. snd_seq_addr_t addr;
  178. int size;
  179. while ((size = jack_ringbuffer_read(self->port_add, (char *)&addr, sizeof(addr))) != 0) {
  180. snd_seq_port_info_t * info;
  181. int err;
  182. snd_seq_port_info_alloca(&info);
  183. assert (size == sizeof(addr));
  184. assert (addr.client != self->client_id);
  185. if ((err = snd_seq_get_any_port_info(self->seq, addr.client, addr.port, info)) >= 0) {
  186. a2j_update_port(self, addr, info);
  187. } else {
  188. a2j_port_setdead(self->stream[A2J_PORT_CAPTURE].port_hash, addr);
  189. a2j_port_setdead(self->stream[A2J_PORT_PLAYBACK].port_hash, addr);
  190. }
  191. }
  192. }