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,
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
53 #include <semaphore.h>
55 #include <sys/types.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
71 #define SNDCTL_DSP_COOKEDMODE _SIOWR('P', 30, int)
73 #warning "Unable to define cooked mode!"
74 #define OSS_NO_COOKED_MODE
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
] = {
83 { .ui
= OSS_DRIVER_DEF_FS
},
90 { .ui
= OSS_DRIVER_DEF_BLKSIZE
},
97 { .ui
= OSS_DRIVER_DEF_NPERIODS
},
98 "number of periods in buffer",
99 "number of periods in buffer"
104 { .i
= OSS_DRIVER_DEF_BITS
},
111 { .ui
= OSS_DRIVER_DEF_INS
},
118 { .ui
= OSS_DRIVER_DEF_OUTS
},
124 JackDriverParamString
,
125 { .str
= OSS_DRIVER_DEF_DEV
},
131 JackDriverParamString
,
132 { .str
= OSS_DRIVER_DEF_DEV
},
140 "ignore hardware period size",
141 "ignore hardware period size"
147 "system input latency",
148 "system input latency"
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
)
212 signed short *s16src
= (signed short *) src
;
213 signed int *s32src
= (signed int *) src
;
214 double *f64src
= (double *) src
;
221 scale
= 1.0f
/ 0x7fff;
222 for (dstidx
= 0; dstidx
< nframes
; dstidx
++)
224 dst
[dstidx
] = (jack_sample_t
)
225 s16src
[srcidx
] * scale
;
230 scale
= 1.0f
/ 0x7fffff;
231 for (dstidx
= 0; dstidx
< nframes
; dstidx
++)
233 dst
[dstidx
] = (jack_sample_t
)
234 s32src
[srcidx
] * scale
;
239 scale
= 1.0f
/ 0x7fffffff;
240 for (dstidx
= 0; dstidx
< nframes
; dstidx
++)
242 dst
[dstidx
] = (jack_sample_t
)
243 s32src
[srcidx
] * scale
;
248 for (dstidx
= 0; dstidx
< nframes
; dstidx
++)
250 dst
[dstidx
] = (jack_sample_t
) f64src
[srcidx
];
258 static void copy_and_convert_out (void *dst
, jack_sample_t
*src
,
259 size_t nframes
, int channel
, int chcount
, int bits
)
263 signed short *s16dst
= (signed short *) dst
;
264 signed int *s32dst
= (signed int *) dst
;
265 double *f64dst
= (double *) dst
;
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
);
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
);
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
);
305 for (srcidx
= 0; srcidx
< nframes
; srcidx
++)
307 f64dst
[dstidx
] = (double) src
[srcidx
];
315 static void set_fragment (int fd
, size_t fragsize
, unsigned int fragcount
)
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
)
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
);
344 static void *io_thread (void *);
347 /* jack driver interface */
350 static int oss_driver_attach (oss_driver_t
*driver
, jack_engine_t
*engine
)
353 unsigned int channel
;
354 char channel_name
[64];
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);
371 jack_error("OSS: cannot register port for %s: %s@%i",
372 channel_name
, __FILE__
, __LINE__
);
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);
390 jack_error("OSS: cannot register port for %s: %s@%i",
391 channel_name
, __FILE__
, __LINE__
);
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
);
406 static int oss_driver_detach (oss_driver_t
*driver
, jack_engine_t
*engine
)
410 if (driver
->engine
== NULL
)
413 /*jack_deactivate(driver->client);*/ /* ? */
415 node
= driver
->capture_ports
;
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
;
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
;
441 static int oss_driver_start (oss_driver_t
*driver
)
447 int infd
= driver
->infd
;
448 int outfd
= driver
->outfd
;
449 unsigned int period_size
;
452 const char *indev
= driver
->indev
;
453 const char *outdev
= driver
->outdev
;
455 switch (driver
->bits
)
459 samplesize
= sizeof(int);
462 samplesize
= sizeof(double);
466 samplesize
= sizeof(short);
470 if (strcmp(indev
, outdev
) != 0)
472 if (driver
->capture_channels
> 0)
474 infd
= open(indev
, O_RDONLY
|O_EXCL
);
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
);
484 fragsize
= driver
->period_size
*
485 driver
->capture_channels
* samplesize
;
486 set_fragment(infd
, fragsize
, driver
->nperiods
);
490 if (driver
->playback_channels
> 0)
492 outfd
= open(outdev
, O_WRONLY
|O_EXCL
);
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
);
502 fragsize
= driver
->period_size
*
503 driver
->playback_channels
* samplesize
;
504 set_fragment(outfd
, fragsize
, driver
->nperiods
);
510 if (driver
->capture_channels
!= 0 &&
511 driver
->playback_channels
== 0)
513 infd
= open(indev
, O_RDWR
|O_EXCL
);
518 "OSS: failed to open device %s: %s@%i, errno=%d",
519 indev
, __FILE__
, __LINE__
, errno
);
522 #ifndef OSS_NO_COOKED_MODE
523 ioctl(infd
, SNDCTL_DSP_COOKEDMODE
, &flags
);
526 else if (driver
->capture_channels
== 0 &&
527 driver
->playback_channels
!= 0)
530 outfd
= open(outdev
, O_RDWR
|O_EXCL
);
534 "OSS: failed to open device %s: %s@%i, errno=%d",
535 outdev
, __FILE__
, __LINE__
, errno
);
538 #ifndef OSS_NO_COOKED_MODE
539 ioctl(outfd
, SNDCTL_DSP_COOKEDMODE
, &flags
);
544 infd
= outfd
= open(indev
, O_RDWR
|O_EXCL
);
548 "OSS: failed to open device %s: %s@%i, errno=%d",
549 indev
, __FILE__
, __LINE__
, errno
);
552 #ifndef OSS_NO_COOKED_MODE
553 ioctl(infd
, SNDCTL_DSP_COOKEDMODE
, &flags
);
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 */
564 "OSS: failed to enable full duplex for %s: %s@%i, errno=%d",
565 indev
, __FILE__
, __LINE__
,
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
);
583 driver
->outfd
= outfd
;
587 format
= driver
->format
;
588 if (ioctl(infd
, SNDCTL_DSP_SETFMT
, &format
) < 0)
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)
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)
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",
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)
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)
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)
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",
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",
667 memset(driver
->indevbuf
, 0x00, driver
->indevbufsize
);
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",
686 memset(driver
->outdevbuf
, 0x00, driver
->outdevbufsize
);
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
);
700 puts("oss_driver: using barrier mode, (dual thread)");
701 pthread_barrier_init(&driver
->barrier
, NULL
, 2);
703 puts("oss_driver: not using barrier mode, (single thread)");
705 sem_init(&driver
->sem_start
, 0, 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",
719 driver
->threads
|= 1;
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",
733 driver
->threads
|= 2;
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
;
748 static int oss_driver_stop (oss_driver_t
*driver
)
753 if (driver
->threads
& 1)
755 if (pthread_join(driver
->thread_in
, &retval
) < 0)
757 jack_error("OSS: pthread_join() failed: %s@%i",
762 if (driver
->threads
& 2)
764 if (pthread_join(driver
->thread_out
, &retval
) < 0)
766 jack_error("OSS: pthread_join() failed: %s@%i",
771 sem_destroy(&driver
->sem_start
);
773 pthread_barrier_destroy(&driver
->barrier
);
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
);
783 if (driver
->infd
>= 0)
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
;
804 static int oss_driver_read (oss_driver_t
*driver
, jack_nframes_t nframes
)
807 jack_sample_t
*portbuf
;
811 if (!driver
->run
) return 0;
812 if (nframes
!= driver
->period_size
)
815 "OSS: read failed nframes != period_size (%u/%u): %s@%i",
816 nframes
, driver
->period_size
, __FILE__
, __LINE__
);
820 pthread_mutex_lock(&driver
->mutex_in
);
822 node
= driver
->capture_ports
;
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
,
833 driver
->capture_channels
,
837 node
= jack_slist_next(node
);
841 pthread_mutex_unlock(&driver
->mutex_in
);
847 static int oss_driver_write (oss_driver_t
*driver
, jack_nframes_t nframes
)
850 jack_sample_t
*portbuf
;
854 if (!driver
->run
) return 0;
855 if (nframes
!= driver
->period_size
)
858 "OSS: write failed nframes != period_size (%u/%u): %s@%i",
859 nframes
, driver
->period_size
, __FILE__
, __LINE__
);
863 pthread_mutex_lock(&driver
->mutex_out
);
865 node
= driver
->playback_ports
;
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
,
876 driver
->playback_channels
,
880 node
= jack_slist_next(node
);
884 pthread_mutex_unlock(&driver
->mutex_out
);
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
);
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
);
918 /* internal driver thread */
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
);
934 driver_cycle(driver
);
940 static void *io_thread (void *param
)
945 oss_driver_t
*driver
= (oss_driver_t
*) param
;
947 sem_wait(&driver
->sem_start
);
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",
963 io_res
= read(driver
->infd
, localbuf
, localsize
);
964 if (io_res
< (ssize_t
) localsize
)
967 "OSS: read() failed: %s@%i, count=%d/%d, errno=%d",
968 __FILE__
, __LINE__
, io_res
, localsize
,
973 pthread_mutex_lock(&driver
->mutex_in
);
974 memcpy(driver
->indevbuf
, localbuf
, localsize
);
975 pthread_mutex_unlock(&driver
->mutex_in
);
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",
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
);
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
)
1010 "OSS: write() failed: %s@%i, count=%d/%d, errno=%d",
1011 __FILE__
, __LINE__
, io_res
, localsize
,
1016 synchronize(driver
);
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__
);
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
);
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
)
1052 "OSS: write() failed: %s@%i, count=%d/%d, errno=%d",
1053 __FILE__
, __LINE__
, io_res
,
1054 driver
->outdevbufsize
, errno
);
1059 if (driver
->capture_channels
> 0)
1061 io_res
= read(driver
->infd
, localbuf
,
1062 driver
->indevbufsize
);
1063 if (io_res
< (ssize_t
) driver
->indevbufsize
)
1066 "OSS: read() failed: %s@%i, count=%d/%d, errno=%d",
1067 __FILE__
, __LINE__
, io_res
,
1068 driver
->indevbufsize
, errno
);
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
);
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
));
1105 jack_error("oss_driver: calloc() failed: %s@%i, errno=%d",
1106 __FILE__
, __LINE__
, errno
);
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
));
1115 jack_error("oss_driver: calloc() failed: %s@%i, errno=%d",
1116 __FILE__
, __LINE__
, errno
);
1119 memcpy(params
, oss_params
,
1120 desc
->nparams
* sizeof(jack_driver_param_desc_t
));
1121 desc
->params
= params
;
1127 jack_driver_t
* driver_initialize (jack_client_t
*client
,
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
));
1145 jack_error("OSS: malloc() failed: %s@%i, errno=%d",
1146 __FILE__
, __LINE__
, errno
);
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;
1167 while (pnode
!= NULL
)
1169 param
= (const jack_driver_param_t
*) pnode
->data
;
1171 switch (param
->character
)
1174 sample_rate
= param
->value
.ui
;
1177 period_size
= param
->value
.ui
;
1180 nperiods
= param
->value
.ui
;
1183 bits
= param
->value
.i
;
1186 capture_channels
= param
->value
.ui
;
1189 playback_channels
= param
->value
.ui
;
1192 driver
->indev
= strdup(param
->value
.str
);
1195 driver
->outdev
= strdup(param
->value
.str
);
1198 driver
->ignorehwbuf
= 1;
1201 in_latency
= param
->value
.ui
;
1204 out_latency
= param
->value
.ui
;
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
);
1229 switch (driver
->bits
)
1233 # if (defined(__i386__) || defined(__alpha__) || defined(__arm__) || defined(__x86_64__))
1234 # define OSS_LITTLE_ENDIAN 1234
1235 # define OSS_ENDIAN OSS_LITTLE_ENDIAN
1237 # define OSS_BIG_ENDIAN 4321
1238 # define OSS_ENDIAN OSS_BIG_ENDIAN
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
1245 # define OSS_LITTLE_ENDIAN 1234
1246 # define OSS_ENDIAN OSS_LITTLE_ENDIAN
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;
1255 case 32: /* little-endian 32-bit integer */
1256 driver
->format
= 0x00001000;
1258 case 64: /* native-endian 64-bit float */
1259 driver
->format
= 0x00004000;
1261 case 16: /* little-endian 16-bit integer */
1263 driver
->format
= 0x00000010;
1265 /* big-endian architectures */
1267 case 24: /* big-endian LSB aligned 24-bits in 32-bits integer */
1269 driver
->format
= 0x00010000;
1270 case 32: /* big-endian 32-bit integer */
1271 driver
->format
= 0x00002000;
1273 case 64: /* native-endian 64-bit float */
1274 driver
->format
= 0x00004000;
1276 case 16: /* big-endian 16-bit integer */
1278 driver
->format
= 0x00000020;
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
);