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

« back to all changes in this revision

Viewing changes to drivers/sun/sun_driver.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
        Sun Audio API driver for Jack
 
3
        Copyright (C) 2008 Jacob Meuser <jakemsr@sdf.lonestar.org>
 
4
        Based heavily on oss_driver.c which came with the following
 
5
        copyright notice.
 
6
 
 
7
        Copyright (C) 2003-2007 Jussi Laako <jussi@sonarnerd.net>
 
8
 
 
9
        This program is free software; you can redistribute it and/or modify
 
10
        it under the terms of the GNU General Public License as published by
 
11
        the Free Software Foundation; either version 2 of the License, or
 
12
        (at your option) any later version.
 
13
 
 
14
        This program is distributed in the hope that it will be useful,
 
15
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
        GNU General Public License for more details.
 
18
 
 
19
        You should have received a copy of the GNU General Public License
 
20
        along with this program; if not, write to the Free Software
 
21
        Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 
22
        MA  02111-1307  USA
 
23
 
 
24
*/
 
25
 
 
26
 
 
27
#include <config.h>
 
28
 
 
29
#ifndef _REENTRANT
 
30
#define _REENTRANT
 
31
#endif
 
32
#ifndef _THREAD_SAFE
 
33
#define _THREAD_SAFE
 
34
#endif
 
35
 
 
36
#include <sys/stat.h>
 
37
#include <sys/types.h>
 
38
#include <sys/ioctl.h>
 
39
#include <sys/audioio.h>
 
40
 
 
41
#include <poll.h>
 
42
#include <unistd.h>
 
43
#include <pthread.h>
 
44
#include <stdlib.h>
 
45
#include <string.h>
 
46
#include <stdio.h>
 
47
#include <fcntl.h>
 
48
#include <errno.h>
 
49
#include <math.h>
 
50
#include <float.h>
 
51
#include <stdarg.h>
 
52
#include <getopt.h>
 
53
 
 
54
#include <jack/types.h>
 
55
#include <jack/internal.h>
 
56
#include <jack/engine.h>
 
57
#include <jack/thread.h>
 
58
#include <sysdeps/time.h>
 
59
 
 
60
#include "sun_driver.h"
 
61
 
 
62
 
 
63
#define SUN_DRIVER_N_PARAMS     11
 
64
const static jack_driver_param_desc_t sun_params[SUN_DRIVER_N_PARAMS] = {
 
65
        { "rate",
 
66
          'r',
 
67
          JackDriverParamUInt,
 
68
          { .ui = SUN_DRIVER_DEF_FS },
 
69
          "sample rate",
 
70
          "sample rate"
 
71
        },
 
72
        { "period",
 
73
          'p',
 
74
          JackDriverParamUInt,
 
75
          { .ui = SUN_DRIVER_DEF_BLKSIZE },
 
76
          "period size",
 
77
          "period size"
 
78
        },
 
79
        { "nperiods",
 
80
          'n',
 
81
          JackDriverParamUInt,
 
82
          { .ui = SUN_DRIVER_DEF_NPERIODS },
 
83
          "number of periods in buffer",
 
84
          "number of periods in buffer"
 
85
        },
 
86
        { "wordlength",
 
87
          'w',
 
88
          JackDriverParamInt,
 
89
          { .i = SUN_DRIVER_DEF_BITS },
 
90
          "word length",
 
91
          "word length"
 
92
        },
 
93
        { "inchannels",
 
94
          'i',
 
95
          JackDriverParamUInt,
 
96
          { .ui = SUN_DRIVER_DEF_INS },
 
97
          "capture channels",
 
98
          "capture channels"
 
99
        },
 
100
        { "outchannels",
 
101
          'o',
 
102
          JackDriverParamUInt,
 
103
          { .ui = SUN_DRIVER_DEF_OUTS },
 
104
          "playback channels",
 
105
          "playback channels"
 
106
        },
 
107
        { "capture",
 
108
          'C',
 
109
          JackDriverParamString,
 
110
          { .str = SUN_DRIVER_DEF_DEV },
 
111
          "input device",
 
112
          "input device"
 
113
        },
 
114
        { "playback",
 
115
          'P',
 
116
          JackDriverParamString,
 
117
          { .str = SUN_DRIVER_DEF_DEV },
 
118
          "output device",
 
119
          "output device"
 
120
        },
 
121
        { "ignorehwbuf",
 
122
          'b',
 
123
          JackDriverParamBool,
 
124
          { },
 
125
          "ignore hardware period size",
 
126
          "ignore hardware period size"
 
127
        },
 
128
        { "input latency",
 
129
          'I',
 
130
          JackDriverParamUInt,
 
131
          { .ui = 0 },
 
132
          "system input latency",
 
133
          "system input latency"
 
134
        },
 
135
        { "output latency",
 
136
          'O',
 
137
          JackDriverParamUInt,
 
138
          { .ui = 0 },
 
139
          "system output latency",
 
140
          "system output latency"
 
141
        }
 
142
};
 
143
 
 
144
 
 
145
/* internal functions */
 
146
 
 
147
 
 
148
static void
 
149
set_period_size (sun_driver_t *driver, jack_nframes_t new_period_size)
 
150
{
 
151
        driver->period_size = new_period_size;
 
152
 
 
153
        driver->period_usecs = 
 
154
                ((double) driver->period_size /
 
155
                (double) driver->sample_rate) * 1e6;
 
156
        driver->last_wait_ust = 0;
 
157
        driver->iodelay = 0.0F;
 
158
        driver->poll_timeout = (int)(driver->period_usecs / 666);
 
159
}
 
160
 
 
161
 
 
162
static void
 
163
sun_driver_write_silence (sun_driver_t *driver, jack_nframes_t nframes)
 
164
{
 
165
        size_t localsize;
 
166
        ssize_t io_res;
 
167
        void *localbuf;
 
168
 
 
169
        localsize = nframes * driver->sample_bytes * driver->playback_channels;
 
170
        localbuf = malloc(localsize);
 
171
        if (localbuf == NULL)
 
172
        {
 
173
                jack_error("sun_driver: malloc() failed: %s@%i",
 
174
                        __FILE__, __LINE__);
 
175
                return;
 
176
        }
 
177
 
 
178
        bzero(localbuf, localsize);
 
179
        io_res = write(driver->outfd, localbuf, localsize);
 
180
        if (io_res < (ssize_t) localsize)
 
181
        {
 
182
                jack_error("sun_driver: write() failed: %s: "
 
183
                        "count=%d/%d: %s@%i", strerror(errno), io_res,
 
184
                        localsize, __FILE__, __LINE__);
 
185
        }
 
186
        free(localbuf);
 
187
}
 
188
 
 
189
 
 
190
static void
 
191
sun_driver_read_silence (sun_driver_t *driver, jack_nframes_t nframes)
 
192
{
 
193
        size_t localsize;
 
194
        ssize_t io_res;
 
195
        void *localbuf;
 
196
 
 
197
        localsize = nframes * driver->sample_bytes * driver->capture_channels;
 
198
        localbuf = malloc(localsize);
 
199
        if (localbuf == NULL)
 
200
        {
 
201
                jack_error("sun_driver: malloc() failed: %s@%i",
 
202
                        __FILE__, __LINE__);
 
203
                return;
 
204
        }
 
205
 
 
206
        io_res = read(driver->infd, localbuf, localsize);
 
207
        if (io_res < (ssize_t) localsize)
 
208
        {
 
209
                jack_error("sun_driver: read() failed: %s: "
 
210
                        "count=%d/%d: %s@%i", strerror(errno), io_res,
 
211
                        localsize, __FILE__, __LINE__);
 
212
        }
 
213
        free(localbuf);
 
214
}
 
215
 
 
216
 
 
217
static jack_nframes_t
 
218
sun_driver_wait (sun_driver_t *driver, int *status, float *iodelay)
 
219
{
 
220
        audio_info_t auinfo;
 
221
        struct pollfd pfd[2];
 
222
        nfds_t nfds;
 
223
        float delay;
 
224
        jack_time_t poll_enter;
 
225
        jack_time_t poll_ret;
 
226
        int need_capture = 0;
 
227
        int need_playback = 0;
 
228
        int capture_errors = 0;
 
229
        int playback_errors = 0;
 
230
        int capture_seek;
 
231
        int playback_seek;
 
232
 
 
233
        *status = -1;
 
234
        *iodelay = 0;
 
235
 
 
236
        pfd[0].fd = driver->infd;
 
237
        pfd[0].events = POLLIN;
 
238
        if (driver->infd >= 0)
 
239
                need_capture = 1;
 
240
 
 
241
        pfd[1].fd = driver->outfd;
 
242
        pfd[1].events = POLLOUT;
 
243
        if (driver->outfd >= 0)
 
244
                need_playback = 1;
 
245
 
 
246
        poll_enter = jack_get_microseconds();
 
247
        if (poll_enter > driver->poll_next)
 
248
        {
 
249
                /* late. don't count as wakeup delay. */
 
250
                driver->poll_next = 0;
 
251
        }
 
252
 
 
253
        while (need_capture || need_playback)
 
254
        {
 
255
                nfds = poll(pfd, 2, driver->poll_timeout);
 
256
                if ( nfds == -1 ||
 
257
                    ((pfd[0].revents | pfd[1].revents) &
 
258
                     (POLLERR | POLLHUP | POLLNVAL)) )
 
259
                {
 
260
                        jack_error("sun_driver: poll() error: %s: %s@%i",  
 
261
                                strerror(errno), __FILE__, __LINE__);
 
262
                        *status = -3;
 
263
                        return 0;
 
264
                }
 
265
 
 
266
                if (nfds == 0)
 
267
                {
 
268
                        jack_error("sun_driver: poll() timeout: %s@%i",
 
269
                                __FILE__, __LINE__);
 
270
                        *status = -5;
 
271
                        return 0;
 
272
                }
 
273
 
 
274
                if (need_capture && (pfd[0].revents & POLLIN))
 
275
                {
 
276
                        need_capture = 0;
 
277
                        pfd[0].fd = -1;
 
278
                }
 
279
 
 
280
                if (need_playback && (pfd[1].revents & POLLOUT))
 
281
                {
 
282
                        need_playback = 0;
 
283
                        pfd[1].fd = -1;
 
284
                }
 
285
        }
 
286
 
 
287
        poll_ret = jack_get_microseconds();
 
288
 
 
289
        if (driver->poll_next && poll_ret > driver->poll_next)
 
290
                *iodelay = poll_ret - driver->poll_next;
 
291
 
 
292
        driver->poll_last = poll_ret;
 
293
        driver->poll_next = poll_ret + driver->period_usecs;
 
294
        driver->engine->transport_cycle_start(driver->engine, poll_ret);
 
295
 
 
296
#if defined(AUDIO_RERROR) && defined(AUDIO_PERROR)
 
297
 
 
298
        /* low level error reporting and recovery.  recovery is necessary
 
299
         * when doing both playback and capture and using AUMODE_PLAY,
 
300
         * because we process one period of both playback and capture data
 
301
         * in each cycle, and we wait in each cycle for that to be possible.
 
302
         * for example, playback will continuously underrun if it underruns
 
303
         * and we have to wait for capture data to become available
 
304
         * before we can write enough playback data to catch up.
 
305
         */
 
306
 
 
307
        if (driver->infd >= 0)
 
308
        {
 
309
                if (ioctl(driver->infd, AUDIO_RERROR, &capture_errors) < 0)
 
310
                {
 
311
                        jack_error("sun_driver: AUDIO_RERROR failed: %s: %s@%i",
 
312
                                strerror(errno), __FILE__, __LINE__);
 
313
                        return 0;
 
314
                }
 
315
                capture_errors -= driver->capture_drops;
 
316
                driver->capture_drops += capture_errors;
 
317
        }
 
318
        if (capture_errors > 0)
 
319
        {
 
320
                delay = (capture_errors * 1000.0) / driver->sample_rate;
 
321
                printf("sun_driver: capture xrun of %d frames (%f msec)\n",
 
322
                        capture_errors, delay);
 
323
        }
 
324
 
 
325
        if (driver->outfd >= 0)
 
326
        {
 
327
                if (ioctl(driver->outfd, AUDIO_PERROR, &playback_errors) < 0)
 
328
                {
 
329
                        jack_error("sun_driver: AUDIO_PERROR failed: %s: %s@%i",
 
330
                                strerror(errno), __FILE__, __LINE__);
 
331
                        return 0;
 
332
                }
 
333
                playback_errors -= driver->playback_drops;
 
334
                driver->playback_drops += playback_errors;
 
335
        }
 
336
        if (playback_errors > 0)
 
337
        {
 
338
                delay = (playback_errors * 1000.0) / driver->sample_rate;
 
339
                printf("sun_driver: playback xrun of %d frames (%f msec)\n",
 
340
                        playback_errors, delay);
 
341
        }
 
342
 
 
343
        if ((driver->outfd >= 0 && driver->infd >= 0) &&
 
344
                (capture_errors || playback_errors))
 
345
        {
 
346
                if (ioctl(driver->infd, AUDIO_GETINFO, &auinfo) < 0)
 
347
                {
 
348
                        jack_error("sun_driver: AUDIO_GETINFO failed: %s: "
 
349
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
350
                        return 0;
 
351
                }
 
352
                capture_seek = auinfo.record.seek;
 
353
 
 
354
                if (driver->infd == driver->outfd)
 
355
                        playback_seek = auinfo.play.seek;
 
356
                else
 
357
                {
 
358
                        if (ioctl(driver->outfd, AUDIO_GETINFO, &auinfo) < 0)
 
359
                        {
 
360
                                jack_error("sun_driver: AUDIO_GETINFO failed: "
 
361
                                        "%s: %s@%i", strerror(errno),
 
362
                                        __FILE__, __LINE__);
 
363
                                return 0;
 
364
                        }
 
365
                        playback_seek = auinfo.play.seek;
 
366
                }
 
367
 
 
368
                capture_seek /= driver->capture_channels *
 
369
                        driver->sample_bytes;
 
370
                playback_seek /= driver->playback_channels *
 
371
                        driver->sample_bytes;
 
372
 
 
373
                if (playback_seek == driver->period_size &&
 
374
                        capture_seek == driver->period_size  &&
 
375
                        playback_errors)
 
376
                {
 
377
                        /* normally, 1 period in each buffer is exactly
 
378
                         * what we want, but if there was an error then
 
379
                         * we effectively have 0 periods in the playback
 
380
                         * buffer, because the period in the buffer will
 
381
                         * be used to catch up to realtime.
 
382
                         */
 
383
                        printf("sun_driver: writing %d frames of silence "
 
384
                                "to correct I/O sync\n", driver->period_size);
 
385
                        sun_driver_write_silence(driver, driver->period_size);
 
386
                }
 
387
                else if (capture_errors && playback_errors)
 
388
                {
 
389
                        /* serious delay.  we've lost the ability to
 
390
                         * write capture_errors frames to catch up on
 
391
                         * playback.
 
392
                         */
 
393
                        printf("sun_driver: writing %d frames of silence "
 
394
                                "to correct I/O sync\n", capture_errors);
 
395
                        sun_driver_write_silence(driver, capture_errors);
 
396
                }
 
397
        }
 
398
 
 
399
#endif  // AUDIO_RERROR && AUDIO_PERROR
 
400
 
 
401
        driver->last_wait_ust = poll_ret;
 
402
 
 
403
        *status = 0;
 
404
 
 
405
        return driver->period_size;
 
406
}
 
407
 
 
408
 
 
409
static inline int
 
410
sun_driver_run_cycle (sun_driver_t *driver)
 
411
{
 
412
        jack_nframes_t nframes;
 
413
        jack_time_t now;
 
414
        int wait_status;
 
415
        float iodelay;
 
416
 
 
417
        nframes = sun_driver_wait (driver, &wait_status, &iodelay);
 
418
 
 
419
        if (wait_status < 0)
 
420
        {
 
421
                switch (wait_status)
 
422
                {
 
423
                case -3:
 
424
                        /* poll() error */
 
425
                        return -1;
 
426
                case -5:
 
427
                        /* poll() timeout */
 
428
                        now = jack_get_microseconds();
 
429
                        if (now > driver->poll_next)
 
430
                        {
 
431
                                iodelay = now - driver->poll_next;
 
432
                                driver->poll_next = now + driver->period_usecs;
 
433
                                driver->engine->delay(driver->engine, iodelay);
 
434
                                printf("sun_driver: iodelay = %f\n", iodelay);
 
435
                        }
 
436
                        break;
 
437
                default:
 
438
                        /* any other fatal error */
 
439
                        return -1;
 
440
                }
 
441
        }
 
442
 
 
443
        return driver->engine->run_cycle(driver->engine, nframes, iodelay);
 
444
}
 
445
 
 
446
 
 
447
static void
 
448
copy_and_convert_in (jack_sample_t *dst, void *src, 
 
449
        size_t nframes, int channel, int chcount, int bits)
 
450
{
 
451
        int srcidx;
 
452
        int dstidx;
 
453
        signed short *s16src = (signed short *) src;
 
454
        signed int *s32src = (signed int *) src;
 
455
        double *f64src = (double *) src;
 
456
        jack_sample_t scale;
 
457
 
 
458
        srcidx = channel;
 
459
        switch (bits)
 
460
        {
 
461
                case 16:
 
462
                        scale = 1.0f / 0x7fff;
 
463
                        for (dstidx = 0; dstidx < nframes; dstidx++)
 
464
                        {
 
465
                                dst[dstidx] = (jack_sample_t) 
 
466
                                        s16src[srcidx] * scale;
 
467
                                srcidx += chcount;
 
468
                        }
 
469
                        break;
 
470
                case 24:
 
471
                        scale = 1.0f / 0x7fffff;
 
472
                        for (dstidx = 0; dstidx < nframes; dstidx++)
 
473
                        {
 
474
                                dst[dstidx] = (jack_sample_t)
 
475
                                        s32src[srcidx] * scale;
 
476
                                srcidx += chcount;
 
477
                        }
 
478
                        break;
 
479
                case 32:
 
480
                        scale = 1.0f / 0x7fffffff;
 
481
                        for (dstidx = 0; dstidx < nframes; dstidx++)
 
482
                        {
 
483
                                dst[dstidx] = (jack_sample_t)
 
484
                                        s32src[srcidx] * scale;
 
485
                                srcidx += chcount;
 
486
                        }
 
487
                        break;
 
488
                case 64:
 
489
                        for (dstidx = 0; dstidx < nframes; dstidx++)
 
490
                        {
 
491
                                dst[dstidx] = (jack_sample_t) f64src[srcidx];
 
492
                                srcidx += chcount;
 
493
                        }
 
494
                        break;
 
495
        }
 
496
}
 
497
 
 
498
 
 
499
static void
 
500
copy_and_convert_out (void *dst, jack_sample_t *src, 
 
501
        size_t nframes, int channel, int chcount, int bits)
 
502
{
 
503
        int srcidx;
 
504
        int dstidx;
 
505
        signed short *s16dst = (signed short *) dst;
 
506
        signed int *s32dst = (signed int *) dst;
 
507
        double *f64dst = (double *) dst;
 
508
        jack_sample_t scale;
 
509
 
 
510
        dstidx = channel;
 
511
        switch (bits)
 
512
        {
 
513
                case 16:
 
514
                        scale = 0x7fff;
 
515
                        for (srcidx = 0; srcidx < nframes; srcidx++)
 
516
                        {
 
517
                                s16dst[dstidx] = (signed short)
 
518
                                        (src[srcidx] >= 0.0f) ?
 
519
                                        (src[srcidx] * scale + 0.5f) :
 
520
                                        (src[srcidx] * scale - 0.5f);
 
521
                                dstidx += chcount;
 
522
                        }
 
523
                        break;
 
524
                case 24:
 
525
                        scale = 0x7fffff;
 
526
                        for (srcidx = 0; srcidx < nframes; srcidx++)
 
527
                        {
 
528
                                s32dst[dstidx] = (signed int)
 
529
                                        (src[srcidx] >= 0.0f) ?
 
530
                                        (src[srcidx] * scale + 0.5f) :
 
531
                                        (src[srcidx] * scale - 0.5f);
 
532
                                dstidx += chcount;
 
533
                        }
 
534
                        break;
 
535
                case 32:
 
536
                        scale = 0x7fffffff;
 
537
                        for (srcidx = 0; srcidx < nframes; srcidx++)
 
538
                        {
 
539
                                s32dst[dstidx] = (signed int)
 
540
                                        (src[srcidx] >= 0.0f) ?
 
541
                                        (src[srcidx] * scale + 0.5f) :
 
542
                                        (src[srcidx] * scale - 0.5f);
 
543
                                dstidx += chcount;
 
544
                        }
 
545
                        break;
 
546
                case 64:
 
547
                        for (srcidx = 0; srcidx < nframes; srcidx++)
 
548
                        {
 
549
                                f64dst[dstidx] = (double) src[srcidx];
 
550
                                dstidx += chcount;
 
551
                        }
 
552
                        break;
 
553
        }
 
554
}
 
555
 
 
556
 
 
557
/* jack driver interface */
 
558
 
 
559
 
 
560
static int
 
561
sun_driver_attach (sun_driver_t *driver)
 
562
{
 
563
        int port_flags;
 
564
        int channel;
 
565
        char channel_name[64];
 
566
        jack_port_t *port;
 
567
 
 
568
        driver->engine->set_buffer_size(driver->engine, driver->period_size);
 
569
        driver->engine->set_sample_rate(driver->engine, driver->sample_rate);
 
570
 
 
571
        port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal;
 
572
 
 
573
        for (channel = 0; channel < driver->capture_channels; channel++)
 
574
        {
 
575
                snprintf(channel_name, sizeof(channel_name), 
 
576
                        "capture_%u", channel + 1);
 
577
                port = jack_port_register(driver->client, channel_name,
 
578
                        JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
 
579
                if (port == NULL)
 
580
                {
 
581
                        jack_error("sun_driver: cannot register port for %s: "
 
582
                                "%s@%i", channel_name, __FILE__, __LINE__);
 
583
                        break;
 
584
                }
 
585
                jack_port_set_latency(port,
 
586
                        driver->period_size + driver->sys_in_latency);
 
587
                driver->capture_ports = 
 
588
                        jack_slist_append(driver->capture_ports, port);
 
589
        }
 
590
 
 
591
        port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;
 
592
        for (channel = 0; channel < driver->playback_channels; channel++)
 
593
        {
 
594
                snprintf(channel_name, sizeof(channel_name),
 
595
                        "playback_%u", channel + 1);
 
596
                port = jack_port_register(driver->client, channel_name,
 
597
                        JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
 
598
                if (port == NULL)
 
599
                {
 
600
                        jack_error("sun_driver: cannot register port for "
 
601
                                "%s: %s@%i", channel_name, __FILE__, __LINE__);
 
602
                        break;
 
603
                }
 
604
                jack_port_set_latency(port,
 
605
                        driver->period_size + driver->sys_out_latency);
 
606
                driver->playback_ports =
 
607
                        jack_slist_append(driver->playback_ports, port);
 
608
        }
 
609
 
 
610
        return jack_activate(driver->client);
 
611
}
 
612
 
 
613
 
 
614
static int
 
615
sun_driver_detach (sun_driver_t *driver)
 
616
{
 
617
        JSList *node;
 
618
 
 
619
        if (driver->engine == NULL)
 
620
                return 0;
 
621
 
 
622
        node = driver->capture_ports;
 
623
        while (node != NULL)
 
624
        {
 
625
                jack_port_unregister(driver->client, 
 
626
                        ((jack_port_t *) node->data));
 
627
                node = jack_slist_next(node);
 
628
        }
 
629
        jack_slist_free(driver->capture_ports);
 
630
        driver->capture_ports = NULL;
 
631
 
 
632
        node = driver->playback_ports;
 
633
        while (node != NULL)
 
634
        {
 
635
                jack_port_unregister(driver->client,
 
636
                        ((jack_port_t *) node->data));
 
637
                node = jack_slist_next(node);
 
638
        }
 
639
        jack_slist_free(driver->playback_ports);
 
640
        driver->playback_ports = NULL;
 
641
 
 
642
        return 0;
 
643
}
 
644
 
 
645
 
 
646
static int
 
647
sun_driver_start (sun_driver_t *driver)
 
648
{
 
649
        audio_info_t audio_if;
 
650
 
 
651
        if (driver->infd >= 0)
 
652
        {
 
653
#if defined(AUDIO_FLUSH)
 
654
                if (ioctl(driver->infd, AUDIO_FLUSH, NULL) < 0)
 
655
                {
 
656
                        jack_error("sun_driver: capture flush failed: %s: "
 
657
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
658
                        return -1;
 
659
                }
 
660
#endif
 
661
                AUDIO_INITINFO(&audio_if);
 
662
                audio_if.record.pause = 1;
 
663
                if (driver->outfd == driver->infd)
 
664
                        audio_if.play.pause = 1;
 
665
                if (ioctl(driver->infd, AUDIO_SETINFO, &audio_if) < 0)
 
666
                {
 
667
                        jack_error("sun_driver: pause capture failed: %s: "
 
668
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
669
                        return -1;
 
670
                }
 
671
        }
 
672
        if ((driver->outfd >= 0) && (driver->outfd != driver->infd))
 
673
        {
 
674
#if defined(AUDIO_FLUSH)
 
675
                if (ioctl(driver->outfd, AUDIO_FLUSH, NULL) < 0)
 
676
                {
 
677
                        jack_error("sun_driver: playback flush failed: %s: "
 
678
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
679
                        return -1;
 
680
                }
 
681
#endif
 
682
                AUDIO_INITINFO(&audio_if);
 
683
                audio_if.play.pause = 1;
 
684
                if (ioctl(driver->outfd, AUDIO_SETINFO, &audio_if) < 0)
 
685
                {
 
686
                        jack_error("sun_driver: pause playback failed: %s: "
 
687
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
688
                        return -1;
 
689
                }
 
690
        }
 
691
 
 
692
        /* AUDIO_FLUSH resets the counters these work with */
 
693
        driver->playback_drops = driver->capture_drops = 0;
 
694
 
 
695
        if (driver->outfd >= 0)
 
696
        {
 
697
                /* "prime" the playback buffer.  if we don't do this, we'll
 
698
                 * end up underrunning.  it would get really ugly in duplex
 
699
                 * mode, for example, where we have to wait for a period to
 
700
                 * be available to read before we can write.  also helps to
 
701
                 * keep constant latency from the beginning.
 
702
                 */
 
703
                sun_driver_write_silence(driver,
 
704
                        driver->nperiods * driver->period_size);
 
705
        }
 
706
 
 
707
        if (driver->infd >= 0)
 
708
        {
 
709
                AUDIO_INITINFO(&audio_if);
 
710
                audio_if.record.pause = 0;
 
711
                if (driver->outfd == driver->infd)
 
712
                        audio_if.play.pause = 0;
 
713
                if (ioctl(driver->infd, AUDIO_SETINFO, &audio_if) < 0)
 
714
                {
 
715
                        jack_error("sun_driver: start capture failed: %s: "
 
716
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
717
                        return -1;
 
718
                }
 
719
        }
 
720
        if ((driver->outfd >= 0) && (driver->outfd != driver->infd))
 
721
        {
 
722
                AUDIO_INITINFO(&audio_if);
 
723
                audio_if.play.pause = 0;
 
724
                if (ioctl(driver->outfd, AUDIO_SETINFO, &audio_if) < 0)
 
725
                {
 
726
                        jack_error("sun_driver: trigger playback failed: %s: "
 
727
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
728
                        return -1;
 
729
                }
 
730
        }
 
731
 
 
732
        return 0;
 
733
}
 
734
 
 
735
 
 
736
static int
 
737
enc_equal(int a, int b)
 
738
{
 
739
        if (a == b)
 
740
                return 1;
 
741
 
 
742
#if defined(AUDIO_ENCODING_SLINEAR)     
 
743
#if BYTE_ORDER == LITTLE_ENDIAN
 
744
        if ((a == AUDIO_ENCODING_SLINEAR && b == AUDIO_ENCODING_SLINEAR_LE) ||
 
745
            (a == AUDIO_ENCODING_SLINEAR_LE && b == AUDIO_ENCODING_SLINEAR) ||
 
746
            (a == AUDIO_ENCODING_ULINEAR && b == AUDIO_ENCODING_ULINEAR_LE) ||
 
747
            (a == AUDIO_ENCODING_ULINEAR_LE && b == AUDIO_ENCODING_ULINEAR))
 
748
                return 1;
 
749
#elif BYTE_ORDER == BIG_ENDIAN
 
750
        if ((a == AUDIO_ENCODING_SLINEAR && b == AUDIO_ENCODING_SLINEAR_BE) ||
 
751
            (a == AUDIO_ENCODING_SLINEAR_BE && b == AUDIO_ENCODING_SLINEAR) ||
 
752
            (a == AUDIO_ENCODING_ULINEAR && b == AUDIO_ENCODING_ULINEAR_BE) ||
 
753
            (a == AUDIO_ENCODING_ULINEAR_BE && b == AUDIO_ENCODING_ULINEAR))
 
754
                return 1;
 
755
#endif
 
756
#endif  // AUDIO_ENCODING_SLINEAR
 
757
        return 0;
 
758
}
 
759
 
 
760
 
 
761
static int
 
762
sun_driver_set_parameters (sun_driver_t *driver)
 
763
{
 
764
        audio_info_t audio_if_in, audio_if_out;
 
765
        int infd = -1;
 
766
        int outfd = -1;
 
767
        int s = 1;
 
768
        unsigned int cap_period = 0, play_period = 0, period_size = 0;
 
769
        const char *indev = driver->indev;
 
770
        const char *outdev = driver->outdev;
 
771
 
 
772
        driver->indevbuf = NULL;
 
773
        driver->outdevbuf = NULL;
 
774
        driver->sample_bytes = driver->bits / 8;
 
775
 
 
776
        if ((strcmp(indev, outdev) == 0) &&
 
777
            ((driver->capture_channels > 0) && (driver->playback_channels > 0)))
 
778
        {
 
779
                infd = outfd = open(indev, O_RDWR);
 
780
                if (infd < 0)
 
781
                {
 
782
                        jack_error("sun_driver: failed to open duplex device "
 
783
                                "%s: %s: %s@%i", indev, strerror(errno),
 
784
                                __FILE__, __LINE__);
 
785
                        return -1;
 
786
                }
 
787
#if defined(AUDIO_SETFD)
 
788
                if (ioctl(infd, AUDIO_SETFD, &s) < 0)
 
789
                {
 
790
                        jack_error("sun_driver: failed to enable full duplex: "
 
791
                                "%s: %s@%i", strerror(errno),
 
792
                                __FILE__, __LINE__);
 
793
                        return -1;
 
794
                }
 
795
#endif
 
796
        }
 
797
        else
 
798
        {
 
799
                if (driver->capture_channels > 0)
 
800
                {
 
801
                        infd = open(indev, O_RDONLY);
 
802
                        if (infd < 0)
 
803
                        {
 
804
                                jack_error("sun_driver: failed to open input "
 
805
                                        "device %s: %s: %s@%i", indev,
 
806
                                        strerror(errno), __FILE__, __LINE__);
 
807
                                return -1;
 
808
                        }
 
809
                }
 
810
                if (driver->playback_channels > 0)
 
811
                {
 
812
                        outfd = open(outdev, O_WRONLY);
 
813
                        if (outfd < 0)
 
814
                        {
 
815
                                jack_error("sun_driver: failed to open output "
 
816
                                        "device %s: %s: %s@%i", outdev,
 
817
                                        strerror(errno), __FILE__, __LINE__);
 
818
                                return -1;
 
819
                        }
 
820
                }
 
821
        }
 
822
        if (infd == -1 && outfd == -1)
 
823
        {
 
824
                jack_error("sun_driver: no device was opened: %s@%i",
 
825
                        __FILE__, __LINE__);
 
826
                return -1;
 
827
        }
 
828
 
 
829
        driver->infd = infd;
 
830
        driver->outfd = outfd;
 
831
        
 
832
        AUDIO_INITINFO(&audio_if_in);
 
833
        AUDIO_INITINFO(&audio_if_out);
 
834
 
 
835
        if (infd >= 0)
 
836
        {
 
837
                audio_if_in.record.encoding = driver->format;
 
838
                audio_if_in.record.precision = driver->bits;
 
839
                audio_if_in.record.channels = driver->capture_channels;
 
840
                audio_if_in.record.sample_rate = driver->sample_rate;
 
841
                audio_if_in.record.pause = 1;
 
842
        }
 
843
        if (outfd >= 0)
 
844
        {
 
845
                audio_if_out.play.encoding = driver->format;
 
846
                audio_if_out.play.precision = driver->bits;
 
847
                audio_if_out.play.channels = driver->playback_channels;
 
848
                audio_if_out.play.sample_rate = driver->sample_rate;
 
849
                audio_if_out.play.pause = 1;
 
850
        }
 
851
 
 
852
#if defined(__OpenBSD__) || defined(__NetBSD__)
 
853
#if defined(__OpenBSD__)
 
854
        if (driver->infd >= 0)
 
855
                audio_if_in.record.block_size = driver->capture_channels *
 
856
                driver->period_size * driver->sample_bytes;
 
857
        if (driver->outfd >= 0)
 
858
                audio_if_out.play.block_size = driver->playback_channels *
 
859
                driver->period_size * driver->sample_bytes; 
 
860
#else
 
861
        if (driver->infd >= 0)
 
862
                audio_if_in.blocksize = driver->capture_channels *
 
863
                driver->period_size * driver->sample_bytes;
 
864
        if (driver->outfd >= 0)
 
865
                audio_if_out.blocksize =  driver->playback_channels *
 
866
                driver->period_size * driver->sample_bytes;
 
867
#endif
 
868
        if (infd == outfd)
 
869
                audio_if_in.play = audio_if_out.play;
 
870
 
 
871
        /* this only affects playback.  the capture buffer is
 
872
         * always the max (64k on OpenBSD).
 
873
         */
 
874
        audio_if_in.hiwat = audio_if_out.hiwat = driver->nperiods;
 
875
 
 
876
        /* AUMODE_PLAY makes us "catch up to realtime" if we underrun
 
877
         * playback.  that means, if we are N frames late, the next
 
878
         * N frames written will be discarded.  this keeps playback
 
879
         * time from expanding with each underrun.
 
880
         */ 
 
881
        if (infd == outfd)
 
882
        {
 
883
                audio_if_in.mode = AUMODE_PLAY | AUMODE_RECORD;
 
884
        }
 
885
        else
 
886
        {
 
887
                if (infd >= 0)
 
888
                        audio_if_in.mode = AUMODE_RECORD;
 
889
 
 
890
                if (outfd >= 0)
 
891
                        audio_if_out.mode = AUMODE_PLAY;
 
892
        }
 
893
 
 
894
#endif  // OpenBSD || NetBSD
 
895
 
 
896
        if (infd >= 0)
 
897
        {
 
898
                if (ioctl(infd, AUDIO_SETINFO, &audio_if_in) < 0)
 
899
                {
 
900
                        jack_error("sun_driver: failed to set parameters for "
 
901
                                "%s: %s: %s@%i", indev, strerror(errno),
 
902
                                __FILE__, __LINE__);
 
903
                        return -1;
 
904
                }
 
905
        }
 
906
 
 
907
        if (outfd >= 0 && outfd != infd)
 
908
        {
 
909
                if (ioctl(outfd, AUDIO_SETINFO, &audio_if_out) < 0)
 
910
                {
 
911
                        jack_error("sun_driver: failed to set parameters for "
 
912
                                "%s: %s: %s@%i", outdev, strerror(errno),
 
913
                                __FILE__, __LINE__);
 
914
                        return -1;
 
915
                }
 
916
        }
 
917
 
 
918
        if (infd >= 0)
 
919
        {
 
920
                if (ioctl(infd, AUDIO_GETINFO, &audio_if_in) < 0)
 
921
                {
 
922
                        jack_error("sun_driver: AUDIO_GETINFO failed: %s: "
 
923
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
924
                        return -1;
 
925
                }
 
926
 
 
927
                if (!enc_equal(audio_if_in.record.encoding, driver->format) ||
 
928
                    audio_if_in.record.precision != driver->bits ||
 
929
                    audio_if_in.record.channels != driver->capture_channels ||
 
930
                    audio_if_in.record.sample_rate != driver->sample_rate)
 
931
                {
 
932
                        jack_error("sun_driver: setting capture parameters "
 
933
                                "failed: %s@%i", __FILE__, __LINE__);
 
934
                        return -1;
 
935
                }
 
936
#if defined(__OpenBSD__)
 
937
                cap_period = audio_if_in.record.block_size /
 
938
                        driver->capture_channels / driver->sample_bytes;
 
939
#elif defined(__NetBSD__)
 
940
                cap_period = audio_if_in.blocksize /
 
941
                        driver->capture_channels / driver->sample_bytes;
 
942
#else
 
943
                /* how is this done on Solaris? */
 
944
                cap_period = driver->period_size;
 
945
#endif
 
946
        }
 
947
 
 
948
        if (outfd >= 0)
 
949
        {
 
950
                if (outfd == infd)
 
951
                {
 
952
                        audio_if_out.play = audio_if_in.play;
 
953
                }
 
954
                else
 
955
                {
 
956
                        if (ioctl(outfd, AUDIO_GETINFO, &audio_if_out) < 0)
 
957
                        {
 
958
                                jack_error("sun_driver: AUDIO_GETINFO failed: "
 
959
                                        "%s: %s@%i", strerror(errno),
 
960
                                        __FILE__, __LINE__);
 
961
                                return -1;
 
962
                        }
 
963
                }
 
964
 
 
965
                if (!enc_equal(audio_if_out.play.encoding, driver->format) ||
 
966
                    audio_if_out.play.precision != driver->bits ||
 
967
                    audio_if_out.play.channels != driver->playback_channels ||
 
968
                    audio_if_out.play.sample_rate != driver->sample_rate)
 
969
                {
 
970
                        jack_error("sun_driver: playback settings failed: "
 
971
                                "%s@%i", __FILE__, __LINE__);
 
972
                        return -1;
 
973
                }
 
974
#if defined(__OpenBSD__)
 
975
                play_period = audio_if_out.play.block_size /
 
976
                        driver->playback_channels / driver->sample_bytes;
 
977
#elif defined(__NetBSD__)
 
978
                play_period = audio_if_out.blocksize /
 
979
                        driver->playback_channels / driver->sample_bytes;
 
980
#else
 
981
                /* how is this done on Solaris? */
 
982
                play_period = driver->period_size;
 
983
#endif
 
984
        }
 
985
 
 
986
        if (infd >= 0 && outfd >= 0 && play_period != cap_period)
 
987
        {
 
988
                jack_error("sun_driver: play and capture periods differ: "
 
989
                    "%s@%i", __FILE__, __LINE__);
 
990
                return -1;
 
991
        }
 
992
        if (infd >= 0)
 
993
                period_size = cap_period;
 
994
        else if (outfd >= 0)
 
995
                period_size = play_period;
 
996
 
 
997
        if (period_size != 0 && period_size != driver->period_size && 
 
998
            !driver->ignorehwbuf)
 
999
        {
 
1000
                printf("sun_driver: period size update: %u\n", period_size);
 
1001
 
 
1002
                set_period_size (driver, period_size);
 
1003
 
 
1004
                if (driver->engine)
 
1005
                        driver->engine->set_buffer_size(driver->engine, 
 
1006
                                driver->period_size);
 
1007
        }
 
1008
 
 
1009
        if (driver->infd >= 0 && driver->capture_channels > 0)
 
1010
        {
 
1011
                driver->indevbufsize = driver->period_size * 
 
1012
                        driver->capture_channels * driver->sample_bytes;
 
1013
                driver->indevbuf = malloc(driver->indevbufsize);
 
1014
                if (driver->indevbuf == NULL)
 
1015
                {
 
1016
                        jack_error( "sun_driver: malloc() failed: %s@%i", 
 
1017
                                __FILE__, __LINE__);
 
1018
                        return -1;
 
1019
                }
 
1020
                bzero(driver->indevbuf, driver->indevbufsize);
 
1021
        }
 
1022
        else
 
1023
        {
 
1024
                driver->indevbufsize = 0;
 
1025
                driver->indevbuf = NULL;
 
1026
        }
 
1027
 
 
1028
        if (driver->outfd >= 0 && driver->playback_channels > 0)
 
1029
        {
 
1030
                driver->outdevbufsize = driver->period_size * 
 
1031
                        driver->playback_channels * driver->sample_bytes;
 
1032
                driver->outdevbuf = malloc(driver->outdevbufsize);
 
1033
                if (driver->outdevbuf == NULL)
 
1034
                {
 
1035
                        jack_error("sun_driver: malloc() failed: %s@%i", 
 
1036
                                __FILE__, __LINE__);
 
1037
                        return -1;
 
1038
                }
 
1039
                bzero(driver->outdevbuf, driver->outdevbufsize);
 
1040
        }
 
1041
        else
 
1042
        {
 
1043
                driver->outdevbufsize = 0;
 
1044
                driver->outdevbuf = NULL;
 
1045
        }
 
1046
 
 
1047
        printf("sun_driver: indevbuf %zd B, outdevbuf %zd B\n",
 
1048
                driver->indevbufsize, driver->outdevbufsize);
 
1049
 
 
1050
        return 0;
 
1051
}
 
1052
 
 
1053
 
 
1054
static int
 
1055
sun_driver_stop (sun_driver_t *driver)
 
1056
{
 
1057
        audio_info_t audio_if;
 
1058
 
 
1059
        if (driver->infd >= 0)
 
1060
        {
 
1061
                AUDIO_INITINFO(&audio_if);
 
1062
                audio_if.record.pause = 1;
 
1063
                if (driver->outfd == driver->infd)
 
1064
                        audio_if.play.pause = 1;
 
1065
                if (ioctl(driver->infd, AUDIO_SETINFO, &audio_if) < 0)
 
1066
                {
 
1067
                        jack_error("sun_driver: capture pause failed: %s: "
 
1068
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
1069
                        return -1;
 
1070
                }
 
1071
        }
 
1072
 
 
1073
        if ((driver->outfd >= 0) && (driver->outfd != driver->infd))
 
1074
        {
 
1075
                AUDIO_INITINFO(&audio_if);
 
1076
                audio_if.play.pause = 1;
 
1077
                if (ioctl(driver->outfd, AUDIO_SETINFO, &audio_if) < 0)
 
1078
                {
 
1079
                        jack_error("sun_driver: playback pause failed: %s: "
 
1080
                                "%s@%i", strerror(errno), __FILE__, __LINE__);
 
1081
                        return -1;
 
1082
                }
 
1083
        }
 
1084
 
 
1085
        return 0;
 
1086
}
 
1087
 
 
1088
 
 
1089
static int
 
1090
sun_driver_read (sun_driver_t *driver, jack_nframes_t nframes)
 
1091
{
 
1092
        jack_nframes_t nbytes;
 
1093
        int channel;
 
1094
        ssize_t io_res;
 
1095
        jack_sample_t *portbuf;
 
1096
        JSList *node;
 
1097
        jack_port_t *port;
 
1098
 
 
1099
        if (driver->engine->freewheeling || driver->infd < 0)
 
1100
                return 0;
 
1101
 
 
1102
        if (nframes > driver->period_size)
 
1103
        {
 
1104
                jack_error("sun_driver: read failed: nframes > period_size: "
 
1105
                        "(%u/%u): %s@%i", nframes, driver->period_size,
 
1106
                        __FILE__, __LINE__);
 
1107
                return -1;
 
1108
        }
 
1109
 
 
1110
        node = driver->capture_ports;
 
1111
        channel = 0;
 
1112
        while (node != NULL)
 
1113
        {
 
1114
                port = (jack_port_t *) node->data;
 
1115
 
 
1116
                if (jack_port_connected(port))
 
1117
                {
 
1118
                        portbuf = jack_port_get_buffer(port, nframes);
 
1119
                        copy_and_convert_in(portbuf, driver->indevbuf, 
 
1120
                                nframes, channel, 
 
1121
                                driver->capture_channels,
 
1122
                                driver->bits);
 
1123
                }
 
1124
 
 
1125
                node = jack_slist_next(node);
 
1126
                channel++;
 
1127
        }
 
1128
 
 
1129
        nbytes = nframes * driver->capture_channels * driver->sample_bytes;
 
1130
        io_res = 0;
 
1131
        while (nbytes)
 
1132
        {
 
1133
                io_res = read(driver->infd, driver->indevbuf, nbytes);
 
1134
                if (io_res < 0)
 
1135
                {
 
1136
                        jack_error("sun_driver: read() failed: %s: %s@%i",
 
1137
                                strerror(errno), __FILE__, __LINE__);
 
1138
                        break;
 
1139
                }
 
1140
                else
 
1141
                        nbytes -= io_res;
 
1142
        }
 
1143
 
 
1144
        return 0;
 
1145
}
 
1146
 
 
1147
 
 
1148
static int
 
1149
sun_driver_write (sun_driver_t *driver, jack_nframes_t nframes)
 
1150
{
 
1151
        jack_nframes_t nbytes;
 
1152
        int channel;
 
1153
        ssize_t io_res;
 
1154
        jack_sample_t *portbuf;
 
1155
        JSList *node;
 
1156
        jack_port_t *port;
 
1157
 
 
1158
 
 
1159
        if (driver->engine->freewheeling || driver->outfd < 0)
 
1160
                return 0;
 
1161
 
 
1162
        if (nframes > driver->period_size)
 
1163
        {
 
1164
                jack_error("sun_driver: write failed: nframes > period_size "
 
1165
                        "(%u/%u): %s@%i", nframes, driver->period_size,
 
1166
                        __FILE__, __LINE__);
 
1167
                return -1;
 
1168
        }
 
1169
 
 
1170
        bzero(driver->outdevbuf, driver->outdevbufsize);
 
1171
 
 
1172
        node = driver->playback_ports;
 
1173
        channel = 0;
 
1174
        while (node != NULL)
 
1175
        {
 
1176
                port = (jack_port_t *) node->data;
 
1177
 
 
1178
                if (jack_port_connected(port))
 
1179
                {
 
1180
                        portbuf = jack_port_get_buffer(port, nframes);
 
1181
                        copy_and_convert_out(driver->outdevbuf, portbuf, 
 
1182
                                nframes, channel,
 
1183
                                driver->playback_channels,
 
1184
                                driver->bits);
 
1185
                }
 
1186
 
 
1187
                node = jack_slist_next(node);
 
1188
                channel++;
 
1189
        }
 
1190
 
 
1191
        nbytes = nframes * driver->playback_channels * driver->sample_bytes;
 
1192
        io_res = 0;
 
1193
        while (nbytes)
 
1194
        {
 
1195
                io_res = write(driver->outfd, driver->outdevbuf, nbytes);
 
1196
                if (io_res < 0)
 
1197
                {
 
1198
                        jack_error("sun_driver: write() failed: %s: %s@%i",
 
1199
                                strerror(errno), __FILE__, __LINE__);
 
1200
                        break;
 
1201
                }
 
1202
                else
 
1203
                        nbytes -= io_res;
 
1204
        }
 
1205
 
 
1206
        return 0;
 
1207
}
 
1208
 
 
1209
 
 
1210
static int
 
1211
sun_driver_null_cycle (sun_driver_t *driver, jack_nframes_t nframes)
 
1212
{
 
1213
        if (nframes > driver->period_size)
 
1214
        {
 
1215
                jack_error("sun_driver: null cycle failed: "
 
1216
                        "nframes > period_size (%u/%u): %s@%i", nframes,
 
1217
                        driver->period_size, __FILE__, __LINE__);
 
1218
                return -1;
 
1219
        }
 
1220
 
 
1221
        printf("sun_driver: running null cycle\n");
 
1222
 
 
1223
        if (driver->outfd >= 0)
 
1224
                sun_driver_write_silence (driver, nframes);
 
1225
 
 
1226
        if (driver->infd >= 0)
 
1227
                sun_driver_read_silence (driver, nframes);
 
1228
 
 
1229
        return 0;
 
1230
}
 
1231
 
 
1232
 
 
1233
static int
 
1234
sun_driver_bufsize (sun_driver_t *driver, jack_nframes_t nframes)
 
1235
{
 
1236
        return sun_driver_set_parameters(driver);
 
1237
}
 
1238
 
 
1239
 
 
1240
static void
 
1241
sun_driver_delete (sun_driver_t *driver)
 
1242
{
 
1243
        if (driver->outfd >= 0 && driver->outfd != driver->infd)
 
1244
        {
 
1245
                close(driver->outfd);
 
1246
                driver->outfd = -1;
 
1247
        }
 
1248
        if (driver->infd >= 0)
 
1249
        {
 
1250
                close(driver->infd);
 
1251
                driver->infd = -1;
 
1252
        }
 
1253
 
 
1254
        if (driver->indevbuf != NULL)
 
1255
        {
 
1256
                free(driver->indevbuf);
 
1257
                driver->indevbuf = NULL;
 
1258
        }
 
1259
        if (driver->outdevbuf != NULL)
 
1260
        {
 
1261
                free(driver->outdevbuf);
 
1262
                driver->outdevbuf = NULL;
 
1263
        }
 
1264
 
 
1265
        if (driver->indev != NULL)
 
1266
                free(driver->indev);
 
1267
 
 
1268
        if (driver->outdev != NULL)
 
1269
                free(driver->outdev);
 
1270
 
 
1271
        jack_driver_nt_finish((jack_driver_nt_t *) driver);
 
1272
 
 
1273
        free(driver);
 
1274
}
 
1275
 
 
1276
 
 
1277
void
 
1278
driver_finish (jack_driver_t *driver)
 
1279
{
 
1280
        sun_driver_delete ((sun_driver_t *)driver);
 
1281
}
 
1282
 
 
1283
 
 
1284
static jack_driver_t *
 
1285
sun_driver_new (char *indev, char *outdev, jack_client_t *client,
 
1286
        jack_nframes_t sample_rate, jack_nframes_t period_size,
 
1287
        jack_nframes_t nperiods, int bits,
 
1288
        int capture_channels, int playback_channels,
 
1289
        jack_nframes_t in_latency, jack_nframes_t out_latency,
 
1290
        int ignorehwbuf)
 
1291
{
 
1292
        sun_driver_t *driver;
 
1293
 
 
1294
        driver = (sun_driver_t *) malloc(sizeof(sun_driver_t));
 
1295
        if (driver == NULL)
 
1296
        {
 
1297
                jack_error("sun_driver: malloc() failed: %s: %s@%i",
 
1298
                        strerror(errno), __FILE__, __LINE__);
 
1299
                return NULL;
 
1300
        }
 
1301
        driver->engine = NULL;
 
1302
        jack_driver_nt_init((jack_driver_nt_t *) driver);
 
1303
 
 
1304
        driver->nt_attach = (JackDriverNTAttachFunction) sun_driver_attach;
 
1305
        driver->nt_detach = (JackDriverNTDetachFunction) sun_driver_detach;
 
1306
        driver->read = (JackDriverReadFunction) sun_driver_read;
 
1307
        driver->write = (JackDriverWriteFunction) sun_driver_write;
 
1308
        driver->null_cycle = (JackDriverNullCycleFunction) 
 
1309
                sun_driver_null_cycle;
 
1310
        driver->nt_bufsize = (JackDriverNTBufSizeFunction) sun_driver_bufsize;
 
1311
        driver->nt_start = (JackDriverNTStartFunction) sun_driver_start;
 
1312
        driver->nt_stop = (JackDriverNTStopFunction) sun_driver_stop;
 
1313
        driver->nt_run_cycle = (JackDriverNTRunCycleFunction) sun_driver_run_cycle;
 
1314
 
 
1315
        if (indev != NULL)
 
1316
                driver->indev = strdup(indev);
 
1317
        if (outdev != NULL)
 
1318
                driver->outdev = strdup(outdev);
 
1319
 
 
1320
        driver->ignorehwbuf = ignorehwbuf;
 
1321
 
 
1322
        driver->sample_rate = sample_rate;
 
1323
        driver->period_size = period_size;
 
1324
        driver->nperiods = nperiods;
 
1325
        driver->bits = bits;
 
1326
        driver->capture_channels = capture_channels;
 
1327
        driver->playback_channels = playback_channels;
 
1328
        driver->sys_in_latency = in_latency;
 
1329
        driver->sys_out_latency = out_latency;
 
1330
 
 
1331
        set_period_size(driver, period_size);
 
1332
        
 
1333
        if (driver->indev == NULL)
 
1334
                driver->indev = strdup(SUN_DRIVER_DEF_DEV);
 
1335
        if (driver->outdev == NULL)
 
1336
                driver->outdev = strdup(SUN_DRIVER_DEF_DEV);
 
1337
        driver->infd = -1;
 
1338
        driver->outfd = -1;
 
1339
#if defined(AUDIO_ENCODING_SLINEAR)
 
1340
        driver->format = AUDIO_ENCODING_SLINEAR;
 
1341
#else
 
1342
        driver->format = AUDIO_ENCODING_LINEAR;
 
1343
#endif
 
1344
        driver->indevbuf = driver->outdevbuf = NULL;
 
1345
 
 
1346
        driver->capture_ports = NULL;
 
1347
        driver->playback_ports = NULL;
 
1348
 
 
1349
        driver->iodelay = 0.0F;
 
1350
        driver->poll_last = driver->poll_next = 0;
 
1351
 
 
1352
        if (sun_driver_set_parameters (driver) < 0)
 
1353
        {
 
1354
                free(driver);
 
1355
                return NULL;
 
1356
        }
 
1357
 
 
1358
        driver->client = client;
 
1359
 
 
1360
        return (jack_driver_t *) driver;
 
1361
}
 
1362
 
 
1363
 
 
1364
/* jack driver published interface */
 
1365
 
 
1366
 
 
1367
const char driver_client_name[] = "sun";
 
1368
 
 
1369
 
 
1370
jack_driver_desc_t *
 
1371
driver_get_descriptor ()
 
1372
{
 
1373
        jack_driver_desc_t *desc;
 
1374
        jack_driver_param_desc_t *params;
 
1375
 
 
1376
        desc = (jack_driver_desc_t *) calloc(1, sizeof(jack_driver_desc_t));
 
1377
        if (desc == NULL)
 
1378
        {
 
1379
                jack_error("sun_driver: calloc() failed: %s: %s@%i",
 
1380
                        strerror(errno), __FILE__, __LINE__);
 
1381
                return NULL;
 
1382
        }
 
1383
        strcpy(desc->name, driver_client_name);
 
1384
        desc->nparams = SUN_DRIVER_N_PARAMS;
 
1385
 
 
1386
        params = calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
 
1387
        if (params == NULL)
 
1388
        {
 
1389
                jack_error("sun_driver: calloc() failed: %s: %s@%i",
 
1390
                        strerror(errno), __FILE__, __LINE__);
 
1391
                return NULL;
 
1392
        }
 
1393
        memcpy(params, sun_params, 
 
1394
                desc->nparams * sizeof(jack_driver_param_desc_t));
 
1395
        desc->params = params;
 
1396
 
 
1397
        return desc;
 
1398
}
 
1399
 
 
1400
 
 
1401
jack_driver_t *
 
1402
driver_initialize (jack_client_t *client, JSList * params)
 
1403
{
 
1404
        int bits = SUN_DRIVER_DEF_BITS;
 
1405
        jack_nframes_t sample_rate = SUN_DRIVER_DEF_FS;
 
1406
        jack_nframes_t period_size = SUN_DRIVER_DEF_BLKSIZE;
 
1407
        jack_nframes_t in_latency = 0;
 
1408
        jack_nframes_t out_latency = 0;
 
1409
        unsigned int nperiods = SUN_DRIVER_DEF_NPERIODS;
 
1410
        unsigned int capture_channels = SUN_DRIVER_DEF_INS;
 
1411
        unsigned int playback_channels = SUN_DRIVER_DEF_OUTS;
 
1412
        const JSList *pnode;
 
1413
        const jack_driver_param_t *param;
 
1414
        char *indev;
 
1415
        char *outdev;
 
1416
        int ignorehwbuf = 0;
 
1417
 
 
1418
        indev = strdup(SUN_DRIVER_DEF_DEV);
 
1419
        outdev = strdup(SUN_DRIVER_DEF_DEV);
 
1420
 
 
1421
        pnode = params;
 
1422
        while (pnode != NULL)
 
1423
        {
 
1424
                param = (const jack_driver_param_t *) pnode->data;
 
1425
 
 
1426
                switch (param->character)
 
1427
                {
 
1428
                        case 'r':
 
1429
                                sample_rate = param->value.ui;
 
1430
                                break;
 
1431
                        case 'p':
 
1432
                                period_size = param->value.ui;
 
1433
                                break;
 
1434
                        case 'n':
 
1435
                                nperiods = param->value.ui;
 
1436
                                break;
 
1437
                        case 'w':
 
1438
                                bits = param->value.i;
 
1439
                                break;
 
1440
                        case 'i':
 
1441
                                capture_channels = param->value.ui;
 
1442
                                break;
 
1443
                        case 'o':
 
1444
                                playback_channels = param->value.ui;
 
1445
                                break;
 
1446
                        case 'C':
 
1447
                                indev = strdup(param->value.str);
 
1448
                                break;
 
1449
                        case 'P':
 
1450
                                outdev = strdup(param->value.str);
 
1451
                                break;
 
1452
                        case 'b':
 
1453
                                ignorehwbuf = 1;
 
1454
                                break;
 
1455
                        case 'I':
 
1456
                                in_latency = param->value.ui;
 
1457
                                break;
 
1458
                        case 'O':
 
1459
                                out_latency = param->value.ui;
 
1460
                                break;
 
1461
                }
 
1462
                pnode = jack_slist_next(pnode);
 
1463
        }
 
1464
        
 
1465
        return sun_driver_new (indev, outdev, client, sample_rate, period_size,
 
1466
                nperiods, bits, capture_channels, playback_channels, in_latency,
 
1467
                out_latency, ignorehwbuf);
 
1468
}