~ubuntu-branches/ubuntu/saucy/jack-audio-connection-kit/saucy

« back to all changes in this revision

Viewing changes to drivers/alsa/hammerfall.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-12-06 11:05:15 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081206110515-xa9v9pajr9jqvfvg
Tags: 0.115.6-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - Redirect stderr in bash completion (Debian #504488).

Show diffs side-by-side

added added

removed removed

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