oops, paul should remember to try an OSX build before releasing a tarball; fixed...
[jack.git] / drivers / oss / oss_driver.c
blob42226e9fa97b741973dd0f68a723b7ba39b462b6
1 /*
3 OSS driver for Jack
4 Copyright (C) 2003-2007 Jussi Laako <jussi@sonarnerd.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 MA 02111-1307 USA
24 #include <config.h>
26 #ifdef USE_BARRIER
28 * POSIX conformance level should be globally defined somewhere, possibly
29 * in config.h? Otherwise it's pre 1993/09 level, which leaves out significant
30 * parts of threading and realtime stuff. Note: most of the parts are still
31 * defined as optional by the standard, so OS conformance to this level
32 * doesn't necessarily mean everything exists.
34 #define _XOPEN_SOURCE 600
35 #endif
36 #ifndef _REENTRANT
37 #define _REENTRANT
38 #endif
39 #ifndef _THREAD_SAFE
40 #define _THREAD_SAFE
41 #endif
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 #include <semaphore.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <sys/ioctl.h>
58 #include <sys/soundcard.h>
60 #include <jack/types.h>
61 #include <jack/internal.h>
62 #include <jack/engine.h>
63 #include <jack/thread.h>
64 #include <sysdeps/time.h>
66 #include "oss_driver.h"
69 #ifndef SNDCTL_DSP_COOKEDMODE
70 #ifdef _SIOWR
71 #define SNDCTL_DSP_COOKEDMODE _SIOWR('P', 30, int)
72 #else /* _SIOWR */
73 #warning "Unable to define cooked mode!"
74 #define OSS_NO_COOKED_MODE
75 #endif /* _SIOWR */
76 #endif /* SNDCTL_DSP_COOKEDMODE */
78 #define OSS_DRIVER_N_PARAMS 11
79 const static jack_driver_param_desc_t oss_params[OSS_DRIVER_N_PARAMS] = {
80 { "rate",
81 'r',
82 JackDriverParamUInt,
83 { .ui = OSS_DRIVER_DEF_FS },
84 "sample rate",
85 "sample rate"
87 { "period",
88 'p',
89 JackDriverParamUInt,
90 { .ui = OSS_DRIVER_DEF_BLKSIZE },
91 "period size",
92 "period size"
94 { "nperiods",
95 'n',
96 JackDriverParamUInt,
97 { .ui = OSS_DRIVER_DEF_NPERIODS },
98 "number of periods in buffer",
99 "number of periods in buffer"
101 { "wordlength",
102 'w',
103 JackDriverParamInt,
104 { .i = OSS_DRIVER_DEF_BITS },
105 "word length",
106 "word length"
108 { "inchannels",
109 'i',
110 JackDriverParamUInt,
111 { .ui = OSS_DRIVER_DEF_INS },
112 "capture channels",
113 "capture channels"
115 { "outchannels",
116 'o',
117 JackDriverParamUInt,
118 { .ui = OSS_DRIVER_DEF_OUTS },
119 "playback channels",
120 "playback channels"
122 { "capture",
123 'C',
124 JackDriverParamString,
125 { .str = OSS_DRIVER_DEF_DEV },
126 "input device",
127 "input device"
129 { "playback",
130 'P',
131 JackDriverParamString,
132 { .str = OSS_DRIVER_DEF_DEV },
133 "output device",
134 "output device"
136 { "ignorehwbuf",
137 'b',
138 JackDriverParamBool,
139 { },
140 "ignore hardware period size",
141 "ignore hardware period size"
143 { "input latency",
144 'I',
145 JackDriverParamUInt,
146 { .ui = 0 },
147 "system input latency",
148 "system input latency"
150 { "output latency",
151 'O',
152 JackDriverParamUInt,
153 { .ui = 0 },
154 "system output latency",
155 "system output latency"
161 /* internal functions */
164 static void set_period_size (oss_driver_t *driver,
165 jack_nframes_t new_period_size)
167 driver->period_size = new_period_size;
169 driver->period_usecs =
170 ((double) driver->period_size /
171 (double) driver->sample_rate) * 1e6;
172 driver->last_wait_ust = 0;
173 driver->last_periodtime = jack_get_microseconds();
174 driver->next_periodtime = 0;
175 driver->iodelay = 0.0F;
179 static inline void update_times (oss_driver_t *driver)
181 driver->last_periodtime = jack_get_microseconds();
182 if (driver->next_periodtime > 0)
184 driver->iodelay = (float)
185 ((long double) driver->last_periodtime -
186 (long double) driver->next_periodtime);
188 else driver->iodelay = 0.0F;
189 driver->next_periodtime =
190 driver->last_periodtime +
191 driver->period_usecs;
195 static inline void driver_cycle (oss_driver_t *driver)
197 update_times(driver);
198 driver->engine->transport_cycle_start(driver->engine,
199 driver->last_periodtime);
201 driver->last_wait_ust = driver->last_periodtime;
202 driver->engine->run_cycle(driver->engine,
203 driver->period_size, driver->iodelay);
207 static void copy_and_convert_in (jack_sample_t *dst, void *src,
208 size_t nframes, int channel, int chcount, int bits)
210 int srcidx;
211 int dstidx;
212 signed short *s16src = (signed short *) src;
213 signed int *s32src = (signed int *) src;
214 double *f64src = (double *) src;
215 jack_sample_t scale;
217 srcidx = channel;
218 switch (bits)
220 case 16:
221 scale = 1.0f / 0x7fff;
222 for (dstidx = 0; dstidx < nframes; dstidx++)
224 dst[dstidx] = (jack_sample_t)
225 s16src[srcidx] * scale;
226 srcidx += chcount;
228 break;
229 case 24:
230 scale = 1.0f / 0x7fffff;
231 for (dstidx = 0; dstidx < nframes; dstidx++)
233 dst[dstidx] = (jack_sample_t)
234 s32src[srcidx] * scale;
235 srcidx += chcount;
237 break;
238 case 32:
239 scale = 1.0f / 0x7fffffff;
240 for (dstidx = 0; dstidx < nframes; dstidx++)
242 dst[dstidx] = (jack_sample_t)
243 s32src[srcidx] * scale;
244 srcidx += chcount;
246 break;
247 case 64:
248 for (dstidx = 0; dstidx < nframes; dstidx++)
250 dst[dstidx] = (jack_sample_t) f64src[srcidx];
251 srcidx += chcount;
253 break;
258 static void copy_and_convert_out (void *dst, jack_sample_t *src,
259 size_t nframes, int channel, int chcount, int bits)
261 int srcidx;
262 int dstidx;
263 signed short *s16dst = (signed short *) dst;
264 signed int *s32dst = (signed int *) dst;
265 double *f64dst = (double *) dst;
266 jack_sample_t scale;
268 dstidx = channel;
269 switch (bits)
271 case 16:
272 scale = 0x7fff;
273 for (srcidx = 0; srcidx < nframes; srcidx++)
275 s16dst[dstidx] = (signed short)
276 (src[srcidx] >= 0.0f) ?
277 (src[srcidx] * scale + 0.5f) :
278 (src[srcidx] * scale - 0.5f);
279 dstidx += chcount;
281 break;
282 case 24:
283 scale = 0x7fffff;
284 for (srcidx = 0; srcidx < nframes; srcidx++)
286 s32dst[dstidx] = (signed int)
287 (src[srcidx] >= 0.0f) ?
288 (src[srcidx] * scale + 0.5f) :
289 (src[srcidx] * scale - 0.5f);
290 dstidx += chcount;
292 break;
293 case 32:
294 scale = 0x7fffffff;
295 for (srcidx = 0; srcidx < nframes; srcidx++)
297 s32dst[dstidx] = (signed int)
298 (src[srcidx] >= 0.0f) ?
299 (src[srcidx] * scale + 0.5f) :
300 (src[srcidx] * scale - 0.5f);
301 dstidx += chcount;
303 break;
304 case 64:
305 for (srcidx = 0; srcidx < nframes; srcidx++)
307 f64dst[dstidx] = (double) src[srcidx];
308 dstidx += chcount;
310 break;
315 static void set_fragment (int fd, size_t fragsize, unsigned int fragcount)
317 int fragsize_2p;
318 int fragments;
320 fragsize_2p = (int) (log(fragsize) / log(2.0) + 0.5);
321 fragments = ((fragcount << 16) | (fragsize_2p & 0xffff));
322 if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragments) < 0)
324 jack_error("OSS: failed to set fragment size: %s@%i, errno=%d",
325 __FILE__, __LINE__, errno);
330 static int get_fragment (int fd)
332 int fragsize;
334 if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &fragsize) < 0)
336 jack_error("OSS: failed to get fragment size: %s@%i, errno=%d",
337 __FILE__, __LINE__, errno);
338 return 0;
340 return fragsize;
344 static void *io_thread (void *);
347 /* jack driver interface */
350 static int oss_driver_attach (oss_driver_t *driver, jack_engine_t *engine)
352 int port_flags;
353 unsigned int channel;
354 char channel_name[64];
355 jack_port_t *port;
357 driver->engine = engine;
359 engine->set_buffer_size(engine, driver->period_size);
360 engine->set_sample_rate(engine, driver->sample_rate);
362 port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal;
363 for (channel = 0; channel < driver->capture_channels; channel++)
365 snprintf(channel_name, sizeof(channel_name),
366 "capture_%u", channel + 1);
367 port = jack_port_register(driver->client, channel_name,
368 JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
369 if (port == NULL)
371 jack_error("OSS: cannot register port for %s: %s@%i",
372 channel_name, __FILE__, __LINE__);
373 break;
375 jack_port_set_latency(port,
376 driver->period_size + driver->sys_in_latency);
377 driver->capture_ports =
378 jack_slist_append(driver->capture_ports, port);
381 port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;
382 for (channel = 0; channel < driver->playback_channels; channel++)
384 snprintf(channel_name, sizeof(channel_name),
385 "playback_%u", channel + 1);
386 port = jack_port_register(driver->client, channel_name,
387 JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
388 if (port == NULL)
390 jack_error("OSS: cannot register port for %s: %s@%i",
391 channel_name, __FILE__, __LINE__);
392 break;
394 jack_port_set_latency(port,
395 driver->period_size + driver->sys_out_latency);
396 driver->playback_ports =
397 jack_slist_append(driver->playback_ports, port);
400 jack_activate(driver->client);
402 return 0;
406 static int oss_driver_detach (oss_driver_t *driver, jack_engine_t *engine)
408 JSList *node;
410 if (driver->engine == NULL)
411 return -1;
413 /*jack_deactivate(driver->client);*/ /* ? */
415 node = driver->capture_ports;
416 while (node != NULL)
418 jack_port_unregister(driver->client,
419 ((jack_port_t *) node->data));
420 node = jack_slist_next(node);
422 jack_slist_free(driver->capture_ports);
423 driver->capture_ports = NULL;
425 node = driver->playback_ports;
426 while (node != NULL)
428 jack_port_unregister(driver->client,
429 ((jack_port_t *) node->data));
430 node = jack_slist_next(node);
432 jack_slist_free(driver->playback_ports);
433 driver->playback_ports = NULL;
435 driver->engine = NULL;
437 return 0;
441 static int oss_driver_start (oss_driver_t *driver)
443 int flags = 0;
444 int format;
445 int channels;
446 int samplerate;
447 int infd = driver->infd;
448 int outfd = driver->outfd;
449 unsigned int period_size;
450 size_t samplesize;
451 size_t fragsize;
452 const char *indev = driver->indev;
453 const char *outdev = driver->outdev;
455 switch (driver->bits)
457 case 24:
458 case 32:
459 samplesize = sizeof(int);
460 break;
461 case 64:
462 samplesize = sizeof(double);
463 break;
464 case 16:
465 default:
466 samplesize = sizeof(short);
467 break;
469 driver->trigger = 0;
470 if (strcmp(indev, outdev) != 0)
472 if (driver->capture_channels > 0)
474 infd = open(indev, O_RDONLY|O_EXCL);
475 if (infd < 0)
477 jack_error(
478 "OSS: failed to open input device %s: %s@%i, errno=%d",
479 indev, __FILE__, __LINE__, errno);
481 #ifndef OSS_NO_COOKED_MODE
482 ioctl(infd, SNDCTL_DSP_COOKEDMODE, &flags);
483 #endif
484 fragsize = driver->period_size *
485 driver->capture_channels * samplesize;
486 set_fragment(infd, fragsize, driver->nperiods);
488 else infd = -1;
490 if (driver->playback_channels > 0)
492 outfd = open(outdev, O_WRONLY|O_EXCL);
493 if (outfd < 0)
495 jack_error(
496 "OSS: failed to open output device %s: %s@%i, errno=%d",
497 outdev, __FILE__, __LINE__, errno);
499 #ifndef OSS_NO_COOKED_MODE
500 ioctl(outfd, SNDCTL_DSP_COOKEDMODE, &flags);
501 #endif
502 fragsize = driver->period_size *
503 driver->playback_channels * samplesize;
504 set_fragment(outfd, fragsize, driver->nperiods);
506 else outfd = -1;
508 else
510 if (driver->capture_channels != 0 &&
511 driver->playback_channels == 0)
513 infd = open(indev, O_RDWR|O_EXCL);
514 outfd = -1;
515 if (infd < 0)
517 jack_error(
518 "OSS: failed to open device %s: %s@%i, errno=%d",
519 indev, __FILE__, __LINE__, errno);
520 return -1;
522 #ifndef OSS_NO_COOKED_MODE
523 ioctl(infd, SNDCTL_DSP_COOKEDMODE, &flags);
524 #endif
526 else if (driver->capture_channels == 0 &&
527 driver->playback_channels != 0)
529 infd = -1;
530 outfd = open(outdev, O_RDWR|O_EXCL);
531 if (outfd < 0)
533 jack_error(
534 "OSS: failed to open device %s: %s@%i, errno=%d",
535 outdev, __FILE__, __LINE__, errno);
536 return -1;
538 #ifndef OSS_NO_COOKED_MODE
539 ioctl(outfd, SNDCTL_DSP_COOKEDMODE, &flags);
540 #endif
542 else
544 infd = outfd = open(indev, O_RDWR|O_EXCL);
545 if (infd < 0)
547 jack_error(
548 "OSS: failed to open device %s: %s@%i, errno=%d",
549 indev, __FILE__, __LINE__, errno);
550 return -1;
552 #ifndef OSS_NO_COOKED_MODE
553 ioctl(infd, SNDCTL_DSP_COOKEDMODE, &flags);
554 #endif
556 if (infd >= 0 && outfd >= 0)
558 ioctl(outfd, SNDCTL_DSP_SETTRIGGER, &driver->trigger);
559 driver->trigger = (PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT);
560 if (ioctl(infd, SNDCTL_DSP_SETDUPLEX, 0) < 0)
562 if (errno != EINVAL) /* Dont care */
563 jack_error(
564 "OSS: failed to enable full duplex for %s: %s@%i, errno=%d",
565 indev, __FILE__, __LINE__,
566 errno);
569 if (infd >= 0)
571 fragsize = driver->period_size *
572 driver->capture_channels * samplesize;
573 set_fragment(infd, fragsize, driver->nperiods);
575 if (outfd >= 0 && infd < 0)
577 fragsize = driver->period_size *
578 driver->playback_channels * samplesize;
579 set_fragment(outfd, fragsize, driver->nperiods);
582 driver->infd = infd;
583 driver->outfd = outfd;
585 if (infd >= 0)
587 format = driver->format;
588 if (ioctl(infd, SNDCTL_DSP_SETFMT, &format) < 0)
589 jack_error(
590 "OSS: failed to set format for %s: %s@%i, errno=%d",
591 indev, __FILE__, __LINE__, errno);
592 channels = driver->capture_channels;
593 if (ioctl(infd, SNDCTL_DSP_CHANNELS, &channels) < 0)
594 jack_error(
595 "OSS: failed to set channels for %s: %s@%i, errno=%d",
596 indev, __FILE__, __LINE__, errno);
597 samplerate = driver->sample_rate;
598 if (ioctl(infd, SNDCTL_DSP_SPEED, &samplerate) < 0)
599 jack_error(
600 "OSS: failed to set samplerate for %s: %s@%i, errno=%d",
601 indev, __FILE__, __LINE__, errno);
602 jack_info("oss_driver: %s : 0x%x/%i/%i (%i)", indev,
603 format, channels, samplerate, get_fragment(infd));
605 period_size = get_fragment(infd) / samplesize / channels;
606 if (period_size != driver->period_size &&
607 !driver->ignorehwbuf)
609 jack_info("oss_driver: period size update: %u",
610 period_size);
611 driver->period_size = period_size;
612 driver->period_usecs =
613 ((double) driver->period_size /
614 (double) driver->sample_rate) * 1e6;
615 driver->engine->set_buffer_size(driver->engine,
616 driver->period_size);
620 if (outfd >= 0 && infd != outfd)
622 format = driver->format;
623 if (ioctl(outfd, SNDCTL_DSP_SETFMT, &format) < 0)
624 jack_error(
625 "OSS: failed to set format for %s: %s@%i, errno=%d",
626 outdev, __FILE__, __LINE__, errno);
627 channels = driver->playback_channels;
628 if (ioctl(outfd, SNDCTL_DSP_CHANNELS, &channels) < 0)
629 jack_error(
630 "OSS: failed to set channels for %s: %s@%i, errno=%d",
631 outdev, __FILE__, __LINE__, errno);
632 samplerate = driver->sample_rate;
633 if (ioctl(outfd, SNDCTL_DSP_SPEED, &samplerate) < 0)
634 jack_error(
635 "OSS: failed to set samplerate for %s: %s@%i, errno=%d",
636 outdev, __FILE__, __LINE__, errno);
637 jack_info("oss_driver: %s : 0x%x/%i/%i (%i)", outdev,
638 format, channels, samplerate,
639 get_fragment(outfd));
641 period_size = get_fragment(outfd) / samplesize / channels;
642 if (period_size != driver->period_size &&
643 !driver->ignorehwbuf)
645 jack_info("oss_driver: period size update: %u",
646 period_size);
647 driver->period_size = period_size;
648 driver->period_usecs =
649 ((double) driver->period_size /
650 (double) driver->sample_rate) * 1e6;
651 driver->engine->set_buffer_size(driver->engine,
652 driver->period_size);
656 if (driver->capture_channels > 0)
658 driver->indevbufsize = driver->period_size *
659 driver->capture_channels * samplesize;
660 driver->indevbuf = malloc(driver->indevbufsize);
661 if (driver->indevbuf == NULL)
663 jack_error( "OSS: malloc() failed: %s@%i",
664 __FILE__, __LINE__);
665 return -1;
667 memset(driver->indevbuf, 0x00, driver->indevbufsize);
669 else
671 driver->indevbufsize = 0;
672 driver->indevbuf = NULL;
675 if (driver->playback_channels > 0)
677 driver->outdevbufsize = driver->period_size *
678 driver->playback_channels * samplesize;
679 driver->outdevbuf = malloc(driver->outdevbufsize);
680 if (driver->outdevbuf == NULL)
682 jack_error("OSS: malloc() failed: %s@%i",
683 __FILE__, __LINE__);
684 return -1;
686 memset(driver->outdevbuf, 0x00, driver->outdevbufsize);
688 else
690 driver->outdevbufsize = 0;
691 driver->outdevbuf = NULL;
694 jack_info("oss_driver: indevbuf %zd B, outdevbuf %zd B",
695 driver->indevbufsize, driver->outdevbufsize);
697 pthread_mutex_init(&driver->mutex_in, NULL);
698 pthread_mutex_init(&driver->mutex_out, NULL);
699 # ifdef USE_BARRIER
700 puts("oss_driver: using barrier mode, (dual thread)");
701 pthread_barrier_init(&driver->barrier, NULL, 2);
702 # else
703 puts("oss_driver: not using barrier mode, (single thread)");
704 # endif
705 sem_init(&driver->sem_start, 0, 0);
706 driver->run = 1;
707 driver->threads = 0;
708 if (infd >= 0)
710 if (jack_client_create_thread(NULL, &driver->thread_in,
711 driver->engine->rtpriority,
712 driver->engine->control->real_time,
713 io_thread, driver) < 0)
715 jack_error("OSS: jack_client_create_thread() failed: %s@%i",
716 __FILE__, __LINE__);
717 return -1;
719 driver->threads |= 1;
721 # ifdef USE_BARRIER
722 if (outfd >= 0)
724 if (jack_client_create_thread(NULL, &driver->thread_out,
725 driver->engine->rtpriority,
726 driver->engine->control->real_time,
727 io_thread, driver) < 0)
729 jack_error("OSS: jack_client_create_thread() failed: %s@%i",
730 __FILE__, __LINE__);
731 return -1;
733 driver->threads |= 2;
735 # endif
737 if (driver->threads & 1) sem_post(&driver->sem_start);
738 if (driver->threads & 2) sem_post(&driver->sem_start);
740 driver->last_periodtime = jack_get_microseconds();
741 driver->next_periodtime = 0;
742 driver->iodelay = 0.0F;
744 return 0;
748 static int oss_driver_stop (oss_driver_t *driver)
750 void *retval;
752 driver->run = 0;
753 if (driver->threads & 1)
755 if (pthread_join(driver->thread_in, &retval) < 0)
757 jack_error("OSS: pthread_join() failed: %s@%i",
758 __FILE__, __LINE__);
759 return -1;
762 if (driver->threads & 2)
764 if (pthread_join(driver->thread_out, &retval) < 0)
766 jack_error("OSS: pthread_join() failed: %s@%i",
767 __FILE__, __LINE__);
768 return -1;
771 sem_destroy(&driver->sem_start);
772 # ifdef USE_BARRIER
773 pthread_barrier_destroy(&driver->barrier);
774 # endif
775 pthread_mutex_destroy(&driver->mutex_in);
776 pthread_mutex_destroy(&driver->mutex_out);
778 if (driver->outfd >= 0 && driver->outfd != driver->infd)
780 close(driver->outfd);
781 driver->outfd = -1;
783 if (driver->infd >= 0)
785 close(driver->infd);
786 driver->infd = -1;
789 if (driver->indevbuf != NULL)
791 free(driver->indevbuf);
792 driver->indevbuf = NULL;
794 if (driver->outdevbuf != NULL)
796 free(driver->outdevbuf);
797 driver->outdevbuf = NULL;
800 return 0;
804 static int oss_driver_read (oss_driver_t *driver, jack_nframes_t nframes)
806 int channel;
807 jack_sample_t *portbuf;
808 JSList *node;
809 jack_port_t *port;
811 if (!driver->run) return 0;
812 if (nframes != driver->period_size)
814 jack_error(
815 "OSS: read failed nframes != period_size (%u/%u): %s@%i",
816 nframes, driver->period_size, __FILE__, __LINE__);
817 return -1;
820 pthread_mutex_lock(&driver->mutex_in);
822 node = driver->capture_ports;
823 channel = 0;
824 while (node != NULL)
826 port = (jack_port_t *) node->data;
828 if (jack_port_connected(port))
830 portbuf = jack_port_get_buffer(port, nframes);
831 copy_and_convert_in(portbuf, driver->indevbuf,
832 nframes, channel,
833 driver->capture_channels,
834 driver->bits);
837 node = jack_slist_next(node);
838 channel++;
841 pthread_mutex_unlock(&driver->mutex_in);
843 return 0;
847 static int oss_driver_write (oss_driver_t *driver, jack_nframes_t nframes)
849 int channel;
850 jack_sample_t *portbuf;
851 JSList *node;
852 jack_port_t *port;
854 if (!driver->run) return 0;
855 if (nframes != driver->period_size)
857 jack_error(
858 "OSS: write failed nframes != period_size (%u/%u): %s@%i",
859 nframes, driver->period_size, __FILE__, __LINE__);
860 return -1;
863 pthread_mutex_lock(&driver->mutex_out);
865 node = driver->playback_ports;
866 channel = 0;
867 while (node != NULL)
869 port = (jack_port_t *) node->data;
871 if (jack_port_connected(port))
873 portbuf = jack_port_get_buffer(port, nframes);
874 copy_and_convert_out(driver->outdevbuf, portbuf,
875 nframes, channel,
876 driver->playback_channels,
877 driver->bits);
880 node = jack_slist_next(node);
881 channel++;
884 pthread_mutex_unlock(&driver->mutex_out);
886 return 0;
890 static int oss_driver_null_cycle (oss_driver_t *driver, jack_nframes_t nframes)
892 pthread_mutex_lock(&driver->mutex_in);
893 memset(driver->indevbuf, 0x00, driver->indevbufsize);
894 pthread_mutex_unlock(&driver->mutex_in);
896 pthread_mutex_lock(&driver->mutex_out);
897 memset(driver->outdevbuf, 0x00, driver->outdevbufsize);
898 pthread_mutex_unlock(&driver->mutex_out);
900 return 0;
904 static int oss_driver_bufsize (oss_driver_t *driver, jack_nframes_t nframes)
906 oss_driver_stop(driver);
908 set_period_size(driver, nframes);
909 driver->engine->set_buffer_size(driver->engine, driver->period_size);
910 jack_info("oss_driver: period size update: %u", nframes);
912 oss_driver_start(driver);
914 return 0;
918 /* internal driver thread */
921 #ifdef USE_BARRIER
922 static inline void synchronize (oss_driver_t *driver)
924 if (driver->threads == 3)
926 if (pthread_barrier_wait(&driver->barrier) ==
927 PTHREAD_BARRIER_SERIAL_THREAD)
929 driver_cycle(driver);
932 else
934 driver_cycle(driver);
937 #endif
940 static void *io_thread (void *param)
942 size_t localsize;
943 ssize_t io_res;
944 void *localbuf;
945 oss_driver_t *driver = (oss_driver_t *) param;
947 sem_wait(&driver->sem_start);
949 # ifdef USE_BARRIER
950 if (pthread_self() == driver->thread_in)
952 localsize = driver->indevbufsize;
953 localbuf = malloc(localsize);
954 if (localbuf == NULL)
956 jack_error("OSS: malloc() failed: %s@%i",
957 __FILE__, __LINE__);
958 return NULL;
961 while (driver->run)
963 io_res = read(driver->infd, localbuf, localsize);
964 if (io_res < (ssize_t) localsize)
966 jack_error(
967 "OSS: read() failed: %s@%i, count=%d/%d, errno=%d",
968 __FILE__, __LINE__, io_res, localsize,
969 errno);
970 break;
973 pthread_mutex_lock(&driver->mutex_in);
974 memcpy(driver->indevbuf, localbuf, localsize);
975 pthread_mutex_unlock(&driver->mutex_in);
977 synchronize(driver);
980 free(localbuf);
982 else if (pthread_self() == driver->thread_out)
984 localsize = driver->outdevbufsize;
985 localbuf = malloc(localsize);
986 if (localbuf == NULL)
988 jack_error("OSS: malloc() failed: %s@%i",
989 __FILE__, __LINE__);
990 return NULL;
992 if (driver->trigger)
994 /* don't care too much if this fails */
995 memset(localbuf, 0x00, localsize);
996 write(driver->outfd, localbuf, localsize);
997 ioctl(driver->outfd, SNDCTL_DSP_SETTRIGGER, &driver->trigger);
1000 while (driver->run)
1002 pthread_mutex_lock(&driver->mutex_out);
1003 memcpy(localbuf, driver->outdevbuf, localsize);
1004 pthread_mutex_unlock(&driver->mutex_out);
1006 io_res = write(driver->outfd, localbuf, localsize);
1007 if (io_res < (ssize_t) localsize)
1009 jack_error(
1010 "OSS: write() failed: %s@%i, count=%d/%d, errno=%d",
1011 __FILE__, __LINE__, io_res, localsize,
1012 errno);
1013 break;
1016 synchronize(driver);
1019 free(localbuf);
1021 # else
1022 localsize = (driver->indevbufsize >= driver->outdevbufsize) ?
1023 driver->indevbufsize : driver->outdevbufsize;
1024 localbuf = malloc(localsize);
1025 if (localbuf == NULL)
1027 jack_error("OSS: malloc() failed: %s@%i", __FILE__, __LINE__);
1028 return NULL;
1030 if (driver->trigger)
1032 /* don't care too much if this fails */
1033 memset(localbuf, 0x00, localsize);
1034 write(driver->outfd, localbuf, driver->outdevbufsize);
1035 ioctl(driver->outfd, SNDCTL_DSP_SETTRIGGER, &driver->trigger);
1038 while (driver->run)
1040 if (driver->playback_channels > 0)
1042 pthread_mutex_lock(&driver->mutex_out);
1043 memcpy(localbuf, driver->outdevbuf,
1044 driver->outdevbufsize);
1045 pthread_mutex_unlock(&driver->mutex_out);
1047 io_res = write(driver->outfd, localbuf,
1048 driver->outdevbufsize);
1049 if (io_res < (ssize_t) driver->outdevbufsize)
1051 jack_error(
1052 "OSS: write() failed: %s@%i, count=%d/%d, errno=%d",
1053 __FILE__, __LINE__, io_res,
1054 driver->outdevbufsize, errno);
1055 break;
1059 if (driver->capture_channels > 0)
1061 io_res = read(driver->infd, localbuf,
1062 driver->indevbufsize);
1063 if (io_res < (ssize_t) driver->indevbufsize)
1065 jack_error(
1066 "OSS: read() failed: %s@%i, count=%d/%d, errno=%d",
1067 __FILE__, __LINE__, io_res,
1068 driver->indevbufsize, errno);
1069 break;
1072 pthread_mutex_lock(&driver->mutex_in);
1073 memcpy(driver->indevbuf, localbuf,
1074 driver->indevbufsize);
1075 pthread_mutex_unlock(&driver->mutex_in);
1078 driver_cycle(driver);
1081 free(localbuf);
1082 # endif
1084 return NULL;
1088 /* jack driver published interface */
1091 const char driver_client_name[] = "oss";
1094 void driver_finish (jack_driver_t *);
1097 jack_driver_desc_t * driver_get_descriptor ()
1099 jack_driver_desc_t *desc;
1100 jack_driver_param_desc_t *params;
1102 desc = (jack_driver_desc_t *) calloc(1, sizeof(jack_driver_desc_t));
1103 if (desc == NULL)
1105 jack_error("oss_driver: calloc() failed: %s@%i, errno=%d",
1106 __FILE__, __LINE__, errno);
1107 return NULL;
1109 strcpy(desc->name, driver_client_name);
1110 desc->nparams = OSS_DRIVER_N_PARAMS;
1112 params = calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
1113 if (params == NULL)
1115 jack_error("oss_driver: calloc() failed: %s@%i, errno=%d",
1116 __FILE__, __LINE__, errno);
1117 return NULL;
1119 memcpy(params, oss_params,
1120 desc->nparams * sizeof(jack_driver_param_desc_t));
1121 desc->params = params;
1123 return desc;
1127 jack_driver_t * driver_initialize (jack_client_t *client,
1128 JSList * params)
1130 int bits = OSS_DRIVER_DEF_BITS;
1131 jack_nframes_t sample_rate = OSS_DRIVER_DEF_FS;
1132 jack_nframes_t period_size = OSS_DRIVER_DEF_BLKSIZE;
1133 jack_nframes_t in_latency = 0;
1134 jack_nframes_t out_latency = 0;
1135 unsigned int nperiods = OSS_DRIVER_DEF_NPERIODS;
1136 unsigned int capture_channels = OSS_DRIVER_DEF_INS;
1137 unsigned int playback_channels = OSS_DRIVER_DEF_OUTS;
1138 const JSList *pnode;
1139 const jack_driver_param_t *param;
1140 oss_driver_t *driver;
1142 driver = (oss_driver_t *) malloc(sizeof(oss_driver_t));
1143 if (driver == NULL)
1145 jack_error("OSS: malloc() failed: %s@%i, errno=%d",
1146 __FILE__, __LINE__, errno);
1147 return NULL;
1149 jack_driver_init((jack_driver_t *) driver);
1151 driver->attach = (JackDriverAttachFunction) oss_driver_attach;
1152 driver->detach = (JackDriverDetachFunction) oss_driver_detach;
1153 driver->start = (JackDriverStartFunction) oss_driver_start;
1154 driver->stop = (JackDriverStopFunction) oss_driver_stop;
1155 driver->read = (JackDriverReadFunction) oss_driver_read;
1156 driver->write = (JackDriverWriteFunction) oss_driver_write;
1157 driver->null_cycle = (JackDriverNullCycleFunction)
1158 oss_driver_null_cycle;
1159 driver->bufsize = (JackDriverBufSizeFunction) oss_driver_bufsize;
1161 driver->indev = NULL;
1162 driver->outdev = NULL;
1163 driver->ignorehwbuf = 0;
1164 driver->trigger = 0;
1166 pnode = params;
1167 while (pnode != NULL)
1169 param = (const jack_driver_param_t *) pnode->data;
1171 switch (param->character)
1173 case 'r':
1174 sample_rate = param->value.ui;
1175 break;
1176 case 'p':
1177 period_size = param->value.ui;
1178 break;
1179 case 'n':
1180 nperiods = param->value.ui;
1181 break;
1182 case 'w':
1183 bits = param->value.i;
1184 break;
1185 case 'i':
1186 capture_channels = param->value.ui;
1187 break;
1188 case 'o':
1189 playback_channels = param->value.ui;
1190 break;
1191 case 'C':
1192 driver->indev = strdup(param->value.str);
1193 break;
1194 case 'P':
1195 driver->outdev = strdup(param->value.str);
1196 break;
1197 case 'b':
1198 driver->ignorehwbuf = 1;
1199 break;
1200 case 'I':
1201 in_latency = param->value.ui;
1202 break;
1203 case 'O':
1204 out_latency = param->value.ui;
1205 break;
1207 pnode = jack_slist_next(pnode);
1210 driver->sample_rate = sample_rate;
1211 driver->period_size = period_size;
1212 driver->nperiods = nperiods;
1213 driver->bits = bits;
1214 driver->capture_channels = capture_channels;
1215 driver->playback_channels = playback_channels;
1216 driver->sys_in_latency = in_latency;
1217 driver->sys_out_latency = out_latency;
1219 set_period_size(driver, period_size);
1221 driver->finish = driver_finish;
1223 if (driver->indev == NULL)
1224 driver->indev = strdup(OSS_DRIVER_DEF_DEV);
1225 if (driver->outdev == NULL)
1226 driver->outdev = strdup(OSS_DRIVER_DEF_DEV);
1227 driver->infd = -1;
1228 driver->outfd = -1;
1229 switch (driver->bits)
1231 # ifndef OSS_ENDIAN
1232 # ifdef __GNUC__
1233 # if (defined(__i386__) || defined(__alpha__) || defined(__arm__) || defined(__x86_64__))
1234 # define OSS_LITTLE_ENDIAN 1234
1235 # define OSS_ENDIAN OSS_LITTLE_ENDIAN
1236 # else
1237 # define OSS_BIG_ENDIAN 4321
1238 # define OSS_ENDIAN OSS_BIG_ENDIAN
1239 # endif
1240 # else /* __GNUC__ */
1241 # if (defined(_AIX) || defined(AIX) || defined(sparc) || defined(__hppa) || defined(PPC) || defined(__powerpc__) && !defined(i386) && !defined(__i386) && !defined(__i386__))
1242 # define OSS_BIG_ENDIAN 4321
1243 # define OSS_ENDIAN OSS_BIG_ENDIAN
1244 # else
1245 # define OSS_LITTLE_ENDIAN 1234
1246 # define OSS_ENDIAN OSS_LITTLE_ENDIAN
1247 # endif
1248 # endif /* __GNUC__ */
1249 # endif /* OSS_ENDIAN */
1250 # if (OSS_ENDIAN == 1234)
1251 /* little-endian architectures */
1252 case 24: /* little-endian LSB aligned 24-bits in 32-bits integer */
1253 driver->format = 0x00008000;
1254 break;
1255 case 32: /* little-endian 32-bit integer */
1256 driver->format = 0x00001000;
1257 break;
1258 case 64: /* native-endian 64-bit float */
1259 driver->format = 0x00004000;
1260 break;
1261 case 16: /* little-endian 16-bit integer */
1262 default:
1263 driver->format = 0x00000010;
1264 break;
1265 /* big-endian architectures */
1266 # else
1267 case 24: /* big-endian LSB aligned 24-bits in 32-bits integer */
1268 break;
1269 driver->format = 0x00010000;
1270 case 32: /* big-endian 32-bit integer */
1271 driver->format = 0x00002000;
1272 break;
1273 case 64: /* native-endian 64-bit float */
1274 driver->format = 0x00004000;
1275 break;
1276 case 16: /* big-endian 16-bit integer */
1277 default:
1278 driver->format = 0x00000020;
1279 # endif
1282 driver->indevbuf = driver->outdevbuf = NULL;
1284 driver->capture_ports = NULL;
1285 driver->playback_ports = NULL;
1287 driver->engine = NULL;
1288 driver->client = client;
1290 return ((jack_driver_t *) driver);
1294 void driver_finish (jack_driver_t *driver)
1296 oss_driver_t *oss_driver = (oss_driver_t *) driver;
1298 oss_driver = (oss_driver_t *) driver;
1299 if (oss_driver->indev != NULL)
1300 free(oss_driver->indev);
1301 if (oss_driver->outdev != NULL)
1302 free(oss_driver->outdev);
1303 free(driver);