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.

297 lines
7.3KB

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