Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-ports-kde
Path: blob/main/audio/alsa-plugins/files/patch-oss_pcm__oss.c
16462 views
1
--- oss/pcm_oss.c.orig 2024-06-10 09:18:39 UTC
2
+++ oss/pcm_oss.c
3
@@ -20,6 +20,7 @@
4
5
#include "config.h"
6
#include <stdio.h>
7
+#include <stdbool.h>
8
#include <sys/ioctl.h>
9
#include <alsa/asoundlib.h>
10
#include <alsa/pcm_external.h>
11
@@ -31,16 +32,32 @@
12
#include <soundcard.h>
13
#endif
14
15
+#ifndef ARRAY_SIZE
16
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
17
+#endif
18
+
19
+#define ALSA_OSS_RATE_MIN 1
20
+#define ALSA_OSS_RATE_MAX 384000
21
+
22
+#define ALSA_OSS_CHANNELS_MIN 1
23
+#define ALSA_OSS_CHANNELS_MAX 8
24
+
25
+#define ALSA_OSS_BUFSZ_MAX 131072
26
+#define ALSA_OSS_BLKCNT_MIN 2
27
+#define ALSA_OSS_BLKSZ_MIN 16 /* (ALSA_OSS_CHANNELS_MAX * 4) */
28
+
29
+#define ALSA_OSS_BUFSZ_MIN (ALSA_OSS_BLKCNT_MIN * ALSA_OSS_BLKSZ_MIN)
30
+#define ALSA_OSS_BLKCNT_MAX (ALSA_OSS_BUFSZ_MAX / ALSA_OSS_BUFSZ_MIN)
31
+#define ALSA_OSS_BLKSZ_MAX (ALSA_OSS_BUFSZ_MAX / ALSA_OSS_BLKCNT_MIN)
32
+
33
typedef struct snd_pcm_oss {
34
snd_pcm_ioplug_t io;
35
char *device;
36
int fd;
37
- int fragment_set;
38
- int caps;
39
+ int bufsz;
40
int format;
41
- unsigned int period_shift;
42
- unsigned int periods;
43
- unsigned int frame_bytes;
44
+ int frame_bytes;
45
+ bool buffer_used;
46
} snd_pcm_oss_t;
47
48
static snd_pcm_sframes_t oss_write(snd_pcm_ioplug_t *io,
49
@@ -56,8 +73,21 @@ static snd_pcm_sframes_t oss_write(snd_pcm_ioplug_t *i
50
buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
51
size *= oss->frame_bytes;
52
result = write(oss->fd, buf, size);
53
- if (result <= 0)
54
- return result;
55
+#ifdef __FreeBSD__
56
+ if (result == -1) {
57
+ if (errno == EAGAIN)
58
+ return 0;
59
+ else
60
+ return -errno;
61
+ }
62
+#else
63
+ if (result <= 0) {
64
+ if (result == -EAGAIN)
65
+ return 0;
66
+ else
67
+ return result;
68
+ }
69
+#endif
70
return result / oss->frame_bytes;
71
}
72
73
@@ -74,37 +104,122 @@ static snd_pcm_sframes_t oss_read(snd_pcm_ioplug_t *io
74
buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
75
size *= oss->frame_bytes;
76
result = read(oss->fd, buf, size);
77
- if (result <= 0)
78
- return result;
79
+#ifdef __FreeBSD__
80
+ if (result == -1) {
81
+ if (errno == EAGAIN)
82
+ return 0;
83
+ else
84
+ return -errno;
85
+ }
86
+#else
87
+ if (result <= 0) {
88
+ if (result == -EAGAIN)
89
+ return 0;
90
+ else
91
+ return result;
92
+ }
93
+#endif
94
return result / oss->frame_bytes;
95
}
96
97
static snd_pcm_sframes_t oss_pointer(snd_pcm_ioplug_t *io)
98
{
99
snd_pcm_oss_t *oss = io->private_data;
100
- struct count_info info;
101
- int ptr;
102
+ snd_pcm_sframes_t frames;
103
+ audio_buf_info bi;
104
105
- if (ioctl(oss->fd, io->stream == SND_PCM_STREAM_PLAYBACK ?
106
- SNDCTL_DSP_GETOPTR : SNDCTL_DSP_GETIPTR, &info) < 0) {
107
- fprintf(stderr, "*** OSS: oss_pointer error\n");
108
+ switch (io->state) {
109
+ case SND_PCM_STATE_XRUN:
110
+ return -EPIPE;
111
+ case SND_PCM_STATE_RUNNING:
112
+ case SND_PCM_STATE_DRAINING:
113
+ break;
114
+ default:
115
return 0;
116
}
117
- ptr = snd_pcm_bytes_to_frames(io->pcm, info.ptr);
118
- return ptr;
119
+
120
+ if (io->stream == SND_PCM_STREAM_PLAYBACK) {
121
+ if (ioctl(oss->fd, SNDCTL_DSP_GETOSPACE, &bi) < 0)
122
+ return -EINVAL;
123
+ } else {
124
+ if (ioctl(oss->fd, SNDCTL_DSP_GETISPACE, &bi) < 0)
125
+ return -EINVAL;
126
+ }
127
+
128
+ /* check for over- and under- run */
129
+ if (bi.bytes != oss->bufsz) {
130
+ oss->buffer_used = true;
131
+ } else {
132
+ if (oss->buffer_used)
133
+ return -EPIPE;
134
+ }
135
+
136
+ frames = bi.bytes / oss->frame_bytes;
137
+
138
+ /* range check */
139
+ if (frames < 0)
140
+ frames = 0;
141
+ else if (frames > io->buffer_size)
142
+ frames = io->buffer_size;
143
+
144
+ /* set hw_ptr directly */
145
+ if (io->stream == SND_PCM_STREAM_PLAYBACK) {
146
+ io->hw_ptr = io->appl_ptr + frames - io->buffer_size;
147
+ } else {
148
+ io->hw_ptr = io->appl_ptr + frames;
149
+ }
150
+ return 0;
151
}
152
153
+static int oss_prepare(snd_pcm_ioplug_t *io)
154
+{
155
+ snd_pcm_oss_t *oss = io->private_data;
156
+ snd_pcm_sw_params_t *swparams;
157
+ snd_pcm_uframes_t min_avail;
158
+ int tmp;
159
+
160
+ snd_pcm_sw_params_alloca(&swparams);
161
+
162
+ if (snd_pcm_sw_params_current(io->pcm, swparams) == 0) {
163
+ snd_pcm_sw_params_get_avail_min(swparams, &min_avail);
164
+ snd_pcm_sw_params_alloca(&swparams);
165
+ } else {
166
+ min_avail = io->period_size;
167
+ }
168
+
169
+ tmp = min_avail * oss->frame_bytes;
170
+ if (tmp > oss->bufsz)
171
+ tmp = oss->bufsz;
172
+ else if (tmp < 1)
173
+ tmp = 1;
174
+
175
+#ifdef SNDCTL_DSP_LOW_WATER
176
+ if (ioctl(oss->fd, SNDCTL_DSP_LOW_WATER, &tmp) < 0)
177
+ return -EINVAL;
178
+#endif
179
+ oss->buffer_used = false;
180
+
181
+ return 0;
182
+}
183
+
184
static int oss_start(snd_pcm_ioplug_t *io)
185
{
186
snd_pcm_oss_t *oss = io->private_data;
187
int tmp = io->stream == SND_PCM_STREAM_PLAYBACK ?
188
PCM_ENABLE_OUTPUT : PCM_ENABLE_INPUT;
189
190
+#ifdef ALSA_OSS_DEBUG_VERBOSE
191
+ fprintf(stderr, "%s()\n", __func__);
192
+#endif
193
if (ioctl(oss->fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
194
fprintf(stderr, "*** OSS: trigger failed\n");
195
+#ifdef __FreeBSD__
196
+ return -EINVAL;
197
+#else
198
if (io->stream == SND_PCM_STREAM_CAPTURE)
199
/* fake read to trigger */
200
read(oss->fd, &tmp, 0);
201
+#endif
202
}
203
return 0;
204
}
205
@@ -114,6 +229,10 @@ static int oss_stop(snd_pcm_ioplug_t *io)
206
snd_pcm_oss_t *oss = io->private_data;
207
int tmp = 0;
208
209
+#ifdef ALSA_OSS_DEBUG_VERBOSE
210
+ fprintf(stderr, "%s()\n", __func__);
211
+#endif
212
+
213
ioctl(oss->fd, SNDCTL_DSP_SETTRIGGER, &tmp);
214
return 0;
215
}
216
@@ -122,101 +241,164 @@ static int oss_drain(snd_pcm_ioplug_t *io)
217
{
218
snd_pcm_oss_t *oss = io->private_data;
219
220
+#ifdef ALSA_OSS_DEBUG_VERBOSE
221
+ fprintf(stderr, "%s()\n", __func__);
222
+#endif
223
+
224
if (io->stream == SND_PCM_STREAM_PLAYBACK)
225
- ioctl(oss->fd, SNDCTL_DSP_SYNC);
226
+ ioctl(oss->fd, SNDCTL_DSP_SYNC, NULL);
227
return 0;
228
}
229
230
-static int oss_prepare(snd_pcm_ioplug_t *io)
231
+static int oss_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp)
232
{
233
snd_pcm_oss_t *oss = io->private_data;
234
int tmp;
235
236
- ioctl(oss->fd, SNDCTL_DSP_RESET);
237
+ if (oss->fd < 0)
238
+ return -EBADFD;
239
240
- tmp = io->channels;
241
- if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &tmp) < 0) {
242
- perror("SNDCTL_DSP_CHANNELS");
243
- return -EINVAL;
244
+ if (io->stream == SND_PCM_STREAM_PLAYBACK) {
245
+ if (ioctl(oss->fd, SNDCTL_DSP_GETODELAY, &tmp) < 0 || tmp < 0)
246
+ tmp = 0;
247
+ } else {
248
+ tmp = 0;
249
}
250
- tmp = oss->format;
251
- if (ioctl(oss->fd, SNDCTL_DSP_SETFMT, &tmp) < 0) {
252
- perror("SNDCTL_DSP_SETFMT");
253
- return -EINVAL;
254
- }
255
- tmp = io->rate;
256
- if (ioctl(oss->fd, SNDCTL_DSP_SPEED, &tmp) < 0 ||
257
- tmp > io->rate * 1.01 || tmp < io->rate * 0.99) {
258
- perror("SNDCTL_DSP_SPEED");
259
- return -EINVAL;
260
- }
261
- return 0;
262
+ *delayp = tmp / oss->frame_bytes;
263
+
264
+ return (0);
265
}
266
267
+static const struct {
268
+ int oss_format;
269
+ snd_pcm_format_t alsa_format;
270
+} oss_formats_tab[] = {
271
+ { AFMT_U8, SND_PCM_FORMAT_U8 },
272
+ { AFMT_S8, SND_PCM_FORMAT_S8 },
273
+ { AFMT_MU_LAW, SND_PCM_FORMAT_MU_LAW },
274
+ { AFMT_A_LAW, SND_PCM_FORMAT_A_LAW },
275
+ { AFMT_S16_LE, SND_PCM_FORMAT_S16_LE },
276
+ { AFMT_S16_BE, SND_PCM_FORMAT_S16_BE },
277
+ { AFMT_U16_LE, SND_PCM_FORMAT_U16_LE },
278
+ { AFMT_U16_BE, SND_PCM_FORMAT_U16_BE },
279
+ { AFMT_S24_LE, SND_PCM_FORMAT_S24_3LE },
280
+ { AFMT_S24_BE, SND_PCM_FORMAT_S24_3BE },
281
+ { AFMT_U24_LE, SND_PCM_FORMAT_U24_3LE },
282
+ { AFMT_U24_BE, SND_PCM_FORMAT_U24_3BE },
283
+ { AFMT_S32_LE, SND_PCM_FORMAT_S32_LE },
284
+ { AFMT_S32_BE, SND_PCM_FORMAT_S32_BE },
285
+ { AFMT_U32_LE, SND_PCM_FORMAT_U32_LE },
286
+ { AFMT_U32_BE, SND_PCM_FORMAT_U32_BE },
287
+ /* Special */
288
+ { AFMT_S24_LE, SND_PCM_FORMAT_S20_3LE },
289
+ { AFMT_S24_BE, SND_PCM_FORMAT_S20_3BE },
290
+ { AFMT_U24_LE, SND_PCM_FORMAT_U20_3LE },
291
+ { AFMT_U24_BE, SND_PCM_FORMAT_U20_3BE },
292
+ { AFMT_S24_LE, SND_PCM_FORMAT_S18_3LE },
293
+ { AFMT_S24_BE, SND_PCM_FORMAT_S18_3BE },
294
+ { AFMT_U24_LE, SND_PCM_FORMAT_U18_3LE },
295
+ { AFMT_U24_BE, SND_PCM_FORMAT_U18_3BE },
296
+ { AFMT_S32_LE, SND_PCM_FORMAT_S24_LE },
297
+ { AFMT_S32_BE, SND_PCM_FORMAT_S24_BE },
298
+ { AFMT_U32_LE, SND_PCM_FORMAT_U24_LE },
299
+ { AFMT_U32_BE, SND_PCM_FORMAT_U24_BE },
300
+};
301
+
302
static int oss_hw_params(snd_pcm_ioplug_t *io,
303
snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED)
304
{
305
snd_pcm_oss_t *oss = io->private_data;
306
int i, tmp, err;
307
- unsigned int period_bytes;
308
+ int blksz_shift, blkcnt;
309
+ audio_buf_info bi;
310
long oflags, flags;
311
312
+#ifdef ALSA_OSS_DEBUG_VERBOSE
313
+ fprintf(stderr, "%s()\n", __func__);
314
+#endif
315
+
316
oss->frame_bytes = (snd_pcm_format_physical_width(io->format) * io->channels) / 8;
317
- switch (io->format) {
318
- case SND_PCM_FORMAT_U8:
319
- oss->format = AFMT_U8;
320
- break;
321
- case SND_PCM_FORMAT_S16_LE:
322
- oss->format = AFMT_S16_LE;
323
- break;
324
- case SND_PCM_FORMAT_S16_BE:
325
- oss->format = AFMT_S16_BE;
326
- break;
327
- default:
328
+ oss->format = 0;
329
+ for (i = 0; i != ARRAY_SIZE(oss_formats_tab); i++) {
330
+ if (oss_formats_tab[i].alsa_format == io->format) {
331
+ oss->format = oss_formats_tab[i].oss_format;
332
+ break;
333
+ }
334
+ }
335
+ if (oss->format == 0) {
336
fprintf(stderr, "*** OSS: unsupported format %s\n", snd_pcm_format_name(io->format));
337
return -EINVAL;
338
}
339
- period_bytes = io->period_size * oss->frame_bytes;
340
- oss->period_shift = 0;
341
- for (i = 31; i >= 4; i--) {
342
- if (period_bytes & (1U << i)) {
343
- oss->period_shift = i;
344
+
345
+ ioctl(oss->fd, SNDCTL_DSP_RESET);
346
+
347
+ /* use a 8ms HW buffer by default */
348
+ tmp = ((8 * io->rate) / 1000) * oss->frame_bytes;
349
+
350
+ /* round up to nearest power of two */
351
+ while (tmp & (tmp - 1))
352
+ tmp += tmp & ~(tmp - 1);
353
+
354
+ /* get logarithmic value */
355
+ for (blksz_shift = 0; blksz_shift < 24; blksz_shift++) {
356
+ if (tmp == (1 << blksz_shift))
357
break;
358
- }
359
}
360
- if (! oss->period_shift) {
361
- fprintf(stderr, "*** OSS: invalid period size %d\n", (int)io->period_size);
362
- return -EINVAL;
363
+
364
+ tmp = io->buffer_size * oss->frame_bytes;
365
+
366
+ /* compute HW buffer big enough to hold SW buffer */
367
+ for (blkcnt = ALSA_OSS_BLKCNT_MIN; blkcnt != ALSA_OSS_BLKCNT_MAX; blkcnt *= 2) {
368
+ if ((blkcnt << blksz_shift) >= tmp)
369
+ break;
370
}
371
- oss->periods = io->buffer_size / io->period_size;
372
373
- _retry:
374
- tmp = oss->period_shift | (oss->periods << 16);
375
+ tmp = blksz_shift | (blkcnt << 16);
376
if (ioctl(oss->fd, SNDCTL_DSP_SETFRAGMENT, &tmp) < 0) {
377
- if (! oss->fragment_set) {
378
- perror("SNDCTL_DSP_SETFRAGMENT");
379
- fprintf(stderr, "*** period shift = %d, periods = %d\n", oss->period_shift, oss->periods);
380
- return -EINVAL;
381
- }
382
- /* OSS has no proper way to reinitialize the fragments */
383
- /* try to reopen the device */
384
- close(oss->fd);
385
- oss->fd = open(oss->device, io->stream == SND_PCM_STREAM_PLAYBACK ?
386
- O_WRONLY : O_RDONLY);
387
- if (oss->fd < 0) {
388
- err = -errno;
389
- SNDERR("Cannot reopen the device %s", oss->device);
390
- return err;
391
- }
392
- io->poll_fd = oss->fd;
393
- io->poll_events = io->stream == SND_PCM_STREAM_PLAYBACK ?
394
- POLLOUT : POLLIN;
395
- snd_pcm_ioplug_reinit_status(io);
396
- oss->fragment_set = 0;
397
- goto _retry;
398
+ perror("SNDCTL_DSP_SETFRAGMENTS");
399
+ return -EINVAL;
400
}
401
- oss->fragment_set = 1;
402
403
+ tmp = oss->format;
404
+ if (ioctl(oss->fd, SNDCTL_DSP_SETFMT, &tmp) < 0 ||
405
+ tmp != oss->format) {
406
+ perror("SNDCTL_DSP_SETFMT");
407
+ return -EINVAL;
408
+ }
409
+
410
+ tmp = io->channels;
411
+ if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &tmp) < 0 ||
412
+ tmp != io->channels) {
413
+ perror("SNDCTL_DSP_CHANNELS");
414
+ return -EINVAL;
415
+ }
416
+
417
+ tmp = io->rate;
418
+ if (ioctl(oss->fd, SNDCTL_DSP_SPEED, &tmp) < 0 ||
419
+ tmp > io->rate * 1.01 || tmp < io->rate * 0.99) {
420
+ perror("SNDCTL_DSP_SPEED");
421
+ return -EINVAL;
422
+ }
423
+
424
+ if (ioctl(oss->fd, (io->stream == SND_PCM_STREAM_PLAYBACK) ?
425
+ SNDCTL_DSP_GETOSPACE : SNDCTL_DSP_GETISPACE, &bi) < 0) {
426
+ perror("SNDCTL_DSP_GET[I/O]SPACE");
427
+ return -EINVAL;
428
+ }
429
+
430
+ oss->bufsz = bi.fragsize * bi.fragstotal;
431
+
432
+#ifdef ALSA_OSS_DEBUG_VERBOSE
433
+ fprintf(stderr,
434
+ "\n\n[%lu -> %d] %lu ~ %d -> %d, %lu ~ %d -> %d [d:%ld lw:%d]\n\n",
435
+ io->buffer_size / io->period_size, bi.fragstotal,
436
+ io->buffer_size * oss->frame_bytes,
437
+ (1 << blksz_shift) * blkcnt, oss->bufsz,
438
+ io->period_size * oss->frame_bytes, 1 << blksz_shift,
439
+ bi.fragsize,
440
+ (long)(io->buffer_size * oss->frame_bytes) -
441
+ oss->bufsz, tmp);
442
+#endif
443
if ((flags = fcntl(oss->fd, F_GETFL)) < 0) {
444
err = -errno;
445
perror("F_GETFL");
446
@@ -236,16 +418,148 @@ static int oss_hw_params(snd_pcm_ioplug_t *io,
447
return 0;
448
}
449
450
-#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0]))
451
-
452
static int oss_hw_constraint(snd_pcm_oss_t *oss)
453
{
454
+#ifdef __FreeBSD__
455
snd_pcm_ioplug_t *io = &oss->io;
456
static const snd_pcm_access_t access_list[] = {
457
SND_PCM_ACCESS_RW_INTERLEAVED,
458
SND_PCM_ACCESS_MMAP_INTERLEAVED
459
};
460
+#ifdef FREEBSD_OSS_BLKCNT_P2
461
+ unsigned int period_list[30];
462
+#endif
463
+#ifdef FREEBSD_OSS_BUFSZ_P2
464
+ unsigned int bufsz_list[30];
465
+#endif
466
unsigned int nformats;
467
+ unsigned int format[ARRAY_SIZE(oss_formats_tab)];
468
+ int i, err, tmp;
469
+
470
+#ifdef ALSA_OSS_DEBUG_VERBOSE
471
+ fprintf(stderr, "%s()\n", __func__);
472
+#endif
473
+
474
+ /* check trigger */
475
+ tmp = 0;
476
+ if (ioctl(oss->fd, SNDCTL_DSP_GETCAPS, &tmp) >= 0) {
477
+ if (!(tmp & DSP_CAP_TRIGGER))
478
+ fprintf(stderr, "*** OSS: trigger is not supported!\n");
479
+ }
480
+
481
+ /* access type - interleaved only */
482
+ if ((err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
483
+ ARRAY_SIZE(access_list), access_list)) < 0)
484
+ return err;
485
+
486
+ /* supported formats. */
487
+ tmp = 0;
488
+ ioctl(oss->fd, SNDCTL_DSP_GETFMTS, &tmp);
489
+ nformats = 0;
490
+ for (i = 0; i < ARRAY_SIZE(oss_formats_tab); i++) {
491
+ if (tmp & oss_formats_tab[i].oss_format)
492
+ format[nformats++] = oss_formats_tab[i].alsa_format;
493
+ }
494
+ if (! nformats)
495
+ format[nformats++] = SND_PCM_FORMAT_S16;
496
+ if ((err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
497
+ nformats, format)) < 0)
498
+ return err;
499
+
500
+#if 0
501
+ /* supported channels */
502
+ nchannels = 0;
503
+ for (i = 0; i < ARRAY_SIZE(channel); i++) {
504
+ tmp = i + 1;
505
+ if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &tmp) >= 0 &&
506
+ 1 + i == tmp)
507
+ channel[nchannels++] = tmp;
508
+ }
509
+ if (! nchannels) /* assume 2ch stereo */
510
+ err = snd_pcm_ioplug_set_param_minmax(io,
511
+ SND_PCM_IOPLUG_HW_CHANNELS, 2, 2);
512
+ else
513
+ err = snd_pcm_ioplug_set_param_list(io,
514
+ SND_PCM_IOPLUG_HW_CHANNELS, nchannels, channel);
515
+ if (err < 0)
516
+ return err;
517
+#endif
518
+ err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
519
+ ALSA_OSS_CHANNELS_MIN, ALSA_OSS_CHANNELS_MAX);
520
+ if (err < 0)
521
+ return err;
522
+
523
+ /* supported rates */
524
+ err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
525
+ ALSA_OSS_RATE_MIN, ALSA_OSS_RATE_MAX);
526
+ if (err < 0)
527
+ return err;
528
+
529
+ /*
530
+ * Maximum buffer size on FreeBSD can go up to 131072 bytes without
531
+ * strict ^2 alignment so that s24le in 3bytes packing can be fed
532
+ * directly.
533
+ */
534
+
535
+#ifdef FREEBSD_OSS_BLKCNT_P2
536
+ tmp = 0;
537
+ for (i = 1; i < 31 && tmp < ARRAY_SIZE(period_list); i++) {
538
+ if ((1 << i) > ALSA_OSS_BLKCNT_MAX)
539
+ break;
540
+ if ((1 << i) < ALSA_OSS_BLKCNT_MIN)
541
+ continue;
542
+ period_list[tmp++] = 1 << i;
543
+ }
544
+
545
+ if (tmp > 0)
546
+ err = snd_pcm_ioplug_set_param_list(io,
547
+ SND_PCM_IOPLUG_HW_PERIODS, tmp, period_list);
548
+ else
549
+#endif
550
+ /* periods , not strictly ^2 but later on will be refined */
551
+ err = snd_pcm_ioplug_set_param_minmax(io,
552
+ SND_PCM_IOPLUG_HW_PERIODS, ALSA_OSS_BLKCNT_MIN,
553
+ ALSA_OSS_BLKCNT_MAX);
554
+ if (err < 0)
555
+ return err;
556
+
557
+ /* period size , not strictly ^2 */
558
+ err = snd_pcm_ioplug_set_param_minmax(io,
559
+ SND_PCM_IOPLUG_HW_PERIOD_BYTES, ALSA_OSS_BLKSZ_MIN,
560
+ ALSA_OSS_BLKSZ_MAX);
561
+ if (err < 0)
562
+ return err;
563
+
564
+#ifdef FREEBSD_OSS_BUFSZ_P2
565
+ tmp = 0;
566
+ for (i = 1; i < 31 && tmp < ARRAY_SIZE(bufsz_list); i++) {
567
+ if ((1 << i) > ALSA_OSS_BUFSZ_MAX)
568
+ break;
569
+ if ((1 << i) < ALSA_OSS_BUFSZ_MIN)
570
+ continue;
571
+ bufsz_list[tmp++] = 1 << i;
572
+ }
573
+
574
+ if (tmp > 0)
575
+ err = snd_pcm_ioplug_set_param_list(io,
576
+ SND_PCM_IOPLUG_HW_BUFFER_BYTES, tmp, bufsz_list);
577
+ else
578
+#endif
579
+ /* buffer size , not strictly ^2 */
580
+ err = snd_pcm_ioplug_set_param_minmax(io,
581
+ SND_PCM_IOPLUG_HW_BUFFER_BYTES, ALSA_OSS_BUFSZ_MIN,
582
+ ALSA_OSS_BUFSZ_MAX);
583
+ if (err < 0)
584
+ return err;
585
+
586
+ return 0;
587
+#else
588
+ snd_pcm_ioplug_t *io = &oss->io;
589
+ static const snd_pcm_access_t access_list[] = {
590
+ SND_PCM_ACCESS_RW_INTERLEAVED,
591
+ SND_PCM_ACCESS_MMAP_INTERLEAVED
592
+ };
593
+ unsigned int nformats;
594
unsigned int format[5];
595
unsigned int nchannels;
596
unsigned int channel[6];
597
@@ -324,6 +638,7 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss)
598
return err;
599
600
return 0;
601
+#endif
602
}
603
604
605
@@ -331,6 +646,10 @@ static int oss_close(snd_pcm_ioplug_t *io)
606
{
607
snd_pcm_oss_t *oss = io->private_data;
608
609
+#ifdef ALSA_OSS_DEBUG_VERBOSE
610
+ fprintf(stderr, "%s()\n", __func__);
611
+#endif
612
+
613
close(oss->fd);
614
free(oss->device);
615
free(oss);
616
@@ -346,6 +665,7 @@ static const snd_pcm_ioplug_callback_t oss_playback_ca
617
.hw_params = oss_hw_params,
618
.prepare = oss_prepare,
619
.drain = oss_drain,
620
+ .delay = oss_delay,
621
};
622
623
static const snd_pcm_ioplug_callback_t oss_capture_callback = {
624
@@ -357,6 +677,7 @@ static const snd_pcm_ioplug_callback_t oss_capture_cal
625
.hw_params = oss_hw_params,
626
.prepare = oss_prepare,
627
.drain = oss_drain,
628
+ .delay = oss_delay,
629
};
630
631
632
@@ -367,6 +688,10 @@ SND_PCM_PLUGIN_DEFINE_FUNC(oss)
633
int err;
634
snd_pcm_oss_t *oss;
635
636
+#ifdef ALSA_OSS_DEBUG_VERBOSE
637
+ fprintf(stderr, "%s()\n", __func__);
638
+#endif
639
+
640
snd_config_for_each(i, next, conf) {
641
snd_config_t *n = snd_config_iterator_entry(i);
642
const char *id;
643
644