** Warning: Cannot open xref database.
1 /*
2 Copyright (C) 2001 Paul Davis
3
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.
8
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.
13
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.
17
18 $Id: hammerfall.c,v 1.5 2003/08/29 00:06:30 trutkin Exp $
19 */
20
21 #include <jack/hardware.h>
22 #include "alsa_driver.h"
23 #include "hammerfall.h"
24 #include <jack/internal.h>
25
26 /* Set this to 1 if you want this compile error:
27 * warning: `hammerfall_monitor_controls' defined but not used */
28 #define HAMMERFALL_MONITOR_CONTROLS 0
29
30 static void
31 set_control_id (snd_ctl_elem_id_t *ctl, const char *name)
32 {
33 snd_ctl_elem_id_set_name (ctl, name);
34 snd_ctl_elem_id_set_numid (ctl, 0);
35 snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_PCM);
36 snd_ctl_elem_id_set_device (ctl, 0);
37 snd_ctl_elem_id_set_subdevice (ctl, 0);
38 snd_ctl_elem_id_set_index (ctl, 0);
39 }
40
41 #if HAMMERFALL_MONITOR_CONTROLS
42 static void
43 hammerfall_broadcast_channel_status_change (hammerfall_t *h, int lock, int sync, channel_t lowchn, channel_t highchn)
44
45 {
46 channel_t chn;
47 ClockSyncStatus status = 0;
48
49 if (lock) {
50 status |= Lock;
51 } else {
52 status |= NoLock;
53 }
54
55 if (sync) {
56 status |= Sync;
57 } else {
58 status |= NoSync;
59 }
60
61 for (chn = lowchn; chn < highchn; chn++) {
62 alsa_driver_set_clock_sync_status (h->driver, chn, status);
63 }
64 }
65
66 static void
67 hammerfall_check_sync_state (hammerfall_t *h, int val, int adat_id)
68
69 {
70 int lock;
71 int sync;
72
73 /* S/PDIF channel is always locked and synced, but we only
74 need tell people once that this is TRUE.
75
76 XXX - maybe need to make sure that the rate matches our
77 idea of the current rate ?
78 */
79
80 if (!h->said_that_spdif_is_fine) {
81 ClockSyncStatus status;
82
83 status = Lock|Sync;
84
85 /* XXX broken! fix for hammerfall light ! */
86
87 alsa_driver_set_clock_sync_status (h->driver, 24, status);
88 alsa_driver_set_clock_sync_status (h->driver, 25, status);
89
90 h->said_that_spdif_is_fine = TRUE;
91 }
92
93 lock = (val & 0x1) ? TRUE : FALSE;
94 sync = (val & 0x2) ? TRUE : FALSE;
95
96 if (h->lock_status[adat_id] != lock ||
97 h->sync_status[adat_id] != sync) {
98 hammerfall_broadcast_channel_status_change (h, lock, sync, adat_id*8, (adat_id*8)+8);
99 }
100
101 h->lock_status[adat_id] = lock;
102 h->sync_status[adat_id] = sync;
103 }
104
105 static void
106 hammerfall_check_sync (hammerfall_t *h, snd_ctl_elem_value_t *ctl)
107
108 {
109 const char *name;
110 int val;
111 snd_ctl_elem_id_t *ctl_id;
112
113 printf ("check sync\n");
114
115 snd_ctl_elem_id_alloca (&ctl_id);
116 snd_ctl_elem_value_get_id (ctl, ctl_id);
117
118 name = snd_ctl_elem_id_get_name (ctl_id);
119
120 if (strcmp (name, "ADAT1 Sync Check") == 0) {
121 val = snd_ctl_elem_value_get_enumerated (ctl, 0);
122 hammerfall_check_sync_state (h, val, 0);
123 } else if (strcmp (name, "ADAT2 Sync Check") == 0) {
124 val = snd_ctl_elem_value_get_enumerated (ctl, 0);
125 hammerfall_check_sync_state (h, val, 1);
126 } else if (strcmp (name, "ADAT3 Sync Check") == 0) {
127 val = snd_ctl_elem_value_get_enumerated (ctl, 0);
128 hammerfall_check_sync_state (h, val, 2);
129 } else {
130 jack_error ("Hammerfall: unknown control \"%s\"", name);
131 }
132 }
133 #endif /* HAMMERFALL_MONITOR_CONTROLS */
134
135 static int
136 hammerfall_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask)
137 {
138 hammerfall_t *h = (hammerfall_t *) hw->private;
139 snd_ctl_elem_value_t *ctl;
140 snd_ctl_elem_id_t *ctl_id;
141 int err;
142 int i;
143
144 snd_ctl_elem_value_alloca (&ctl);
145 snd_ctl_elem_id_alloca (&ctl_id);
146 set_control_id (ctl_id, "Channels Thru");
147 snd_ctl_elem_value_set_id (ctl, ctl_id);
148
149 for (i = 0; i < 26; i++) {
150 snd_ctl_elem_value_set_integer (ctl, i, (mask & (1<<i)) ? 1 : 0);
151 }
152
153 if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) != 0) {
154 jack_error ("ALSA/Hammerfall: cannot set input monitoring (%s)", snd_strerror (err));
155 return -1;
156 }
157
158 hw->input_monitor_mask = mask;
159
160 return 0;
161 }
162
163 static int
164 hammerfall_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode)
165 {
166 hammerfall_t *h = (hammerfall_t *) hw->private;
167 snd_ctl_elem_value_t *ctl;
168 snd_ctl_elem_id_t *ctl_id;
169 int err;
170
171 snd_ctl_elem_value_alloca (&ctl);
172 snd_ctl_elem_id_alloca (&ctl_id);
173 set_control_id (ctl_id, "Sync Mode");
174 snd_ctl_elem_value_set_id (ctl, ctl_id);
175
176 switch (mode) {
177 case AutoSync:
178 snd_ctl_elem_value_set_enumerated (ctl, 0, 0);
179 break;
180 case ClockMaster:
181 snd_ctl_elem_value_set_enumerated (ctl, 0, 1);
182 break;
183 case WordClock:
184 snd_ctl_elem_value_set_enumerated (ctl, 0, 2);
185 break;
186 }
187
188 if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) < 0) {
189 jack_error ("ALSA-Hammerfall: cannot set clock mode");
190 }
191
192 return 0;
193 }
194
195 static void
196 hammerfall_release (jack_hardware_t *hw)
197
198 {
199 hammerfall_t *h = (hammerfall_t *) hw->private;
200 void *status;
201
202 if (h == 0) {
203 return;
204 }
205
206 pthread_cancel (h->monitor_thread);
207 pthread_join (h->monitor_thread, &status);
208
209 free (h);
210 }
211
212 #if HAMMERFALL_MONITOR_CONTROLS
213 static void *
214 hammerfall_monitor_controls (void *arg)
215 {
216 jack_hardware_t *hw = (jack_hardware_t *) arg;
217 hammerfall_t *h = (hammerfall_t *) hw->private;
218 snd_ctl_elem_id_t *switch_id[3];
219 snd_ctl_elem_value_t *sw[3];
220
221 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
222
223 snd_ctl_elem_id_malloc (&switch_id[0]);
224 snd_ctl_elem_id_malloc (&switch_id[1]);
225 snd_ctl_elem_id_malloc (&switch_id[2]);
226
227 snd_ctl_elem_value_malloc (&sw[0]);
228 snd_ctl_elem_value_malloc (&sw[1]);
229 snd_ctl_elem_value_malloc (&sw[2]);
230
231 set_control_id (switch_id[0], "ADAT1 Sync Check");
232 set_control_id (switch_id[1], "ADAT2 Sync Check");
233 set_control_id (switch_id[2], "ADAT3 Sync Check");
234
235 snd_ctl_elem_value_set_id (sw[0], switch_id[0]);
236 snd_ctl_elem_value_set_id (sw[1], switch_id[1]);
237 snd_ctl_elem_value_set_id (sw[2], switch_id[2]);
238
239 while (1) {
240 if (snd_ctl_elem_read (h->driver->ctl_handle, sw[0])) {
241 jack_error ("cannot read control switch 0 ...");
242 }
243 hammerfall_check_sync (h, sw[0]);
244
245 if (snd_ctl_elem_read (h->driver->ctl_handle, sw[1])) {
246 jack_error ("cannot read control switch 0 ...");
247 }
248 hammerfall_check_sync (h, sw[1]);
249
250 if (snd_ctl_elem_read (h->driver->ctl_handle, sw[2])) {
251 jack_error ("cannot read control switch 0 ...");
252 }
253 hammerfall_check_sync (h, sw[2]);
254
255 if (nanosleep (&h->monitor_interval, 0)) {
256 break;
257 }
258 }
259
260 pthread_exit (0);
261 }
262 #endif /* HAMMERFALL_MONITOR_CONTROLS */
263
264 jack_hardware_t *
265 jack_alsa_hammerfall_hw_new (alsa_driver_t *driver)
266
267 {
268 jack_hardware_t *hw;
269 hammerfall_t *h;
270
271 hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t));
272
273 hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting;
274 hw->input_monitor_mask = 0;
275 hw->private = 0;
276
277 hw->set_input_monitor_mask = hammerfall_set_input_monitor_mask;
278 hw->change_sample_clock = hammerfall_change_sample_clock;
279 hw->release = hammerfall_release;
280
281 h = (hammerfall_t *) malloc (sizeof (hammerfall_t));
282
283 h->lock_status[0] = FALSE;
284 h->sync_status[0] = FALSE;
285 h->lock_status[1] = FALSE;
286 h->sync_status[1] = FALSE;
287 h->lock_status[2] = FALSE;
288 h->sync_status[2] = FALSE;
289 h->said_that_spdif_is_fine = FALSE;
290 h->driver = driver;
291
292 h->monitor_interval.tv_sec = 1;
293 h->monitor_interval.tv_nsec = 0;
294
295 hw->private = h;
296
297 #if 0
298 if (pthread_create (&h->monitor_thread, 0, hammerfall_monitor_controls, hw)) {
299 jack_error ("ALSA/Hammerfall: cannot create sync monitor thread");
300 }
301 #endif
302
303 return hw;
304 }
305
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.