View | Details | Raw Unified | Return to bug 217385
Collapse All | Expand All

(-)b/audio/portaudio/Makefile (-3 / +11 lines)
Lines 14-26 COMMENT= Portable cross-platform Audio API Link Here
14
LICENSE=	MIT
14
LICENSE=	MIT
15
LICENSE_FILE=	${WRKSRC}/LICENSE.txt
15
LICENSE_FILE=	${WRKSRC}/LICENSE.txt
16
16
17
USES=		dos2unix gmake libtool pathfix pkgconfig tar:tgz
17
USES=		autoreconf dos2unix gmake libtool pathfix pkgconfig tar:tgz
18
GNU_CONFIGURE=	yes
18
GNU_CONFIGURE=	yes
19
CONFIGURE_ARGS=	PKG_CONFIG_LIBDIR=${PREFIX}/libdata/pkgconfig \
19
CONFIGURE_ARGS=	PKG_CONFIG_LIBDIR=${PREFIX}/libdata/pkgconfig \
20
		--without-alsa
20
		--without-alsa
21
USE_LDCONFIG=	yes
21
USE_LDCONFIG=	yes
22
22
23
CPPFLAGS+=	-I${LOCALBASE}/include
23
CFLAGS+=	-I${WRKSRC}/include -I${LOCALBASE}/include
24
LDFLAGS+=	-lpthread -L${LOCALBASE}/lib
24
LDFLAGS+=	-lpthread -L${LOCALBASE}/lib
25
25
26
WRKSRC=		${WRKDIR}/${PORTNAME}
26
WRKSRC=		${WRKDIR}/${PORTNAME}
Lines 31-37 PORTEXAMPLES= * Link Here
31
DOCSRCDIR1=	${WRKSRC}
31
DOCSRCDIR1=	${WRKSRC}
32
DOC_FILES1=	README.txt index.html
32
DOC_FILES1=	README.txt index.html
33
33
34
OPTIONS_DEFINE=	DOCS DOXYGEN EXAMPLES JACK PATEST
34
OPTIONS_DEFINE=	DOCS DOXYGEN EXAMPLES JACK PATEST SNDIO
35
OPTIONS_DEFAULT=PATEST
35
OPTIONS_DEFAULT=PATEST
36
36
37
PATEST_DESC=	PortAudio Test Programs
37
PATEST_DESC=	PortAudio Test Programs
Lines 45-53 JACK_CONFIGURE_OFF= --without-jack Link Here
45
45
46
PATEST_BIN=	pa_m* paqa_* patest*
46
PATEST_BIN=	pa_m* paqa_* patest*
47
47
48
SNDIO_LIB_DEPENDS=	libsndio.so:audio/sndio
49
SNDIO_CONFIGURE_ON=	--with-sndio
50
SNDIO_CONFIGURE_OFF=	--without-sndio
51
48
DOXYGEN_IMPLIES=	DOCS
52
DOXYGEN_IMPLIES=	DOCS
49
DOXYGEN_BUILD_DEPENDS=	doxygen:devel/doxygen
53
DOXYGEN_BUILD_DEPENDS=	doxygen:devel/doxygen
50
54
55
post-extract:
56
	@${MKDIR} ${WRKSRC}/src/hostapi/sndio
57
	@${CP} ${FILESDIR}/pa_sndio.c ${WRKSRC}/src/hostapi/sndio
58
51
post-patch:
59
post-patch:
52
	@${REINPLACE_CMD} -e 's|machine/soundcard.h|sys/soundcard.h|' ${WRKSRC}/configure.in \
60
	@${REINPLACE_CMD} -e 's|machine/soundcard.h|sys/soundcard.h|' ${WRKSRC}/configure.in \
53
		${WRKSRC}/src/hostapi/oss/pa_unix_oss.c ${WRKSRC}/src/SConscript
61
		${WRKSRC}/src/hostapi/oss/pa_unix_oss.c ${WRKSRC}/src/SConscript
(-)b/audio/portaudio/files/pa_sndio.c (+713 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2009 Alexandre Ratchov <alex@caoua.org>
3
 *
4
 * Permission to use, copy, modify, and distribute this software for any
5
 * purpose with or without fee is hereby granted, provided that the above
6
 * copyright notice and this permission notice appear in all copies.
7
 *
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
 */
16
#include <sys/types.h>
17
#include <pthread.h>
18
#include <poll.h>
19
#include <errno.h>
20
#include <string.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <sndio.h>
24
25
#include "pa_util.h"
26
#include "pa_hostapi.h"
27
#include "pa_stream.h"
28
#include "pa_process.h"
29
#include "pa_allocation.h"
30
31
#if 0
32
#define DPR(...) do { fprintf(stderr, __VA_ARGS__); } while (0)
33
#else
34
#define DPR(...) do {} while (0)
35
#endif
36
37
/*
38
 * per-stream data
39
 */
40
typedef struct PaSndioStream
41
{
42
	PaUtilStreamRepresentation base;
43
	PaUtilBufferProcessor bufproc;	/* format conversion */
44
	struct sio_hdl *hdl;		/* handle for device i/o */
45
	struct sio_par par;		/* current device parameters */	
46
	unsigned mode;			/* SIO_PLAY, SIO_REC or both */
47
	int stopped;			/* stop requested or not started */
48
	int active;			/* thread is running */
49
	unsigned long long realpos;	/* frame number h/w is processing */
50
	char *rbuf, *wbuf;		/* bounce buffers for conversions */
51
	unsigned long long rpos, wpos;	/* bytes read/written */
52
	pthread_t thread;		/* thread of the callback interface */
53
} PaSndioStream;
54
55
/*
56
 * api "class" data, common to all streams
57
 */
58
typedef struct PaSndioHostApiRepresentation
59
{
60
	PaUtilHostApiRepresentation base;
61
	PaUtilStreamInterface callback;
62
	PaUtilStreamInterface blocking;
63
	/*
64
	 * sndio has no device discovery mechanism, so expose only
65
	 * the default device, the user will have a chance to change it
66
	 * using the environment variable
67
	 */
68
	PaDeviceInfo *infos[1], default_info;
69
} PaSndioHostApiRepresentation;
70
71
/*
72
 * callback invoked when blocks are processed by the hardware
73
 */
74
static void
75
sndioOnMove(void *addr, int delta)
76
{
77
	PaSndioStream *s = (PaSndioStream *)addr;
78
79
	s->realpos += delta;
80
}
81
82
/*
83
 * convert PA encoding to sndio encoding, return true on success
84
 */
85
static int
86
sndioSetFmt(struct sio_par *sio, PaSampleFormat fmt)
87
{
88
	switch (fmt & ~paNonInterleaved) {
89
	case paInt32:
90
		sio->sig = 1;
91
		sio->bits = 32;
92
		break;
93
	case paInt24:
94
		sio->sig = 1;
95
		sio->bits = 24;
96
		sio->bps = 3;	/* paInt24 is packed format */
97
		break;
98
	case paInt16:
99
	case paFloat32:
100
		sio->sig = 1;
101
		sio->bits = 16;
102
		break;
103
	case paInt8:
104
		sio->sig = 1;
105
		sio->bits = 8;
106
		break;
107
	case paUInt8:
108
		sio->sig = 0;
109
		sio->bits = 8;
110
		break;
111
	default:
112
		DPR("sndioSetFmt: %x: unsupported\n", fmt);
113
		return 0;
114
	}
115
	sio->le = SIO_LE_NATIVE;
116
	return 1;
117
}
118
119
/*
120
 * convert sndio encoding to PA encoding, return true on success
121
 */
122
static int
123
sndioGetFmt(struct sio_par *sio, PaSampleFormat *fmt)
124
{
125
	if ((sio->bps * 8 != sio->bits && !sio->msb) ||
126
	    (sio->bps > 1 && sio->le != SIO_LE_NATIVE)) {
127
		DPR("sndioGetFmt: bits = %u, le = %u, msb = %u, bps = %u\n",
128
		    sio->bits, sio->le, sio->msb, sio->bps);
129
		return 0;
130
	}
131
132
	switch (sio->bits) {
133
	case 32:
134
		if (!sio->sig)
135
			return 0;
136
		*fmt = paInt32;
137
		break;
138
	case 24:
139
		if (!sio->sig)
140
			return 0;
141
		*fmt = (sio->bps == 3) ? paInt24 : paInt32;
142
		break;
143
	case 16:
144
		if (!sio->sig)
145
			return 0;
146
		*fmt = paInt16;
147
		break;
148
	case 8:
149
		*fmt = sio->sig ? paInt8 : paUInt8;
150
		break;
151
	default:
152
		DPR("sndioGetFmt: %u: unsupported\n", sio->bits);
153
		return 0;
154
	}
155
	return 1;
156
}
157
158
/*
159
 * I/O loop for callback interface
160
 */
161
static void *
162
sndioThread(void *arg)
163
{
164
	PaSndioStream *s = (PaSndioStream *)arg;
165
	PaStreamCallbackTimeInfo ti;
166
	unsigned char *data;
167
	unsigned todo, rblksz, wblksz;
168
	int n, result;
169
	
170
	rblksz = s->par.round * s->par.rchan * s->par.bps;
171
	wblksz = s->par.round * s->par.pchan * s->par.bps;
172
	
173
	DPR("sndioThread: mode = %x, round = %u, rblksz = %u, wblksz = %u\n",
174
	    s->mode, s->par.round, rblksz, wblksz);
175
	
176
	while (!s->stopped) {
177
		if (s->mode & SIO_REC) {
178
			todo = rblksz;
179
			data = s->rbuf;
180
			while (todo > 0) {
181
				n = sio_read(s->hdl, data, todo);
182
				if (n == 0) {
183
					DPR("sndioThread: sio_read failed\n");
184
					goto failed;
185
				}
186
				todo -= n;
187
				data += n;
188
			}
189
			s->rpos += s->par.round;
190
			ti.inputBufferAdcTime = 
191
			    (double)s->realpos / s->par.rate;
192
		}
193
		if (s->mode & SIO_PLAY) {
194
			ti.outputBufferDacTime =
195
			    (double)(s->realpos + s->par.bufsz) / s->par.rate;
196
		}
197
		ti.currentTime = s->realpos / (double)s->par.rate;
198
		PaUtil_BeginBufferProcessing(&s->bufproc, &ti, 0);
199
		if (s->mode & SIO_PLAY) {
200
			PaUtil_SetOutputFrameCount(&s->bufproc, s->par.round);
201
			PaUtil_SetInterleavedOutputChannels(&s->bufproc,
202
			    0, s->wbuf, s->par.pchan);
203
		}
204
		if (s->mode & SIO_REC) {
205
			PaUtil_SetInputFrameCount(&s->bufproc, s->par.round);
206
			PaUtil_SetInterleavedInputChannels(&s->bufproc,
207
			    0, s->rbuf, s->par.rchan);
208
		}
209
		result = paContinue;
210
		n = PaUtil_EndBufferProcessing(&s->bufproc, &result);
211
		if (n != s->par.round) {
212
			DPR("sndioThread: %d < %u frames, result = %d\n",
213
			    n, s->par.round, result);
214
		}
215
		if (result != paContinue) {
216
			break;
217
		}
218
		if (s->mode & SIO_PLAY) {
219
			n = sio_write(s->hdl, s->wbuf, wblksz);
220
			if (n < wblksz) {
221
				DPR("sndioThread: sio_write failed\n");
222
				goto failed;
223
			}
224
			s->wpos += s->par.round;
225
		}
226
	}
227
 failed:
228
	s->active = 0;
229
	DPR("sndioThread: done\n");
230
}
231
232
static PaError
233
OpenStream(struct PaUtilHostApiRepresentation *hostApi,
234
    PaStream **stream,
235
    const PaStreamParameters *inputPar,
236
    const PaStreamParameters *outputPar,
237
    double sampleRate,
238
    unsigned long framesPerBuffer,
239
    PaStreamFlags streamFlags,
240
    PaStreamCallback *streamCallback,
241
    void *userData)
242
{
243
	PaSndioHostApiRepresentation *sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
244
	PaSndioStream *s;
245
	PaError err;
246
	struct sio_hdl *hdl;
247
	struct sio_par par;
248
	unsigned mode;
249
	int inch, onch;
250
	PaSampleFormat ifmt, ofmt, siofmt;
251
252
	DPR("OpenStream:\n");
253
254
	mode = 0;
255
	inch = onch = 0;
256
	ifmt = ofmt = 0;
257
	sio_initpar(&par);
258
259
	if (outputPar && outputPar->channelCount > 0) {
260
		if (outputPar->device != 0) {
261
			DPR("OpenStream: %d: bad output device\n", outputPar->device);
262
			return paInvalidDevice;
263
		}
264
		if (outputPar->hostApiSpecificStreamInfo) {
265
			DPR("OpenStream: output specific info\n");
266
			return paIncompatibleHostApiSpecificStreamInfo;
267
		}
268
		if (!sndioSetFmt(&par, outputPar->sampleFormat)) {
269
			return paSampleFormatNotSupported;
270
		}
271
		ofmt = outputPar->sampleFormat;
272
		onch = par.pchan = outputPar->channelCount;
273
		mode |= SIO_PLAY;
274
	}
275
	if (inputPar && inputPar->channelCount > 0) {
276
		if (inputPar->device != 0) {
277
			DPR("OpenStream: %d: bad input device\n", inputPar->device);
278
			return paInvalidDevice;
279
		}
280
		if (inputPar->hostApiSpecificStreamInfo) {
281
			DPR("OpenStream: input specific info\n");
282
			return paIncompatibleHostApiSpecificStreamInfo;
283
		}
284
		if (!sndioSetFmt(&par, inputPar->sampleFormat)) {
285
			return paSampleFormatNotSupported;
286
		}
287
		ifmt = inputPar->sampleFormat;
288
		inch = par.rchan = inputPar->channelCount;
289
		mode |= SIO_REC;
290
	}
291
	par.rate = sampleRate;
292
	if (framesPerBuffer != paFramesPerBufferUnspecified)
293
		par.round = framesPerBuffer;
294
295
	DPR("OpenStream: mode = %x, trying rate = %u\n", mode, par.rate);
296
297
	hdl = sio_open(SIO_DEVANY, mode, 0);
298
	if (hdl == NULL)
299
		return paUnanticipatedHostError;
300
	if (!sio_setpar(hdl, &par)) {
301
		sio_close(hdl);
302
		return paUnanticipatedHostError;
303
	}
304
	if (!sio_getpar(hdl, &par)) {
305
		sio_close(hdl);
306
		return paUnanticipatedHostError;
307
	}
308
	if (!sndioGetFmt(&par, &siofmt)) {
309
		sio_close(hdl);
310
		return paSampleFormatNotSupported;
311
	}
312
	if ((mode & SIO_REC) && par.rchan != inputPar->channelCount) {
313
		DPR("OpenStream: rchan(%u) != %d\n", par.rchan, inputPar->channelCount);
314
		sio_close(hdl);
315
		return paInvalidChannelCount;
316
	}
317
	if ((mode & SIO_PLAY) && par.pchan != outputPar->channelCount) {
318
		DPR("OpenStream: pchan(%u) != %d\n", par.pchan, outputPar->channelCount);
319
		sio_close(hdl);
320
		return paInvalidChannelCount;
321
	}
322
	if ((double)par.rate < sampleRate * 0.995 ||
323
	    (double)par.rate > sampleRate * 1.005) {
324
		DPR("OpenStream: rate(%u) != %g\n", par.rate, sampleRate);
325
		sio_close(hdl);
326
		return paInvalidSampleRate;
327
	}
328
	
329
	s = (PaSndioStream *)PaUtil_AllocateMemory(sizeof(PaSndioStream));
330
	if (s == NULL) {
331
		sio_close(hdl);
332
		return paInsufficientMemory;
333
	}
334
	PaUtil_InitializeStreamRepresentation(&s->base, 
335
	    streamCallback ? &sndioHostApi->callback : &sndioHostApi->blocking,
336
	    streamCallback, userData);
337
	DPR("inch = %d, onch = %d, ifmt = %x, ofmt = %x\n", 
338
	    inch, onch, ifmt, ofmt);
339
	err = PaUtil_InitializeBufferProcessor(&s->bufproc,
340
	    inch, ifmt, siofmt,
341
	    onch, ofmt, siofmt,
342
	    sampleRate,
343
	    streamFlags,
344
	    framesPerBuffer,
345
	    par.round,
346
	    paUtilFixedHostBufferSize, 
347
	    streamCallback, userData);
348
	if (err) {
349
		DPR("OpenStream: PaUtil_InitializeBufferProcessor failed\n");
350
		PaUtil_FreeMemory(s);
351
		sio_close(hdl);
352
		return err;
353
	}
354
	if (mode & SIO_REC) {
355
		s->rbuf = malloc(par.round * par.rchan * par.bps);
356
		if (s->rbuf == NULL) {
357
			DPR("OpenStream: failed to allocate rbuf\n");
358
			PaUtil_FreeMemory(s);
359
			sio_close(hdl);
360
			return paInsufficientMemory;
361
		}
362
	}
363
	if (mode & SIO_PLAY) {
364
		s->wbuf = malloc(par.round * par.pchan * par.bps);
365
		if (s->wbuf == NULL) {
366
			DPR("OpenStream: failed to allocate wbuf\n");
367
			free(s->rbuf);
368
			PaUtil_FreeMemory(s);
369
			sio_close(hdl);
370
			return paInsufficientMemory;
371
		}
372
	}	
373
	s->base.streamInfo.inputLatency = 0;
374
	s->base.streamInfo.outputLatency = (mode & SIO_PLAY) ?
375
	    (double)(par.bufsz + PaUtil_GetBufferProcessorOutputLatencyFrames(&s->bufproc)) / (double)par.rate : 0;
376
	s->base.streamInfo.sampleRate = par.rate;
377
	s->active = 0;
378
	s->stopped = 1;
379
	s->mode = mode;
380
	s->hdl = hdl;
381
	s->par = par;
382
	*stream = s;	
383
	DPR("OpenStream: done\n");
384
	return paNoError;
385
}
386
387
static PaError
388
BlockingReadStream(PaStream *stream, void *data, unsigned long numFrames)
389
{
390
	PaSndioStream *s = (PaSndioStream *)stream;
391
	unsigned n, res, todo;
392
	void *buf;
393
	
394
	while (numFrames > 0) {
395
		n = s->par.round;
396
		if (n > numFrames)
397
			n = numFrames;
398
		buf = s->rbuf;
399
		todo = n * s->par.rchan * s->par.bps;
400
		while (todo > 0) {
401
			res = sio_read(s->hdl, buf, todo);
402
			if (res == 0)
403
				return paUnanticipatedHostError;
404
			buf = (char *)buf + res;
405
			todo -= res;
406
		}
407
		s->rpos += n;
408
		PaUtil_SetInputFrameCount(&s->bufproc, n);
409
		PaUtil_SetInterleavedInputChannels(&s->bufproc, 0, s->rbuf, s->par.rchan);
410
		res = PaUtil_CopyInput(&s->bufproc, &data, n);
411
		if (res != n) {
412
			DPR("BlockingReadStream: copyInput: %u != %u\n");
413
			return paUnanticipatedHostError;
414
		}
415
		numFrames -= n;
416
	}
417
	return paNoError;
418
}
419
420
static PaError
421
BlockingWriteStream(PaStream* stream, const void *data, unsigned long numFrames)
422
{
423
	PaSndioStream *s = (PaSndioStream *)stream;
424
	unsigned n, res;
425
426
	while (numFrames > 0) {
427
		n = s->par.round;
428
		if (n > numFrames)
429
			n = numFrames;
430
		PaUtil_SetOutputFrameCount(&s->bufproc, n);
431
		PaUtil_SetInterleavedOutputChannels(&s->bufproc, 0, s->wbuf, s->par.pchan);
432
		res = PaUtil_CopyOutput(&s->bufproc, &data, n);
433
		if (res != n) {
434
			DPR("BlockingWriteStream: copyOutput: %u != %u\n");
435
			return paUnanticipatedHostError;
436
		}
437
		res = sio_write(s->hdl, s->wbuf, n * s->par.pchan * s->par.bps);
438
		if (res == 0)
439
			return paUnanticipatedHostError;		
440
		s->wpos += n;
441
		numFrames -= n;
442
	}
443
	return paNoError;
444
}
445
446
static signed long
447
BlockingGetStreamReadAvailable(PaStream *stream)
448
{
449
	PaSndioStream *s = (PaSndioStream *)stream;
450
	struct pollfd pfd;
451
	int n, events;
452
453
	n = sio_pollfd(s->hdl, &pfd, POLLIN);
454
	while (poll(&pfd, n, 0) < 0) {
455
		if (errno == EINTR)
456
			continue;
457
		perror("poll");
458
		abort();
459
	}
460
	events = sio_revents(s->hdl, &pfd);
461
	if (!(events & POLLIN))
462
		return 0;
463
464
	return s->realpos - s->rpos;
465
}
466
467
static signed long
468
BlockingGetStreamWriteAvailable(PaStream *stream)
469
{
470
	PaSndioStream *s = (PaSndioStream *)stream;
471
	struct pollfd pfd;
472
	int n, events;
473
474
	n = sio_pollfd(s->hdl, &pfd, POLLOUT);
475
	while (poll(&pfd, n, 0) < 0) {
476
		if (errno == EINTR)
477
			continue;
478
		perror("poll");
479
		abort();
480
	}
481
	events = sio_revents(s->hdl, &pfd);
482
	if (!(events & POLLOUT))
483
		return 0;
484
485
	return s->par.bufsz - (s->wpos - s->realpos);
486
}
487
488
static PaError
489
BlockingWaitEmpty( PaStream *stream )
490
{
491
	PaSndioStream *s = (PaSndioStream *)stream;
492
493
	/*
494
	 * drain playback buffers; sndio always does it in background
495
	 * and there is no way to wait for completion
496
	 */
497
	DPR("BlockingWaitEmpty: s=%d, a=%d\n", s->stopped, s->active);
498
499
	return paNoError;
500
}
501
502
static PaError
503
StartStream(PaStream *stream)
504
{
505
	PaSndioStream *s = (PaSndioStream *)stream;
506
	unsigned primes, wblksz;
507
	int err;
508
509
	DPR("StartStream: s=%d, a=%d\n", s->stopped, s->active);
510
511
	if (!s->stopped) {
512
		DPR("StartStream: already started\n");
513
		return paNoError;
514
	}
515
	s->stopped = 0;
516
	s->active = 1;
517
	s->realpos = 0;
518
	s->wpos = 0;
519
	s->rpos = 0;
520
	PaUtil_ResetBufferProcessor(&s->bufproc);
521
	if (!sio_start(s->hdl))
522
		return paUnanticipatedHostError;
523
524
	/*
525
	 * send a complete buffer of silence
526
	 */
527
	if (s->mode & SIO_PLAY) {
528
		wblksz = s->par.round * s->par.pchan * s->par.bps;
529
		memset(s->wbuf, 0, wblksz);
530
		for (primes = s->par.bufsz / s->par.round; primes > 0; primes--)
531
			s->wpos += sio_write(s->hdl, s->wbuf, wblksz);
532
	}
533
	if (s->base.streamCallback) {
534
		err = pthread_create(&s->thread, NULL, sndioThread, s);
535
		if (err) {
536
			DPR("SndioStartStream: couldn't create thread\n");
537
			return paUnanticipatedHostError;
538
		}
539
		DPR("StartStream: started...\n");
540
	}
541
	return paNoError;
542
}
543
544
static PaError
545
StopStream(PaStream *stream)
546
{
547
	PaSndioStream *s = (PaSndioStream *)stream;
548
	void *ret;
549
	int err;
550
551
	DPR("StopStream: s=%d, a=%d\n", s->stopped, s->active);
552
553
	if (s->stopped) {
554
		DPR("StartStream: already started\n");
555
		return paNoError;
556
	}
557
	s->stopped = 1;
558
	if (s->base.streamCallback) {
559
		err = pthread_join(s->thread, &ret);
560
		if (err) {
561
			DPR("SndioStop: couldn't join thread\n");
562
			return paUnanticipatedHostError;
563
		}
564
	}
565
	if (!sio_stop(s->hdl))
566
		return paUnanticipatedHostError;
567
	return paNoError;
568
}
569
570
static PaError
571
CloseStream(PaStream *stream)
572
{
573
	PaSndioStream *s = (PaSndioStream *)stream;
574
575
	DPR("CloseStream:\n");
576
577
	if (!s->stopped)
578
		StopStream(stream);
579
580
	if (s->mode & SIO_REC)
581
		free(s->rbuf);
582
	if (s->mode & SIO_PLAY)
583
		free(s->wbuf);
584
	sio_close(s->hdl);
585
        PaUtil_TerminateStreamRepresentation(&s->base);
586
	PaUtil_TerminateBufferProcessor(&s->bufproc);
587
	PaUtil_FreeMemory(s);
588
	return paNoError;
589
}
590
591
static PaError
592
AbortStream(PaStream *stream)
593
{
594
	DPR("AbortStream:\n");
595
596
	return StopStream(stream);
597
}
598
599
static PaError
600
IsStreamStopped(PaStream *stream)
601
{
602
	PaSndioStream *s = (PaSndioStream *)stream;
603
604
	//DPR("IsStreamStopped: s=%d, a=%d\n", s->stopped, s->active);
605
606
	return s->stopped;
607
}
608
609
static PaError
610
IsStreamActive(PaStream *stream)
611
{
612
	PaSndioStream *s = (PaSndioStream *)stream;
613
614
	//DPR("IsStreamActive: s=%d, a=%d\n", s->stopped, s->active);
615
616
	return s->active;
617
}
618
619
static PaTime
620
GetStreamTime(PaStream *stream)
621
{
622
	PaSndioStream *s = (PaSndioStream *)stream;
623
624
	return (double)s->realpos / s->base.streamInfo.sampleRate;
625
}
626
627
static PaError
628
IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi,
629
    const PaStreamParameters *inputPar,
630
    const PaStreamParameters *outputPar,
631
    double sampleRate)
632
{
633
	return paFormatIsSupported;
634
}
635
636
static void
637
Terminate(struct PaUtilHostApiRepresentation *hostApi)
638
{
639
	PaUtil_FreeMemory(hostApi);
640
}
641
642
PaError
643
PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex)
644
{
645
	PaSndioHostApiRepresentation *sndioHostApi;
646
	PaDeviceInfo *info;
647
	struct sio_hdl *hdl;
648
	
649
	DPR("PaSndio_Initialize: initializing...\n");
650
651
	/* unusable APIs should return paNoError and a NULL hostApi */
652
	*hostApi = NULL;
653
654
	sndioHostApi = PaUtil_AllocateMemory(sizeof(PaSndioHostApiRepresentation));
655
	if (sndioHostApi == NULL)
656
		return paNoError;
657
658
	info = &sndioHostApi->default_info;
659
	info->structVersion = 2;
660
	info->name = "default";
661
	info->hostApi = hostApiIndex;
662
	info->maxInputChannels = 128;
663
	info->maxOutputChannels = 128;
664
	info->defaultLowInputLatency = 0.01;
665
	info->defaultLowOutputLatency = 0.01;
666
	info->defaultHighInputLatency = 0.5;
667
	info->defaultHighOutputLatency = 0.5;
668
	info->defaultSampleRate = 48000;
669
	sndioHostApi->infos[0] = info;
670
	
671
	*hostApi = &sndioHostApi->base;
672
	(*hostApi)->info.structVersion = 1;
673
	(*hostApi)->info.type = paSndio;
674
	(*hostApi)->info.name = "sndio";
675
	(*hostApi)->info.deviceCount = 1;
676
	(*hostApi)->info.defaultInputDevice = 0;
677
	(*hostApi)->info.defaultOutputDevice = 0;
678
	(*hostApi)->deviceInfos = sndioHostApi->infos;
679
	(*hostApi)->Terminate = Terminate;
680
	(*hostApi)->OpenStream = OpenStream;
681
	(*hostApi)->IsFormatSupported = IsFormatSupported;
682
	
683
	PaUtil_InitializeStreamInterface(&sndioHostApi->blocking,
684
	    CloseStream,
685
	    StartStream,
686
	    StopStream,
687
	    AbortStream,
688
	    IsStreamStopped,
689
	    IsStreamActive,
690
	    GetStreamTime,
691
	    PaUtil_DummyGetCpuLoad,
692
	    BlockingReadStream,
693
	    BlockingWriteStream,
694
	    BlockingGetStreamReadAvailable,
695
	    BlockingGetStreamWriteAvailable);
696
697
	PaUtil_InitializeStreamInterface(&sndioHostApi->callback,
698
	    CloseStream,
699
	    StartStream,
700
	    StopStream,
701
	    AbortStream,
702
	    IsStreamStopped,
703
	    IsStreamActive,
704
	    GetStreamTime,
705
	    PaUtil_DummyGetCpuLoad,
706
	    PaUtil_DummyRead,
707
	    PaUtil_DummyWrite,
708
	    PaUtil_DummyGetReadAvailable,
709
	    PaUtil_DummyGetWriteAvailable);
710
711
	DPR("PaSndio_Initialize: done\n");
712
	return paNoError;
713
}
(-)b/audio/portaudio/files/patch-Makefile.in (+11 lines)
Added Link Here
1
$OpenBSD: patch-Makefile_in,v 1.4 2013/03/12 00:59:50 brad Exp $
2
--- Makefile.in.orig	2016-06-22 08:28:31 UTC
3
+++ Makefile.in
4
@@ -146,6 +146,7 @@ SRC_DIRS = \
5
 	src/hostapi/dsound \
6
 	src/hostapi/jack \
7
 	src/hostapi/oss \
8
+	src/hostapi/sndio \
9
 	src/hostapi/wasapi \
10
 	src/hostapi/wdmks \
11
 	src/hostapi/wmme \
(-)b/audio/portaudio/files/patch-configure.in (+47 lines)
Added Link Here
1
$OpenBSD: patch-configure_in,v 1.4 2014/09/13 04:56:28 bentley Exp $
2
--- configure.in.orig	2016-06-22 08:28:31 UTC
3
+++ configure.in
4
@@ -24,6 +24,10 @@ AC_ARG_WITH(alsa,
5
             AS_HELP_STRING([--with-alsa], [Enable support for ALSA @<:@autodetect@:>@]),
6
             [with_alsa=$withval])
7
 
8
+AC_ARG_WITH(sndio,
9
+            AS_HELP_STRING([--with-sndio], [Enable support for sndio @<:@autodetect@:>@]),
10
+            [with_sndio=$withval])
11
+
12
 AC_ARG_WITH(jack,
13
             AS_HELP_STRING([--with-jack], [Enable support for JACK @<:@autodetect@:>@]),
14
             [with_jack=$withval])
15
@@ -120,6 +124,10 @@ have_alsa=no
16
 if test "x$with_alsa" != "xno"; then
17
     AC_CHECK_LIB(asound, snd_pcm_open, have_alsa=yes, have_alsa=no)
18
 fi
19
+have_sndio=no
20
+if test "x$with_sndio" != "xno"; then
21
+    AC_CHECK_LIB(sndio, sio_open, have_sndio=yes, have_sndio=no)
22
+fi
23
 have_asihpi=no
24
 if test "x$with_asihpi" != "xno"; then
25
     AC_CHECK_LIB(hpi, HPI_SubSysCreate, have_asihpi=yes, have_asihpi=no, -lm)
26
@@ -397,6 +405,13 @@ case "${host_os}" in
27
            AC_DEFINE(PA_USE_ALSA,1)
28
         fi
29
 
30
+        if [[ "$have_sndio" = "yes" -a "$with_sndio" != "no" ]] ; then
31
+           DLL_LIBS="$DLL_LIBS -lsndio"
32
+           LIBS="$LIBS -lsndio"
33
+           OTHER_OBJS="$OTHER_OBJS src/hostapi/sndio/pa_sndio.o"
34
+           AC_DEFINE(PA_USE_SNDIO,1)
35
+        fi
36
+
37
         if [[ "$have_jack" = "yes" ] && [ "$with_jack" != "no" ]] ; then
38
            DLL_LIBS="$DLL_LIBS $JACK_LIBS"
39
            CFLAGS="$CFLAGS $JACK_CFLAGS"
40
@@ -500,6 +515,7 @@ case "$target_os" in
41
         ;;
42
      *)
43
 	AC_MSG_RESULT([
44
+  Sndio ....................... $have_sndio
45
   OSS ......................... $have_oss
46
   JACK ........................ $have_jack
47
 ])
(-)b/audio/portaudio/files/patch-include_portaudio.h (+13 lines)
Added Link Here
1
$OpenBSD: patch-include_portaudio_h,v 1.2 2013/03/12 00:59:50 brad Exp $
2
--- include/portaudio.h.orig	2016-06-22 08:28:31 UTC
3
+++ include/portaudio.h
4
@@ -236,7 +236,8 @@ typedef enum PaHostApiTypeId
5
     paWDMKS=11,
6
     paJACK=12,
7
     paWASAPI=13,
8
-    paAudioScienceHPI=14
9
+    paAudioScienceHPI=14,
10
+    paSndio=15
11
 } PaHostApiTypeId;
12
 
13
 
(-)b/audio/portaudio/files/patch-src_os_unix_pa__unix__hostapis.c (+26 lines)
Added Link Here
1
$OpenBSD: patch-src_os_unix_pa_unix_hostapis_c,v 1.2 2013/03/12 00:59:50 brad Exp $
2
3
Difference to OpenBSD patch: PA_USE_SNDIO has been moved before
4
PA_USE_OSS, so that portaudio prefers the sndio output.
5
6
--- src/os/unix/pa_unix_hostapis.c.orig	2016-06-22 08:28:31 UTC
7
+++ src/os/unix/pa_unix_hostapis.c
8
@@ -44,6 +44,7 @@
9
 
10
 PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
11
 PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
12
+PaError PaSndio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
13
 PaError PaOSS_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
14
 /* Added for IRIX, Pieter, oct 2, 2003: */
15
 PaError PaSGI_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
16
@@ -69,6 +70,10 @@ PaUtilHostApiInitializer *paHostApiIniti
17
 
18
 #else   /* __linux__ */
19
 
20
+#ifdef PA_USE_SNDIO
21
+	PaSndio_Initialize,
22
+#endif
23
+
24
 #if PA_USE_OSS
25
         PaOSS_Initialize,
26
 #endif

Return to bug 217385