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.

312 lines
7.7KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. $Id: hammerfall.c,v 1.3 2005/09/29 14:51:59 letz Exp $
  15. */
  16. //#include <jack/hardware.h>
  17. //#include <jack/internal.h>
  18. //#include "internal.h"
  19. #include "hardware.h"
  20. #include "alsa_driver.h"
  21. #include "hammerfall.h"
  22. #include "JackError.h"
  23. #define FALSE 0
  24. #define TRUE 1
  25. /* Set this to 1 if you want this compile error:
  26. * warning: `hammerfall_monitor_controls' defined but not used */
  27. #define HAMMERFALL_MONITOR_CONTROLS 0
  28. static void
  29. set_control_id (snd_ctl_elem_id_t *ctl, const char *name)
  30. {
  31. snd_ctl_elem_id_set_name (ctl, name);
  32. snd_ctl_elem_id_set_numid (ctl, 0);
  33. snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_MIXER);
  34. snd_ctl_elem_id_set_device (ctl, 0);
  35. snd_ctl_elem_id_set_subdevice (ctl, 0);
  36. snd_ctl_elem_id_set_index (ctl, 0);
  37. }
  38. #if HAMMERFALL_MONITOR_CONTROLS
  39. static void
  40. hammerfall_broadcast_channel_status_change (hammerfall_t *h, int lock, int sync, channel_t lowchn, channel_t highchn)
  41. {
  42. channel_t chn;
  43. ClockSyncStatus status = 0;
  44. if (lock) {
  45. status |= Lock;
  46. } else {
  47. status |= NoLock;
  48. }
  49. if (sync) {
  50. status |= Sync;
  51. } else {
  52. status |= NoSync;
  53. }
  54. for (chn = lowchn; chn < highchn; chn++) {
  55. alsa_driver_set_clock_sync_status (h->driver, chn, status);
  56. }
  57. }
  58. static void
  59. hammerfall_check_sync_state (hammerfall_t *h, int val, int adat_id)
  60. {
  61. int lock;
  62. int sync;
  63. /* S/PDIF channel is always locked and synced, but we only
  64. need tell people once that this is TRUE.
  65. XXX - maybe need to make sure that the rate matches our
  66. idea of the current rate ?
  67. */
  68. if (!h->said_that_spdif_is_fine) {
  69. ClockSyncStatus status;
  70. status = Lock|Sync;
  71. /* XXX broken! fix for hammerfall light ! */
  72. alsa_driver_set_clock_sync_status (h->driver, 24, status);
  73. alsa_driver_set_clock_sync_status (h->driver, 25, status);
  74. h->said_that_spdif_is_fine = TRUE;
  75. }
  76. lock = (val & 0x1) ? TRUE : FALSE;
  77. sync = (val & 0x2) ? TRUE : FALSE;
  78. if (h->lock_status[adat_id] != lock ||
  79. h->sync_status[adat_id] != sync) {
  80. hammerfall_broadcast_channel_status_change (h, lock, sync, adat_id*8, (adat_id*8)+8);
  81. }
  82. h->lock_status[adat_id] = lock;
  83. h->sync_status[adat_id] = sync;
  84. }
  85. static void
  86. hammerfall_check_sync (hammerfall_t *h, snd_ctl_elem_value_t *ctl)
  87. {
  88. const char *name;
  89. int val;
  90. snd_ctl_elem_id_t *ctl_id;
  91. jack_info ("check sync");
  92. snd_ctl_elem_id_alloca (&ctl_id);
  93. snd_ctl_elem_value_get_id (ctl, ctl_id);
  94. name = snd_ctl_elem_id_get_name (ctl_id);
  95. if (strcmp (name, "ADAT1 Sync Check") == 0) {
  96. val = snd_ctl_elem_value_get_enumerated (ctl, 0);
  97. hammerfall_check_sync_state (h, val, 0);
  98. } else if (strcmp (name, "ADAT2 Sync Check") == 0) {
  99. val = snd_ctl_elem_value_get_enumerated (ctl, 0);
  100. hammerfall_check_sync_state (h, val, 1);
  101. } else if (strcmp (name, "ADAT3 Sync Check") == 0) {
  102. val = snd_ctl_elem_value_get_enumerated (ctl, 0);
  103. hammerfall_check_sync_state (h, val, 2);
  104. } else {
  105. jack_error ("Hammerfall: unknown control \"%s\"", name);
  106. }
  107. }
  108. #endif /* HAMMERFALL_MONITOR_CONTROLS */
  109. static int
  110. hammerfall_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask)
  111. {
  112. hammerfall_t *h = (hammerfall_t *) hw->private_hw;
  113. snd_ctl_elem_value_t *ctl;
  114. snd_ctl_elem_id_t *ctl_id;
  115. int err;
  116. int i;
  117. snd_ctl_elem_value_alloca (&ctl);
  118. snd_ctl_elem_id_alloca (&ctl_id);
  119. set_control_id (ctl_id, "Channels Thru");
  120. snd_ctl_elem_value_set_id (ctl, ctl_id);
  121. for (i = 0; i < 26; i++) {
  122. snd_ctl_elem_value_set_integer (ctl, i, (mask & (1<<i)) ? 1 : 0);
  123. }
  124. if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) != 0) {
  125. jack_error ("ALSA/Hammerfall: cannot set input monitoring (%s)", snd_strerror (err));
  126. return -1;
  127. }
  128. hw->input_monitor_mask = mask;
  129. return 0;
  130. }
  131. static int
  132. hammerfall_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode)
  133. {
  134. hammerfall_t *h = (hammerfall_t *) hw->private_hw;
  135. snd_ctl_elem_value_t *ctl;
  136. snd_ctl_elem_id_t *ctl_id;
  137. int err;
  138. snd_ctl_elem_value_alloca (&ctl);
  139. snd_ctl_elem_id_alloca (&ctl_id);
  140. set_control_id (ctl_id, "Sync Mode");
  141. snd_ctl_elem_value_set_id (ctl, ctl_id);
  142. switch (mode) {
  143. case AutoSync:
  144. snd_ctl_elem_value_set_enumerated (ctl, 0, 0);
  145. break;
  146. case ClockMaster:
  147. snd_ctl_elem_value_set_enumerated (ctl, 0, 1);
  148. break;
  149. case WordClock:
  150. snd_ctl_elem_value_set_enumerated (ctl, 0, 2);
  151. break;
  152. }
  153. if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) < 0) {
  154. jack_error ("ALSA-Hammerfall: cannot set clock mode");
  155. }
  156. return 0;
  157. }
  158. static void
  159. hammerfall_release (jack_hardware_t *hw)
  160. {
  161. hammerfall_t *h = (hammerfall_t *) hw->private_hw;
  162. void *status;
  163. if (h == 0) {
  164. return;
  165. }
  166. pthread_cancel (h->monitor_thread);
  167. pthread_join (h->monitor_thread, &status);
  168. free (h);
  169. }
  170. #if HAMMERFALL_MONITOR_CONTROLS
  171. static void *
  172. hammerfall_monitor_controls (void *arg)
  173. {
  174. jack_hardware_t *hw = (jack_hardware_t *) arg;
  175. hammerfall_t *h = (hammerfall_t *) hw->private_hw;
  176. snd_ctl_elem_id_t *switch_id[3];
  177. snd_ctl_elem_value_t *sw[3];
  178. pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  179. snd_ctl_elem_id_malloc (&switch_id[0]);
  180. snd_ctl_elem_id_malloc (&switch_id[1]);
  181. snd_ctl_elem_id_malloc (&switch_id[2]);
  182. snd_ctl_elem_value_malloc (&sw[0]);
  183. snd_ctl_elem_value_malloc (&sw[1]);
  184. snd_ctl_elem_value_malloc (&sw[2]);
  185. set_control_id (switch_id[0], "ADAT1 Sync Check");
  186. set_control_id (switch_id[1], "ADAT2 Sync Check");
  187. set_control_id (switch_id[2], "ADAT3 Sync Check");
  188. snd_ctl_elem_value_set_id (sw[0], switch_id[0]);
  189. snd_ctl_elem_value_set_id (sw[1], switch_id[1]);
  190. snd_ctl_elem_value_set_id (sw[2], switch_id[2]);
  191. while (1) {
  192. if (snd_ctl_elem_read (h->driver->ctl_handle, sw[0])) {
  193. jack_error ("cannot read control switch 0 ...");
  194. }
  195. hammerfall_check_sync (h, sw[0]);
  196. if (snd_ctl_elem_read (h->driver->ctl_handle, sw[1])) {
  197. jack_error ("cannot read control switch 0 ...");
  198. }
  199. hammerfall_check_sync (h, sw[1]);
  200. if (snd_ctl_elem_read (h->driver->ctl_handle, sw[2])) {
  201. jack_error ("cannot read control switch 0 ...");
  202. }
  203. hammerfall_check_sync (h, sw[2]);
  204. if (nanosleep (&h->monitor_interval, 0)) {
  205. break;
  206. }
  207. }
  208. pthread_exit (0);
  209. }
  210. #endif /* HAMMERFALL_MONITOR_CONTROLS */
  211. jack_hardware_t *
  212. jack_alsa_hammerfall_hw_new (alsa_driver_t *driver)
  213. {
  214. jack_hardware_t *hw;
  215. hammerfall_t *h;
  216. hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t));
  217. hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting;
  218. hw->input_monitor_mask = 0;
  219. hw->private_hw = 0;
  220. hw->set_input_monitor_mask = hammerfall_set_input_monitor_mask;
  221. hw->change_sample_clock = hammerfall_change_sample_clock;
  222. hw->release = hammerfall_release;
  223. h = (hammerfall_t *) malloc (sizeof (hammerfall_t));
  224. h->lock_status[0] = FALSE;
  225. h->sync_status[0] = FALSE;
  226. h->lock_status[1] = FALSE;
  227. h->sync_status[1] = FALSE;
  228. h->lock_status[2] = FALSE;
  229. h->sync_status[2] = FALSE;
  230. h->said_that_spdif_is_fine = FALSE;
  231. h->driver = driver;
  232. h->monitor_interval.tv_sec = 1;
  233. h->monitor_interval.tv_nsec = 0;
  234. hw->private_hw = h;
  235. #if 0
  236. if (pthread_create (&h->monitor_thread, 0, hammerfall_monitor_controls, hw)) {
  237. jack_error ("ALSA/Hammerfall: cannot create sync monitor thread");
  238. }
  239. #endif
  240. return hw;
  241. }