Tim Bechmann patch : hammerfall, only release monitor thread, if it has been created.
[jack2.git] / linux / alsa / hammerfall.c
blobc2e3efea715b1031b12941310b13f920985b63d7
1 /*
2 Copyright (C) 2001 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 $Id: hammerfall.c,v 1.3 2005/09/29 14:51:59 letz Exp $
21 #include "hardware.h"
22 #include "alsa_driver.h"
23 #include "hammerfall.h"
24 #include "JackError.h"
26 #define FALSE 0
27 #define TRUE 1
29 /* Set this to 1 if you want this compile error:
30 * warning: `hammerfall_monitor_controls' defined but not used */
31 #define HAMMERFALL_MONITOR_CONTROLS 0
33 static void
34 set_control_id (snd_ctl_elem_id_t *ctl, const char *name)
36 snd_ctl_elem_id_set_name (ctl, name);
37 snd_ctl_elem_id_set_numid (ctl, 0);
38 snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_MIXER);
39 snd_ctl_elem_id_set_device (ctl, 0);
40 snd_ctl_elem_id_set_subdevice (ctl, 0);
41 snd_ctl_elem_id_set_index (ctl, 0);
44 #if HAMMERFALL_MONITOR_CONTROLS
45 static void
46 hammerfall_broadcast_channel_status_change (hammerfall_t *h, int lock, int sync, channel_t lowchn, channel_t highchn)
49 channel_t chn;
50 ClockSyncStatus status = 0;
52 if (lock) {
53 status |= Lock;
54 } else {
55 status |= NoLock;
58 if (sync) {
59 status |= Sync;
60 } else {
61 status |= NoSync;
64 for (chn = lowchn; chn < highchn; chn++) {
65 alsa_driver_set_clock_sync_status (h->driver, chn, status);
69 static void
70 hammerfall_check_sync_state (hammerfall_t *h, int val, int adat_id)
73 int lock;
74 int sync;
76 /* S/PDIF channel is always locked and synced, but we only
77 need tell people once that this is TRUE.
79 XXX - maybe need to make sure that the rate matches our
80 idea of the current rate ?
83 if (!h->said_that_spdif_is_fine) {
84 ClockSyncStatus status;
86 status = Lock|Sync;
88 /* XXX broken! fix for hammerfall light ! */
90 alsa_driver_set_clock_sync_status (h->driver, 24, status);
91 alsa_driver_set_clock_sync_status (h->driver, 25, status);
93 h->said_that_spdif_is_fine = TRUE;
96 lock = (val & 0x1) ? TRUE : FALSE;
97 sync = (val & 0x2) ? TRUE : FALSE;
99 if (h->lock_status[adat_id] != lock ||
100 h->sync_status[adat_id] != sync) {
101 hammerfall_broadcast_channel_status_change (h, lock, sync, adat_id*8, (adat_id*8)+8);
104 h->lock_status[adat_id] = lock;
105 h->sync_status[adat_id] = sync;
108 static void
109 hammerfall_check_sync (hammerfall_t *h, snd_ctl_elem_value_t *ctl)
112 const char *name;
113 int val;
114 snd_ctl_elem_id_t *ctl_id;
116 jack_info ("check sync");
118 snd_ctl_elem_id_alloca (&ctl_id);
119 snd_ctl_elem_value_get_id (ctl, ctl_id);
121 name = snd_ctl_elem_id_get_name (ctl_id);
123 if (strcmp (name, "ADAT1 Sync Check") == 0) {
124 val = snd_ctl_elem_value_get_enumerated (ctl, 0);
125 hammerfall_check_sync_state (h, val, 0);
126 } else if (strcmp (name, "ADAT2 Sync Check") == 0) {
127 val = snd_ctl_elem_value_get_enumerated (ctl, 0);
128 hammerfall_check_sync_state (h, val, 1);
129 } else if (strcmp (name, "ADAT3 Sync Check") == 0) {
130 val = snd_ctl_elem_value_get_enumerated (ctl, 0);
131 hammerfall_check_sync_state (h, val, 2);
132 } else {
133 jack_error ("Hammerfall: unknown control \"%s\"", name);
136 #endif /* HAMMERFALL_MONITOR_CONTROLS */
138 static int
139 hammerfall_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask)
141 hammerfall_t *h = (hammerfall_t *) hw->private_hw;
142 snd_ctl_elem_value_t *ctl;
143 snd_ctl_elem_id_t *ctl_id;
144 int err;
145 int i;
147 snd_ctl_elem_value_alloca (&ctl);
148 snd_ctl_elem_id_alloca (&ctl_id);
149 set_control_id (ctl_id, "Channels Thru");
150 snd_ctl_elem_value_set_id (ctl, ctl_id);
152 for (i = 0; i < 26; i++) {
153 snd_ctl_elem_value_set_integer (ctl, i, (mask & (1<<i)) ? 1 : 0);
156 if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) != 0) {
157 jack_error ("ALSA/Hammerfall: cannot set input monitoring (%s)", snd_strerror (err));
158 return -1;
161 hw->input_monitor_mask = mask;
163 return 0;
166 static int
167 hammerfall_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode)
169 hammerfall_t *h = (hammerfall_t *) hw->private_hw;
170 snd_ctl_elem_value_t *ctl;
171 snd_ctl_elem_id_t *ctl_id;
172 int err;
174 snd_ctl_elem_value_alloca (&ctl);
175 snd_ctl_elem_id_alloca (&ctl_id);
176 set_control_id (ctl_id, "Sync Mode");
177 snd_ctl_elem_value_set_id (ctl, ctl_id);
179 switch (mode) {
180 case AutoSync:
181 snd_ctl_elem_value_set_enumerated (ctl, 0, 0);
182 break;
183 case ClockMaster:
184 snd_ctl_elem_value_set_enumerated (ctl, 0, 1);
185 break;
186 case WordClock:
187 snd_ctl_elem_value_set_enumerated (ctl, 0, 2);
188 break;
191 if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) < 0) {
192 jack_error ("ALSA-Hammerfall: cannot set clock mode");
195 return 0;
198 static void
199 hammerfall_release (jack_hardware_t *hw)
202 hammerfall_t *h = (hammerfall_t *) hw->private_hw;
203 void *status;
205 if (h == 0) {
206 return;
209 if (h->monitor_thread) {
210 pthread_cancel (h->monitor_thread);
211 pthread_join (h->monitor_thread, &status);
214 free (h);
217 #if HAMMERFALL_MONITOR_CONTROLS
218 static void *
219 hammerfall_monitor_controls (void *arg)
221 jack_hardware_t *hw = (jack_hardware_t *) arg;
222 hammerfall_t *h = (hammerfall_t *) hw->private_hw;
223 snd_ctl_elem_id_t *switch_id[3];
224 snd_ctl_elem_value_t *sw[3];
226 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
228 snd_ctl_elem_id_malloc (&switch_id[0]);
229 snd_ctl_elem_id_malloc (&switch_id[1]);
230 snd_ctl_elem_id_malloc (&switch_id[2]);
232 snd_ctl_elem_value_malloc (&sw[0]);
233 snd_ctl_elem_value_malloc (&sw[1]);
234 snd_ctl_elem_value_malloc (&sw[2]);
236 set_control_id (switch_id[0], "ADAT1 Sync Check");
237 set_control_id (switch_id[1], "ADAT2 Sync Check");
238 set_control_id (switch_id[2], "ADAT3 Sync Check");
240 snd_ctl_elem_value_set_id (sw[0], switch_id[0]);
241 snd_ctl_elem_value_set_id (sw[1], switch_id[1]);
242 snd_ctl_elem_value_set_id (sw[2], switch_id[2]);
244 while (1) {
245 if (snd_ctl_elem_read (h->driver->ctl_handle, sw[0])) {
246 jack_error ("cannot read control switch 0 ...");
248 hammerfall_check_sync (h, sw[0]);
250 if (snd_ctl_elem_read (h->driver->ctl_handle, sw[1])) {
251 jack_error ("cannot read control switch 0 ...");
253 hammerfall_check_sync (h, sw[1]);
255 if (snd_ctl_elem_read (h->driver->ctl_handle, sw[2])) {
256 jack_error ("cannot read control switch 0 ...");
258 hammerfall_check_sync (h, sw[2]);
260 if (nanosleep (&h->monitor_interval, 0)) {
261 break;
265 pthread_exit (0);
267 #endif /* HAMMERFALL_MONITOR_CONTROLS */
269 jack_hardware_t *
270 jack_alsa_hammerfall_hw_new (alsa_driver_t *driver)
272 jack_hardware_t *hw;
273 hammerfall_t *h;
275 hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t));
277 hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting;
278 hw->input_monitor_mask = 0;
279 hw->private_hw = 0;
281 hw->set_input_monitor_mask = hammerfall_set_input_monitor_mask;
282 hw->change_sample_clock = hammerfall_change_sample_clock;
283 hw->release = hammerfall_release;
285 h = (hammerfall_t *) malloc (sizeof (hammerfall_t));
287 h->lock_status[0] = FALSE;
288 h->sync_status[0] = FALSE;
289 h->lock_status[1] = FALSE;
290 h->sync_status[1] = FALSE;
291 h->lock_status[2] = FALSE;
292 h->sync_status[2] = FALSE;
293 h->said_that_spdif_is_fine = FALSE;
294 h->driver = driver;
296 h->monitor_interval.tv_sec = 1;
297 h->monitor_interval.tv_nsec = 0;
299 hw->private_hw = h;
301 #if 0
302 if (pthread_create (&h->monitor_thread, 0, hammerfall_monitor_controls, hw)) {
303 jack_error ("ALSA/Hammerfall: cannot create sync monitor thread");
305 #endif
307 return hw;