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.

302 lines
7.5KB

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