git-svn-id: svn+ssh://jackaudio.org/trunk/jack@673 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
| @@ -1,25 +1,19 @@ | |||||
| *.desc | |||||
| *.pc | |||||
| *.tar.gz | |||||
| *diff | |||||
| *diffs | |||||
| .deps | |||||
| Makefile | |||||
| Makefile.in | |||||
| aclocal.m4 | |||||
| autom4te.cache | autom4te.cache | ||||
| config.cache | |||||
| config.h | config.h | ||||
| config.h.in | config.h.in | ||||
| stamp-h1 | |||||
| config.log | config.log | ||||
| aclocal.m4 | |||||
| config.status | config.status | ||||
| config.cache | |||||
| libtool | |||||
| *.pc | |||||
| .deps | |||||
| Makefile | |||||
| Makefile.in | |||||
| jack.spec | |||||
| configure | configure | ||||
| *.tar.gz | |||||
| *.desc | |||||
| *diff | |||||
| *diffs | |||||
| compile | |||||
| depcomp | |||||
| install-sh | |||||
| missing | |||||
| mkinstalldirs | |||||
| doxygen-build.stamp | |||||
| jack.spec | |||||
| libtool | |||||
| stamp-h1 | |||||
| @@ -1,8 +1,6 @@ | |||||
| MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure config.h.in \ | |||||
| MAINTAINERCLEANFILES = Makefile.in configure config.h.in \ | |||||
| stamp-h.in config.log config.cache \ | stamp-h.in config.log config.cache \ | ||||
| config.guess mkinstalldirs config.status \ | |||||
| missing install-sh config.sub ltconfig \ | |||||
| ltmain.sh | |||||
| config.status | |||||
| if HAVE_DOXYGEN | if HAVE_DOXYGEN | ||||
| DOC_DIR = doc | DOC_DIR = doc | ||||
| @@ -16,14 +14,13 @@ dist-check-doxygen: | |||||
| @false | @false | ||||
| endif | endif | ||||
| SUBDIRS = jack libjack jackd drivers example-clients $(DOC_DIR) | |||||
| DIST_SUBDIRS = jack libjack jackd drivers example-clients doc | |||||
| SUBDIRS = config jack libjack jackd drivers example-clients $(DOC_DIR) | |||||
| DIST_SUBDIRS = config jack libjack jackd drivers example-clients doc | |||||
| pkgconfigdir = $(libdir)/pkgconfig | pkgconfigdir = $(libdir)/pkgconfig | ||||
| pkgconfig_DATA = jack.pc | pkgconfig_DATA = jack.pc | ||||
| EXTRA_DIST = depcomp COPYING COPYING.GPL COPYING.LGPL | |||||
| EXTRA_DIST = COPYING COPYING.GPL COPYING.LGPL | |||||
| AUTOMAKE_OPTIONS = foreign | AUTOMAKE_OPTIONS = foreign | ||||
| @@ -20,6 +20,15 @@ send a change request to Kai Vehmanen (mailto:k_at_eca.cx). | |||||
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | ||||
| TODO for merging Mac OS X support | |||||
| - <sysdeps/atomicity.h> | |||||
| -- fix cpu/generic/atomicity.h:36:#include <bits/gthr.h> | |||||
| - clean up other header files | |||||
| -- <sysdeps/poll.h>, fakepoll.h, etc. | |||||
| -- <sysdeps/ipc.h>, <sys/ipc.h> in shm.c | |||||
| -- need config/os/generic/time.h implementation | |||||
| TODO before-1.0 | TODO before-1.0 | ||||
| - add explanation of protocol versioning to README.developers (kaiv) | - add explanation of protocol versioning to README.developers (kaiv) | ||||
| @@ -1,11 +1,25 @@ | |||||
| #!/bin/sh | #!/bin/sh | ||||
| libtoolize --force 2>&1 | sed '/^You should/d' || { | |||||
| if which libtoolize >/dev/null | |||||
| then | |||||
| LIBTOOLIZE=libtoolize | |||||
| else | |||||
| if which glibtoolize >/dev/null | |||||
| then | |||||
| # on the Mac it's called glibtoolize for some reason | |||||
| LIBTOOLIZE=glibtoolize | |||||
| else | |||||
| echo "libtoolize not found" | |||||
| exit 1 | |||||
| fi | |||||
| fi | |||||
| $LIBTOOLIZE --force 2>&1 | sed '/^You should/d' || { | |||||
| echo "libtool failed, exiting..." | echo "libtool failed, exiting..." | ||||
| exit 1 | exit 1 | ||||
| } | } | ||||
| aclocal $ACLOCAL_FLAGS || { | |||||
| aclocal $ACLOCAL_FLAGS -I config || { | |||||
| echo "aclocal \$ACLOCAL_FLAGS where \$ACLOCAL_FLAGS= failed, exiting..." | echo "aclocal \$ACLOCAL_FLAGS where \$ACLOCAL_FLAGS= failed, exiting..." | ||||
| exit 1 | exit 1 | ||||
| } | } | ||||
| @@ -0,0 +1,10 @@ | |||||
| Makefile | |||||
| Makefile.in | |||||
| compile | |||||
| config.guess | |||||
| config.sub | |||||
| depcomp | |||||
| install-sh | |||||
| ltmain.sh | |||||
| missing | |||||
| mkinstalldirs | |||||
| @@ -0,0 +1,14 @@ | |||||
| # Currently, we don't actually build anything in the `cpu' and `os' | |||||
| # subdirectories. If we ever do, they will need Makefiles. For now, | |||||
| # this is sufficient. Unfortunately, their CVS subdirectories also | |||||
| # get distributed as a side-effect. | |||||
| EXTRA_DIST = configure.host depcomp cpu os | |||||
| MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.sub \ | |||||
| install-sh ltmain.sh missing mkinstalldirs | |||||
| # Link all relevant headers into the `sysdeps' directory. The order | |||||
| # of these loops determines header file precedence. | |||||
| SUBDIRS = sysdeps | |||||
| DIST_SUBDIRS = sysdeps | |||||
| @@ -0,0 +1,41 @@ | |||||
| dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) | |||||
| dnl example | |||||
| dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) | |||||
| dnl will set SYSCONFDIR to /usr/local/etc | |||||
| dnl written by thomas vander stichele | |||||
| AC_DEFUN(AS_AC_EXPAND, | |||||
| [ | |||||
| EXP_VAR=[$1] | |||||
| FROM_VAR=[$2] | |||||
| dnl first expand prefix and exec_prefix if necessary | |||||
| prefix_save=$prefix | |||||
| if test "x$prefix" = "xNONE"; then | |||||
| prefix=/usr/local | |||||
| fi | |||||
| exec_prefix_save=$exec_prefix | |||||
| if test "x$exec_prefix" = "xNONE"; then | |||||
| if test "x$prefix_save" = "xNONE"; then | |||||
| exec_prefix=/usr/local | |||||
| else | |||||
| exec_prefix=$prefix | |||||
| fi | |||||
| fi | |||||
| full_var="$FROM_VAR" | |||||
| dnl loop until it doesn't change anymore | |||||
| while true; do | |||||
| new_full_var="`eval echo $full_var`" | |||||
| if test "x$new_full_var" = "x$full_var"; then break; fi | |||||
| full_var=$new_full_var | |||||
| done | |||||
| dnl clean up | |||||
| full_var=$new_full_var | |||||
| [$1]=$full_var | |||||
| prefix=$prefix_save | |||||
| exec_prefix=$exec_prefix_save | |||||
| ]) | |||||
| @@ -0,0 +1,159 @@ | |||||
| ######################################################################## | |||||
| # | |||||
| # configure.host -- JACK Audio Connection Kit version. | |||||
| # | |||||
| # This script and the system-dependent header directories it uses were | |||||
| # adapted for JACK from gcc/libstdc++-v3/configure.host. | |||||
| # | |||||
| # We've tried to keep it as close to the original as possible, while | |||||
| # removing a bunch of os-specific files that didn't seem relevant. | |||||
| # The primary goal has been to avoid changing the cpu-dependent | |||||
| # atomicity.h headers. | |||||
| # | |||||
| # If you need to make changes, the relevant GCC documentation may | |||||
| # prove helpful, <http://gcc.gnu.org/onlinedocs/porting>, especially | |||||
| # the <http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html> | |||||
| # discussion of <atomicity.h>. | |||||
| # | |||||
| ######################################################################## | |||||
| # This shell script handles all host based configuration for libstdc++. | |||||
| # It sets various shell variables based on the the host and the | |||||
| # configuration options. You can modify this shell script without needing | |||||
| # to rerun autoconf/aclocal/etc. This file is "sourced" not executed. | |||||
| # | |||||
| # You should read docs/html/17_intro/porting.* to make sense of this file. | |||||
| # | |||||
| # | |||||
| # It uses the following shell variables as set by config.guess: | |||||
| # host The configuration host (full CPU-vendor-OS triplet) | |||||
| # host_cpu The configuration host CPU | |||||
| # host_os The configuration host OS | |||||
| # | |||||
| # | |||||
| # It sets the following shell variables: | |||||
| # | |||||
| # cpu_include_dir CPU-specific directory, defaults to cpu/generic | |||||
| # if cpu/host_cpu doesn't exist. This is | |||||
| # used to set atomicity_include_dir. | |||||
| # | |||||
| # os_include_dir OS-specific directory, defaults to os/generic. | |||||
| # | |||||
| # atomicity_include_dir location of atomicity.h, | |||||
| # defaults to cpu_include_dir | |||||
| # | |||||
| # It possibly modifies the following variables: | |||||
| # | |||||
| # OS_LDFLAGS extra flags to pass when linking the library, of | |||||
| # the form '-Wl,blah' | |||||
| # (defaults to empty in acinclude.m4) | |||||
| # | |||||
| # If the defaults will not work for your platform, you need only change the | |||||
| # variables that won't work, i.e., you do not need to explicitly set a | |||||
| # working variable to its default. Most hosts only need to change the two | |||||
| # *_include_dir variables. | |||||
| # DEFAULTS | |||||
| # Try to guess a default cpu_include_dir based on the name of the CPU. We | |||||
| # cannot do this for os_include_dir; there are too many portable operating | |||||
| # systems out there. :-) | |||||
| # HOST-SPECIFIC OVERRIDES | |||||
| # Set any CPU-dependent bits. | |||||
| # Here we override defaults and catch more general cases due to naming | |||||
| # conventions (e.g., chip_name* to catch all variants). | |||||
| # THIS TABLE IS SORTED. KEEP IT THAT WAY. | |||||
| case "${host_cpu}" in | |||||
| alpha*) | |||||
| try_cpu=alpha | |||||
| ;; | |||||
| i[3567]86 | x86_64) | |||||
| try_cpu=i486 | |||||
| ;; | |||||
| hppa*) | |||||
| try_cpu=hppa | |||||
| ;; | |||||
| mips*) | |||||
| # NB: cpu/mips/atomicity.h needs MIPS II or above. | |||||
| # Of course, there is no sane way to test for this, no ABI macro, | |||||
| # and no consistent host_cpu name differentiation. Therefore, only | |||||
| # use it where it is known to be safe, ie it runs linux (see below). | |||||
| try_cpu=generic | |||||
| ;; | |||||
| m680[246]0) | |||||
| try_cpu=m68k | |||||
| ;; | |||||
| powerpc* | rs6000) | |||||
| try_cpu=powerpc | |||||
| ;; | |||||
| s390x) | |||||
| try_cpu=s390 | |||||
| ;; | |||||
| sparc* | ultrasparc) | |||||
| try_cpu=sparc | |||||
| ;; | |||||
| *) | |||||
| if test -d $srcdir/config/cpu/${host_cpu}; then | |||||
| try_cpu=${host_cpu} | |||||
| else | |||||
| try_cpu=generic | |||||
| fi | |||||
| ;; | |||||
| esac | |||||
| # Now look for the file(s) usually tied to a CPU model, and make | |||||
| # default choices for those if they haven't been explicitly set | |||||
| # already. | |||||
| cpu_include_dir="cpu/${try_cpu}" | |||||
| atomicity_include_dir=$cpu_include_dir | |||||
| # Set any OS-dependent bits. | |||||
| # Set the os_include_dir. | |||||
| # If atomic ops and/or numeric limits are OS-specific rather than | |||||
| # CPU-specifc, set those here too. | |||||
| # THIS TABLE IS SORTED. KEEP IT THAT WAY. | |||||
| case "${host_os}" in | |||||
| aix4.[3456789]* | aix[56789]*) | |||||
| # We set os_include_dir to os/aix only on AIX 4.3 and newer, but | |||||
| # os/aix/atomicity.h works on earlier versions of AIX 4.*, so we | |||||
| # explicitly duplicate the directory for 4.[<3]. | |||||
| os_include_dir="os/aix" | |||||
| atomicity_include_dir="os/aix" | |||||
| OS_LDFLAGS="-Wl,-G" | |||||
| ;; | |||||
| aix4.*) | |||||
| os_include_dir="os/generic" | |||||
| atomicity_include_dir="os/aix" | |||||
| ;; | |||||
| aix*) | |||||
| os_include_dir="os/generic" | |||||
| atomicity_include_dir="cpu/generic" | |||||
| ;; | |||||
| gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) | |||||
| os_include_dir="os/gnu-linux" | |||||
| ;; | |||||
| irix*) | |||||
| os_include_dir="os/irix" | |||||
| atomicity_include_dir=$os_include_dir | |||||
| ;; | |||||
| darwin*) | |||||
| os_include_dir="os/macosx" | |||||
| OS_LDFLAGS="-framework CoreAudio" | |||||
| TRY_POSIX_SHM=yes # POSIX shm works better on darwin | |||||
| ;; | |||||
| *) | |||||
| os_include_dir="os/generic" | |||||
| ;; | |||||
| esac | |||||
| # Set any OS-dependent and CPU-dependent bits. | |||||
| # THIS TABLE IS SORTED. KEEP IT THAT WAY. | |||||
| case "${host}" in | |||||
| mips*-*-linux*) | |||||
| atomicity_include_dir="cpu/mips" | |||||
| ;; | |||||
| esac | |||||
| @@ -0,0 +1,76 @@ | |||||
| // Low-level functions for atomic operations: Alpha version -*- C++ -*- | |||||
| // Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| /* @@@ With gas we can play nice .subsection games to get the | |||||
| non-predicted branch pointing forward. But Digital assemblers | |||||
| don't understand those directives. This isn't a terribly | |||||
| important issue, so just ignore it. */ | |||||
| typedef int _Atomic_word; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| register int __result, __tmp; | |||||
| __asm__ __volatile__ ( | |||||
| "\n$Lxadd_%=:\n\t" | |||||
| "ldl_l %0,%3\n\t" | |||||
| "addl %0,%4,%1\n\t" | |||||
| "stl_c %1,%2\n\t" | |||||
| "beq %1,$Lxadd_%=\n\t" | |||||
| "mb" | |||||
| : "=&r"(__result), "=&r"(__tmp), "=m"(*__mem) | |||||
| : "m" (*__mem), "r"(__val)); | |||||
| return __result; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| register _Atomic_word __result; | |||||
| __asm__ __volatile__ ( | |||||
| "\n$Ladd_%=:\n\t" | |||||
| "ldl_l %0,%2\n\t" | |||||
| "addl %0,%3,%0\n\t" | |||||
| "stl_c %0,%1\n\t" | |||||
| "beq %0,$Ladd_%=\n\t" | |||||
| "mb" | |||||
| : "=&r"(__result), "=m"(*__mem) | |||||
| : "m" (*__mem), "r"(__val)); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,35 @@ | |||||
| /* | |||||
| Copyright (C) 2001 Paul Davis | |||||
| Code derived from various headers from the Linux kernel | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __jack_cycles_h__ | |||||
| #define __jack_cycles_h__ | |||||
| /* alpha */ | |||||
| typedef unsigned int cycles_t; | |||||
| static inline cycles_t get_cycles (void) | |||||
| { | |||||
| cycles_t ret; | |||||
| __asm__ __volatile__ ("rpcc %0" : "=r"(ret)); | |||||
| return ret; | |||||
| } | |||||
| #endif /* __jack_cycles_h__ */ | |||||
| @@ -0,0 +1,78 @@ | |||||
| // Low-level functions for atomic operations: CRIS version -*- C++ -*- | |||||
| // Copyright (C) 2001, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| // This entity must not cross a page boundary. | |||||
| typedef int _Atomic_word __attribute__ ((__aligned__ (4))); | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(_Atomic_word* __mem, int __val) | |||||
| { | |||||
| int __tmp; | |||||
| _Atomic_word __result; | |||||
| #if (__CRIS_arch_version >= 10) | |||||
| __asm__ __volatile__ (" clearf \n" | |||||
| "0: \n" | |||||
| " move.d %4,%2 \n" | |||||
| " move.d [%3],%0 \n" | |||||
| " add.d %0,%2 \n" | |||||
| " ax \n" | |||||
| " move.d %2,[%3] \n" | |||||
| " bwf 0b \n" | |||||
| " clearf \n" | |||||
| : "=&r" (__result), "=m" (*__mem), "=&r" (__tmp) | |||||
| : "r" (__mem), "g" (__val), "m" (*__mem)); | |||||
| #else | |||||
| __asm__ __volatile__ (" move $ccr,$r9 \n" | |||||
| " di \n" | |||||
| " move.d %4,%2 \n" | |||||
| " move.d [%3],%0 \n" | |||||
| " add.d %0,%2 \n" | |||||
| " move.d %2,[%3] \n" | |||||
| " move $r9,$ccr \n" | |||||
| : "=&r" (__result), "=m" (*__mem), "=&r" (__tmp) | |||||
| : "r" (__mem), "g" (__val), "m" (*__mem) | |||||
| : "r9"); | |||||
| #endif | |||||
| return __result; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(_Atomic_word* __mem, int __val) | |||||
| { | |||||
| __exchange_and_add(__mem, __val); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,80 @@ | |||||
| // Low-level functions for atomic operations: Generic version -*- C++ -*- | |||||
| // Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| #warning No native atomic operations are provided for this platform. | |||||
| #warning They will be faked using a mutex, degrading performance. | |||||
| #include <bits/gthr.h> | |||||
| #define _GLIBCXX_NEED_GENERIC_MUTEX | |||||
| typedef int _Atomic_word; | |||||
| namespace __gnu_cxx | |||||
| { | |||||
| extern __gthread_mutex_t _Atomic_add_mutex; | |||||
| #ifndef __GTHREAD_MUTEX_INIT | |||||
| extern __gthread_once_t _Atomic_add_mutex_once; | |||||
| extern void __gthread_atomic_add_mutex_once(); | |||||
| #endif | |||||
| } | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| #ifndef __GTHREAD_MUTEX_INIT | |||||
| __gthread_once(&__gnu_cxx::_Atomic_add_mutex_once, | |||||
| __gnu_cxx::__gthread_atomic_add_mutex_once); | |||||
| #endif | |||||
| _Atomic_word __result; | |||||
| __gthread_mutex_lock(&__gnu_cxx::_Atomic_add_mutex); | |||||
| __result = *__mem; | |||||
| *__mem += __val; | |||||
| __gthread_mutex_unlock(&__gnu_cxx::_Atomic_add_mutex); | |||||
| return __result; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| (void) __exchange_and_add(__mem, __val); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -1,6 +1,7 @@ | |||||
| /* | /* | ||||
| Copyright © Grame 2003 | |||||
| Copyright (C) 2001 Paul Davis | |||||
| Code derived from various headers from the Linux kernel | |||||
| This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | the Free Software Foundation; either version 2 of the License, or | ||||
| @@ -14,24 +15,27 @@ | |||||
| You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | ||||
| along with this program; if not, write to the Free Software | along with this program; if not, write to the Free Software | ||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France | |||||
| grame@rd.grame.fr | |||||
| $Id$ | |||||
| */ | */ | ||||
| #ifndef __ipc__ | |||||
| #define __ipc__ | |||||
| #ifndef __jack_cycles_h__ | |||||
| #define __jack_cycles_h__ | |||||
| /* generic solution */ | |||||
| #include <jack/internal.h> | |||||
| #include <jack/engine.h> | |||||
| #include <local.h> | |||||
| #warning You are compiling JACK on a platform for which jack/cycles.h needs work | |||||
| #include <sys/time.h> | |||||
| int jack_client_resume(jack_client_internal_t *client); | |||||
| int jack_client_suspend(jack_client_t * client); | |||||
| typedef long cycles_t; | |||||
| extern cycles_t cacheflush_time; | |||||
| void allocate_mach_serverport(jack_engine_t * engine, jack_client_internal_t *client); | |||||
| int allocate_mach_clientport(jack_client_t * client, int portnum); | |||||
| static inline cycles_t get_cycles(void) | |||||
| { | |||||
| struct timeval tv; | |||||
| gettimeofday (&tv, NULL); | |||||
| typedef int socklen_t; | |||||
| return tv.tv_usec; | |||||
| } | |||||
| #endif | |||||
| #endif /* __jack_cycles_h__ */ | |||||
| @@ -0,0 +1,90 @@ | |||||
| /* Low-level functions for atomic operations. PA-RISC version. -*- C++ -*- | |||||
| Copyright 2002 Free Software Foundation, Inc. | |||||
| This file is part of the GNU C Library. | |||||
| The GNU C Library is free software; you can redistribute it and/or | |||||
| modify it under the terms of the GNU Library General Public License as | |||||
| published by the Free Software Foundation; either version 2 of the | |||||
| License, or (at your option) any later version. | |||||
| The GNU C Library is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| Library General Public License for more details. | |||||
| You should have received a copy of the GNU Library General Public | |||||
| License along with the GNU C Library; see the file COPYING.LIB. If not, | |||||
| write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |||||
| Boston, MA 02111-1307, USA. */ | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| typedef int _Atomic_word; | |||||
| template <int __inst> | |||||
| struct __Atomicity_lock | |||||
| { | |||||
| static volatile int _S_atomicity_lock; | |||||
| }; | |||||
| template <int __inst> | |||||
| volatile int | |||||
| __Atomicity_lock<__inst>::_S_atomicity_lock __attribute__ ((aligned (16))) = 1; | |||||
| /* Because of the lack of weak support when using the hpux | |||||
| som linker, we explicitly instantiate the atomicity lock | |||||
| in src/misc-inst.cc when _GLIBCXX_INST_ATOMICITY_LOCK | |||||
| is defined. */ | |||||
| #ifndef _GLIBCXX_INST_ATOMICITY_LOCK | |||||
| template volatile int __Atomicity_lock<0>::_S_atomicity_lock; | |||||
| #endif | |||||
| static inline int | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word result; | |||||
| int tmp; | |||||
| volatile int& lock = __Atomicity_lock<0>::_S_atomicity_lock; | |||||
| __asm__ __volatile__ ("ldcw 0(%1),%0\n\t" | |||||
| "cmpib,<>,n 0,%0,.+20\n\t" | |||||
| "ldw 0(%1),%0\n\t" | |||||
| "cmpib,= 0,%0,.-4\n\t" | |||||
| "nop\n\t" | |||||
| "b,n .-20" | |||||
| : "=&r" (tmp) | |||||
| : "r" (&lock)); | |||||
| result = *__mem; | |||||
| *__mem = result + __val; | |||||
| /* Reset lock with PA 2.0 "ordered" store. */ | |||||
| __asm__ __volatile__ ("stw,ma %1,0(%0)" | |||||
| : : "r" (&lock), "r" (tmp) : "memory"); | |||||
| return result; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(_Atomic_word* __mem, int __val) | |||||
| { | |||||
| int tmp; | |||||
| volatile int& lock = __Atomicity_lock<0>::_S_atomicity_lock; | |||||
| __asm__ __volatile__ ("ldcw 0(%1),%0\n\t" | |||||
| "cmpib,<>,n 0,%0,.+20\n\t" | |||||
| "ldw 0(%1),%0\n\t" | |||||
| "cmpib,= 0,%0,.-4\n\t" | |||||
| "nop\n\t" | |||||
| "b,n .-20" | |||||
| : "=&r" (tmp) | |||||
| : "r" (&lock)); | |||||
| *__mem += __val; | |||||
| /* Reset lock with PA 2.0 "ordered" store. */ | |||||
| __asm__ __volatile__ ("stw,ma %1,0(%0)" | |||||
| : : "r" (&lock), "r" (tmp) : "memory"); | |||||
| } | |||||
| #endif | |||||
| @@ -0,0 +1,76 @@ | |||||
| // Low-level functions for atomic operations: x86, x >= 3 version -*- C++ -*- | |||||
| // Copyright (C) 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| typedef int _Atomic_word; | |||||
| template<int __inst> | |||||
| struct __Atomicity_lock | |||||
| { | |||||
| static volatile _Atomic_word _S_atomicity_lock; | |||||
| }; | |||||
| template<int __inst> | |||||
| volatile _Atomic_word __Atomicity_lock<__inst>::_S_atomicity_lock = 0; | |||||
| template volatile _Atomic_word __Atomicity_lock<0>::_S_atomicity_lock; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| register _Atomic_word __result, __tmp = 1; | |||||
| /* obtain the atomic exchange/add spin lock */ | |||||
| do { | |||||
| __asm__ __volatile__ ("xchg{l} {%0,%1|%1,%0}" | |||||
| : "=m" (__Atomicity_lock<0>::_S_atomicity_lock), | |||||
| "+r" (__tmp) | |||||
| : "m" (__Atomicity_lock<0>::_S_atomicity_lock)); | |||||
| } while (__tmp); | |||||
| __result = *__mem; | |||||
| *__mem += __val; | |||||
| /* release spin lock */ | |||||
| __Atomicity_lock<0>::_S_atomicity_lock = 0; | |||||
| return __result; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| __exchange_and_add(__mem, __val); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,24 @@ | |||||
| /* | |||||
| Copyright (C) 2001 Paul Davis | |||||
| Code derived from various headers from the Linux kernel | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| $Id$ | |||||
| */ | |||||
| /* the i486 version of this header is compatible */ | |||||
| #include <config/cpu/i486/cycles.h> | |||||
| @@ -0,0 +1,54 @@ | |||||
| // Low-level functions for atomic operations: x86, x >= 4 version -*- C++ -*- | |||||
| // Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| typedef int _Atomic_word; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| register _Atomic_word __result; | |||||
| __asm__ __volatile__ ("lock; xaddl %0,%1" | |||||
| : "=r" (__result), "=m" (*__mem) | |||||
| : "0" (__val), "m" (*__mem)); | |||||
| return __result; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| __asm__ __volatile__ ("lock; addl %1,%0" | |||||
| : "=m" (*__mem) : "ir" (__val), "m" (*__mem)); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -22,8 +22,6 @@ | |||||
| #ifndef __jack_cycles_h__ | #ifndef __jack_cycles_h__ | ||||
| #define __jack_cycles_h__ | #define __jack_cycles_h__ | ||||
| #if defined(__i386__) || defined(__x86_64__) | |||||
| /* | /* | ||||
| * Standard way to access the cycle counter on i586+ CPUs. | * Standard way to access the cycle counter on i586+ CPUs. | ||||
| * Currently only used on SMP. | * Currently only used on SMP. | ||||
| @@ -53,76 +51,4 @@ static inline cycles_t get_cycles (void) | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| #elif defined(__powerpc__) | |||||
| #define CPU_FTR_601 0x00000100 | |||||
| typedef unsigned long cycles_t; | |||||
| /* | |||||
| * For the "cycle" counter we use the timebase lower half. | |||||
| * Currently only used on SMP. | |||||
| */ | |||||
| extern cycles_t cacheflush_time; | |||||
| static inline cycles_t get_cycles(void) | |||||
| { | |||||
| cycles_t ret = 0; | |||||
| __asm__ __volatile__( | |||||
| "98: mftb %0\n" | |||||
| "99:\n" | |||||
| ".section __ftr_fixup,\"a\"\n" | |||||
| " .long %1\n" | |||||
| " .long 0\n" | |||||
| " .long 98b\n" | |||||
| " .long 99b\n" | |||||
| ".previous" | |||||
| : "=r" (ret) : "i" (CPU_FTR_601)); | |||||
| return ret; | |||||
| } | |||||
| #elif defined(__ia64__) | |||||
| /* ia64 */ | |||||
| typedef unsigned long cycles_t; | |||||
| static inline cycles_t | |||||
| get_cycles (void) | |||||
| { | |||||
| cycles_t ret; | |||||
| __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret)); | |||||
| return ret; | |||||
| } | |||||
| #elif defined(__alpha__) | |||||
| /* alpha */ | |||||
| typedef unsigned int cycles_t; | |||||
| static inline cycles_t get_cycles (void) | |||||
| { | |||||
| cycles_t ret; | |||||
| __asm__ __volatile__ ("rpcc %0" : "=r"(ret)); | |||||
| return ret; | |||||
| } | |||||
| #else | |||||
| /* generic solution */ | |||||
| #warning You are compiling JACK on a platform for which jack/cycles.h needs work | |||||
| #include <sys/time.h> | |||||
| typedef long cycles_t; | |||||
| extern cycles_t cacheflush_time; | |||||
| static inline cycles_t get_cycles(void) | |||||
| { | |||||
| struct timeval tv; | |||||
| gettimeofday (&tv, NULL); | |||||
| return tv.tv_usec; | |||||
| } | |||||
| #endif | |||||
| #endif /* __jack_cycles_h__ */ | #endif /* __jack_cycles_h__ */ | ||||
| @@ -0,0 +1,51 @@ | |||||
| // Low-level functions for atomic operations: IA64 version -*- C++ -*- | |||||
| // Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| #include <sysdeps/ia64intrin.h> | |||||
| typedef int _Atomic_word; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| return __sync_fetch_and_add(__mem, __val); | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| __sync_fetch_and_add(__mem, __val); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,36 @@ | |||||
| /* | |||||
| Copyright (C) 2001 Paul Davis | |||||
| Code derived from various headers from the Linux kernel | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __jack_cycles_h__ | |||||
| #define __jack_cycles_h__ | |||||
| /* ia64 */ | |||||
| typedef unsigned long cycles_t; | |||||
| static inline cycles_t | |||||
| get_cycles (void) | |||||
| { | |||||
| cycles_t ret; | |||||
| __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret)); | |||||
| return ret; | |||||
| } | |||||
| #endif /* __jack_cycles_h__ */ | |||||
| @@ -0,0 +1,130 @@ | |||||
| #ifndef _IA64INTRIN_H_INCLUDED | |||||
| #define _IA64INTRIN_H_INCLUDED | |||||
| /* Actually, everything is a compiler builtin, but just so | |||||
| there's no confusion... */ | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #endif | |||||
| extern void __sync_synchronize (void); | |||||
| extern int __sync_val_compare_and_swap_si (int *, int, int); | |||||
| extern long __sync_val_compare_and_swap_di (long *, long, long); | |||||
| #define __sync_val_compare_and_swap(PTR, OLD, NEW) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) \ | |||||
| __sync_val_compare_and_swap_si((int *)(PTR),(int)(OLD),(int)(NEW)) \ | |||||
| : (__typeof__(*(PTR))) \ | |||||
| __sync_val_compare_and_swap_di((long *)(PTR),(long)(OLD),(long)(NEW))) | |||||
| extern int __sync_bool_compare_and_swap_si (int *, int, int); | |||||
| extern int __sync_bool_compare_and_swap_di (long *, long, long); | |||||
| #define __sync_bool_compare_and_swap(PTR, OLD, NEW) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? __sync_bool_compare_and_swap_si((int *)(PTR),(int)(OLD),(int)(NEW)) \ | |||||
| : __sync_bool_compare_and_swap_di((long *)(PTR),(long)(OLD),(long)(NEW))) | |||||
| extern void __sync_lock_release_si (int *); | |||||
| extern void __sync_lock_release_di (long *); | |||||
| #define __sync_lock_release(PTR) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? __sync_lock_release_si((int *)(PTR)) \ | |||||
| : __sync_lock_release_di((long *)(PTR))) | |||||
| extern int __sync_lock_test_and_set_si (int *, int); | |||||
| extern long __sync_lock_test_and_set_di (long *, long); | |||||
| #define __sync_lock_test_and_set(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_lock_test_and_set_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_lock_test_and_set_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_fetch_and_add_si (int *, int); | |||||
| extern long __sync_fetch_and_add_di (long *, long); | |||||
| #define __sync_fetch_and_add(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_fetch_and_add_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_fetch_and_add_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_fetch_and_sub_si (int *, int); | |||||
| extern long __sync_fetch_and_sub_di (long *, long); | |||||
| #define __sync_fetch_and_sub(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_fetch_and_sub_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_fetch_and_sub_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_fetch_and_and_si (int *, int); | |||||
| extern long __sync_fetch_and_and_di (long *, long); | |||||
| #define __sync_fetch_and_and(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_fetch_and_and_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_fetch_and_and_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_fetch_and_or_si (int *, int); | |||||
| extern long __sync_fetch_and_or_di (long *, long); | |||||
| #define __sync_fetch_and_or(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_fetch_and_or_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_fetch_and_or_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_fetch_and_xor_si (int *, int); | |||||
| extern long __sync_fetch_and_xor_di (long *, long); | |||||
| #define __sync_fetch_and_xor(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_fetch_and_xor_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_fetch_and_xor_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_fetch_and_nand_si (int *, int); | |||||
| extern long __sync_fetch_and_nand_di (long *, long); | |||||
| #define __sync_fetch_and_nand(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_fetch_and_nand_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_fetch_and_nand_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_add_and_fetch_si (int *, int); | |||||
| extern long __sync_add_and_fetch_di (long *, long); | |||||
| #define __sync_add_and_fetch(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_add_and_fetch_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_add_and_fetch_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_sub_and_fetch_si (int *, int); | |||||
| extern long __sync_sub_and_fetch_di (long *, long); | |||||
| #define __sync_sub_and_fetch(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_sub_and_fetch_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_sub_and_fetch_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_and_and_fetch_si (int *, int); | |||||
| extern long __sync_and_and_fetch_di (long *, long); | |||||
| #define __sync_and_and_fetch(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_and_and_fetch_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_and_and_fetch_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_or_and_fetch_si (int *, int); | |||||
| extern long __sync_or_and_fetch_di (long *, long); | |||||
| #define __sync_or_and_fetch(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_or_and_fetch_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_or_and_fetch_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_xor_and_fetch_si (int *, int); | |||||
| extern long __sync_xor_and_fetch_di (long *, long); | |||||
| #define __sync_xor_and_fetch(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_xor_and_fetch_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_xor_and_fetch_di((long *)(PTR),(long)(VAL))) | |||||
| extern int __sync_nand_and_fetch_si (int *, int); | |||||
| extern long __sync_nand_and_fetch_di (long *, long); | |||||
| #define __sync_nand_and_fetch(PTR,VAL) \ | |||||
| ((sizeof (*(PTR)) == sizeof(int)) \ | |||||
| ? (__typeof__(*(PTR))) __sync_nand_and_fetch_si((int *)(PTR),(int)(VAL)) \ | |||||
| : (__typeof__(*(PTR))) __sync_nand_and_fetch_di((long *)(PTR),(long)(VAL))) | |||||
| #ifdef __cplusplus | |||||
| } | |||||
| #endif | |||||
| #endif | |||||
| @@ -0,0 +1,139 @@ | |||||
| // Low-level functions for atomic operations: m68k version -*- C++ -*- | |||||
| // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| typedef int _Atomic_word; | |||||
| #if ( defined(__mc68020__) || defined(__mc68030__) \ | |||||
| || defined(__mc68040__) || defined(__mc68060__) ) \ | |||||
| && !defined(__mcpu32__) | |||||
| // These variants support compare-and-swap. | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| register _Atomic_word __result = *__mem; | |||||
| register _Atomic_word __temp; | |||||
| __asm__ __volatile__ ("1: move%.l %0,%1\n\t" | |||||
| "add%.l %3,%1\n\t" | |||||
| "cas%.l %0,%1,%2\n\t" | |||||
| "jne 1b" | |||||
| : "=d" (__result), "=&d" (__temp), "=m" (*__mem) | |||||
| : "d" (__val), "0" (__result), "m" (*__mem)); | |||||
| return __result; | |||||
| } | |||||
| #elif defined(__rtems__) | |||||
| /* | |||||
| * TAS/JBNE is unsafe on systems with strict priority-based scheduling. | |||||
| * Disable interrupts, which we can do only from supervisor mode. | |||||
| */ | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __result; | |||||
| short __level, __tmpsr; | |||||
| __asm__ __volatile__ ("move%.w %%sr,%0\n\tor%.l %0,%1\n\tmove%.w %1,%%sr" | |||||
| : "=d"(__level), "=d"(__tmpsr) : "1"(0x700)); | |||||
| __result = *__mem; | |||||
| *__mem = __result + __val; | |||||
| __asm__ __volatile__ ("move%.w %0,%%sr" : : "d"(__level)); | |||||
| return __result; | |||||
| } | |||||
| #else | |||||
| template<int __inst> | |||||
| struct __Atomicity_lock | |||||
| { | |||||
| static volatile unsigned char _S_atomicity_lock; | |||||
| }; | |||||
| template<int __inst> | |||||
| volatile unsigned char __Atomicity_lock<__inst>::_S_atomicity_lock = 0; | |||||
| template volatile unsigned char __Atomicity_lock<0>::_S_atomicity_lock; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __result; | |||||
| // bset with no immediate addressing (not SMP-safe) | |||||
| #if defined(__mcf5200__) || defined(__mcf5300__) | |||||
| __asm__ __volatile__("1: bset.b #7,%0@\n\tjbne 1b" | |||||
| : /* no outputs */ | |||||
| : "a"(&__Atomicity_lock<0>::_S_atomicity_lock) | |||||
| : "cc", "memory"); | |||||
| // CPU32 and MCF5400 support test-and-set (SMP-safe). | |||||
| #elif defined(__mcpu32__) || defined(__mcf5400__) | |||||
| __asm__ __volatile__("1: tas %0\n\tjbne 1b" | |||||
| : "+m"(__Atomicity_lock<0>::_S_atomicity_lock) | |||||
| : /* none */ | |||||
| : "cc"); | |||||
| // Use bset with immediate addressing for 68000/68010 (not SMP-safe) | |||||
| // NOTE: TAS is available on the 68000, but unsupported by some Amiga | |||||
| // memory controllers. | |||||
| #else | |||||
| __asm__ __volatile__("1: bset.b #7,%0\n\tjbne 1b" | |||||
| : "+m"(__Atomicity_lock<0>::_S_atomicity_lock) | |||||
| : /* none */ | |||||
| : "cc"); | |||||
| #endif | |||||
| __result = *__mem; | |||||
| *__mem = __result + __val; | |||||
| __Atomicity_lock<0>::_S_atomicity_lock = 0; | |||||
| return __result; | |||||
| } | |||||
| #endif /* TAS / BSET */ | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| // Careful: using add.l with a memory destination is not | |||||
| // architecturally guaranteed to be atomic. | |||||
| (void) __exchange_and_add(__mem, __val); | |||||
| } | |||||
| #endif /* !_GLIBCXX_ATOMICITY_H */ | |||||
| @@ -0,0 +1,83 @@ | |||||
| // Low-level functions for atomic operations. | |||||
| // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| typedef int _Atomic_word; | |||||
| static inline int | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| int __result, __tmp; | |||||
| __asm__ __volatile__ | |||||
| ("/* Inline exchange & add */\n\t" | |||||
| "1:\n\t" | |||||
| ".set push\n\t" | |||||
| #if _MIPS_SIM == _ABIO32 | |||||
| ".set mips2\n\t" | |||||
| #endif | |||||
| "ll %0,%3\n\t" | |||||
| "addu %1,%4,%0\n\t" | |||||
| "sc %1,%2\n\t" | |||||
| ".set pop\n\t" | |||||
| "beqz %1,1b\n\t" | |||||
| "/* End exchange & add */" | |||||
| : "=&r"(__result), "=&r"(__tmp), "=m"(*__mem) | |||||
| : "m" (*__mem), "r"(__val)); | |||||
| return __result; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| int __result; | |||||
| __asm__ __volatile__ | |||||
| ("/* Inline atomic add */\n\t" | |||||
| "1:\n\t" | |||||
| ".set push\n\t" | |||||
| #if _MIPS_SIM == _ABIO32 | |||||
| ".set mips2\n\t" | |||||
| #endif | |||||
| "ll %0,%2\n\t" | |||||
| "addu %0,%3,%0\n\t" | |||||
| "sc %0,%1\n\t" | |||||
| ".set pop\n\t" | |||||
| "beqz %0,1b\n\t" | |||||
| "/* End atomic add */" | |||||
| : "=&r"(__result), "=m"(*__mem) | |||||
| : "m" (*__mem), "r"(__val)); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,78 @@ | |||||
| // Low-level functions for atomic operations: PowerPC version -*- C++ -*- | |||||
| // Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| #ifdef __PPC405__ | |||||
| #define _STWCX "sync \n\tstwcx. " | |||||
| #else | |||||
| #define _STWCX "stwcx. " | |||||
| #endif | |||||
| typedef int _Atomic_word; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __tmp, __res; | |||||
| __asm__ __volatile__ ( | |||||
| "/* Inline exchange & add */\n" | |||||
| "0:\t" | |||||
| "lwarx %0,0,%3 \n\t" | |||||
| "add%I4 %1,%0,%4 \n\t" | |||||
| _STWCX " %1,0,%3 \n\t" | |||||
| "bne- 0b \n\t" | |||||
| "/* End exchange & add */" | |||||
| : "=&b"(__res), "=&r"(__tmp), "=m" (*__mem) | |||||
| : "r" (__mem), "Ir"(__val), "m" (*__mem) | |||||
| : "cr0"); | |||||
| return __res; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __tmp; | |||||
| __asm__ __volatile__ ( | |||||
| "/* Inline atomic add */\n" | |||||
| "0:\t" | |||||
| "lwarx %0,0,%2 \n\t" | |||||
| "add%I3 %0,%0,%3 \n\t" | |||||
| _STWCX " %0,0,%2 \n\t" | |||||
| "bne- 0b \n\t" | |||||
| "/* End atomic add */" | |||||
| : "=&b"(__tmp), "=m" (*__mem) | |||||
| : "r" (__mem), "Ir"(__val), "m" (*__mem) | |||||
| : "cr0"); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,55 @@ | |||||
| /* | |||||
| Copyright (C) 2001 Paul Davis | |||||
| Code derived from various headers from the Linux kernel | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __jack_cycles_h__ | |||||
| #define __jack_cycles_h__ | |||||
| /* PowerPC */ | |||||
| #define CPU_FTR_601 0x00000100 | |||||
| typedef unsigned long cycles_t; | |||||
| /* | |||||
| * For the "cycle" counter we use the timebase lower half. | |||||
| * Currently only used on SMP. | |||||
| */ | |||||
| extern cycles_t cacheflush_time; | |||||
| static inline cycles_t get_cycles(void) | |||||
| { | |||||
| cycles_t ret = 0; | |||||
| __asm__ __volatile__( | |||||
| "98: mftb %0\n" | |||||
| "99:\n" | |||||
| ".section __ftr_fixup,\"a\"\n" | |||||
| " .long %1\n" | |||||
| " .long 0\n" | |||||
| " .long 98b\n" | |||||
| " .long 99b\n" | |||||
| ".previous" | |||||
| : "=r" (ret) : "i" (CPU_FTR_601)); | |||||
| return ret; | |||||
| } | |||||
| #endif /* __jack_cycles_h__ */ | |||||
| @@ -0,0 +1,60 @@ | |||||
| // Low-level functions for atomic operations: S/390 version -*- C++ -*- | |||||
| // Copyright (C) 2001, 2003 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| typedef int _Atomic_word; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| register _Atomic_word __old_val, __new_val; | |||||
| __asm__ __volatile__ (" l %0,0(%3)\n" | |||||
| "0: lr %1,%0\n" | |||||
| " ar %1,%4\n" | |||||
| " cs %0,%1,0(%3)\n" | |||||
| " jl 0b" | |||||
| : "=&d" (__old_val), "=&d" (__new_val), "=m" (*__mem) | |||||
| : "a" (__mem), "d" (__val), "m" (*__mem) : "cc"); | |||||
| return __old_val; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| __exchange_and_add(__mem, __val); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,131 @@ | |||||
| // Low-level functions for atomic operations: Sparc version -*- C++ -*- | |||||
| // Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _GLIBCXX_ATOMICITY_H | |||||
| #define _GLIBCXX_ATOMICITY_H 1 | |||||
| #ifdef __arch64__ | |||||
| typedef long _Atomic_word; | |||||
| static inline _Atomic_word | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __tmp1, __tmp2; | |||||
| _Atomic_word __val_extended = __val; | |||||
| __asm__ __volatile__("1: ldx [%3], %0\n\t" | |||||
| " add %0, %4, %1\n\t" | |||||
| " casx [%3], %0, %1\n\t" | |||||
| " sub %0, %1, %0\n\t" | |||||
| " brnz,pn %0, 1b\n\t" | |||||
| " nop" | |||||
| : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__mem) | |||||
| : "r" (__mem), "r" (__val_extended), "m" (*__mem)); | |||||
| return __tmp2; | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __tmp1, __tmp2; | |||||
| _Atomic_word __val_extended = __val; | |||||
| __asm__ __volatile__("1: ldx [%3], %0\n\t" | |||||
| " add %0, %4, %1\n\t" | |||||
| " casx [%3], %0, %1\n\t" | |||||
| " sub %0, %1, %0\n\t" | |||||
| " brnz,pn %0, 1b\n\t" | |||||
| " nop" | |||||
| : "=&r" (__tmp1), "=&r" (__tmp2), "=m" (*__mem) | |||||
| : "r" (__mem), "r" (__val_extended), "m" (*__mem)); | |||||
| } | |||||
| #else /* __arch32__ */ | |||||
| typedef int _Atomic_word; | |||||
| template<int __inst> | |||||
| struct __Atomicity_lock | |||||
| { | |||||
| static unsigned char _S_atomicity_lock; | |||||
| }; | |||||
| template<int __inst> | |||||
| unsigned char __Atomicity_lock<__inst>::_S_atomicity_lock = 0; | |||||
| template unsigned char __Atomicity_lock<0>::_S_atomicity_lock; | |||||
| static int | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __result, __tmp; | |||||
| __asm__ __volatile__("1: ldstub [%1], %0\n\t" | |||||
| " cmp %0, 0\n\t" | |||||
| " bne 1b\n\t" | |||||
| " nop" | |||||
| : "=&r" (__tmp) | |||||
| : "r" (&__Atomicity_lock<0>::_S_atomicity_lock) | |||||
| : "memory"); | |||||
| __result = *__mem; | |||||
| *__mem += __val; | |||||
| __asm__ __volatile__("stb %%g0, [%0]" | |||||
| : /* no outputs */ | |||||
| : "r" (&__Atomicity_lock<0>::_S_atomicity_lock) | |||||
| : "memory"); | |||||
| return __result; | |||||
| } | |||||
| static void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add(volatile _Atomic_word* __mem, int __val) | |||||
| { | |||||
| _Atomic_word __tmp; | |||||
| __asm__ __volatile__("1: ldstub [%1], %0\n\t" | |||||
| " cmp %0, 0\n\t" | |||||
| " bne 1b\n\t" | |||||
| " nop" | |||||
| : "=&r" (__tmp) | |||||
| : "r" (&__Atomicity_lock<0>::_S_atomicity_lock) | |||||
| : "memory"); | |||||
| *__mem += __val; | |||||
| __asm__ __volatile__("stb %%g0, [%0]" | |||||
| : /* no outputs */ | |||||
| : "r" (&__Atomicity_lock<0>::_S_atomicity_lock) | |||||
| : "memory"); | |||||
| } | |||||
| #endif /* __arch32__ */ | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,59 @@ | |||||
| // Low-level functions for atomic operations: AIX version -*- C++ -*- | |||||
| // Copyright (C) 2000, 2001 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _BITS_ATOMICITY_H | |||||
| #define _BITS_ATOMICITY_H 1 | |||||
| /* We cannot use the cpu/powerpc/bits/atomicity.h inline assembly | |||||
| definitions for these operations since they depend on operations | |||||
| that are not available on the original POWER architecture. AIX | |||||
| still runs on the POWER architecture, so it would be incorrect to | |||||
| assume the existence of these instructions. */ | |||||
| /* This should match the type pointed to by atomic_p in | |||||
| <sys/atomic_op.h>. */ | |||||
| typedef int _Atomic_word; | |||||
| #include <sys/atomic_op.h> | |||||
| static inline int | |||||
| __attribute__ ((__unused__)) | |||||
| __exchange_and_add (atomic_p __mem, int __val) | |||||
| { | |||||
| return fetch_and_add (__mem, __val); | |||||
| } | |||||
| static inline void | |||||
| __attribute__ ((__unused__)) | |||||
| __atomic_add (atomic_p __mem, int __val) | |||||
| { | |||||
| (void) fetch_and_add (__mem, __val); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,28 @@ | |||||
| /* | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| Generic version, overridden by OS-specific defines when needed. | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef _jack_sys_ipc | |||||
| #define _jack_sys_ipc 1 | |||||
| #include <sys/ipc.h> | |||||
| #endif /* _jack_sys_ipc */ | |||||
| @@ -0,0 +1,30 @@ | |||||
| /* | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| Generic version, overridden by OS-specific defines when available. | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef _jack_os_defines | |||||
| #define _jack_os_defines 1 | |||||
| #define JACK_THREAD_STACK_TOUCH 1048576 | |||||
| #define PORTAUDIO_H <portaudio.h> | |||||
| #define GETOPT_H <getopt.h> | |||||
| #endif /* _jack_os_defines */ | |||||
| @@ -0,0 +1,28 @@ | |||||
| /* | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| Generic version, overridden by OS-specific defines when needed. | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef _jack_sys_poll | |||||
| #define _jack_sys_poll 1 | |||||
| #include <sys/poll.h> | |||||
| #endif /* _jack_sys_poll */ | |||||
| @@ -0,0 +1,42 @@ | |||||
| /* | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| Generic version, overridden by OS-specific defines when available. | |||||
| In this case, that is necessary, because the generic version | |||||
| hasn't been written, yet. | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __jack_time_h__ | |||||
| #define __jack_time_h__ | |||||
| #include <jack/internal.h> | |||||
| #error No generic <sysdeps/time.h> available. | |||||
| /* This is a kludge. We need one global instantiation of this | |||||
| * variable in each address space. So, libjack/client.c declares the | |||||
| * actual storage. Other source files will see it as an extern. */ | |||||
| #define JACK_TIME_GLOBAL_DECL jack_time_t __jack_cpu_mhz | |||||
| extern JACK_TIME_GLOBAL_DECL; | |||||
| /* Need implementations. jack_init_time() should only be called ONCE | |||||
| * per process. */ | |||||
| static inline jack_time_t jack_get_microseconds (void); | |||||
| static inline void jack_init_time (void); | |||||
| #endif /* __jack_time_h__ */ | |||||
| @@ -0,0 +1,97 @@ | |||||
| /* | |||||
| Copyright (C) 2001-2003 Paul Davis | |||||
| This is the GNU/Linux version. | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __jack_time_h__ | |||||
| #define __jack_time_h__ | |||||
| #include <stdio.h> | |||||
| #include <jack/internal.h> | |||||
| #include <sysdeps/cycles.h> | |||||
| /* This is a kludge. We need one global instantiation of this | |||||
| * variable in each address space. So, libjack/client.c declares the | |||||
| * actual storage. Other source files will see it as an extern. */ | |||||
| #define JACK_TIME_GLOBAL_DECL jack_time_t __jack_cpu_mhz | |||||
| extern JACK_TIME_GLOBAL_DECL; | |||||
| static inline jack_time_t | |||||
| jack_get_microseconds (void) { | |||||
| return get_cycles() / __jack_cpu_mhz; | |||||
| } | |||||
| /* | |||||
| * This is another kludge. It looks CPU-dependent, but actually it | |||||
| * reflects the lack of standards for the Linux kernel formatting of | |||||
| * /proc/cpuinfo. | |||||
| */ | |||||
| static inline jack_time_t | |||||
| jack_get_mhz (void) | |||||
| { | |||||
| FILE *f = fopen("/proc/cpuinfo", "r"); | |||||
| if (f == 0) | |||||
| { | |||||
| perror("can't open /proc/cpuinfo\n"); | |||||
| exit(1); | |||||
| } | |||||
| for ( ; ; ) | |||||
| { | |||||
| jack_time_t mhz; | |||||
| int ret; | |||||
| char buf[1000]; | |||||
| if (fgets(buf, sizeof(buf), f) == NULL) { | |||||
| jack_error ("FATAL: cannot locate cpu MHz in " | |||||
| "/proc/cpuinfo\n"); | |||||
| exit(1); | |||||
| } | |||||
| #if defined(__powerpc__) | |||||
| ret = sscanf(buf, "clock\t: %" SCNu64 "MHz", &mhz); | |||||
| #elif defined( __i386__ ) || defined (__hppa__) || defined (__ia64__) || \ | |||||
| defined(__x86_64__) | |||||
| ret = sscanf(buf, "cpu MHz : %" SCNu64, &mhz); | |||||
| #elif defined( __sparc__ ) | |||||
| ret = sscanf(buf, "Cpu0Bogo : %" SCNu64, &mhz); | |||||
| #elif defined( __mc68000__ ) | |||||
| ret = sscanf(buf, "Clocking: %" SCNu64, &mhz); | |||||
| #elif defined( __s390__ ) | |||||
| ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz); | |||||
| #else /* MIPS, ARM, alpha */ | |||||
| ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz); | |||||
| #endif | |||||
| if (ret == 1) | |||||
| { | |||||
| fclose(f); | |||||
| return (jack_time_t)mhz; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* This should only be called ONCE per process. */ | |||||
| static inline void | |||||
| jack_init_time () | |||||
| { | |||||
| __jack_cpu_mhz = jack_get_mhz (); | |||||
| } | |||||
| #endif /* __jack_time_h__ */ | |||||
| @@ -0,0 +1,50 @@ | |||||
| // Low-level functions for atomic operations: IRIX version -*- C++ -*- | |||||
| // Copyright (C) 2000, 2001 Free Software Foundation, Inc. | |||||
| // | |||||
| // This file is part of the GNU ISO C++ Library. This library is free | |||||
| // software; you can redistribute it and/or modify it under the | |||||
| // terms of the GNU General Public License as published by the | |||||
| // Free Software Foundation; either version 2, or (at your option) | |||||
| // any later version. | |||||
| // This library is distributed in the hope that it will be useful, | |||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| // GNU General Public License for more details. | |||||
| // You should have received a copy of the GNU General Public License along | |||||
| // with this library; see the file COPYING. If not, write to the Free | |||||
| // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |||||
| // USA. | |||||
| // As a special exception, you may use this file as part of a free software | |||||
| // library without restriction. Specifically, if other files instantiate | |||||
| // templates or use macros or inline functions from this file, or you compile | |||||
| // this file and link it with other files to produce an executable, this | |||||
| // file does not by itself cause the resulting executable to be covered by | |||||
| // the GNU General Public License. This exception does not however | |||||
| // invalidate any other reasons why the executable file might be covered by | |||||
| // the GNU General Public License. | |||||
| #ifndef _BITS_ATOMICITY_H | |||||
| #define _BITS_ATOMICITY_H 1 | |||||
| #include <mutex.h> | |||||
| typedef long _Atomic_word; | |||||
| static inline _Atomic_word | |||||
| __exchange_and_add (_Atomic_word* __mem, int __val) | |||||
| { | |||||
| return (_Atomic_word) test_then_add ((unsigned long*) __mem, __val); | |||||
| } | |||||
| static inline void | |||||
| __atomic_add (_Atomic_word* __mem, int __val) | |||||
| { | |||||
| __exchange_and_add (__mem, __val); | |||||
| } | |||||
| #endif /* atomicity.h */ | |||||
| @@ -0,0 +1,183 @@ | |||||
| Darwin/MacOSX port for Jack : architecture changes in the implementation | |||||
| ======================================================================== | |||||
| Build Dependencies | |||||
| ================== | |||||
| Apple Developer Tools | |||||
| gcc 2.95.x or 3.x, the standard OSX 10.3 gcc-3.3 compiler works fine | |||||
| MacOSX10.3 SDK package | |||||
| GNU tools | |||||
| autoconf >= 2.57 | |||||
| automake >= 1.6.3 | |||||
| optional tools | |||||
| libtool >= 1.5 (to build from CVS) | |||||
| pkg-config >= 0.15.0 (to build from CVS) | |||||
| doxygen (to build documentation) | |||||
| libsndfile >= 1.0.0 (for some example-clients) | |||||
| GNU readline (for some example-clients) | |||||
| All non-Apple tools are available from `fink' or `darwinports'. | |||||
| Since fink is not well-integrated with OS X, you must define a bunch | |||||
| of environment variables... | |||||
| export ACLOCAL_FLAGS="-I /sw/share/aclocal" | |||||
| export CFLAGS="-I/sw/include" | |||||
| export CPPFLAGS=$CFLAGS | |||||
| export LDFLAGS="-L/sw/lib" | |||||
| export PKG_CONFIG_PATH="/sw/lib/pkgconfig:/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/opt/local/lib/pkgconfig" | |||||
| Shared memory | |||||
| ============= | |||||
| The system V shared memory is not very reliable on Darwin/MacOSX, so | |||||
| POSIX shared memory API is the preferred default. To override, use... | |||||
| ./configure --disable-posix-shm | |||||
| Jack server audio cycle | |||||
| ======================== | |||||
| On Linux, the jack server audio cycle (jack_run_cycle function) is | |||||
| called in a real-time SCHED_FIFO thread. On Darwin/MacOSX, the | |||||
| jack_run_cycle is directly called inside the CoreAudio audio callback. | |||||
| External client activation | |||||
| =========================== | |||||
| Jack Linux implementation use system fifo/pipe to trigger the clients | |||||
| real-time callback from the server : the first client of an external | |||||
| subgraph is triggered, does it's job and wakes up the next one in the | |||||
| list, and so on until the last client that wakes up the Jack | |||||
| server. This avoid uneeded context switches between the server and | |||||
| clients and thus is more efficient. | |||||
| This Linux implementation works also on Darwin/MacOSX but is not very | |||||
| efficient : audio gliches occur quite frequently. | |||||
| A more efficient system for external client activation has been | |||||
| developed. It use low-level mach messages system to implement fast IPC | |||||
| between the Jack server and the running clients. The Darwin/MacOSX has | |||||
| a very efficient Remote Procedure Call (RPC) implementation that can | |||||
| be used: the Jack server activate each external client in turn in a | |||||
| loop. | |||||
| On the client side, each client uses an additionnal thread only used | |||||
| for the real-time process callback, that will be triggered by the Jack | |||||
| server using this fast RPC mechanism. | |||||
| Real-time threads | |||||
| ================== | |||||
| The Darwin/MacOSX system use a special class of scheduling for | |||||
| real-time threads. | |||||
| Since the server audio cycle is called directly from the CoreAudio | |||||
| callback, there is nothing special to do on the server side. On the | |||||
| client side, the thread used to call the "process" callback from the | |||||
| server is made real-time, using the mach thread API. | |||||
| Compilation and installation | |||||
| ============================= | |||||
| - In the jack/jack folder, you'll have to produce the version.h | |||||
| manually from the version.h.in file ): Edit the version.h.in, replace | |||||
| the JACK_PROTOCOL_VERSION value with the one found in configure.in and | |||||
| save as a new version.h file. You should get something like "#define | |||||
| jack_protocol_version 6" in the file. | |||||
| Several packages need to be installed before compiling Jack : | |||||
| - Fink dlcompat (fink.sourceforge.net) : this package define the | |||||
| dlopen, dlsym... API used in Jack to load drivers and internal | |||||
| clients. The package has to be installed before compiling Jack. | |||||
| - fakepoll is a implementation of the poll function using select. The | |||||
| Fink version of poll does not work correctly, thus the public domain | |||||
| "fakepoll" code has been used instead. It is directly included in the | |||||
| Jack Darwin/MacOSX port. | |||||
| - PortAudio (www.portaudio.com) : PortAudio is a free, cross platform, | |||||
| open-source, audio I/O library. The Jack CoreAudio driver actually is | |||||
| implemented using PortAudio. The PortAudio source code for MacOSX has | |||||
| to be installed and compiled to produce a framework called | |||||
| "PortAudio.framework" that will be used in the Jack link phase. | |||||
| Several targets are available in the Project Builder project : | |||||
| - jackd : build the Jack server ("jackd" executable) | |||||
| - jack framework : build the "Jack.framework" library. | |||||
| - driver : build the PortAudio driver as a "jack_portaudio.so" shared library. | |||||
| - jack_metro : build the "jack_metro" executable. | |||||
| - jack_lsp : build the "jack_lsp" executable. | |||||
| - jack_connect : build the "jack_connect" executable. | |||||
| - jack_disconnect : build the "jack_disconnect" executable. | |||||
| Server, driver and library installation : | |||||
| ----------------------------------------- | |||||
| First copy the Jack.framework in /Library/Framework. Then as root : | |||||
| # cp jack_portaudio /usr/local/lib | |||||
| # cp jackd /usr/local/bin | |||||
| Launching Jack server : | |||||
| ----------------------- | |||||
| By default buffer size is 128 frames and sample rate is 44100. | |||||
| $ jackd -v -R -d coreaudio | |||||
| To setup a 32 frames buffer and a 4800 Hz sample rate : | |||||
| $ jackd -v -R -d coreaudio -p 32 -r 48000 | |||||
| Performances | |||||
| ============= | |||||
| The Darwin/MacOSX implementation is quite efficient: on a G4/867 Mhz, | |||||
| the Jack server can run with a 32 frames buffer size without noticable | |||||
| problems. | |||||
| Known problems or unimplemented features | |||||
| ========================================= | |||||
| - thread cancellation : the pthread API pthread_cancel is not | |||||
| completely available on Darwin/MacOSX. Thread cannot be cancelled in | |||||
| the general case: they must use explicit cancelation points like | |||||
| "pthread_testcancel" (see the "jack_client_thread" function) | |||||
| - xruns detection and report: not implemented. | |||||
| Possible improvements | |||||
| ====================== | |||||
| - The audio driver is built on top of PortAudio. It may be more | |||||
| efficient to directly use the CoreAudio API in order to avoid | |||||
| additional buffer copy and interleaving/disinterleaving operations. | |||||
| - The project uses Project Builder. It would be helpful to work on | |||||
| the autoconf and automake tools as the Linux version. In this case, | |||||
| the macosx/config.h file would have to be removed and generated by | |||||
| configure, and jack/version.h will be generated automatically from | |||||
| jack/version.h.in | |||||
| - Better separation of Linux and Darwin/MacOSX only code. | |||||
| The Jack port for Darwin/MacOSX version has be done by: | |||||
| Grame Research Laboratory | |||||
| 9, rue du Garet 69001 Lyon - France | |||||
| Mail : letz@grame.fr | |||||
| @@ -17,7 +17,6 @@ | |||||
| #define _FAKE_POLL_H | #define _FAKE_POLL_H | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #define FD_SETSIZE OPEN_MAX | |||||
| #include <sys/types.h> | #include <sys/types.h> | ||||
| #include <sys/time.h> | #include <sys/time.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| @@ -19,13 +19,4 @@ | |||||
| grame@rd.grame.fr | grame@rd.grame.fr | ||||
| */ | */ | ||||
| /* Replacement for getopt_long */ | |||||
| #include <unistd.h> | |||||
| #define getopt_long(a,b,c,d,e) getopt(a,b,c) | |||||
| struct option { | |||||
| const char *name; | |||||
| enum { required_argument, no_argument } arg; | |||||
| void *unused; | |||||
| char val; | |||||
| }; | |||||
| #include "/Developer/SDKs/MacOSX10.3.0.sdk/usr/include/getopt.h" | |||||
| @@ -19,27 +19,57 @@ | |||||
| grame@rd.grame.fr | grame@rd.grame.fr | ||||
| */ | */ | ||||
| #include "ipc.h" | |||||
| #ifndef __ipc__ | |||||
| #define __ipc__ | |||||
| #include <mach/mach_error.h> | |||||
| #include <servers/bootstrap.h> | |||||
| #include <jack/internal.h> | |||||
| #include <jack/engine.h> | |||||
| #include <libjack/local.h> /* JOQ: fix me */ | |||||
| /* | |||||
| Copyright © Grame 2003 | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France | |||||
| grame@rd.grame.fr | |||||
| */ | |||||
| /* | /* | ||||
| RPC without time out can put the jack server in a blocked state (waiting for the client answer) when a client is killed. | |||||
| The mach_msg function does not return any error in this case. Using time out solve the problem but does not seems really | |||||
| satisfactory. | |||||
| RPC without time out can put the jack server in a blocked state | |||||
| (waiting for the client answer) when a client is killed. The | |||||
| mach_msg function does not return any error in this case. Using | |||||
| time out solve the problem but does not seems really satisfactory. | |||||
| */ | */ | ||||
| #define WAIT 25 /* in millisecond */ | #define WAIT 25 /* in millisecond */ | ||||
| int | |||||
| static inline int | |||||
| jack_client_resume(jack_client_internal_t *client) | jack_client_resume(jack_client_internal_t *client) | ||||
| { | { | ||||
| mach_msg_header_t *head = &client->message.header; | mach_msg_header_t *head = &client->message.header; | ||||
| int err; | int err; | ||||
| if (!client->running) { | if (!client->running) { | ||||
| err = mach_msg (head, MACH_RCV_MSG, 0, sizeof(client->message), client->serverport, 0, MACH_PORT_NULL); | |||||
| err = mach_msg (head, MACH_RCV_MSG, 0, sizeof(client->message), | |||||
| client->serverport, 0, MACH_PORT_NULL); | |||||
| if (err) { | if (err) { | ||||
| jack_error("jack_client_resume: priming receive error: %s\n", mach_error_string(err)); | |||||
| jack_error("jack_client_resume: priming receive error: %s\n", | |||||
| mach_error_string(err)); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| client->running = TRUE; | client->running = TRUE; | ||||
| @@ -49,28 +79,34 @@ jack_client_resume(jack_client_internal_t *client) | |||||
| head->msgh_local_port = MACH_PORT_NULL; | head->msgh_local_port = MACH_PORT_NULL; | ||||
| head->msgh_size = sizeof(mach_msg_header_t); | head->msgh_size = sizeof(mach_msg_header_t); | ||||
| err = mach_msg(head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT, | |||||
| sizeof(*head), sizeof(client->message), client->serverport, WAIT, MACH_PORT_NULL); | |||||
| err = mach_msg(head, (MACH_SEND_MSG|MACH_RCV_MSG| | |||||
| MACH_SEND_TIMEOUT|MACH_RCV_TIMEOUT), | |||||
| sizeof(*head), sizeof(client->message), | |||||
| client->serverport, WAIT, MACH_PORT_NULL); | |||||
| if (err) { | if (err) { | ||||
| /* | /* | ||||
| switch(err) { | switch(err) { | ||||
| case MACH_SEND_TIMED_OUT: | case MACH_SEND_TIMED_OUT: | ||||
| jack_error("MACH_SEND_TIMED_OUT %s\n", client->control->name); | |||||
| jack_error("MACH_SEND_TIMED_OUT %s\n", | |||||
| client->control->name); | |||||
| break; | break; | ||||
| case MACH_RCV_TIMED_OUT: | case MACH_RCV_TIMED_OUT: | ||||
| jack_error("MACH_RCV_TIMED_OUT %s\n", client->control->name); | |||||
| jack_error("MACH_RCV_TIMED_OUT %s\n", | |||||
| client->control->name); | |||||
| break; | break; | ||||
| case MACH_SEND_INVALID_DEST: | case MACH_SEND_INVALID_DEST: | ||||
| jack_error("MACH_SEND_INVALID_DEST %s\n", client->control->name); | |||||
| jack_error("MACH_SEND_INVALID_DEST %s\n", | |||||
| client->control->name); | |||||
| break; | break; | ||||
| } | } | ||||
| */ | */ | ||||
| jack_error("jack_client_resume: send error for %s\n", mach_error_string(err)); | |||||
| jack_error("jack_client_resume: send error for %s\n", | |||||
| mach_error_string(err)); | |||||
| return err; | return err; | ||||
| } | } | ||||
| } | } | ||||
| @@ -78,39 +114,44 @@ jack_client_resume(jack_client_internal_t *client) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int | |||||
| static inline int | |||||
| jack_client_suspend(jack_client_t * client) | jack_client_suspend(jack_client_t * client) | ||||
| { | { | ||||
| int err = 0; | int err = 0; | ||||
| mach_msg_header_t * head = &client->message.header; | mach_msg_header_t * head = &client->message.header; | ||||
| head->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_MAKE_SEND_ONCE); | |||||
| head->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, | |||||
| MACH_MSG_TYPE_MAKE_SEND_ONCE); | |||||
| head->msgh_remote_port = client->serverport; | head->msgh_remote_port = client->serverport; | ||||
| head->msgh_local_port = client->replyport; | head->msgh_local_port = client->replyport; | ||||
| head->msgh_size = sizeof(mach_msg_header_t); | head->msgh_size = sizeof(mach_msg_header_t); | ||||
| err = mach_msg(head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_SEND_TIMEOUT, | err = mach_msg(head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_SEND_TIMEOUT, | ||||
| sizeof(mach_msg_header_t), sizeof(client->message), client->replyport, WAIT, MACH_PORT_NULL); | |||||
| sizeof(mach_msg_header_t), sizeof(client->message), | |||||
| client->replyport, WAIT, MACH_PORT_NULL); | |||||
| if (err) { | if (err) { | ||||
| jack_error("jack_client_suspend: RPC error: %s\n", mach_error_string(err)); | |||||
| jack_error("jack_client_suspend: RPC error: %s\n", | |||||
| mach_error_string(err)); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| void | |||||
| static inline void | |||||
| allocate_mach_serverport(jack_engine_t * engine, jack_client_internal_t *client) | allocate_mach_serverport(jack_engine_t * engine, jack_client_internal_t *client) | ||||
| { | { | ||||
| char buf[256]; | char buf[256]; | ||||
| snprintf(buf, 256, "JackMachPort_%d", engine->portnum); | snprintf(buf, 256, "JackMachPort_%d", engine->portnum); | ||||
| if (mach_port_allocate(engine->servertask, MACH_PORT_RIGHT_RECEIVE, &client->serverport)){ | |||||
| if (mach_port_allocate(engine->servertask, MACH_PORT_RIGHT_RECEIVE, | |||||
| &client->serverport)){ | |||||
| jack_error("allocate_mach_serverport: can't allocate mach port"); | jack_error("allocate_mach_serverport: can't allocate mach port"); | ||||
| } | } | ||||
| if (mach_port_insert_right(engine->servertask, client->serverport, client->serverport, MACH_MSG_TYPE_MAKE_SEND)){ | |||||
| if (mach_port_insert_right(engine->servertask, client->serverport, | |||||
| client->serverport, MACH_MSG_TYPE_MAKE_SEND)){ | |||||
| jack_error("allocate_mach_serverport: error inserting mach rights"); | jack_error("allocate_mach_serverport: error inserting mach rights"); | ||||
| } | } | ||||
| @@ -122,7 +163,7 @@ allocate_mach_serverport(jack_engine_t * engine, jack_client_internal_t *client) | |||||
| engine->portnum++; | engine->portnum++; | ||||
| } | } | ||||
| int | |||||
| static inline int | |||||
| allocate_mach_clientport(jack_client_t * client, int portnum) | allocate_mach_clientport(jack_client_t * client, int portnum) | ||||
| { | { | ||||
| char buf[256]; | char buf[256]; | ||||
| @@ -133,7 +174,8 @@ allocate_mach_clientport(jack_client_t * client, int portnum) | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| if (mach_port_allocate(client->clienttask, MACH_PORT_RIGHT_RECEIVE, &client->replyport)){ | |||||
| if (mach_port_allocate(client->clienttask, MACH_PORT_RIGHT_RECEIVE, | |||||
| &client->replyport)){ | |||||
| jack_error("allocate_mach_clientport: can't allocate mach port"); | jack_error("allocate_mach_clientport: can't allocate mach port"); | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -141,4 +183,4 @@ allocate_mach_clientport(jack_client_t * client, int portnum) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| #endif /* __ipc__ */ | |||||
| @@ -0,0 +1,39 @@ | |||||
| /* | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| MacOS X specific defines. | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef _jack_os_defines | |||||
| #define _jack_os_defines 1 | |||||
| /* a bigger process stack makes the application crash... */ | |||||
| #define JACK_THREAD_STACK_TOUCH 10000 | |||||
| #define JACK_CPP_VARARGS_BROKEN 1 | |||||
| #define JACK_USE_MACH_THREADS 1 | |||||
| #define JACK_DO_NOT_MLOCK 1 | |||||
| #define PORTAUDIO_H <PortAudio.h> | |||||
| #define GETOPT_H <sysdeps/getopt.h> | |||||
| /* MacOSX defines __POWERPC__ rather than __powerpc__ */ | |||||
| #if defined(__POWERPC__) && !defined(__powerpc__) | |||||
| #define __powerpc__ __POWERPC__ | |||||
| #endif | |||||
| #endif /* _jack_os_defines */ | |||||
| @@ -0,0 +1,203 @@ | |||||
| /* | |||||
| Copyright: © Copyright 2002 Apple Computer, Inc. All rights | |||||
| reserved. | |||||
| Disclaimer: IMPORTANT: This Apple software is supplied to | |||||
| you by Apple Computer, Inc. ("Apple") in | |||||
| consideration of your agreement to the | |||||
| following terms, and your use, installation, | |||||
| modification or redistribution of this Apple | |||||
| software constitutes acceptance of these | |||||
| terms. If you do not agree with these terms, | |||||
| please do not use, install, modify or | |||||
| redistribute this Apple software. | |||||
| In consideration of your agreement to abide by | |||||
| the following terms, and subject to these | |||||
| terms, Apple grants you a personal, | |||||
| non-exclusive license, under AppleÕs | |||||
| copyrights in this original Apple software | |||||
| (the "Apple Software"), to use, reproduce, | |||||
| modify and redistribute the Apple Software, | |||||
| with or without modifications, in source | |||||
| and/or binary forms; provided that if you | |||||
| redistribute the Apple Software in its | |||||
| entirety and without modifications, you must | |||||
| retain this notice and the following text and | |||||
| disclaimers in all such redistributions of the | |||||
| Apple Software. Neither the name, trademarks, | |||||
| service marks or logos of Apple Computer, | |||||
| Inc. may be used to endorse or promote | |||||
| products derived from the Apple Software | |||||
| without specific prior written permission from | |||||
| Apple. Except as expressly stated in this | |||||
| notice, no other rights or licenses, express | |||||
| or implied, are granted by Apple herein, | |||||
| including but not limited to any patent rights | |||||
| that may be infringed by your derivative works | |||||
| or by other works in which the Apple Software | |||||
| may be incorporated. | |||||
| The Apple Software is provided by Apple on an | |||||
| "AS IS" basis. APPLE MAKES NO WARRANTIES, | |||||
| EXPRESS OR IMPLIED, INCLUDING WITHOUT | |||||
| LIMITATION THE IMPLIED WARRANTIES OF | |||||
| NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS | |||||
| FOR A PARTICULAR PURPOSE, REGARDING THE APPLE | |||||
| SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | |||||
| COMBINATION WITH YOUR PRODUCTS. | |||||
| IN NO EVENT SHALL APPLE BE LIABLE FOR ANY | |||||
| SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL | |||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||||
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||||
| INTERRUPTION) ARISING IN ANY WAY OUT OF THE | |||||
| USE, REPRODUCTION, MODIFICATION AND/OR | |||||
| DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER | |||||
| CAUSED AND WHETHER UNDER THEORY OF CONTRACT, | |||||
| TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY | |||||
| OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED | |||||
| OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| */ | |||||
| /* pThreadUtilities.h */ | |||||
| #ifndef __PTHREADUTILITIES_H__ | |||||
| #define __PTHREADUTILITIES_H__ | |||||
| #import "pthread.h" | |||||
| #import <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> | |||||
| #define THREAD_SET_PRIORITY 0 | |||||
| #define THREAD_SCHEDULED_PRIORITY 1 | |||||
| #include <mach/mach_error.h> | |||||
| #include <mach/thread_policy.h> | |||||
| #include <mach/thread_act.h> | |||||
| #include <CoreAudio/HostTime.h> | |||||
| static inline UInt32 | |||||
| _getThreadPriority(pthread_t inThread, int inWhichPriority) | |||||
| { | |||||
| thread_basic_info_data_t threadInfo; | |||||
| policy_info_data_t thePolicyInfo; | |||||
| unsigned int count; | |||||
| // get basic info | |||||
| count = THREAD_BASIC_INFO_COUNT; | |||||
| thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, | |||||
| (thread_info_t)&threadInfo, &count); | |||||
| switch (threadInfo.policy) { | |||||
| case POLICY_TIMESHARE: | |||||
| count = POLICY_TIMESHARE_INFO_COUNT; | |||||
| thread_info(pthread_mach_thread_np (inThread), | |||||
| THREAD_SCHED_TIMESHARE_INFO, | |||||
| (thread_info_t)&(thePolicyInfo.ts), &count); | |||||
| if (inWhichPriority == THREAD_SCHEDULED_PRIORITY) { | |||||
| return thePolicyInfo.ts.cur_priority; | |||||
| } else { | |||||
| return thePolicyInfo.ts.base_priority; | |||||
| } | |||||
| break; | |||||
| case POLICY_FIFO: | |||||
| count = POLICY_FIFO_INFO_COUNT; | |||||
| thread_info(pthread_mach_thread_np (inThread), | |||||
| THREAD_SCHED_FIFO_INFO, | |||||
| (thread_info_t)&(thePolicyInfo.fifo), &count); | |||||
| if ( (thePolicyInfo.fifo.depressed) | |||||
| && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) { | |||||
| return thePolicyInfo.fifo.depress_priority; | |||||
| } | |||||
| return thePolicyInfo.fifo.base_priority; | |||||
| break; | |||||
| case POLICY_RR: | |||||
| count = POLICY_RR_INFO_COUNT; | |||||
| thread_info(pthread_mach_thread_np (inThread), | |||||
| THREAD_SCHED_RR_INFO, | |||||
| (thread_info_t)&(thePolicyInfo.rr), &count); | |||||
| if ( (thePolicyInfo.rr.depressed) | |||||
| && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) { | |||||
| return thePolicyInfo.rr.depress_priority; | |||||
| } | |||||
| return thePolicyInfo.rr.base_priority; | |||||
| break; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| // returns the thread's priority as it was last set by the API | |||||
| static inline UInt32 | |||||
| getThreadSetPriority(pthread_t inThread) | |||||
| { | |||||
| return _getThreadPriority (inThread, THREAD_SET_PRIORITY); | |||||
| } | |||||
| // returns the thread's priority as it was last scheduled by the Kernel | |||||
| static inline UInt32 | |||||
| getThreadScheduledPriority(pthread_t inThread) | |||||
| { | |||||
| return _getThreadPriority (inThread, THREAD_SCHEDULED_PRIORITY); | |||||
| } | |||||
| static inline void | |||||
| setThreadToPriority(pthread_t inThread, UInt32 inPriority, Boolean inIsFixed, | |||||
| UInt64 inHALIOProcCycleDurationInNanoseconds) | |||||
| { | |||||
| if (inPriority == 96) | |||||
| { | |||||
| // REAL-TIME / TIME-CONSTRAINT THREAD | |||||
| thread_time_constraint_policy_data_t theTCPolicy; | |||||
| UInt64 theComputeQuanta; | |||||
| UInt64 thePeriod; | |||||
| UInt64 thePeriodNanos; | |||||
| thePeriodNanos = inHALIOProcCycleDurationInNanoseconds; | |||||
| theComputeQuanta = AudioConvertNanosToHostTime ( thePeriodNanos * 0.15 ); | |||||
| thePeriod = AudioConvertNanosToHostTime (thePeriodNanos); | |||||
| theTCPolicy.period = thePeriod; | |||||
| theTCPolicy.computation = theComputeQuanta; | |||||
| theTCPolicy.constraint = thePeriod; | |||||
| theTCPolicy.preemptible = true; | |||||
| thread_policy_set (pthread_mach_thread_np(inThread), | |||||
| THREAD_TIME_CONSTRAINT_POLICY, | |||||
| (thread_policy_t)&theTCPolicy, | |||||
| THREAD_TIME_CONSTRAINT_POLICY_COUNT); | |||||
| } else { | |||||
| // OTHER THREADS | |||||
| thread_extended_policy_data_t theFixedPolicy; | |||||
| thread_precedence_policy_data_t thePrecedencePolicy; | |||||
| SInt32 relativePriority; | |||||
| // [1] SET FIXED / NOT FIXED | |||||
| theFixedPolicy.timeshare = !inIsFixed; | |||||
| thread_policy_set (pthread_mach_thread_np(inThread), | |||||
| THREAD_EXTENDED_POLICY, | |||||
| (thread_policy_t)&theFixedPolicy, | |||||
| THREAD_EXTENDED_POLICY_COUNT); | |||||
| // [2] SET PRECEDENCE N.B.: We expect that if thread A | |||||
| // created thread B, and the program wishes to change the | |||||
| // priority of thread B, then the call to change the | |||||
| // priority of thread B must be made by thread A. This | |||||
| // assumption allows us to use pthread_self() to correctly | |||||
| // calculate the priority of the feeder thread (since | |||||
| // precedency policy's importance is relative to the | |||||
| // spawning thread's priority.) | |||||
| relativePriority = inPriority - | |||||
| getThreadSetPriority (pthread_self()); | |||||
| thePrecedencePolicy.importance = relativePriority; | |||||
| thread_policy_set (pthread_mach_thread_np(inThread), | |||||
| THREAD_PRECEDENCE_POLICY, | |||||
| (thread_policy_t)&thePrecedencePolicy, | |||||
| THREAD_PRECEDENCE_POLICY_COUNT); | |||||
| } | |||||
| } | |||||
| #endif /* __PTHREADUTILITIES_H__ */ | |||||
| @@ -0,0 +1,29 @@ | |||||
| /* | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| Mac OS/X replacement for <sys/poll.h>. Overrides system version, | |||||
| using <sysdeps/fakepoll.h> to emulate the needed features. | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __poll_h__ | |||||
| #define __poll_h__ | |||||
| #include <poll.h> | |||||
| #endif /* __poll_h__ */ | |||||
| @@ -1,6 +1,8 @@ | |||||
| /* | /* | ||||
| Copyright (C) 2001 Paul Davis | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| Mac OS/X specific defines. | |||||
| This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU Lesser General Public License as published by | it under the terms of the GNU Lesser General Public License as published by | ||||
| the Free Software Foundation; either version 2.1 of the License, or | the Free Software Foundation; either version 2.1 of the License, or | ||||
| @@ -18,12 +20,9 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| /* Defined "by hand" on Darwin/MacOSX */ | |||||
| #define VERSION "0.74.2" | |||||
| #define ADDON_DIR "/usr/local/lib" | |||||
| #ifndef _macosx_portaudio | |||||
| #define _macosx_portaudio 1 | |||||
| #define USE_POSIX_SHM 1 | |||||
| #include <PortAudio.h> | |||||
| #define HAVE_ATEXIT 1 | |||||
| #endif /* _macosx_portaudio */ | |||||
| @@ -21,33 +21,32 @@ | |||||
| #ifndef __jack_time_h__ | #ifndef __jack_time_h__ | ||||
| #define __jack_time_h__ | #define __jack_time_h__ | ||||
| /* | |||||
| * This is the MacOSX version of <jack/time.h>. It overrides the | |||||
| * generic version via the configure.hosts mechanism. | |||||
| */ | |||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| extern void jack_init_time (); | |||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #include <mach/mach_time.h> | #include <mach/mach_time.h> | ||||
| extern double __jack_time_ratio; | |||||
| /* This is a kludge. We need one global instantiation of this | |||||
| * variable in each address space. So, libjack/client.c declares the | |||||
| * actual storage. Other source files will see it as an extern. */ | |||||
| #define JACK_TIME_GLOBAL_DECL double __jack_time_ratio | |||||
| extern JACK_TIME_GLOBAL_DECL; | |||||
| static inline jack_time_t jack_get_microseconds(void) | |||||
| static inline jack_time_t | |||||
| jack_get_microseconds(void) | |||||
| { | { | ||||
| return mach_absolute_time () * __jack_time_ratio; | return mach_absolute_time () * __jack_time_ratio; | ||||
| } | } | ||||
| #else | |||||
| #include <jack/cycles.h> | |||||
| extern jack_time_t __jack_cpu_mhz; | |||||
| extern jack_time_t jack_get_mhz(); | |||||
| extern void jack_init_time (); | |||||
| static inline jack_time_t jack_get_microseconds (void) { | |||||
| return get_cycles() / __jack_cpu_mhz; | |||||
| /* This should only be called ONCE per process. */ | |||||
| static inline void | |||||
| jack_init_time () | |||||
| { | |||||
| mach_timebase_info_data_t info; | |||||
| mach_timebase_info(&info); | |||||
| __jack_time_ratio = ((float)info.numer/info.denom) / 1000; | |||||
| } | } | ||||
| #endif | |||||
| #endif /* __jack_time_h__ */ | #endif /* __jack_time_h__ */ | ||||
| @@ -0,0 +1,3 @@ | |||||
| Makefile | |||||
| Makefile.in | |||||
| *.h | |||||
| @@ -0,0 +1,23 @@ | |||||
| # This directory contains links to platform-dependent headers in the | |||||
| # source tree. None are installed or distributed from here. Remember | |||||
| # that the build tree and the source tree are not always the same. | |||||
| MAINTAINERCLEANFILES = Makefile.in | |||||
| CLEANFILES = *.h | |||||
| # Link all relevant headers into the `sysdeps' directory. The order | |||||
| # of these loops determines header file precedence. | |||||
| all-local: | |||||
| for h in ${top_srcdir}/config/cpu/generic/*.h; do \ | |||||
| $(LN_S) -f $$h .; \ | |||||
| done | |||||
| for h in ${top_srcdir}/config/@cpu_include_dir@/*.h; do \ | |||||
| $(LN_S) -f $$h .; \ | |||||
| done | |||||
| for h in ${top_srcdir}/config/os/generic/*.h; do \ | |||||
| $(LN_S) -f $$h .; \ | |||||
| done | |||||
| for h in ${top_srcdir}/config/@os_include_dir@/*.h; do \ | |||||
| $(LN_S) -f $$h .; \ | |||||
| done | |||||
| @@ -1,7 +1,7 @@ | |||||
| dnl Process this file with autoconf to produce a configure script. | dnl Process this file with autoconf to produce a configure script. | ||||
| AC_INIT(jackd/jackd.c) | AC_INIT(jackd/jackd.c) | ||||
| AC_CONFIG_AUX_DIR(.) | |||||
| AC_CONFIG_AUX_DIR(config) | |||||
| AC_CANONICAL_TARGET | AC_CANONICAL_TARGET | ||||
| dnl --- | dnl --- | ||||
| @@ -14,8 +14,8 @@ dnl micro version = incremented when implementation-only | |||||
| dnl changes are made | dnl changes are made | ||||
| dnl --- | dnl --- | ||||
| JACK_MAJOR_VERSION=0 | JACK_MAJOR_VERSION=0 | ||||
| JACK_MINOR_VERSION=95 | |||||
| JACK_MICRO_VERSION=11 | |||||
| JACK_MINOR_VERSION=96 | |||||
| JACK_MICRO_VERSION=0 | |||||
| dnl --- | dnl --- | ||||
| dnl HOWTO: updating the jack protocol version | dnl HOWTO: updating the jack protocol version | ||||
| @@ -68,63 +68,58 @@ AM_INIT_AUTOMAKE(jack-audio-connection-kit,${JACK_VERSION}) | |||||
| AM_MAINTAINER_MODE | AM_MAINTAINER_MODE | ||||
| AM_CONFIG_HEADER(config.h) | AM_CONFIG_HEADER(config.h) | ||||
| AC_ENABLE_STATIC(no) | AC_ENABLE_STATIC(no) | ||||
| AC_ENABLE_SHARED(yes) | AC_ENABLE_SHARED(yes) | ||||
| AC_PROG_CC | AC_PROG_CC | ||||
| AC_PROG_CXX | AC_PROG_CXX | ||||
| AC_PROG_LD | AC_PROG_LD | ||||
| AM_PROG_LIBTOOL | AM_PROG_LIBTOOL | ||||
| AC_PROG_LN_S | |||||
| AC_C_BIGENDIAN | AC_C_BIGENDIAN | ||||
| # configure CPU and OS dependencies for host platform | |||||
| AC_MSG_CHECKING([platform dependencies]) | |||||
| source $srcdir/config/configure.host | |||||
| AC_MSG_RESULT([${os_include_dir}, ${cpu_include_dir}]) | |||||
| AC_SUBST(OS_LDFLAGS) | |||||
| AC_SUBST(os_include_dir) | |||||
| AC_SUBST(cpu_include_dir) | |||||
| AC_CHECK_HEADERS(string.h strings.h) | AC_CHECK_HEADERS(string.h strings.h) | ||||
| AC_CHECK_FUNC(getopt_long, , AC_MSG_ERROR([GNU getopt is required to build jack])) | |||||
| AC_CHECK_FUNC(getopt_long, , | |||||
| AC_MSG_ERROR([GNU getopt is required to build jack])) | |||||
| AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent)) | AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent)) | ||||
| AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) | AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) | ||||
| AC_CHECK_FUNC(connect, , AC_CHECK_LIB(inet, connect)) | AC_CHECK_FUNC(connect, , AC_CHECK_LIB(inet, connect)) | ||||
| AC_CHECK_FUNCS(on_exit atexit) | AC_CHECK_FUNCS(on_exit atexit) | ||||
| AC_CHECK_FUNCS(posix_memalign) | |||||
| dnl | |||||
| dnl look for system support for POSIX shm API | |||||
| dnl XXX this could probably be improved | |||||
| dnl | |||||
| # look for system support for POSIX shm API | |||||
| AC_ARG_ENABLE(posix-shm, [ --enable-posix-shm use POSIX shm API ], | AC_ARG_ENABLE(posix-shm, [ --enable-posix-shm use POSIX shm API ], | ||||
| TRY_POSIX_SHM=$enableval , TRY_POSIX_SHM=no ) | |||||
| TRY_POSIX_SHM=$enableval , ) | |||||
| AC_MSG_CHECKING([shared memory support]) | |||||
| if test "x$TRY_POSIX_SHM" = "xyes" | if test "x$TRY_POSIX_SHM" = "xyes" | ||||
| then | then | ||||
| AC_MSG_CHECKING([POSIX shm support (compile time) ]) | |||||
| df | grep -s /dev/shm >/dev/null 2>&1 | |||||
| if test $? = 0 ; then | |||||
| AC_DEFINE(USE_POSIX_SHM,1,[Use POSIX shared memory interface]) | |||||
| AC_MSG_RESULT([found. | |||||
| JACK will use shm_open() and friends.]) | |||||
| else | |||||
| AC_MSG_RESULT([not found. | |||||
| JACK will use System V shm API (shmget() and friends]) | |||||
| fi | |||||
| AC_MSG_RESULT([POSIX shm_open().]) | |||||
| AC_DEFINE(USE_POSIX_SHM,1,[Use POSIX shared memory interface]) | |||||
| else | else | ||||
| echo ' JACK will use System V shm API (shmget() and friends)' | |||||
| AC_MSG_RESULT([System V shmget().]) | |||||
| fi | fi | ||||
| JACK_CORE_CFLAGS="$CFLAGS -I\$(top_srcdir) -I\$(top_builddir) -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -Wall" | |||||
| JACK_CORE_CFLAGS="$CFLAGS -I\$(top_builddir)/config -I\$(top_srcdir) -I\$(top_builddir) -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -Wall" | |||||
| JACK_CFLAGS="$JACK_CORE_CFLAGS -g" | JACK_CFLAGS="$JACK_CORE_CFLAGS -g" | ||||
| JACK_OPT_CFLAGS="$JACK_CORE_CFLAGS -g -march=pentium2 -mcpu=pentium4 -O3 -ffast-math -funroll-loops -fprefetch-loop-arrays" | JACK_OPT_CFLAGS="$JACK_CORE_CFLAGS -g -march=pentium2 -mcpu=pentium4 -O3 -ffast-math -funroll-loops -fprefetch-loop-arrays" | ||||
| dnl | dnl | ||||
| dnl figure out how best to optimize | dnl figure out how best to optimize | ||||
| dnl JOQ: this should be done via config/configure.hosts | |||||
| dnl | dnl | ||||
| if test "$target_cpu" = "powerpc"; then | if test "$target_cpu" = "powerpc"; then | ||||
| AC_DEFINE(POWERPC, 1, "Are we running a ppc CPU?") | AC_DEFINE(POWERPC, 1, "Are we running a ppc CPU?") | ||||
| altivecLinux=`cat /proc/cpuinfo | grep -i altivec >/dev/null` | |||||
| altivecLinux=`test -f /proc/cpuinfo && cat /proc/cpuinfo | grep -i altivec >/dev/null` | |||||
| if test "$?" = "0"; then | if test "$?" = "0"; then | ||||
| AC_DEFINE(HAVE_ALTIVEC_LINUX, 1, "Is there Altivec Support ?") | AC_DEFINE(HAVE_ALTIVEC_LINUX, 1, "Is there Altivec Support ?") | ||||
| if test "$gcc_major_version" = "3"; then | if test "$gcc_major_version" = "3"; then | ||||
| @@ -164,8 +159,10 @@ elif echo $target_cpu | grep "i*86" >/dev/null; then | |||||
| fi | fi | ||||
| AC_ARG_ENABLE(optimize, | AC_ARG_ENABLE(optimize, | ||||
| [ --enable-optimize ask the compiler for its best optimizations], | |||||
| [ if test "x$enable_optimize" != "xno" ; then JACK_CFLAGS="$JACK_OPT_CFLAGS" ; fi ]) | |||||
| [ --enable-optimize ask the compiler for its best optimizations], | |||||
| [ if test "x$enable_optimize" != "xno" ; then | |||||
| JACK_CFLAGS="$JACK_CORE_CFLAGS $JACK_OPT_FLAGS" ; | |||||
| fi ]) | |||||
| AC_SUBST(JACK_CFLAGS) | AC_SUBST(JACK_CFLAGS) | ||||
| @@ -387,8 +384,8 @@ fi | |||||
| # on some systems, readline depends on termcap or ncurses, respectively | # on some systems, readline depends on termcap or ncurses, respectively | ||||
| READLINE_DEPS="" | READLINE_DEPS="" | ||||
| AC_CHECK_LIB(termcap, tgetent, [READLINE_DEPS="$READLINE_DEPS -ltermcap"]) | |||||
| AC_CHECK_LIB(ncurses, tgetent, [READLINE_DEPS="$READLINE_DEPS -lncurses"]) | |||||
| ##AC_CHECK_LIB(termcap, tgetent, [READLINE_DEPS="$READLINE_DEPS -ltermcap"]) | |||||
| ##AC_CHECK_LIB(ncurses, tgetent, [READLINE_DEPS="$READLINE_DEPS -lncurses"]) | |||||
| AC_CHECK_LIB(readline, readline, | AC_CHECK_LIB(readline, readline, | ||||
| [HAVE_READLINE=true], [HAVE_READLINE=false], [$READLINE_DEPS] | [HAVE_READLINE=true], [HAVE_READLINE=false], [$READLINE_DEPS] | ||||
| ) | ) | ||||
| @@ -411,6 +408,8 @@ AM_CONDITIONAL(STRIPPED_JACKD, $STRIPPED_JACKD) | |||||
| AC_OUTPUT( | AC_OUTPUT( | ||||
| Makefile | Makefile | ||||
| config/Makefile | |||||
| config/sysdeps/Makefile | |||||
| doc/Makefile | doc/Makefile | ||||
| doc/reference.doxygen | doc/reference.doxygen | ||||
| drivers/Makefile | drivers/Makefile | ||||
| @@ -4,12 +4,12 @@ MAINTAINERCLEANFILES=Makefile.in | |||||
| CLEANFILES=doxygen-build.stamp | CLEANFILES=doxygen-build.stamp | ||||
| DOX=reference.doxygen | DOX=reference.doxygen | ||||
| DOXSOURCES=mainpage.dox transport.dox fsm.png \ | |||||
| DOXSOURCES=mainpage.dox transport.dox fsm.png fsm.eps \ | |||||
| ../jack/jack.h ../jack/types.h ../jack/transport.h \ | ../jack/jack.h ../jack/types.h ../jack/transport.h \ | ||||
| ../jack/ringbuffer.h ../jack/port.h \ | ../jack/ringbuffer.h ../jack/port.h \ | ||||
| ../example-clients/simple_client.c ../example-clients/inprocess.c | ../example-clients/simple_client.c ../example-clients/inprocess.c | ||||
| EXTRA_DIST=mainpage.dox transport.dox fsm.png | |||||
| EXTRA_DIST=mainpage.dox transport.dox fsm.png fsm.eps porting.dox | |||||
| INSTIMAGES=reference/html/doxygen.png reference/html/fsm.png | INSTIMAGES=reference/html/doxygen.png reference/html/fsm.png | ||||
| @@ -104,6 +104,14 @@ useful. It includes | |||||
| - simple examples of wrapping a GUI around a JACK application. | - simple examples of wrapping a GUI around a JACK application. | ||||
| - tools for checking the status of a running JACK system. | - tools for checking the status of a running JACK system. | ||||
| @section porting Porting | |||||
| JACK is designed to be portable to any system supporting the relevant | |||||
| POSIX and ANSI C standards. It currently runs under GNU/Linux and Mac | |||||
| OS X on several different processor architectures. If you want to | |||||
| port JACK to another platform, please read the @ref porting-guide | |||||
| document. | |||||
| @section license License | @section license License | ||||
| Copyright (C) 2001-2003 by Paul Davis and others. | Copyright (C) 2001-2003 by Paul Davis and others. | ||||
| @@ -0,0 +1,119 @@ | |||||
| /* | |||||
| * This file documents the process of porting JACK to new platforms. | |||||
| * It is part of the JACK reference manual, built using doxygen. | |||||
| */ | |||||
| /** | |||||
| @page porting-guide Porting JACK | |||||
| The @ref index is designed to be portable to any system supporting the | |||||
| relevant POSIX and C language standards. It currently works with | |||||
| GNU/Linux and Mac OS X on several different processor architectures. | |||||
| This document describes the steps needed to port JACK to another | |||||
| platform, and the methods used to provide portability. | |||||
| - @ref portrequirements | |||||
| - @ref portoverview | |||||
| - @ref portopsys | |||||
| - @ref portcpu | |||||
| - @ref portissues | |||||
| @section portrequirements Requirements | |||||
| - Each platform should build directly from CVS or from a tarball | |||||
| using the GNU @c ./configure tools. Platform-specific toolsets can | |||||
| by used for development, but the GNU tools should at least work for | |||||
| basic distribution and configuration. | |||||
| - For long-term maintainability we want to minimize the use of | |||||
| conditional compilation in source files. | |||||
| - We should provide generic versions of all system-dependent | |||||
| headers, so platforms need only provide those they modify. | |||||
| - In some cases, operating system-specific information must be able | |||||
| to override processor-specific data. | |||||
| @section portoverview Overview | |||||
| JACK relies on two types of platform-specific headers: | |||||
| - @ref portopsys | |||||
| - @ref portcpu | |||||
| OS-specific headers take precedence over CPU-specific headers. | |||||
| The JACK @c configure.host script and its system-dependent header | |||||
| directories were adapted from the @c libstdc++-v3 component of the GNU | |||||
| Compiler Collective, <http://gcc.gnu.org>. | |||||
| @section portopsys Operating System Dependencies | |||||
| JACK is intended to conform with C99, as defined in International | |||||
| Standard ISO/IEC 9899. Because many existing C compilers do not fully | |||||
| support this standard, some new features should be avoided for better | |||||
| portablility. For example, variables should not be declared in the | |||||
| middle of a compound statement, because many compilers still cannot | |||||
| handle that extension to the language. | |||||
| Whenever possible, OS dependencies should be isolated in OS-specific | |||||
| header files. Each target OS may optionally provide a @c | |||||
| <sysdeps/os_defines.h> header, otherwise @c | |||||
| conf/os/generic/os_defines.h will be used. The @c configure.host | |||||
| script distinguishes OS variations using a case statement based on the | |||||
| host system's type and version. | |||||
| Some needed POSIX features may be missing on certain platforms. If | |||||
| so, the preferred solution is to provide a substitute, like the @c | |||||
| fakepoll.c implementation for Mac OS X. | |||||
| If conditional compilation is required in mainline | |||||
| platform-independent code, avoid using the system name. Instead, @c | |||||
| #define a descriptive name in your @c <sysdeps/os_defines.h>, and test | |||||
| it like this: | |||||
| @code | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| allocate_mach_serverport(engine, client); | |||||
| client->running = FALSE; | |||||
| #endif | |||||
| @endcode | |||||
| Be sure to place any generic implementation alternative in the @c | |||||
| #else or use an @c #ifndef, so other OS ports are not required to know | |||||
| your platform's conditional labels. | |||||
| @section portcpu Processor Dependencies | |||||
| JACK uses some low-level machine operations for thread-safe updates to | |||||
| shared memory. A low-level implementation of @c <sysdeps/atomicity.h> | |||||
| is provided for every target processor architecture. There is also a | |||||
| generic implementation using POSIX spin locks, but that is not a good | |||||
| enough solution for serious use. | |||||
| The GCC package provides versions that work on most modern hardware. | |||||
| We've tried to keep things as close to the original as possible, while | |||||
| removing a bunch of os-specific files that didn't seem relevant. A | |||||
| primary goal has been to avoid changing the CPU-dependent @c | |||||
| <sysdeps/atomicity.h> headers. | |||||
| The relevant GCC documentation provides some helpful background, | |||||
| especially the @c atomicity.h discussion at | |||||
| <http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html>. | |||||
| @section portissues Issues Not Addressed | |||||
| - Cross-compilation has not been tested, or even thought through in | |||||
| much detail. The @a host is the system on which JACK will run. | |||||
| This may differ from the @a build system doing the compilation. | |||||
| These are selected using the standard @c ./configure options @c | |||||
| --host and @c --build. Usually, @c ./config.guess can print the | |||||
| appropriate canonical name for any system on which it runs. | |||||
| - Platform-specific build tools like Apple's Project Builder are not | |||||
| well-supported. | |||||
| */ | |||||
| @@ -363,7 +363,8 @@ WARN_LOGFILE = | |||||
| # with spaces. | # with spaces. | ||||
| INPUT = @top_srcdir@/doc/mainpage.dox \ | INPUT = @top_srcdir@/doc/mainpage.dox \ | ||||
| @top_srcdir@/doc/transport.dox \ | |||||
| @top_srcdir@/doc/transport.dox \ | |||||
| @top_srcdir@/doc/porting.dox \ | |||||
| @top_srcdir@/jack/jack.h \ | @top_srcdir@/jack/jack.h \ | ||||
| @top_srcdir@/jack/types.h \ | @top_srcdir@/jack/types.h \ | ||||
| @top_srcdir@/jack/transport.h \ | @top_srcdir@/jack/transport.h \ | ||||
| @@ -14,7 +14,6 @@ noinst_HEADERS = alsa_driver.h \ | |||||
| generic.h \ | generic.h \ | ||||
| hammerfall.h \ | hammerfall.h \ | ||||
| hdsp.h \ | hdsp.h \ | ||||
| ice1712.h \ | |||||
| memops.h | |||||
| ice1712.h | |||||
| jack_alsa_la_LIBADD = $(ALSA_LIBS) | jack_alsa_la_LIBADD = $(ALSA_LIBS) | ||||
| @@ -26,20 +26,22 @@ | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <stdarg.h> | #include <stdarg.h> | ||||
| #include <getopt.h> | |||||
| #include <signal.h> | #include <signal.h> | ||||
| #include <sys/types.h> | #include <sys/types.h> | ||||
| #include <regex.h> | #include <regex.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include "alsa_driver.h" | |||||
| #include <jack/types.h> | |||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #include GETOPT_H | |||||
| #include <sysdeps/time.h> | |||||
| #include "alsa_driver.h" | |||||
| #include "hammerfall.h" | #include "hammerfall.h" | ||||
| #include "hdsp.h" | #include "hdsp.h" | ||||
| #include "ice1712.h" | #include "ice1712.h" | ||||
| #include "generic.h" | #include "generic.h" | ||||
| #include <jack/time.h> | |||||
| extern void store_work_time (int); | extern void store_work_time (int); | ||||
| extern void store_wait_time (int); | extern void store_wait_time (int); | ||||
| @@ -36,7 +36,7 @@ | |||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| #include <jack/hardware.h> | #include <jack/hardware.h> | ||||
| #include <jack/driver.h> | #include <jack/driver.h> | ||||
| #include "memops.h" | |||||
| #include <jack/memops.h> | |||||
| #include <jack/jack.h> | #include <jack/jack.h> | ||||
| typedef void (*ReadCopyFunction) (jack_default_audio_sample_t *dst, char *src, | typedef void (*ReadCopyFunction) (jack_default_audio_sample_t *dst, char *src, | ||||
| @@ -31,7 +31,7 @@ | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #include "memops.h" | |||||
| #include <jack/memops.h> | |||||
| #define SAMPLE_MAX_24BIT 8388608.0f | #define SAMPLE_MAX_24BIT 8388608.0f | ||||
| #define SAMPLE_MAX_16BIT 32768.0f | #define SAMPLE_MAX_16BIT 32768.0f | ||||
| @@ -20,6 +20,8 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include GETOPT_H | |||||
| #include <math.h> | #include <math.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <memory.h> | #include <memory.h> | ||||
| @@ -27,13 +29,12 @@ | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <stdarg.h> | #include <stdarg.h> | ||||
| #include <getopt.h> | |||||
| #include <sys/mman.h> | #include <sys/mman.h> | ||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #include <jack/time.h> | |||||
| #include <sysdeps/time.h> | |||||
| #include "dummy_driver.h" | #include "dummy_driver.h" | ||||
| @@ -20,9 +20,10 @@ | |||||
| * | * | ||||
| */ | */ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include GETOPT_H | |||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <stdarg.h> | #include <stdarg.h> | ||||
| #include <getopt.h> | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| @@ -43,7 +43,7 @@ | |||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #include <jack/time.h> | |||||
| #include <sysdeps/time.h> | |||||
| #include "oss_driver.h" | #include "oss_driver.h" | ||||
| @@ -30,7 +30,6 @@ | |||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| #include <jack/jslist.h> | #include <jack/jslist.h> | ||||
| #include <jack/driver.h> | #include <jack/driver.h> | ||||
| #include <jack/time.h> | |||||
| #include <jack/jack.h> | #include <jack/jack.h> | ||||
| @@ -19,13 +19,27 @@ | |||||
| Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France | Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France | ||||
| grame@rd.grame.fr | grame@rd.grame.fr | ||||
| 02-09-03 : Modify jack port naming : add the name of the used driver | |||||
| Add the -n option to load a specific driver using it's name | |||||
| 04-09-03 : Correct bug in -n option management : input and ouput have to be treated separately | |||||
| 08-09-03 : More robust driver loading code : new portaudio_load_default and portaudio_load_driver functions. | |||||
| 24-09-03 : Does not tries to load default device if the required one is not found, returns and error. | |||||
| 14-10-03 : After jack port name size extension, does not use fixed length for CoreAudio driver name anymore | |||||
| 09-01-04 : Handle different value for channel in and channel out (using -i and -o) | |||||
| 12-01-04 : Connect port names (inverse "in" and "out") | |||||
| 13-01-04 : Correct the length of jack port : use JACK_PORT_NAME_SIZE | |||||
| 22-03-04 : Remove jack_init_time, rename input and ouput ports using "capture" and "playback" | |||||
| */ | */ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include GETOPT_H | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <getopt.h> | |||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #include "portaudio_driver.h" | #include "portaudio_driver.h" | ||||
| @@ -37,8 +51,8 @@ paCallback(void *inputBuffer, void *outputBuffer, | |||||
| portaudio_driver_t * driver = (portaudio_driver_t*)userData; | portaudio_driver_t * driver = (portaudio_driver_t*)userData; | ||||
| driver->inPortAudio = (float*)inputBuffer; | driver->inPortAudio = (float*)inputBuffer; | ||||
| driver->outPortAudio = (float*)outputBuffer; | |||||
| driver->outPortAudio = (float*)outputBuffer; | |||||
| driver->last_wait_ust = jack_get_microseconds(); | |||||
| return driver->engine->run_cycle(driver->engine, framesPerBuffer, 0); | return driver->engine->run_cycle(driver->engine, framesPerBuffer, 0); | ||||
| } | } | ||||
| @@ -48,7 +62,7 @@ portaudio_driver_attach (portaudio_driver_t *driver, jack_engine_t *engine) | |||||
| jack_port_t *port; | jack_port_t *port; | ||||
| int port_flags; | int port_flags; | ||||
| channel_t chn; | channel_t chn; | ||||
| char buf[32]; | |||||
| char buf[JACK_PORT_NAME_SIZE]; | |||||
| driver->engine = engine; | driver->engine = engine; | ||||
| @@ -65,7 +79,7 @@ portaudio_driver_attach (portaudio_driver_t *driver, jack_engine_t *engine) | |||||
| for (chn = 0; chn < driver->capture_nchannels; chn++) { | for (chn = 0; chn < driver->capture_nchannels; chn++) { | ||||
| snprintf (buf, sizeof(buf) - 1, "capture_%lu", chn+1); | |||||
| snprintf (buf, sizeof(buf) - 1, "%s:capture%lu", driver->driver_name, chn+1); | |||||
| if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) { | if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) { | ||||
| jack_error ("portaudio: cannot register port for %s", buf); | jack_error ("portaudio: cannot register port for %s", buf); | ||||
| @@ -83,7 +97,7 @@ portaudio_driver_attach (portaudio_driver_t *driver, jack_engine_t *engine) | |||||
| port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal; | port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal; | ||||
| for (chn = 0; chn < driver->playback_nchannels; chn++) { | for (chn = 0; chn < driver->playback_nchannels; chn++) { | ||||
| snprintf (buf, sizeof(buf) - 1, "playback_%lu", chn+1); | |||||
| snprintf (buf, sizeof(buf) - 1, "%s:playback%lu", driver->driver_name, chn+1); | |||||
| if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) { | if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) { | ||||
| jack_error ("portaudio: cannot register port for %s", buf); | jack_error ("portaudio: cannot register port for %s", buf); | ||||
| @@ -229,12 +243,12 @@ portaudio_driver_set_parameters (portaudio_driver_t* driver, | |||||
| nframes, /* frames per buffer */ | nframes, /* frames per buffer */ | ||||
| 0, /* number of buffers = default min */ | 0, /* number of buffers = default min */ | ||||
| paClipOff, /* we won't output out of | paClipOff, /* we won't output out of | ||||
| * range samples so don't | |||||
| * bother clipping them */ | |||||
| * range samples so don't | |||||
| * bother clipping them */ | |||||
| paCallback, | paCallback, | ||||
| driver); | driver); | ||||
| if (err == paNoError) { | |||||
| if (err == paNoError) { | |||||
| driver->period_usecs = (((float) driver->frames_per_cycle) | driver->period_usecs = (((float) driver->frames_per_cycle) | ||||
| / driver->frame_rate) * 1000000.0f; | / driver->frame_rate) * 1000000.0f; | ||||
| @@ -251,7 +265,7 @@ portaudio_driver_set_parameters (portaudio_driver_t* driver, | |||||
| } else { | } else { | ||||
| // JOQ: this driver is dead. How do we terminate it? | // JOQ: this driver is dead. How do we terminate it? | ||||
| // Pa_Terminate(); | |||||
| Pa_Terminate(); | |||||
| fprintf(stderr, "Unable to set portaudio parameters\n"); | fprintf(stderr, "Unable to set portaudio parameters\n"); | ||||
| fprintf(stderr, "Error number: %d\n", err); | fprintf(stderr, "Error number: %d\n", err); | ||||
| fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); | ||||
| @@ -270,7 +284,7 @@ portaudio_driver_reset_parameters (portaudio_driver_t* driver, | |||||
| return EINVAL; | return EINVAL; | ||||
| } | } | ||||
| Pa_CloseStream(driver->stream); | |||||
| Pa_CloseStream(driver->stream); | |||||
| return portaudio_driver_set_parameters (driver, nframes, rate); | return portaudio_driver_set_parameters (driver, nframes, rate); | ||||
| } | } | ||||
| @@ -302,27 +316,156 @@ portaudio_driver_bufsize (portaudio_driver_t* driver, jack_nframes_t nframes) | |||||
| //== instance creation/destruction ============================================= | //== instance creation/destruction ============================================= | ||||
| static int portaudio_load_default (portaudio_driver_t *driver, | |||||
| int numDevices, | |||||
| int capturing, | |||||
| int playing, | |||||
| int* inputDeviceID, | |||||
| int* outputDeviceID) | |||||
| { | |||||
| const PaDeviceInfo *pdi; | |||||
| int i,j; | |||||
| int found = 0; | |||||
| printf("Look for default driver\n"); | |||||
| *inputDeviceID = Pa_GetDefaultInputDeviceID(); | |||||
| *outputDeviceID = Pa_GetDefaultOutputDeviceID(); | |||||
| for(i=0; i<numDevices; i++) | |||||
| { | |||||
| pdi = Pa_GetDeviceInfo(i); | |||||
| printf("---------------------------------------------- #%d\n", i); | |||||
| if (i == Pa_GetDefaultInputDeviceID()) { | |||||
| driver->capture_nchannels = (capturing) ? pdi->maxInputChannels : 0; | |||||
| strcpy (driver->driver_name,pdi->name); | |||||
| found = 1; | |||||
| } | |||||
| if (i == Pa_GetDefaultOutputDeviceID()){ | |||||
| driver->playback_nchannels = (playing) ? pdi->maxOutputChannels : 0; | |||||
| strcpy (driver->driver_name,pdi->name); | |||||
| found = 1; | |||||
| } | |||||
| printf("\nName = %s\n", pdi->name); | |||||
| printf("Max Inputs = %d ", pdi->maxInputChannels); | |||||
| printf("Max Outputs = %d\n", pdi->maxOutputChannels); | |||||
| if( pdi->numSampleRates == -1 ){ | |||||
| printf("Sample Rate Range = %f to %f\n", pdi->sampleRates[0], pdi->sampleRates[1]); | |||||
| }else{ | |||||
| printf("Sample Rates ="); | |||||
| for(j=0; j<pdi->numSampleRates; j++){ | |||||
| printf(" %8.2f,", pdi->sampleRates[j]); | |||||
| } | |||||
| printf("\n"); | |||||
| } | |||||
| printf("Native Sample Formats = "); | |||||
| if( pdi->nativeSampleFormats & paInt8 ) printf("paInt8, "); | |||||
| if( pdi->nativeSampleFormats & paUInt8 ) printf("paUInt8, "); | |||||
| if( pdi->nativeSampleFormats & paInt16 ) printf("paInt16, "); | |||||
| if( pdi->nativeSampleFormats & paInt32 ) printf("paInt32, "); | |||||
| if( pdi->nativeSampleFormats & paFloat32 ) printf("paFloat32, "); | |||||
| if( pdi->nativeSampleFormats & paInt24 ) printf("paInt24, "); | |||||
| if( pdi->nativeSampleFormats & paPackedInt24 ) printf("paPackedInt24, "); | |||||
| printf("\n"); | |||||
| } | |||||
| return found; | |||||
| } | |||||
| static int portaudio_load_driver (portaudio_driver_t *driver, | |||||
| int numDevices, | |||||
| int capturing, | |||||
| int playing, | |||||
| int* inputDeviceID, | |||||
| int* outputDeviceID, | |||||
| char* driver_name) | |||||
| { | |||||
| const PaDeviceInfo *pdi; | |||||
| int found = 0; | |||||
| int i,j; | |||||
| printf("Look for %s driver\n",driver_name); | |||||
| for(i=0; i<numDevices; i++) | |||||
| { | |||||
| pdi = Pa_GetDeviceInfo(i); | |||||
| printf("---------------------------------------------- #%d\n", i); | |||||
| //if (strcmp(driver_name,pdi->name) == 0) { | |||||
| if (strncmp(driver_name,pdi->name,JACK_DRIVER_PARAM_STRING_MAX) == 0) { // compare the JACK_DRIVER_PARAM_STRING_MAX first character | |||||
| if (pdi->maxInputChannels > 0) { | |||||
| *inputDeviceID = i; | |||||
| driver->capture_nchannels = (capturing) ? pdi->maxInputChannels : 0; | |||||
| strcpy(driver->driver_name,pdi->name); | |||||
| printf("Found input driver = %s\n", driver_name); | |||||
| found = 1; | |||||
| }else if (pdi->maxOutputChannels > 0) { | |||||
| *outputDeviceID = i; | |||||
| driver->playback_nchannels = (playing) ? pdi->maxOutputChannels : 0; | |||||
| strcpy (driver->driver_name,pdi->name); | |||||
| printf("Found output driver = %s\n", driver_name); | |||||
| found = 1; | |||||
| }else { | |||||
| printf("Found driver without input or ouput = %s\n", driver_name); | |||||
| } | |||||
| } | |||||
| printf("\nName = %s\n", pdi->name); | |||||
| printf("Max Inputs = %d ", pdi->maxInputChannels); | |||||
| printf("Max Outputs = %d\n", pdi->maxOutputChannels); | |||||
| if( pdi->numSampleRates == -1 ){ | |||||
| printf("Sample Rate Range = %f to %f\n", pdi->sampleRates[0], pdi->sampleRates[1]); | |||||
| }else{ | |||||
| printf("Sample Rates ="); | |||||
| for(j=0; j<pdi->numSampleRates; j++){ | |||||
| printf(" %8.2f,", pdi->sampleRates[j]); | |||||
| } | |||||
| printf("\n"); | |||||
| } | |||||
| printf("Native Sample Formats = "); | |||||
| if( pdi->nativeSampleFormats & paInt8 ) printf("paInt8, "); | |||||
| if( pdi->nativeSampleFormats & paUInt8 ) printf("paUInt8, "); | |||||
| if( pdi->nativeSampleFormats & paInt16 ) printf("paInt16, "); | |||||
| if( pdi->nativeSampleFormats & paInt32 ) printf("paInt32, "); | |||||
| if( pdi->nativeSampleFormats & paFloat32 ) printf("paFloat32, "); | |||||
| if( pdi->nativeSampleFormats & paInt24 ) printf("paInt24, "); | |||||
| if( pdi->nativeSampleFormats & paPackedInt24 ) printf("paPackedInt24, "); | |||||
| printf("\n"); | |||||
| } | |||||
| return found; | |||||
| } | |||||
| /** create a new driver instance | /** create a new driver instance | ||||
| */ | */ | ||||
| static jack_driver_t * | static jack_driver_t * | ||||
| portaudio_driver_new (char *name, | portaudio_driver_new (char *name, | ||||
| jack_client_t* client, | |||||
| jack_nframes_t frames_per_cycle, | |||||
| jack_nframes_t rate, | |||||
| int capturing, | |||||
| int playing, | |||||
| int chan, | |||||
| DitherAlgorithm dither) | |||||
| jack_client_t* client, | |||||
| jack_nframes_t frames_per_cycle, | |||||
| jack_nframes_t rate, | |||||
| int capturing, | |||||
| int playing, | |||||
| int chan_in, | |||||
| int chan_out, | |||||
| DitherAlgorithm dither, | |||||
| char* driver_name) | |||||
| { | { | ||||
| portaudio_driver_t *driver; | portaudio_driver_t *driver; | ||||
| PaError err = paNoError; | |||||
| const PaDeviceInfo *pdi; | |||||
| int numDevices; | |||||
| int i,j; | |||||
| printf ("creating portaudio driver ... %" PRIu32 "|%" | |||||
| PRIu32 "\n", frames_per_cycle, rate); | |||||
| PaError err = paNoError; | |||||
| int numDevices; | |||||
| int inputDeviceID,outputDeviceID; | |||||
| int found; | |||||
| printf ("portaudio driver version : %d\n", kVersion); | |||||
| printf ("creating portaudio driver ... %" PRIu32 "|%" PRIu32 "\n", | |||||
| frames_per_cycle, rate); | |||||
| driver = (portaudio_driver_t *) calloc (1, sizeof (portaudio_driver_t)); | driver = (portaudio_driver_t *) calloc (1, sizeof (portaudio_driver_t)); | ||||
| jack_driver_init ((jack_driver_t *) driver); | jack_driver_init ((jack_driver_t *) driver); | ||||
| @@ -333,109 +476,106 @@ portaudio_driver_new (char *name, | |||||
| } | } | ||||
| driver->frames_per_cycle = frames_per_cycle; | driver->frames_per_cycle = frames_per_cycle; | ||||
| driver->frame_rate = rate; | |||||
| driver->frame_rate = rate; | |||||
| driver->capturing = capturing; | driver->capturing = capturing; | ||||
| driver->playing = playing; | driver->playing = playing; | ||||
| driver->attach = (JackDriverAttachFunction) portaudio_driver_attach; | driver->attach = (JackDriverAttachFunction) portaudio_driver_attach; | ||||
| driver->detach = (JackDriverDetachFunction) portaudio_driver_detach; | driver->detach = (JackDriverDetachFunction) portaudio_driver_detach; | ||||
| driver->read = (JackDriverReadFunction) portaudio_driver_read; | |||||
| driver->read = (JackDriverReadFunction) portaudio_driver_read; | |||||
| driver->write = (JackDriverReadFunction) portaudio_driver_write; | driver->write = (JackDriverReadFunction) portaudio_driver_write; | ||||
| driver->null_cycle = (JackDriverNullCycleFunction) portaudio_driver_null_cycle; | driver->null_cycle = (JackDriverNullCycleFunction) portaudio_driver_null_cycle; | ||||
| driver->bufsize = (JackDriverBufSizeFunction) portaudio_driver_bufsize; | driver->bufsize = (JackDriverBufSizeFunction) portaudio_driver_bufsize; | ||||
| driver->start = (JackDriverStartFunction) portaudio_driver_audio_start; | |||||
| driver->start = (JackDriverStartFunction) portaudio_driver_audio_start; | |||||
| driver->stop = (JackDriverStopFunction) portaudio_driver_audio_stop; | driver->stop = (JackDriverStopFunction) portaudio_driver_audio_stop; | ||||
| driver->stream = NULL; | |||||
| err = Pa_Initialize(); | |||||
| numDevices = Pa_CountDevices(); | |||||
| if( numDevices < 0 ) | |||||
| { | |||||
| printf("ERROR: Pa_CountDevices returned 0x%x\n", numDevices ); | |||||
| err = numDevices; | |||||
| goto error; | |||||
| } | |||||
| printf("Number of devices = %d\n", numDevices ); | |||||
| for( i=0; i<numDevices; i++ ) | |||||
| { | |||||
| pdi = Pa_GetDeviceInfo( i ); | |||||
| printf("---------------------------------------------- #%d", i ); | |||||
| if( i == Pa_GetDefaultInputDeviceID() ) { | |||||
| driver->capture_nchannels = (capturing) ? pdi->maxInputChannels : 0; | |||||
| } | |||||
| if( i == Pa_GetDefaultOutputDeviceID() ){ | |||||
| driver->playback_nchannels = (playing) ? pdi->maxOutputChannels : 0; | |||||
| } | |||||
| printf("\nName = %s\n", pdi->name); | |||||
| printf("Max Inputs = %d ", pdi->maxInputChannels); | |||||
| printf("Max Outputs = %d\n", pdi->maxOutputChannels); | |||||
| if( pdi->numSampleRates == -1 ){ | |||||
| printf("Sample Rate Range = %f to %f\n", pdi->sampleRates[0], pdi->sampleRates[1] ); | |||||
| }else{ | |||||
| printf("Sample Rates ="); | |||||
| for(j=0; j<pdi->numSampleRates; j++){ | |||||
| printf(" %8.2f,", pdi->sampleRates[j] ); | |||||
| } | |||||
| printf("\n"); | |||||
| } | |||||
| printf("Native Sample Formats = "); | |||||
| if( pdi->nativeSampleFormats & paInt8 ) printf("paInt8, "); | |||||
| if( pdi->nativeSampleFormats & paUInt8 ) printf("paUInt8, "); | |||||
| if( pdi->nativeSampleFormats & paInt16 ) printf("paInt16, "); | |||||
| if( pdi->nativeSampleFormats & paInt32 ) printf("paInt32, "); | |||||
| if( pdi->nativeSampleFormats & paFloat32 ) printf("paFloat32, "); | |||||
| if( pdi->nativeSampleFormats & paInt24 ) printf("paInt24, "); | |||||
| if( pdi->nativeSampleFormats & paPackedInt24 ) printf("paPackedInt24, "); | |||||
| printf("\n"); | |||||
| } | |||||
| if(err != paNoError) goto error; | |||||
| printf("Pa_GetDefaultOutputDeviceID() %d\n", Pa_GetDefaultOutputDeviceID()); | |||||
| printf("Pa_GetDefaultInputDeviceID() %d\n", Pa_GetDefaultInputDeviceID()); | |||||
| if (chan > 0) { | |||||
| driver->capture_nchannels = (driver->capture_nchannels < chan) ? driver->capture_nchannels : chan; | |||||
| driver->playback_nchannels = (driver->playback_nchannels < chan) ? driver->playback_nchannels : chan; | |||||
| } | |||||
| err = Pa_Initialize(); | |||||
| printf("Pa_Initialize OK \n"); | |||||
| printf("Driver name required %s\n",driver_name); | |||||
| numDevices = Pa_CountDevices(); | |||||
| if( numDevices < 0 ) | |||||
| { | |||||
| printf("ERROR: Pa_CountDevices returned 0x%x\n", numDevices ); | |||||
| err = numDevices; | |||||
| goto error; | |||||
| } | |||||
| printf("Number of devices = %d\n", numDevices); | |||||
| if (strcmp(driver_name,"") == 0) { | |||||
| found = portaudio_load_default(driver,numDevices,capturing,playing,&inputDeviceID,&outputDeviceID); | |||||
| if (!found) { | |||||
| printf("ERROR : default driver has not been found\n"); | |||||
| err = paHostError; | |||||
| goto error; | |||||
| } | |||||
| }else{ | |||||
| found = portaudio_load_driver(driver,numDevices,capturing,playing,&inputDeviceID,&outputDeviceID,driver_name); | |||||
| if (!found) { | |||||
| printf("ERROR : driver %s has not been found \n",driver_name); | |||||
| err = paHostError; | |||||
| goto error; | |||||
| } | |||||
| } | |||||
| // JOQ: should use portaudio_driver_set_parameters(), instead | |||||
| err = Pa_OpenStream(&driver->stream, | |||||
| ((capturing) ? Pa_GetDefaultInputDeviceID() : paNoDevice), | |||||
| ((capturing) ? driver->capture_nchannels : 0), | |||||
| paFloat32, /* 32 bit floating point input */ | |||||
| NULL, | |||||
| ((playing) ? Pa_GetDefaultOutputDeviceID() : paNoDevice), | |||||
| ((playing) ? driver->playback_nchannels : 0), | |||||
| paFloat32, /* 32 bit floating point output */ | |||||
| NULL, | |||||
| rate, | |||||
| frames_per_cycle, /* frames per buffer */ | |||||
| 0, /* number of buffers, if zero then use default minimum */ | |||||
| paClipOff, /* we won't output out of range samples so don't bother clipping them */ | |||||
| paCallback, | |||||
| driver); | |||||
| if (err != paNoError) goto error; | |||||
| driver->client = client; | |||||
| driver->period_usecs = (((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f; | |||||
| if (err != paNoError) goto error; | |||||
| printf("Pa_GetDefaultOutputDeviceID() %ld\n", (long)Pa_GetDefaultOutputDeviceID()); | |||||
| printf("Pa_GetDefaultInputDeviceID() %ld\n", (long)Pa_GetDefaultInputDeviceID()); | |||||
| printf("--------------------------------------------------\n"); | |||||
| printf("CoreAudio driver %s will be loaded\n", driver->driver_name); | |||||
| printf("inputDeviceID %ld\n", (long)inputDeviceID); | |||||
| printf("outputDeviceID %ld\n", (long)outputDeviceID); | |||||
| printf("driver->capture_nchannels %ld\n", driver->capture_nchannels); | |||||
| printf("driver->playback_nchannels %ld\n", driver->playback_nchannels); | |||||
| printf("chan_in, chan_out %ld %ld\n", (long)chan_in, (long)chan_out); | |||||
| jack_init_time(); | |||||
| return((jack_driver_t *) driver); | |||||
| if (chan_in > 0) | |||||
| driver->capture_nchannels = (driver->capture_nchannels < chan_in) ? driver->capture_nchannels : chan_in; | |||||
| if (chan_out > 0) | |||||
| driver->playback_nchannels = (driver->playback_nchannels < chan_out) ? driver->playback_nchannels : chan_out; | |||||
| printf("driver->capture_nchannels %ld\n", driver->capture_nchannels); | |||||
| printf("driver->playback_nchannels %ld\n", driver->playback_nchannels); | |||||
| err = Pa_OpenStream(&driver->stream, | |||||
| ((capturing && (driver->capture_nchannels > 0)) ? inputDeviceID : paNoDevice), | |||||
| ((capturing) ? driver->capture_nchannels : 0), | |||||
| paFloat32, // 32 bit floating point input | |||||
| NULL, | |||||
| ((playing && (driver->playback_nchannels > 0)) ? outputDeviceID : paNoDevice), | |||||
| ((playing) ? driver->playback_nchannels : 0), | |||||
| paFloat32, // 32 bit floating point output | |||||
| NULL, | |||||
| rate, | |||||
| frames_per_cycle, // frames per buffer | |||||
| 0, // number of buffers, if zero then use default minimum | |||||
| paClipOff, // we won't output out of range samples so don't bother clipping them | |||||
| paCallback, | |||||
| driver); | |||||
| if (err != paNoError) goto error; | |||||
| driver->client = client; | |||||
| driver->period_usecs = (((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f; | |||||
| return((jack_driver_t *) driver); | |||||
| error: | error: | ||||
| Pa_Terminate(); | |||||
| fprintf(stderr, "An error occured while using the portaudio stream\n"); | |||||
| fprintf(stderr, "Error number: %d\n", err); | |||||
| fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); | |||||
| free(driver); | |||||
| return NULL; | |||||
| Pa_Terminate(); | |||||
| fprintf(stderr, "An error occured while using the portaudio stream\n"); | |||||
| fprintf(stderr, "Error number: %d\n", err); | |||||
| fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); | |||||
| free(driver); | |||||
| return NULL; | |||||
| } | } | ||||
| /** free all memory allocated by a driver instance | /** free all memory allocated by a driver instance | ||||
| @@ -461,7 +601,7 @@ driver_get_descriptor () | |||||
| desc = calloc (1, sizeof (jack_driver_desc_t)); | desc = calloc (1, sizeof (jack_driver_desc_t)); | ||||
| strcpy (desc->name, "portaudio"); | strcpy (desc->name, "portaudio"); | ||||
| desc->nparams = 7; | |||||
| desc->nparams = 10; | |||||
| desc->params = calloc (desc->nparams, | desc->params = calloc (desc->nparams, | ||||
| sizeof (jack_driver_param_desc_t)); | sizeof (jack_driver_param_desc_t)); | ||||
| @@ -470,7 +610,23 @@ driver_get_descriptor () | |||||
| desc->params[i].character = 'c'; | desc->params[i].character = 'c'; | ||||
| desc->params[i].type = JackDriverParamInt; | desc->params[i].type = JackDriverParamInt; | ||||
| desc->params[i].value.ui = 0; | desc->params[i].value.ui = 0; | ||||
| strcpy (desc->params[i].short_desc, "Maximium number of channels"); | |||||
| strcpy (desc->params[i].short_desc, "Maximum number of channels"); | |||||
| strcpy (desc->params[i].long_desc, desc->params[i].short_desc); | |||||
| i++; | |||||
| strcpy (desc->params[i].name, "channelin"); | |||||
| desc->params[i].character = 'i'; | |||||
| desc->params[i].type = JackDriverParamInt; | |||||
| desc->params[i].value.ui = 0; | |||||
| strcpy (desc->params[i].short_desc, "Maximum number of input channels"); | |||||
| strcpy (desc->params[i].long_desc, desc->params[i].short_desc); | |||||
| i++; | |||||
| strcpy (desc->params[i].name, "channelout"); | |||||
| desc->params[i].character = 'o'; | |||||
| desc->params[i].type = JackDriverParamInt; | |||||
| desc->params[i].value.ui = 0; | |||||
| strcpy (desc->params[i].short_desc, "Maximum number of ouput channels"); | |||||
| strcpy (desc->params[i].long_desc, desc->params[i].short_desc); | strcpy (desc->params[i].long_desc, desc->params[i].short_desc); | ||||
| i++; | i++; | ||||
| @@ -509,9 +665,17 @@ driver_get_descriptor () | |||||
| strcpy (desc->params[i].name, "period"); | strcpy (desc->params[i].name, "period"); | ||||
| desc->params[i].character = 'p'; | desc->params[i].character = 'p'; | ||||
| desc->params[i].type = JackDriverParamUInt; | desc->params[i].type = JackDriverParamUInt; | ||||
| desc->params[i].value.ui = 128U; | |||||
| desc->params[i].value.ui = 1024U; | |||||
| strcpy (desc->params[i].short_desc, "Frames per period"); | strcpy (desc->params[i].short_desc, "Frames per period"); | ||||
| strcpy (desc->params[i].long_desc, desc->params[i].short_desc); | strcpy (desc->params[i].long_desc, desc->params[i].short_desc); | ||||
| i++; | |||||
| strcpy (desc->params[i].name, "name"); | |||||
| desc->params[i].character = 'n'; | |||||
| desc->params[i].type = JackDriverParamString; | |||||
| desc->params[i].value.ui = 128U; | |||||
| strcpy (desc->params[i].short_desc, "Driver name"); | |||||
| strcpy (desc->params[i].long_desc, desc->params[i].short_desc); | |||||
| i++; | i++; | ||||
| strcpy (desc->params[i].name, "dither"); | strcpy (desc->params[i].name, "dither"); | ||||
| @@ -525,8 +689,6 @@ driver_get_descriptor () | |||||
| " t : triangular\n" | " t : triangular\n" | ||||
| " s : shaped\n" | " s : shaped\n" | ||||
| " - : no dithering"); | " - : no dithering"); | ||||
| return desc; | return desc; | ||||
| } | } | ||||
| @@ -537,18 +699,25 @@ driver_initialize (jack_client_t *client, const JSList * params) | |||||
| { | { | ||||
| jack_nframes_t srate = 48000; | jack_nframes_t srate = 48000; | ||||
| jack_nframes_t frames_per_interrupt = 1024; | jack_nframes_t frames_per_interrupt = 1024; | ||||
| int capture = FALSE; | int capture = FALSE; | ||||
| int playback = FALSE; | int playback = FALSE; | ||||
| int chan = -1; | |||||
| int chan_in = -1; | |||||
| int chan_out = -1; | |||||
| DitherAlgorithm dither = None; | DitherAlgorithm dither = None; | ||||
| const JSList * node; | const JSList * node; | ||||
| const jack_driver_param_t * param; | const jack_driver_param_t * param; | ||||
| char *name = ""; | |||||
| for (node = params; node; node = jack_slist_next (node)) { | for (node = params; node; node = jack_slist_next (node)) { | ||||
| param = (const jack_driver_param_t *) node->data; | param = (const jack_driver_param_t *) node->data; | ||||
| switch (param->character) { | switch (param->character) { | ||||
| case 'n': | |||||
| name = (char *) param->value.str; | |||||
| printf("Driver name found %s\n",name); | |||||
| break; | |||||
| case 'D': | case 'D': | ||||
| capture = TRUE; | capture = TRUE; | ||||
| @@ -556,15 +725,24 @@ driver_initialize (jack_client_t *client, const JSList * params) | |||||
| break; | break; | ||||
| case 'c': | case 'c': | ||||
| chan = (int) param->value.ui; | |||||
| chan_in = (int) param->value.ui; | |||||
| chan_out = (int) param->value.ui; | |||||
| break; | |||||
| case 'i': | |||||
| chan_in = (int) param->value.ui; | |||||
| break; | |||||
| case 'o': | |||||
| chan_out = (int) param->value.ui; | |||||
| break; | break; | ||||
| case 'C': | case 'C': | ||||
| capture = TRUE; | |||||
| capture = param->value.i; | |||||
| break; | break; | ||||
| case 'P': | case 'P': | ||||
| playback = TRUE; | |||||
| playback = param->value.i; | |||||
| break; | break; | ||||
| case 'r': | case 'r': | ||||
| @@ -605,9 +783,11 @@ driver_initialize (jack_client_t *client, const JSList * params) | |||||
| } | } | ||||
| return portaudio_driver_new ("portaudio", client, frames_per_interrupt, | return portaudio_driver_new ("portaudio", client, frames_per_interrupt, | ||||
| srate, capture, playback, chan, dither); | |||||
| srate, capture, playback, chan_in, | |||||
| chan_out, dither,name); | |||||
| } | } | ||||
| void | void | ||||
| driver_finish (jack_driver_t *driver) | driver_finish (jack_driver_t *driver) | ||||
| { | { | ||||
| @@ -23,19 +23,14 @@ | |||||
| #define __jack_portaudio_driver_h__ | #define __jack_portaudio_driver_h__ | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #include <jack/memops.h> | |||||
| #include <PortAudio.h> | |||||
| #else | |||||
| #include "../alsa/memops.h" | |||||
| #include <portaudio.h> | |||||
| #endif | |||||
| #include PORTAUDIO_H | |||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| #include <jack/hardware.h> | #include <jack/hardware.h> | ||||
| #include <jack/driver.h> | #include <jack/driver.h> | ||||
| #include <jack/jack.h> | #include <jack/jack.h> | ||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/memops.h> | |||||
| typedef struct { | typedef struct { | ||||
| @@ -57,10 +52,12 @@ typedef struct { | |||||
| JSList *playback_ports; | JSList *playback_ports; | ||||
| float *inPortAudio; | float *inPortAudio; | ||||
| float *outPortAudio; | |||||
| float *outPortAudio; | |||||
| char driver_name[256]; | |||||
| PortAudioStream* stream; | PortAudioStream* stream; | ||||
| } portaudio_driver_t; | } portaudio_driver_t; | ||||
| #define kVersion 101 | |||||
| #endif /* __jack_portaudio_driver_h__ */ | #endif /* __jack_portaudio_driver_h__ */ | ||||
| @@ -48,55 +48,56 @@ AM_CFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||||
| AM_CXXFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | AM_CXXFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | ||||
| jack_simple_client_SOURCES = simple_client.c | jack_simple_client_SOURCES = simple_client.c | ||||
| jack_simple_client_LDFLAGS = -lrt -ldl -lpthread | |||||
| jack_simple_client_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_simple_client_LDADD = ../libjack/libjack.la | jack_simple_client_LDADD = ../libjack/libjack.la | ||||
| jack_connect_SOURCES = connect.c | jack_connect_SOURCES = connect.c | ||||
| jack_connect_LDFLAGS = -lrt -ldl -lpthread | |||||
| jack_connect_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_connect_LDADD = ../libjack/libjack.la | jack_connect_LDADD = ../libjack/libjack.la | ||||
| jack_disconnect_SOURCES = connect.c | jack_disconnect_SOURCES = connect.c | ||||
| jack_disconnect_LDFLAGS = -lrt -ldl -lpthread | |||||
| jack_disconnect_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_disconnect_LDADD = ../libjack/libjack.la | jack_disconnect_LDADD = ../libjack/libjack.la | ||||
| jack_monitor_client_SOURCES = monitor_client.c | jack_monitor_client_SOURCES = monitor_client.c | ||||
| jack_monitor_client_LDFLAGS = -lrt -ldl -lpthread | |||||
| jack_monitor_client_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_monitor_client_LDADD = ../libjack/libjack.la | jack_monitor_client_LDADD = ../libjack/libjack.la | ||||
| jack_metro_SOURCES = metro.c | jack_metro_SOURCES = metro.c | ||||
| jack_metro_LDFLAGS = -lrt -ldl -lpthread | |||||
| jack_metro_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_metro_LDADD = ../libjack/libjack.la | jack_metro_LDADD = ../libjack/libjack.la | ||||
| jack_lsp_SOURCES = lsp.c | jack_lsp_SOURCES = lsp.c | ||||
| jack_lsp_LDFLAGS = -lrt -ldl -lpthread | |||||
| jack_lsp_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_lsp_LDADD = ../libjack/libjack.la | jack_lsp_LDADD = ../libjack/libjack.la | ||||
| jack_showtime_SOURCES = showtime.c | jack_showtime_SOURCES = showtime.c | ||||
| jack_showtime_LDFLAGS = -lrt -ldl -lpthread | |||||
| jack_showtime_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_showtime_LDADD = ../libjack/libjack.la | jack_showtime_LDADD = ../libjack/libjack.la | ||||
| jack_bufsize_SOURCES = bufsize.c | jack_bufsize_SOURCES = bufsize.c | ||||
| jack_bufsize_LDFLAGS = | |||||
| jack_bufsize_LDFLAGS = @OS_LDFLAGS@ | |||||
| jack_bufsize_LDADD = ../libjack/libjack.la | jack_bufsize_LDADD = ../libjack/libjack.la | ||||
| jack_freewheel_SOURCES = freewheel.c | jack_freewheel_SOURCES = freewheel.c | ||||
| jack_freewheel_LDFLAGS = | |||||
| jack_freewheel_LDFLAGS = @OS_LDFLAGS@ | |||||
| jack_freewheel_LDADD = ../libjack/libjack.la | jack_freewheel_LDADD = ../libjack/libjack.la | ||||
| if HAVE_SNDFILE | if HAVE_SNDFILE | ||||
| jackrec_SOURCES = capture_client.c | jackrec_SOURCES = capture_client.c | ||||
| jackrec_LDFLAGS = @SNDFILE_LIBS@ -lrt -ldl -lpthread | |||||
| jackrec_LDFLAGS = @SNDFILE_LIBS@ -ldl -lpthread @OS_LDFLAGS@ | |||||
| jackrec_LDADD = ../libjack/libjack.la | jackrec_LDADD = ../libjack/libjack.la | ||||
| endif | endif | ||||
| if HAVE_READLINE | if HAVE_READLINE | ||||
| jack_transport_SOURCES = transport.c | jack_transport_SOURCES = transport.c | ||||
| jack_transport_LDFLAGS = -lhistory -lreadline @READLINE_DEPS@ -lrt -ldl -lpthread | |||||
| jack_transport_LDFLAGS = -lreadline @READLINE_DEPS@ \ | |||||
| -ldl -lpthread @OS_LDFLAGS@ | |||||
| jack_transport_LDADD = ../libjack/libjack.la | jack_transport_LDADD = ../libjack/libjack.la | ||||
| endif | endif | ||||
| jack_impulse_grabber_SOURCES = impulse_grabber.c | jack_impulse_grabber_SOURCES = impulse_grabber.c | ||||
| jack_impulse_grabber_LDFLAGS = -lrt -ldl -lpthread -lm | |||||
| jack_impulse_grabber_LDFLAGS = -ldl -lpthread -lm @OS_LDFLAGS@ | |||||
| jack_impulse_grabber_LDADD = ../libjack/libjack.la | jack_impulse_grabber_LDADD = ../libjack/libjack.la | ||||
| # | # | ||||
| @@ -104,11 +105,11 @@ jack_impulse_grabber_LDADD = ../libjack/libjack.la | |||||
| # | # | ||||
| jack_load_SOURCES = ipload.c | jack_load_SOURCES = ipload.c | ||||
| jack_load_LDFLAGS = -lrt -ldl -lpthread -lm | |||||
| jack_load_LDFLAGS = -ldl -lpthread -lm @OS_LDFLAGS@ | |||||
| jack_load_LDADD = ../libjack/libjack.la | jack_load_LDADD = ../libjack/libjack.la | ||||
| jack_unload_SOURCES = ipunload.c | jack_unload_SOURCES = ipunload.c | ||||
| jack_unload_LDFLAGS = -lrt -ldl -lpthread -lm | |||||
| jack_unload_LDFLAGS = -ldl -lpthread -lm @OS_LDFLAGS@ | |||||
| jack_unload_LDADD = ../libjack/libjack.la | jack_unload_LDADD = ../libjack/libjack.la | ||||
| # | # | ||||
| @@ -119,10 +120,10 @@ ip_clientdir = $(ADDON_DIR) | |||||
| ip_client_LTLIBRARIES = inprocess.la intime.la | ip_client_LTLIBRARIES = inprocess.la intime.la | ||||
| inprocess_la_LDFLAGS = -module -avoid-version | |||||
| inprocess_la_LDFLAGS = -module -avoid-version @OS_LDFLAGS@ | |||||
| inprocess_la_SOURCES = inprocess.c | inprocess_la_SOURCES = inprocess.c | ||||
| intime_la_LDFLAGS = -module -avoid-version | |||||
| intime_la_LDFLAGS = -module -avoid-version @OS_LDFLAGS@ | |||||
| intime_la_SOURCES = intime.c | intime_la_SOURCES = intime.c | ||||
| dist-hook: dist-check-sndfile | dist-hook: dist-check-sndfile | ||||
| @@ -22,6 +22,7 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| @@ -29,7 +30,7 @@ | |||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <sndfile.h> | #include <sndfile.h> | ||||
| #include <pthread.h> | #include <pthread.h> | ||||
| #include <getopt.h> | |||||
| #include GETOPT_H | |||||
| #include <jack/jack.h> | #include <jack/jack.h> | ||||
| #include <jack/ringbuffer.h> | #include <jack/ringbuffer.h> | ||||
| @@ -45,7 +46,7 @@ typedef struct _thread_info { | |||||
| volatile int can_capture; | volatile int can_capture; | ||||
| volatile int can_process; | volatile int can_process; | ||||
| volatile int status; | volatile int status; | ||||
| } thread_info_t; | |||||
| } jack_thread_info_t; | |||||
| /* JACK data */ | /* JACK data */ | ||||
| unsigned int nports; | unsigned int nports; | ||||
| @@ -65,7 +66,7 @@ long overruns = 0; | |||||
| void * | void * | ||||
| disk_thread (void *arg) | disk_thread (void *arg) | ||||
| { | { | ||||
| thread_info_t *info = (thread_info_t *) arg; | |||||
| jack_thread_info_t *info = (jack_thread_info_t *) arg; | |||||
| static jack_nframes_t total_captured = 0; | static jack_nframes_t total_captured = 0; | ||||
| jack_nframes_t samples_per_frame = info->channels; | jack_nframes_t samples_per_frame = info->channels; | ||||
| size_t bytes_per_frame = samples_per_frame * sample_size; | size_t bytes_per_frame = samples_per_frame * sample_size; | ||||
| @@ -116,7 +117,7 @@ process (jack_nframes_t nframes, void *arg) | |||||
| { | { | ||||
| int chn; | int chn; | ||||
| size_t i; | size_t i; | ||||
| thread_info_t *info = (thread_info_t *) arg; | |||||
| jack_thread_info_t *info = (jack_thread_info_t *) arg; | |||||
| /* Do nothing until we're ready to begin. */ | /* Do nothing until we're ready to begin. */ | ||||
| if ((!info->can_process) || (!info->can_capture)) | if ((!info->can_process) || (!info->can_capture)) | ||||
| @@ -158,7 +159,7 @@ jack_shutdown (void *arg) | |||||
| } | } | ||||
| void | void | ||||
| setup_disk_thread (thread_info_t *info) | |||||
| setup_disk_thread (jack_thread_info_t *info) | |||||
| { | { | ||||
| SF_INFO sf_info; | SF_INFO sf_info; | ||||
| int short_mask; | int short_mask; | ||||
| @@ -195,7 +196,7 @@ setup_disk_thread (thread_info_t *info) | |||||
| } | } | ||||
| void | void | ||||
| run_disk_thread (thread_info_t *info) | |||||
| run_disk_thread (jack_thread_info_t *info) | |||||
| { | { | ||||
| info->can_capture = 1; | info->can_capture = 1; | ||||
| pthread_join (info->thread_id, NULL); | pthread_join (info->thread_id, NULL); | ||||
| @@ -213,7 +214,7 @@ run_disk_thread (thread_info_t *info) | |||||
| } | } | ||||
| void | void | ||||
| setup_ports (int sources, char *source_names[], thread_info_t *info) | |||||
| setup_ports (int sources, char *source_names[], jack_thread_info_t *info) | |||||
| { | { | ||||
| unsigned int i; | unsigned int i; | ||||
| size_t in_size; | size_t in_size; | ||||
| @@ -261,7 +262,7 @@ main (int argc, char *argv[]) | |||||
| { | { | ||||
| jack_client_t *client; | jack_client_t *client; | ||||
| thread_info_t thread_info; | |||||
| jack_thread_info_t thread_info; | |||||
| int c; | int c; | ||||
| int longopt_index = 0; | int longopt_index = 0; | ||||
| extern int optind, opterr; | extern int optind, opterr; | ||||
| @@ -18,12 +18,13 @@ | |||||
| * $Id$ | * $Id$ | ||||
| */ | */ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <math.h> | #include <math.h> | ||||
| #include <getopt.h> | |||||
| #include GETOPT_H | |||||
| #include <jack/jack.h> | #include <jack/jack.h> | ||||
| @@ -4,7 +4,7 @@ | |||||
| * that runs within the JACK server process. | * that runs within the JACK server process. | ||||
| * | * | ||||
| * For the sake of example, a port_pair_t is allocated in | * For the sake of example, a port_pair_t is allocated in | ||||
| * jack_initialize(), passed to process() as an argument, then freed | |||||
| * jack_initialize(), passed to inprocess() as an argument, then freed | |||||
| * in jack_finish(). | * in jack_finish(). | ||||
| */ | */ | ||||
| @@ -15,7 +15,7 @@ | |||||
| /** | /** | ||||
| * For the sake of example, an instance of this struct is allocated in | * For the sake of example, an instance of this struct is allocated in | ||||
| * jack_initialize(), passed to process() as an argument, then freed | |||||
| * jack_initialize(), passed to inprocess() as an argument, then freed | |||||
| * in jack_finish(). | * in jack_finish(). | ||||
| */ | */ | ||||
| typedef struct { | typedef struct { | ||||
| @@ -25,14 +25,15 @@ typedef struct { | |||||
| /** | /** | ||||
| * Called in the realtime thread on every process cycle. The entry | * Called in the realtime thread on every process cycle. The entry | ||||
| * point name was passed to jack_set_process_callback() by | |||||
| * jack_initialize(). | |||||
| * point name was passed to jack_set_process_callback() from | |||||
| * jack_initialize(). Although this is an internal client, its | |||||
| * process() interface is identical to @ref simple_client.c. | |||||
| * | * | ||||
| * @return 0 if successful; otherwise jack_finish() will be called and | * @return 0 if successful; otherwise jack_finish() will be called and | ||||
| * the client terminated immediately. | * the client terminated immediately. | ||||
| */ | */ | ||||
| int | int | ||||
| process (jack_nframes_t nframes, void *arg) | |||||
| inprocess (jack_nframes_t nframes, void *arg) | |||||
| { | { | ||||
| port_pair_t *pp = arg; | port_pair_t *pp = arg; | ||||
| jack_default_audio_sample_t *out = | jack_default_audio_sample_t *out = | ||||
| @@ -63,7 +64,7 @@ jack_initialize (jack_client_t *client, const char *so_data) | |||||
| if (pp == NULL) | if (pp == NULL) | ||||
| return 1; /* heap exhausted */ | return 1; /* heap exhausted */ | ||||
| jack_set_process_callback (client, process, pp); | |||||
| jack_set_process_callback (client, inprocess, pp); | |||||
| /* create a pair of ports */ | /* create a pair of ports */ | ||||
| pp->input_port = jack_port_register (client, "input", | pp->input_port = jack_port_register (client, "input", | ||||
| @@ -96,9 +97,9 @@ jack_initialize (jack_client_t *client, const char *so_data) | |||||
| * This required entry point is called immediately before the client | * This required entry point is called immediately before the client | ||||
| * is unloaded, which could happen due to a call to | * is unloaded, which could happen due to a call to | ||||
| * jack_internal_client_close(), or a nonzero return from either | * jack_internal_client_close(), or a nonzero return from either | ||||
| * jack_initialize() or process(). | |||||
| * jack_initialize() or inprocess(). | |||||
| * | * | ||||
| * @param arg the same parameter provided to process(). | |||||
| * @param arg the same parameter provided to inprocess(). | |||||
| */ | */ | ||||
| void | void | ||||
| jack_finish (void *arg) | jack_finish (void *arg) | ||||
| @@ -1,8 +1,9 @@ | |||||
| #include <sysdeps/os_defines.h> | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <getopt.h> | |||||
| #include GETOPT_H | |||||
| #include <config.h> | #include <config.h> | ||||
| @@ -16,15 +16,17 @@ | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| */ | */ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <math.h> | #include <math.h> | ||||
| #include GETOPT_H | |||||
| #include <string.h> | |||||
| #include <jack/jack.h> | #include <jack/jack.h> | ||||
| #include <jack/transport.h> | #include <jack/transport.h> | ||||
| #include <getopt.h> | |||||
| #include <string.h> | |||||
| typedef jack_default_audio_sample_t sample_t; | typedef jack_default_audio_sample_t sample_t; | ||||
| @@ -6,5 +6,5 @@ includedir=@includedir@ | |||||
| Name: jack | Name: jack | ||||
| Description: the Jack Audio Connection Kit: a low-latency synchronous callback-based media server | Description: the Jack Audio Connection Kit: a low-latency synchronous callback-based media server | ||||
| Version: @JACK_VERSION@ | Version: @JACK_VERSION@ | ||||
| Libs: -L${libdir} -ljack -lpthread -ldl -lrt | |||||
| Libs: -L${libdir} -ljack -lpthread -ldl | |||||
| Cflags: -I${includedir} | Cflags: -I${includedir} | ||||
| @@ -10,19 +10,18 @@ libjackinclude_HEADERS = \ | |||||
| types.h | types.h | ||||
| noinst_HEADERS = \ | noinst_HEADERS = \ | ||||
| cycles.h \ | |||||
| atomicity.h \ | |||||
| driver.h \ | driver.h \ | ||||
| driver_interface.h \ | |||||
| driver_parse.h \ | |||||
| engine.h \ | engine.h \ | ||||
| hardware.h \ | hardware.h \ | ||||
| internal.h \ | internal.h \ | ||||
| jslist.h \ | jslist.h \ | ||||
| memops.h \ | |||||
| pool.h \ | pool.h \ | ||||
| port.h \ | port.h \ | ||||
| ringbuffer.h \ | ringbuffer.h \ | ||||
| shm.h \ | shm.h \ | ||||
| start.h \ | start.h \ | ||||
| time.h \ | |||||
| version.h \ | |||||
| driver_interface.h \ | |||||
| driver_parse.h | |||||
| version.h | |||||
| @@ -0,0 +1,39 @@ | |||||
| /* | |||||
| Copyright (C) 2004 Jack O'Quin | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __jack_atomicity_h__ | |||||
| #define __jack_atomicity_h__ | |||||
| /* | |||||
| * Interface with various machine-dependent headers derived from the | |||||
| * gcc/libstdc++.v3 sources. We try to modify the GCC sources as | |||||
| * little as possible. The following include is resolved using the | |||||
| * config/configure.hosts mechanism. It will use an OS-dependent | |||||
| * version if available, otherwise the one for this CPU. Some of | |||||
| * these files might not work with older GCC compilers. | |||||
| */ | |||||
| #include <sysdeps/atomicity.h> | |||||
| /* These functions are defined for each platform. The C++ library | |||||
| * function names start with "__" to avoid namespace pollution. */ | |||||
| #define exchange_and_add __exchange_and_add | |||||
| #define atomic_add __atomic_add | |||||
| #endif /* __jack_atomicity_h__ */ | |||||
| @@ -137,7 +137,7 @@ struct _jack_engine { | |||||
| float spare_usecs; | float spare_usecs; | ||||
| float usecs_per_cycle; | float usecs_per_cycle; | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific resources for server/client real-time thread communication */ | /* specific resources for server/client real-time thread communication */ | ||||
| mach_port_t servertask, bp; | mach_port_t servertask, bp; | ||||
| int portnum; | int portnum; | ||||
| @@ -27,29 +27,35 @@ | |||||
| #ifndef __jack_internal_h__ | #ifndef __jack_internal_h__ | ||||
| #define __jack_internal_h__ | #define __jack_internal_h__ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #include <dlfcn.h> | #include <dlfcn.h> | ||||
| #include <pthread.h> | |||||
| #include <sys/types.h> | #include <sys/types.h> | ||||
| #include <sys/time.h> | #include <sys/time.h> | ||||
| #include <pthread.h> | |||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #include "mach_port.h" | |||||
| #endif | |||||
| /* Needed by <sysdeps/time.h> */ | |||||
| extern void jack_error (const char *fmt, ...); | |||||
| #include <jack/jack.h> | #include <jack/jack.h> | ||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| #include <jack/port.h> | #include <jack/port.h> | ||||
| #include <jack/transport.h> | #include <jack/transport.h> | ||||
| #include <jack/time.h> | |||||
| #include <sysdeps/time.h> | |||||
| #include <sysdeps/atomicity.h> | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| #include <sysdeps/mach_port.h> | |||||
| #endif | |||||
| #ifdef DEBUG_ENABLED | #ifdef DEBUG_ENABLED | ||||
| #define DEBUG(format,args...) \ | #define DEBUG(format,args...) \ | ||||
| fprintf (stderr, "jack:%5d:%" PRIu64 " %s:%s:%d: " format "\n", getpid(), jack_get_microseconds(), __FILE__, __FUNCTION__, __LINE__ , ## args) | fprintf (stderr, "jack:%5d:%" PRIu64 " %s:%s:%d: " format "\n", getpid(), jack_get_microseconds(), __FILE__, __FUNCTION__, __LINE__ , ## args) | ||||
| #else | #else | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #if JACK_CPP_VARARGS_BROKEN | |||||
| #define DEBUG(format...) | #define DEBUG(format...) | ||||
| #else | #else | ||||
| #define DEBUG(format,args...) | #define DEBUG(format,args...) | ||||
| @@ -92,7 +98,7 @@ typedef struct { | |||||
| jack_position_t pending_time; /* position for next cycle */ | jack_position_t pending_time; /* position for next cycle */ | ||||
| jack_position_t request_time; /* latest requested position */ | jack_position_t request_time; /* latest requested position */ | ||||
| jack_unique_t prev_request; /* previous request unique ID */ | jack_unique_t prev_request; /* previous request unique ID */ | ||||
| volatile uint32_t seq_number; /* unique ID sequence number */ | |||||
| volatile _Atomic_word seq_number; /* unique ID sequence number */ | |||||
| int8_t new_pos; /* new position this cycle */ | int8_t new_pos; /* new position this cycle */ | ||||
| int8_t pending_pos; /* new position request pending */ | int8_t pending_pos; /* new position request pending */ | ||||
| jack_nframes_t pending_frame; /* pending frame number */ | jack_nframes_t pending_frame; /* pending frame number */ | ||||
| @@ -112,7 +118,7 @@ typedef struct { | |||||
| float cpu_load; | float cpu_load; | ||||
| uint32_t port_max; | uint32_t port_max; | ||||
| int32_t engine_ok; | int32_t engine_ok; | ||||
| uint32_t n_port_types; | |||||
| jack_port_type_id_t n_port_types; | |||||
| jack_port_type_info_t port_types[JACK_MAX_PORT_TYPES]; | jack_port_type_info_t port_types[JACK_MAX_PORT_TYPES]; | ||||
| jack_port_shared_t ports[0]; | jack_port_shared_t ports[0]; | ||||
| @@ -249,7 +255,7 @@ typedef struct { | |||||
| jack_client_control_t *client_control; /* JOQ: 64/32 problem */ | jack_client_control_t *client_control; /* JOQ: 64/32 problem */ | ||||
| jack_control_t *engine_control; /* JOQ: 64/32 problem */ | jack_control_t *engine_control; /* JOQ: 64/32 problem */ | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific resources for server/client real-time thread communication */ | /* specific resources for server/client real-time thread communication */ | ||||
| int32_t portnum; | int32_t portnum; | ||||
| #endif | #endif | ||||
| @@ -338,13 +344,13 @@ typedef struct _jack_client_internal { | |||||
| void (*finish)(void *); /* internal clients only */ | void (*finish)(void *); /* internal clients only */ | ||||
| int error; | int error; | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific resources for server/client real-time thread communication */ | /* specific resources for server/client real-time thread communication */ | ||||
| mach_port_t serverport; | mach_port_t serverport; | ||||
| trivial_message message; | trivial_message message; | ||||
| int running; | int running; | ||||
| int portnum; | int portnum; | ||||
| #endif | |||||
| #endif /* JACK_USE_MACH_THREADS */ | |||||
| } jack_client_internal_t; | } jack_client_internal_t; | ||||
| @@ -364,8 +370,6 @@ extern char *jack_server_dir; | |||||
| extern void *jack_zero_filled_buffer; | extern void *jack_zero_filled_buffer; | ||||
| extern void jack_error (const char *fmt, ...); | |||||
| extern jack_port_functions_t jack_builtin_audio_functions; | extern jack_port_functions_t jack_builtin_audio_functions; | ||||
| extern jack_port_type_info_t jack_builtin_port_types[]; | extern jack_port_type_info_t jack_builtin_port_types[]; | ||||
| @@ -148,15 +148,16 @@ int jack_set_freewheel_callback (jack_client_t *client, | |||||
| void *arg); | void *arg); | ||||
| /** | /** | ||||
| * Start or stop JACK's "freewheel" mode. | |||||
| * Start/Stop JACK's "freewheel" mode. | |||||
| * | * | ||||
| * When in "freewheel" mode, JACK no longer waits for any external | |||||
| * event to begin the start of the next process cycle. External | |||||
| * hardware I/O is muted. | |||||
| * When in "freewheel" mode, JACK no longer waits for | |||||
| * any external event to begin the start of the next process | |||||
| * cycle. | |||||
| * | * | ||||
| * As a result, freewheel mode causes "faster than realtime" execution | |||||
| * of a JACK graph. If possessed, real-time scheduling is dropped when | |||||
| * entering freewheel mode, and reacquired when stopping. | |||||
| * As a result, freewheel mode causes "faster than realtime" | |||||
| * execution of a JACK graph. If possessed, real-time | |||||
| * scheduling is dropped when entering freewheel mode, and | |||||
| * if appropriate it is reacquired when stopping. | |||||
| * | * | ||||
| * @param client pointer to JACK client structure | * @param client pointer to JACK client structure | ||||
| * @param onoff if non-zero, freewheel mode starts. Otherwise | * @param onoff if non-zero, freewheel mode starts. Otherwise | ||||
| @@ -0,0 +1,97 @@ | |||||
| /* | |||||
| Copyright (C) 1999-2000 Paul Davis | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| $Id$ | |||||
| */ | |||||
| #ifndef __jack_memops_h__ | |||||
| #define __jack_memops_h__ | |||||
| #include <jack/types.h> | |||||
| typedef enum { | |||||
| None, | |||||
| Rectangular, | |||||
| Triangular, | |||||
| Shaped | |||||
| } DitherAlgorithm; | |||||
| #define DITHER_BUF_SIZE 8 | |||||
| #define DITHER_BUF_MASK 7 | |||||
| typedef struct { | |||||
| unsigned int depth; | |||||
| float rm1; | |||||
| unsigned int idx; | |||||
| float e[DITHER_BUF_SIZE]; | |||||
| } dither_state_t; | |||||
| void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_rect_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_tri_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_shaped_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_rect_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_tri_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_shaped_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_rect_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_tri_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_shaped_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
| void sample_move_dS_s24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
| void sample_move_dS_s16 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
| void sample_merge_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_merge_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| static __inline__ void | |||||
| sample_merge (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) | |||||
| { | |||||
| while (cnt--) { | |||||
| *dst += *src; | |||||
| dst++; | |||||
| src++; | |||||
| } | |||||
| } | |||||
| static __inline__ void | |||||
| sample_memcpy (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) | |||||
| { | |||||
| memcpy (dst, src, cnt * sizeof (jack_default_audio_sample_t)); | |||||
| } | |||||
| void memset_interleave (char *dst, char val, unsigned long bytes, unsigned long unit_bytes, unsigned long skip_bytes); | |||||
| void memcpy_fake (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||||
| void memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
| void memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
| void memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
| void merge_memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
| void merge_memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
| void merge_memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
| void merge_memcpy_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||||
| void merge_memcpy_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||||
| #endif /* __jack_memops_h__ */ | |||||
| @@ -41,15 +41,7 @@ typedef uint32_t jack_nframes_t; | |||||
| * Type used to represent the value of free running | * Type used to represent the value of free running | ||||
| * monotonic clock with units of microseconds. | * monotonic clock with units of microseconds. | ||||
| */ | */ | ||||
| /* JOQ: this is trouble. APPLE POWERPC should use a compatible | |||||
| * typedef, explicitly converting from double, if necessary. | |||||
| * Otherwise applications cannot safely print a jack_time_t. */ | |||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| typedef double jack_time_t; | |||||
| #else | |||||
| typedef uint64_t jack_time_t; | typedef uint64_t jack_time_t; | ||||
| #endif | |||||
| /** | /** | ||||
| * jack_port_t is an opaque type. You may only access it using the | * jack_port_t is an opaque type. You may only access it using the | ||||
| @@ -1,5 +1,7 @@ | |||||
| /* | /* | ||||
| Copyright (C) 2003 Paul Davis | Copyright (C) 2003 Paul Davis | ||||
| @configure_input@ | |||||
| This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | it under the terms of the GNU General Public License as published by | ||||
| @@ -14,6 +16,5 @@ | |||||
| You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | ||||
| along with this program; if not, write to the Free Software | along with this program; if not, write to the Free Software | ||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| */ | */ | ||||
| #define jack_protocol_version @JACK_PROTOCOL_VERSION@ | #define jack_protocol_version @JACK_PROTOCOL_VERSION@ | ||||
| @@ -24,7 +24,7 @@ bin_PROGRAMS = jackd $(CAP_PROGS) | |||||
| AM_CFLAGS = $(JACK_CFLAGS) -DJACK_LOCATION=\"$(bindir)\" | AM_CFLAGS = $(JACK_CFLAGS) -DJACK_LOCATION=\"$(bindir)\" | ||||
| jackd_SOURCES = jackd.c engine.c transengine.c | jackd_SOURCES = jackd.c engine.c transengine.c | ||||
| jackd_LDADD = ../libjack/libjack.la -lm -ldl -lrt -lpthread $(CAP_LIBS) | |||||
| jackd_LDADD = ../libjack/libjack.la -lm -ldl -lpthread $(CAP_LIBS) @OS_LDFLAGS@ | |||||
| noinst_HEADERS = jack_md5.h md5.h md5_loc.h transengine.h | noinst_HEADERS = jack_md5.h md5.h md5_loc.h transengine.h | ||||
| @@ -19,17 +19,11 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #include <config.h> | |||||
| #include <math.h> | #include <math.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <sys/socket.h> | #include <sys/socket.h> | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #include "fakepoll.h" | |||||
| #include "ipc.h" | |||||
| #else | |||||
| #include <sys/poll.h> | |||||
| #endif | |||||
| #include <sys/un.h> | #include <sys/un.h> | ||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| @@ -38,21 +32,22 @@ | |||||
| #include <stdarg.h> | #include <stdarg.h> | ||||
| #include <stdint.h> | #include <stdint.h> | ||||
| #include <dirent.h> | #include <dirent.h> | ||||
| #include <sys/ipc.h> | |||||
| #include <signal.h> | #include <signal.h> | ||||
| #include <sys/types.h> | #include <sys/types.h> | ||||
| #include <sys/mman.h> | |||||
| #include <string.h> | #include <string.h> | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #include <config.h> | |||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #include <jack/driver.h> | #include <jack/driver.h> | ||||
| #include <jack/time.h> | |||||
| #include <jack/version.h> | #include <jack/version.h> | ||||
| #include <jack/shm.h> | #include <jack/shm.h> | ||||
| #include <sysdeps/poll.h> | |||||
| #include <sysdeps/ipc.h> | |||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| #include <sys/mman.h> | |||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| #ifdef USE_CAPABILITIES | #ifdef USE_CAPABILITIES | ||||
| /* capgetp and capsetp are linux only extensions, not posix */ | /* capgetp and capsetp are linux only extensions, not posix */ | ||||
| @@ -454,7 +449,8 @@ jack_resize_port_segment (jack_engine_t *engine, | |||||
| memset (jack_zero_filled_buffer, 0, one_buffer); | memset (jack_zero_filled_buffer, 0, one_buffer); | ||||
| } | } | ||||
| if (engine->control->real_time && engine->control->do_mlock) { | |||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| if (engine->control->real_time) { | |||||
| /* Although we've called mlockall(CURRENT|FUTURE), the | /* Although we've called mlockall(CURRENT|FUTURE), the | ||||
| * Linux VM manager still allows newly allocated pages | * Linux VM manager still allows newly allocated pages | ||||
| @@ -471,6 +467,7 @@ jack_resize_port_segment (jack_engine_t *engine, | |||||
| "%s", strerror(errno)); | "%s", strerror(errno)); | ||||
| } | } | ||||
| } | } | ||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| /* Tell everybody about this segment. */ | /* Tell everybody about this segment. */ | ||||
| event.type = AttachPortSegment; | event.type = AttachPortSegment; | ||||
| @@ -577,7 +574,7 @@ jack_process_internal(jack_engine_t *engine, JSList *node, | |||||
| return jack_slist_next (node); | return jack_slist_next (node); | ||||
| } | } | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| static JSList * | static JSList * | ||||
| jack_process_external(jack_engine_t *engine, JSList *node) | jack_process_external(jack_engine_t *engine, JSList *node) | ||||
| { | { | ||||
| @@ -595,11 +592,14 @@ jack_process_external(jack_engine_t *engine, JSList *node) | |||||
| ctl->awake_at = 0; | ctl->awake_at = 0; | ||||
| ctl->finished_at = 0; | ctl->finished_at = 0; | ||||
| jack_client_resume(client); | |||||
| if (jack_client_resume(client) < 0) { | |||||
| jack_error("Client will be removed\n"); | |||||
| ctl->state = Finished; | |||||
| } | |||||
| return jack_slist_next (node); | return jack_slist_next (node); | ||||
| } | } | ||||
| #else | |||||
| #else /* !JACK_USE_MACH_THREADS */ | |||||
| static JSList * | static JSList * | ||||
| jack_process_external(jack_engine_t *engine, JSList *node) | jack_process_external(jack_engine_t *engine, JSList *node) | ||||
| { | { | ||||
| @@ -610,7 +610,7 @@ jack_process_external(jack_engine_t *engine, JSList *node) | |||||
| jack_client_internal_t *client; | jack_client_internal_t *client; | ||||
| jack_client_control_t *ctl; | jack_client_control_t *ctl; | ||||
| jack_time_t now, then; | jack_time_t now, then; | ||||
| client = (jack_client_internal_t *) node->data; | client = (jack_client_internal_t *) node->data; | ||||
| ctl = client->control; | ctl = client->control; | ||||
| @@ -731,7 +731,7 @@ jack_process_external(jack_engine_t *engine, JSList *node) | |||||
| return node; | return node; | ||||
| } | } | ||||
| #endif | |||||
| #endif /* JACK_USE_MACH_THREADS */ | |||||
| static int | static int | ||||
| @@ -1022,8 +1022,8 @@ setup_client (jack_engine_t *engine, int client_fd, | |||||
| res->engine_shm = engine->control_shm; | res->engine_shm = engine->control_shm; | ||||
| res->realtime = engine->control->real_time; | res->realtime = engine->control->real_time; | ||||
| res->realtime_priority = engine->rtpriority - 1; | res->realtime_priority = engine->rtpriority - 1; | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific resources for server/client real-time thread | /* specific resources for server/client real-time thread | ||||
| * communication */ | * communication */ | ||||
| res->portnum = client->portnum; | res->portnum = client->portnum; | ||||
| @@ -1840,9 +1840,9 @@ jack_server_thread (void *arg) | |||||
| (engine, pfd[i].fd)) { | (engine, pfd[i].fd)) { | ||||
| jack_error ("could not handle external" | jack_error ("could not handle external" | ||||
| " client request"); | " client request"); | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* poll is implemented using | /* poll is implemented using | ||||
| select (see the fakepool | |||||
| select (see the macosx/fakepoll | |||||
| code). When the socket is closed | code). When the socket is closed | ||||
| select does not return any error, | select does not return any error, | ||||
| POLLIN is true and the next read | POLLIN is true and the next read | ||||
| @@ -1854,7 +1854,7 @@ jack_server_thread (void *arg) | |||||
| */ | */ | ||||
| handle_client_socket_error(engine, | handle_client_socket_error(engine, | ||||
| pfd[i].fd); | pfd[i].fd); | ||||
| #endif | |||||
| #endif /* JACK_USE_MACH_THREADS */ | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -2068,8 +2068,8 @@ jack_engine_new (int realtime, int rtpriority, int do_mlock, int temporary, | |||||
| engine->control->has_capabilities = 0; | engine->control->has_capabilities = 0; | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| /* specific ressources for server/client real-time thread | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific resources for server/client real-time thread | |||||
| * communication */ | * communication */ | ||||
| engine->servertask = mach_task_self(); | engine->servertask = mach_task_self(); | ||||
| if (task_get_bootstrap_port(engine->servertask, &engine->bp)){ | if (task_get_bootstrap_port(engine->servertask, &engine->bp)){ | ||||
| @@ -2077,7 +2077,7 @@ jack_engine_new (int realtime, int rtpriority, int do_mlock, int temporary, | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| engine->portnum = 0; | engine->portnum = 0; | ||||
| #endif | |||||
| #endif /* JACK_USE_MACH_THREADS */ | |||||
| #ifdef USE_CAPABILITIES | #ifdef USE_CAPABILITIES | ||||
| @@ -2131,18 +2131,16 @@ jack_become_real_time (jack_engine_t *engine, pthread_t thread, int priority) | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| // To be implemented | |||||
| #else | |||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| if (engine->control->do_mlock | if (engine->control->do_mlock | ||||
| && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | ||||
| jack_error ("cannot lock down memory for RT thread (%s)", | jack_error ("cannot lock down memory for RT thread (%s)", | ||||
| strerror (errno)); | strerror (errno)); | ||||
| #ifdef ENSURE_MLOCK | #ifdef ENSURE_MLOCK | ||||
| return -1; | |||||
| return -1; | |||||
| #endif /* ENSURE_MLOCK */ | #endif /* ENSURE_MLOCK */ | ||||
| } | } | ||||
| #endif | |||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -2168,7 +2166,6 @@ jack_watchdog_thread (void *arg) | |||||
| while (1) { | while (1) { | ||||
| usleep (5000000); | usleep (5000000); | ||||
| pthread_testcancel(); | |||||
| if ( engine->watchdog_check == 0) { | if ( engine->watchdog_check == 0) { | ||||
| jack_error ("jackd watchdog: timeout - killing jackd"); | jack_error ("jackd watchdog: timeout - killing jackd"); | ||||
| @@ -2183,6 +2180,11 @@ jack_watchdog_thread (void *arg) | |||||
| kill (-getpgrp(), SIGABRT); | kill (-getpgrp(), SIGABRT); | ||||
| /*NOTREACHED*/ | /*NOTREACHED*/ | ||||
| exit (1); | exit (1); | ||||
| #if 0 /* suppress watchdog message */ | |||||
| } else { | |||||
| VERBOSE(engine, "jackd watchdog: all is well.\n"); | |||||
| #endif | |||||
| } | } | ||||
| engine->watchdog_check = 0; | engine->watchdog_check = 0; | ||||
| } | } | ||||
| @@ -2564,7 +2566,7 @@ jack_setup_client_control (jack_engine_t *engine, int fd, | |||||
| jack_transport_client_new (client); | jack_transport_client_new (client); | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific resources for server/client real-time thread | /* specific resources for server/client real-time thread | ||||
| * communication */ | * communication */ | ||||
| allocate_mach_serverport(engine, client); | allocate_mach_serverport(engine, client); | ||||
| @@ -19,9 +19,12 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #include <config.h> | |||||
| #include <sysdeps/os_defines.h> | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <signal.h> | #include <signal.h> | ||||
| #include <getopt.h> | |||||
| #include GETOPT_H | |||||
| #include <sys/types.h> | #include <sys/types.h> | ||||
| #include <sys/shm.h> | #include <sys/shm.h> | ||||
| #include <sys/wait.h> | #include <sys/wait.h> | ||||
| @@ -31,8 +34,6 @@ | |||||
| #include <dirent.h> | #include <dirent.h> | ||||
| #include <dlfcn.h> | #include <dlfcn.h> | ||||
| #include <config.h> | |||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/driver.h> | #include <jack/driver.h> | ||||
| @@ -144,7 +145,8 @@ jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params) | |||||
| fprintf (stderr, "loading driver ..\n"); | fprintf (stderr, "loading driver ..\n"); | ||||
| if (jack_engine_load_driver (engine, driver_desc, driver_params)) { | if (jack_engine_load_driver (engine, driver_desc, driver_params)) { | ||||
| fprintf (stderr, "cannot load driver module %s\n", driver_desc->name); | |||||
| fprintf (stderr, "cannot load driver module %s\n", | |||||
| driver_desc->name); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -255,7 +257,6 @@ jack_drivers_get_descriptor (JSList * drivers, const char * sofile) | |||||
| jack_error ("error closing driver .so '%s': %s\n", filename, dlerror ()); | jack_error ("error closing driver .so '%s': %s\n", filename, dlerror ()); | ||||
| } | } | ||||
| /* check it doesn't exist already */ | /* check it doesn't exist already */ | ||||
| for (node = drivers; node; node = jack_slist_next (node)) { | for (node = drivers; node; node = jack_slist_next (node)) { | ||||
| other_descriptor = (jack_driver_desc_t *) node->data; | other_descriptor = (jack_driver_desc_t *) node->data; | ||||
| @@ -377,7 +378,7 @@ int | |||||
| main (int argc, char *argv[]) | main (int argc, char *argv[]) | ||||
| { | { | ||||
| jack_driver_desc_t * desc; | |||||
| jack_driver_desc_t * desc; | |||||
| const char *options = "-ad:P:vshVRTFl:t:m"; | const char *options = "-ad:P:vshVRTFl:t:m"; | ||||
| struct option long_options[] = | struct option long_options[] = | ||||
| { | { | ||||
| @@ -6,6 +6,12 @@ | |||||
| int jack_port_name_size(void); | int jack_port_name_size(void); | ||||
| int jack_port_type_size(void); | int jack_port_type_size(void); | ||||
| 2004-02-16 Jack O'Quin <joq@io.com> | |||||
| * Changed JACK_PORT_NAME_SIZE from 32 to 256 | |||||
| This could affect some client that defines its own value. | |||||
| 2003-10-15 Paul Davis <paul@linuxaudiosystems.com> | 2003-10-15 Paul Davis <paul@linuxaudiosystems.com> | ||||
| * new ring buffer interface: <jack/ringbuffer.h> | * new ring buffer interface: <jack/ringbuffer.h> | ||||
| @@ -20,6 +20,6 @@ AM_CXXFLAGS = $(JACK_CFLAGS) | |||||
| libjack_la_CFLAGS = $(AM_CFLAGS) | libjack_la_CFLAGS = $(AM_CFLAGS) | ||||
| libjack_la_SOURCES = $(SOURCE_FILES) | libjack_la_SOURCES = $(SOURCE_FILES) | ||||
| libjack_la_LIBADD = -lm -lpthread -lrt | |||||
| libjack_la_LIBADD = -lm -lpthread @OS_LDFLAGS@ | |||||
| libjack_la_LDFLAGS = -export-dynamic -version-info @JACK_SO_VERSION@ | libjack_la_LDFLAGS = -export-dynamic -version-info @JACK_SO_VERSION@ | ||||
| @@ -19,42 +19,40 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #include "pThreadUtilities.h" | |||||
| #include "ipc.h" | |||||
| #include "fakepoll.h" | |||||
| #else | |||||
| #include <sys/poll.h> | |||||
| #endif | |||||
| #include <config.h> | |||||
| #include <sys/socket.h> | |||||
| #include <sys/un.h> | |||||
| #include <pthread.h> | #include <pthread.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <fcntl.h> | #include <fcntl.h> | ||||
| #include <sys/types.h> | |||||
| #include <sys/ipc.h> | |||||
| #include <sys/mman.h> | |||||
| #include <stdarg.h> | #include <stdarg.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdint.h> | #include <stdint.h> | ||||
| #include <regex.h> | #include <regex.h> | ||||
| #include <signal.h> | |||||
| #include <config.h> | |||||
| #include <sys/types.h> | |||||
| #include <sys/mman.h> | |||||
| #include <sys/socket.h> | |||||
| #include <sys/un.h> | |||||
| #include <jack/jack.h> | |||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/jack.h> | |||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #include <jack/pool.h> | #include <jack/pool.h> | ||||
| #include <jack/time.h> | |||||
| #include <jack/jslist.h> | #include <jack/jslist.h> | ||||
| #include <jack/version.h> | #include <jack/version.h> | ||||
| #include <jack/shm.h> | #include <jack/shm.h> | ||||
| #include <sysdeps/time.h> | |||||
| JACK_TIME_GLOBAL_DECL; /* One instance per process. */ | |||||
| #include "local.h" | #include "local.h" | ||||
| #include <sysdeps/poll.h> | |||||
| #include <sysdeps/ipc.h> | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| #include <sysdeps/pThreadUtilities.h> | |||||
| #endif | |||||
| #ifdef WITH_TIMESTAMPS | #ifdef WITH_TIMESTAMPS | ||||
| #include <jack/timestamps.h> | #include <jack/timestamps.h> | ||||
| #endif /* WITH_TIMESTAMPS */ | #endif /* WITH_TIMESTAMPS */ | ||||
| @@ -168,6 +166,9 @@ jack_client_alloc () | |||||
| client->engine = NULL; | client->engine = NULL; | ||||
| client->control = NULL; | client->control = NULL; | ||||
| client->thread_ok = FALSE; | client->thread_ok = FALSE; | ||||
| #if JACK_USE_MACH_THREADS | |||||
| client->rt_thread_ok = FALSE; | |||||
| #endif | |||||
| client->first_active = TRUE; | client->first_active = TRUE; | ||||
| client->on_shutdown = NULL; | client->on_shutdown = NULL; | ||||
| client->n_port_types = 0; | client->n_port_types = 0; | ||||
| @@ -433,7 +434,7 @@ _start_server (void) | |||||
| } | } | ||||
| if (!good) { | if (!good) { | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #if 0 /* JOQ: need a good way to select the right default MACOSX driver */ | |||||
| command = JACK_LOCATION "/jackd"; | command = JACK_LOCATION "/jackd"; | ||||
| strncpy(arguments, JACK_LOCATION "/jackd -T -d portaudio -p 512", 255); | strncpy(arguments, JACK_LOCATION "/jackd -T -d portaudio -p 512", 255); | ||||
| #elif defined(USE_CAPABILITIES) | #elif defined(USE_CAPABILITIES) | ||||
| @@ -624,7 +625,7 @@ jack_attach_port_segment (jack_client_t *client, jack_port_type_id_t ptid) | |||||
| client->port_segment = (jack_shm_info_t*) | client->port_segment = (jack_shm_info_t*) | ||||
| realloc (client->port_segment, | realloc (client->port_segment, | ||||
| sizeof (jack_shm_info_t) * (ptid+1)); | sizeof (jack_shm_info_t) * (ptid+1)); | ||||
| memset (&client->port_segment[client->n_port_types], | memset (&client->port_segment[client->n_port_types], | ||||
| 0, | 0, | ||||
| sizeof (jack_shm_info_t) * | sizeof (jack_shm_info_t) * | ||||
| @@ -636,7 +637,14 @@ jack_attach_port_segment (jack_client_t *client, jack_port_type_id_t ptid) | |||||
| /* release any previous segment */ | /* release any previous segment */ | ||||
| #if JACK_USE_MACH_THREADS | |||||
| /* Stephane Letz : letz@grame.fr | |||||
| Need a fix : this crash on MacOSX : temporary removed | |||||
| jack_release_shm (&client->port_segment[ptid]); | |||||
| */ | |||||
| #else | |||||
| jack_release_shm (&client->port_segment[ptid]); | jack_release_shm (&client->port_segment[ptid]); | ||||
| #endif | |||||
| } | } | ||||
| /* get the index into the shm registry */ | /* get the index into the shm registry */ | ||||
| @@ -747,7 +755,7 @@ jack_client_new (const char *client_name) | |||||
| client->event_fd = ev_fd; | client->event_fd = ev_fd; | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific resources for server/client real-time thread | /* specific resources for server/client real-time thread | ||||
| * communication */ | * communication */ | ||||
| client->clienttask = mach_task_self(); | client->clienttask = mach_task_self(); | ||||
| @@ -761,7 +769,7 @@ jack_client_new (const char *client_name) | |||||
| jack_error("Can't allocate mach port"); | jack_error("Can't allocate mach port"); | ||||
| goto fail; | goto fail; | ||||
| }; | }; | ||||
| #endif | |||||
| #endif /* JACK_USE_MACH_THREADS */ | |||||
| return client; | return client; | ||||
| fail: | fail: | ||||
| @@ -815,6 +823,24 @@ jack_internal_client_close (const char *client_name) | |||||
| return; | return; | ||||
| } | } | ||||
| #if JACK_USE_MACH_THREADS | |||||
| int | |||||
| jack_drop_real_time_scheduling (pthread_t thread) | |||||
| { | |||||
| setThreadToPriority(thread, 31, false, 10000000); | |||||
| return 0; | |||||
| } | |||||
| int | |||||
| jack_acquire_real_time_scheduling (pthread_t thread, int priority) //priority is unused | |||||
| { | |||||
| setThreadToPriority(thread, 96, true, 10000000); | |||||
| return 0; | |||||
| } | |||||
| #else | |||||
| int | int | ||||
| jack_drop_real_time_scheduling (pthread_t thread) | jack_drop_real_time_scheduling (pthread_t thread) | ||||
| { | { | ||||
| @@ -849,6 +875,8 @@ jack_acquire_real_time_scheduling (pthread_t thread, int priority) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| #endif | |||||
| int | int | ||||
| jack_set_freewheel (jack_client_t* client, int onoff) | jack_set_freewheel (jack_client_t* client, int onoff) | ||||
| { | { | ||||
| @@ -863,7 +891,11 @@ jack_start_freewheel (jack_client_t* client) | |||||
| jack_client_control_t *control = client->control; | jack_client_control_t *control = client->control; | ||||
| if (client->engine->real_time) { | if (client->engine->real_time) { | ||||
| #if JACK_USE_MACH_THREADS | |||||
| jack_drop_real_time_scheduling (client->process_thread); | |||||
| #else | |||||
| jack_drop_real_time_scheduling (client->thread); | jack_drop_real_time_scheduling (client->thread); | ||||
| #endif | |||||
| } | } | ||||
| if (control->freewheel_cb) { | if (control->freewheel_cb) { | ||||
| @@ -881,8 +913,13 @@ jack_stop_freewheel (jack_client_t* client) | |||||
| } | } | ||||
| if (client->engine->real_time) { | if (client->engine->real_time) { | ||||
| #if JACK_USE_MACH_THREADS | |||||
| jack_acquire_real_time_scheduling (client->process_thread, | |||||
| client->engine->client_priority); | |||||
| #else | |||||
| jack_acquire_real_time_scheduling (client->thread, | jack_acquire_real_time_scheduling (client->thread, | ||||
| client->engine->client_priority); | client->engine->client_priority); | ||||
| #endif | |||||
| } | } | ||||
| } | } | ||||
| @@ -1164,7 +1201,7 @@ jack_client_thread (void *arg) | |||||
| } | } | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* real-time thread : separated from the normal client thread, it will | /* real-time thread : separated from the normal client thread, it will | ||||
| * communicate with the server using fast mach RPC mechanism */ | * communicate with the server using fast mach RPC mechanism */ | ||||
| @@ -1176,14 +1213,17 @@ jack_client_process_thread (void *arg) | |||||
| int err = 0; | int err = 0; | ||||
| client->control->pid = getpid(); | client->control->pid = getpid(); | ||||
| DEBUG ("client process thread is now running"); | |||||
| DEBUG ("client process thread is now running"); | |||||
| pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||||
| pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||||
| client->rt_thread_ok = TRUE; | |||||
| while (err == 0) { | while (err == 0) { | ||||
| if (jack_client_suspend(client) < 0) { | if (jack_client_suspend(client) < 0) { | ||||
| pthread_exit (0); | |||||
| jack_error ("jack_client_process_thread : resume error"); | |||||
| goto zombie; | |||||
| } | } | ||||
| control->awake_at = jack_get_microseconds(); | control->awake_at = jack_get_microseconds(); | ||||
| @@ -1192,6 +1232,9 @@ jack_client_process_thread (void *arg) | |||||
| control->state = Running; | control->state = Running; | ||||
| if (control->sync_cb) | |||||
| jack_call_sync_client (client); | |||||
| if (control->process) { | if (control->process) { | ||||
| if (control->process (control->nframes, | if (control->process (control->nframes, | ||||
| control->process_arg) == 0) { | control->process_arg) == 0) { | ||||
| @@ -1200,6 +1243,9 @@ jack_client_process_thread (void *arg) | |||||
| } else { | } else { | ||||
| control->state = Finished; | control->state = Finished; | ||||
| } | } | ||||
| if (control->timebase_cb) | |||||
| jack_call_timebase_master (client); | |||||
| control->finished_at = jack_get_microseconds(); | control->finished_at = jack_get_microseconds(); | ||||
| @@ -1226,27 +1272,31 @@ jack_client_process_thread (void *arg) | |||||
| jack_error ("jack_client_process_thread : zombified"); | jack_error ("jack_client_process_thread : zombified"); | ||||
| client->rt_thread_ok = FALSE; | |||||
| if (client->on_shutdown) { | if (client->on_shutdown) { | ||||
| jack_error ("zombified - calling shutdown handler"); | jack_error ("zombified - calling shutdown handler"); | ||||
| client->on_shutdown (client->on_shutdown_arg); | client->on_shutdown (client->on_shutdown_arg); | ||||
| } else { | } else { | ||||
| jack_error ("zombified - exiting from JACK"); | jack_error ("zombified - exiting from JACK"); | ||||
| jack_client_close (client); /* Need a fix : possibly make client crash if zombified without shutdown handler */ | |||||
| jack_client_close (client); /* Need a fix : possibly make client crash if zombified without shutdown handler */ | |||||
| } | } | ||||
| pthread_exit (0); | pthread_exit (0); | ||||
| /*NOTREACHED*/ | /*NOTREACHED*/ | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| #endif | |||||
| #endif /* JACK_USE_MACH_THREADS */ | |||||
| static int | static int | ||||
| jack_start_thread (jack_client_t *client) | jack_start_thread (jack_client_t *client) | ||||
| { | { | ||||
| pthread_attr_t *attributes = 0; | |||||
| #ifndef JACK_USE_MACH_THREADS | |||||
| int policy = SCHED_OTHER; | int policy = SCHED_OTHER; | ||||
| struct sched_param client_param, temp_param; | struct sched_param client_param, temp_param; | ||||
| #endif | |||||
| pthread_attr_t *attributes = 0; | |||||
| if (client->engine->real_time) { | if (client->engine->real_time) { | ||||
| @@ -1282,9 +1332,7 @@ jack_start_thread (jack_client_t *client) | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| // To be implemented | |||||
| #else | |||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| if (client->engine->do_mlock | if (client->engine->do_mlock | ||||
| && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | ||||
| jack_error ("cannot lock down memory for RT thread (%s)", | jack_error ("cannot lock down memory for RT thread (%s)", | ||||
| @@ -1293,23 +1341,17 @@ jack_start_thread (jack_client_t *client) | |||||
| return -1; | return -1; | ||||
| #endif /* ENSURE_MLOCK */ | #endif /* ENSURE_MLOCK */ | ||||
| } | } | ||||
| #endif | |||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| } | } | ||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| if (pthread_create (&client->thread, attributes, | if (pthread_create (&client->thread, attributes, | ||||
| jack_client_thread, client)) { | jack_client_thread, client)) { | ||||
| if (client->engine->real_time) { | |||||
| /* we are probably dealing with a broken glibc so try | |||||
| to work around the bug, see below for more details | |||||
| */ | |||||
| goto realtime_workaround; | |||||
| } | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| /* a spcial real-time thread to call the "process" | |||||
| /* a special real-time thread to call the "process" | |||||
| * callback. It will communicate with the server using fast | * callback. It will communicate with the server using fast | ||||
| * mach RPC mechanism */ | * mach RPC mechanism */ | ||||
| if (pthread_create (&client->process_thread, attributes, | if (pthread_create (&client->process_thread, attributes, | ||||
| @@ -1319,18 +1361,22 @@ jack_start_thread (jack_client_t *client) | |||||
| } | } | ||||
| if (client->engine->real_time){ | if (client->engine->real_time){ | ||||
| /* time constraint thread */ | /* time constraint thread */ | ||||
| setThreadToPriority(client->process_thread, 96, true, 10000000); | |||||
| setThreadToPriority(client->process_thread, 96, TRUE, 10000000); | |||||
| }else{ | }else{ | ||||
| /* fixed priority thread */ | /* fixed priority thread */ | ||||
| setThreadToPriority(client->process_thread, 63, true, 10000000); | |||||
| setThreadToPriority(client->process_thread, 63, TRUE, 10000000); | |||||
| } | } | ||||
| #endif | |||||
| return 0; | |||||
| /* we get here only with engine running realtime */ | |||||
| #else /* !JACK_USE_MACH_THREADS */ | |||||
| realtime_workaround: | |||||
| if (pthread_create (&client->thread, attributes, | |||||
| jack_client_thread, client) == 0) { | |||||
| return 0; | |||||
| } | |||||
| if (!client->engine->real_time) { | |||||
| return -1; | |||||
| } | |||||
| /* the version of glibc I've played with has a bug that makes | /* the version of glibc I've played with has a bug that makes | ||||
| that code fail when running under a non-root user but with the | that code fail when running under a non-root user but with the | ||||
| @@ -1420,6 +1466,8 @@ jack_start_thread (jack_client_t *client) | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif /* JACK_USE_MACH_THREADS */ | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1433,22 +1481,13 @@ jack_activate (jack_client_t *client) | |||||
| * usage in jack_start_thread()) | * usage in jack_start_thread()) | ||||
| */ | */ | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| /* a bigger stack makes the application crash... */ | |||||
| #define BIG_ENOUGH_STACK 10000 | |||||
| #else | |||||
| #define BIG_ENOUGH_STACK 1048576 | |||||
| #endif | |||||
| char buf[BIG_ENOUGH_STACK]; | |||||
| char buf[JACK_THREAD_STACK_TOUCH]; | |||||
| int i; | int i; | ||||
| for (i = 0; i < BIG_ENOUGH_STACK; i++) { | |||||
| for (i = 0; i < JACK_THREAD_STACK_TOUCH; i++) { | |||||
| buf[i] = (char) (i & 0xff); | buf[i] = (char) (i & 0xff); | ||||
| } | } | ||||
| #undef BIG_ENOUGH_STACK | |||||
| if (client->control->type == ClientInternal || | if (client->control->type == ClientInternal || | ||||
| client->control->type == ClientDriver) { | client->control->type == ClientDriver) { | ||||
| goto startit; | goto startit; | ||||
| @@ -1546,6 +1585,16 @@ jack_client_close (jack_client_t *client) | |||||
| } | } | ||||
| if (client->control->type == ClientExternal) { | if (client->control->type == ClientExternal) { | ||||
| #if JACK_USE_MACH_THREADS | |||||
| if (client->rt_thread_ok) { | |||||
| // MacOSX pthread_cancel not implemented in | |||||
| // Darwin 5.5, 6.4 | |||||
| mach_port_t machThread = | |||||
| pthread_mach_thread_np (client->process_thread); | |||||
| thread_terminate (machThread); | |||||
| } | |||||
| #endif | |||||
| /* stop the thread that communicates with the jack | /* stop the thread that communicates with the jack | ||||
| * server, only if it was actually running | * server, only if it was actually running | ||||
| @@ -1889,69 +1938,3 @@ jack_port_type_size(void) | |||||
| { | { | ||||
| return JACK_PORT_TYPE_SIZE; | return JACK_PORT_TYPE_SIZE; | ||||
| } | } | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| double __jack_time_ratio; | |||||
| void jack_init_time () | |||||
| { | |||||
| mach_timebase_info_data_t info; | |||||
| mach_timebase_info(&info); | |||||
| __jack_time_ratio = ((float)info.numer/info.denom) / 1000; | |||||
| } | |||||
| #else | |||||
| jack_time_t | |||||
| jack_get_mhz (void) | |||||
| { | |||||
| FILE *f = fopen("/proc/cpuinfo", "r"); | |||||
| if (f == 0) | |||||
| { | |||||
| perror("can't open /proc/cpuinfo\n"); | |||||
| exit(1); | |||||
| } | |||||
| for ( ; ; ) | |||||
| { | |||||
| jack_time_t mhz; | |||||
| int ret; | |||||
| char buf[1000]; | |||||
| if (fgets(buf, sizeof(buf), f) == NULL) { | |||||
| jack_error ("FATAL: cannot locate cpu MHz in " | |||||
| "/proc/cpuinfo\n"); | |||||
| exit(1); | |||||
| } | |||||
| #if defined(__powerpc__) | |||||
| ret = sscanf(buf, "clock\t: %" SCNu64 "MHz", &mhz); | |||||
| #elif defined( __i386__ ) || defined (__hppa__) || defined (__ia64__) || \ | |||||
| defined(__x86_64__) | |||||
| ret = sscanf(buf, "cpu MHz : %" SCNu64, &mhz); | |||||
| #elif defined( __sparc__ ) | |||||
| ret = sscanf(buf, "Cpu0Bogo : %" SCNu64, &mhz); | |||||
| #elif defined( __mc68000__ ) | |||||
| ret = sscanf(buf, "Clocking: %" SCNu64, &mhz); | |||||
| #elif defined( __s390__ ) | |||||
| ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz); | |||||
| #else /* MIPS, ARM, alpha */ | |||||
| ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz); | |||||
| #endif | |||||
| if (ret == 1) | |||||
| { | |||||
| fclose(f); | |||||
| return (jack_time_t)mhz; | |||||
| } | |||||
| } | |||||
| } | |||||
| jack_time_t __jack_cpu_mhz; | |||||
| void jack_init_time () | |||||
| { | |||||
| __jack_cpu_mhz = jack_get_mhz (); | |||||
| } | |||||
| #endif | |||||
| @@ -19,20 +19,22 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #include <config.h> | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <stdarg.h> | #include <stdarg.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <sys/mman.h> | |||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <config.h> | |||||
| #include <jack/driver.h> | |||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/driver.h> | |||||
| #include <jack/engine.h> | #include <jack/engine.h> | ||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| #include <sys/mman.h> | |||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| static int dummy_attach (jack_driver_t *drv, jack_engine_t *eng) { return 0; } | static int dummy_attach (jack_driver_t *drv, jack_engine_t *eng) { return 0; } | ||||
| static int dummy_detach (jack_driver_t *drv, jack_engine_t *eng) { return 0; } | static int dummy_detach (jack_driver_t *drv, jack_engine_t *eng) { return 0; } | ||||
| static int dummy_write (jack_driver_t *drv, | static int dummy_write (jack_driver_t *drv, | ||||
| @@ -105,6 +107,7 @@ jack_driver_nt_become_real_time (jack_driver_nt_t* driver) | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| if (driver->engine->control->do_mlock | if (driver->engine->control->do_mlock | ||||
| && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | ||||
| jack_error ("cannot lock down memory for RT thread (%s)", | jack_error ("cannot lock down memory for RT thread (%s)", | ||||
| @@ -113,6 +116,7 @@ jack_driver_nt_become_real_time (jack_driver_nt_t* driver) | |||||
| return -1; | return -1; | ||||
| #endif /* ENSURE_MLOCK */ | #endif /* ENSURE_MLOCK */ | ||||
| } | } | ||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -31,11 +31,12 @@ struct _jack_client { | |||||
| char first_active : 1; | char first_active : 1; | ||||
| pthread_t thread_id; | pthread_t thread_id; | ||||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||||
| #ifdef JACK_USE_MACH_THREADS | |||||
| /* specific ressources for server/client real-time thread communication */ | /* specific ressources for server/client real-time thread communication */ | ||||
| mach_port_t clienttask, bp, serverport, replyport; | mach_port_t clienttask, bp, serverport, replyport; | ||||
| trivial_message message; | trivial_message message; | ||||
| pthread_t process_thread; | pthread_t process_thread; | ||||
| char rt_thread_ok : 1; | |||||
| #endif | #endif | ||||
| }; | }; | ||||
| @@ -18,18 +18,26 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #include <config.h> | |||||
| #ifdef HAVE_POSIX_MEMALIGN | |||||
| #define _XOPEN_SOURCE 600 | #define _XOPEN_SOURCE 600 | ||||
| #endif | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <config.h> | #include <config.h> | ||||
| #include <jack/pool.h> | #include <jack/pool.h> | ||||
| /* XXX need RT-pool based allocator here */ | |||||
| void * | void * | ||||
| jack_pool_alloc (size_t bytes) | jack_pool_alloc (size_t bytes) | ||||
| { | { | ||||
| /* XXX need RT-pool based allocator here */ | |||||
| #ifdef HAVE_POSIX_MEMALIGN | |||||
| void* m; | void* m; | ||||
| int err = posix_memalign (&m, 16, bytes); | int err = posix_memalign (&m, 16, bytes); | ||||
| return (!err) ? m : 0; | return (!err) ? m : 0; | ||||
| #else | |||||
| return malloc (bytes); | |||||
| #endif /* HAVE_POSIX_MEMALIGN */ | |||||
| } | } | ||||
| void | void | ||||
| @@ -20,9 +20,12 @@ | |||||
| This is safe for the case of one read thread and one write thread. | This is safe for the case of one read thread and one write thread. | ||||
| */ | */ | ||||
| #include <sysdeps/os_defines.h> | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| #include <sys/mman.h> | #include <sys/mman.h> | ||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| #include <jack/ringbuffer.h> | #include <jack/ringbuffer.h> | ||||
| /* Create a new ringbuffer to hold at least `sz' bytes of data. The | /* Create a new ringbuffer to hold at least `sz' bytes of data. The | ||||
| @@ -54,9 +57,11 @@ jack_ringbuffer_create (size_t sz) | |||||
| void | void | ||||
| jack_ringbuffer_free (jack_ringbuffer_t * rb) | jack_ringbuffer_free (jack_ringbuffer_t * rb) | ||||
| { | { | ||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| if (rb->mlocked) { | if (rb->mlocked) { | ||||
| munlock (rb->buf, rb->size); | munlock (rb->buf, rb->size); | ||||
| } | } | ||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| free (rb->buf); | free (rb->buf); | ||||
| } | } | ||||
| @@ -65,9 +70,11 @@ jack_ringbuffer_free (jack_ringbuffer_t * rb) | |||||
| int | int | ||||
| jack_ringbuffer_mlock (jack_ringbuffer_t * rb) | jack_ringbuffer_mlock (jack_ringbuffer_t * rb) | ||||
| { | { | ||||
| #ifndef JACK_DO_NOT_MLOCK | |||||
| if (mlock (rb->buf, rb->size)) { | if (mlock (rb->buf, rb->size)) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| #endif /* JACK_DO_NOT_MLOCK */ | |||||
| rb->mlocked = 1; | rb->mlocked = 1; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -17,6 +17,7 @@ | |||||
| $Id$ | $Id$ | ||||
| */ | */ | ||||
| #include <config.h> | |||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <fcntl.h> | #include <fcntl.h> | ||||
| @@ -25,12 +26,10 @@ | |||||
| #include <signal.h> | #include <signal.h> | ||||
| #include <limits.h> | #include <limits.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <dirent.h> | |||||
| #include <sys/mman.h> | #include <sys/mman.h> | ||||
| #include <sys/types.h> | #include <sys/types.h> | ||||
| #include <dirent.h> | |||||
| #include <sys/ipc.h> | |||||
| #include <sys/shm.h> | #include <sys/shm.h> | ||||
| #include <config.h> | |||||
| #include <jack/shm.h> | #include <jack/shm.h> | ||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| @@ -22,7 +22,7 @@ | |||||
| #include <string.h> | #include <string.h> | ||||
| #include <jack/timestamps.h> | #include <jack/timestamps.h> | ||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include <jack/time.h> | |||||
| #include <sysdeps/time.h> | |||||
| typedef struct { | typedef struct { | ||||
| jack_time_t when; | jack_time_t when; | ||||
| @@ -24,6 +24,7 @@ | |||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <math.h> | #include <math.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <jack/atomicity.h> | |||||
| #include <jack/internal.h> | #include <jack/internal.h> | ||||
| #include "local.h" | #include "local.h" | ||||
| @@ -34,40 +35,8 @@ | |||||
| jack_unique_t | jack_unique_t | ||||
| jack_generate_unique_id (jack_control_t *ectl) | jack_generate_unique_id (jack_control_t *ectl) | ||||
| { | { | ||||
| /* The jack_unique_t is an opaque type. Its structure is only | |||||
| * known here. We use the least significant word of the CPU | |||||
| * cycle counter. For SMP, I would like to include the | |||||
| * current thread ID, since only one thread runs on a CPU at a | |||||
| * time. | |||||
| * | |||||
| * But, pthread_self() is broken on my Debian GNU/Linux | |||||
| * system, it always seems to return 16384. That's useless. | |||||
| * So, I'm using the process ID instead. With Linux 2.4 and | |||||
| * Linuxthreads there is an LWP for each thread so this works, | |||||
| * but is not portable. :-( | |||||
| */ | |||||
| volatile union { | |||||
| jack_unique_t unique; | |||||
| struct { | |||||
| pid_t pid; | |||||
| unsigned long cycle; | |||||
| } field; | |||||
| } id; | |||||
| id.field.cycle = (unsigned long) get_cycles(); | |||||
| id.field.pid = getpid(); | |||||
| // JOQ: Alternatively, we could keep a sequence number in | |||||
| // shared memory, using <asm/atomic.h> to increment it. I | |||||
| // really like the simplicity of that approach. But I hate | |||||
| // forcing JACK to either depend on that pesky header file, or | |||||
| // maintain its own like ardour does. | |||||
| // fprintf (stderr, "unique ID 0x%" PRIx64 | |||||
| // ", process %d, cycle 0x%" PRIx32 "\n", | |||||
| // id.unique, id.field.pid, id.field.cycle); | |||||
| return id.unique; | |||||
| /* The jack_unique_t is an opaque type. */ | |||||
| return exchange_and_add(&ectl->seq_number, 1); | |||||
| } | } | ||||
| static inline void | static inline void | ||||
| @@ -226,7 +195,8 @@ jack_get_current_transport_frame (const jack_client_t *client) | |||||
| */ | */ | ||||
| usecs = jack_get_microseconds() - position.usecs; | usecs = jack_get_microseconds() - position.usecs; | ||||
| elapsed = (jack_nframes_t) floor ((((float) position.frame_rate) / 1000000.0f) * usecs); | |||||
| elapsed = (jack_nframes_t) floor ((((float) position.frame_rate) | |||||
| / 1000000.0f) * usecs); | |||||
| /* return the estimated transport frame position | /* return the estimated transport frame position | ||||
| */ | */ | ||||
| @@ -1,53 +0,0 @@ | |||||
| // fakepoll.h | |||||
| // poll using select | |||||
| // Warning: a call to this poll() takes about 4K of stack space. | |||||
| // Greg Parker gparker-web@sealiesoftware.com December 2000 | |||||
| // This code is in the public domain and may be copied or modified without | |||||
| // permission. | |||||
| // Updated May 2002: | |||||
| // * fix crash when an fd is less than 0 | |||||
| // * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE | |||||
| // * don't set POLLIN or POLLOUT in revents if it wasn't requested | |||||
| // in events (only happens when an fd is in the poll set twice) | |||||
| #ifndef _FAKE_POLL_H | |||||
| #define _FAKE_POLL_H | |||||
| #include <limits.h> | |||||
| #define FD_SETSIZE OPEN_MAX | |||||
| #include <sys/types.h> | |||||
| #include <sys/time.h> | |||||
| #include <unistd.h> | |||||
| #include <stdlib.h> | |||||
| #include <errno.h> | |||||
| typedef struct pollfd { | |||||
| int fd; /* file desc to poll */ | |||||
| short events; /* events of interest on fd */ | |||||
| short revents; /* events that occurred on fd */ | |||||
| } pollfd_t; | |||||
| // poll flags | |||||
| #define POLLIN 0x0001 | |||||
| #define POLLOUT 0x0004 | |||||
| #define POLLERR 0x0008 | |||||
| // synonyms | |||||
| #define POLLNORM POLLIN | |||||
| #define POLLPRI POLLIN | |||||
| #define POLLRDNORM POLLIN | |||||
| #define POLLRDBAND POLLIN | |||||
| #define POLLWRNORM POLLOUT | |||||
| #define POLLWRBAND POLLOUT | |||||
| // ignored | |||||
| #define POLLHUP 0x0010 | |||||
| #define POLLNVAL 0x0020 | |||||
| inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout); | |||||
| #endif | |||||
| @@ -1,150 +0,0 @@ | |||||
| /* Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved. | |||||
| Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. | |||||
| ("Apple") in consideration of your agreement to the following terms, and your | |||||
| use, installation, modification or redistribution of this Apple software | |||||
| constitutes acceptance of these terms. If you do not agree with these terms, | |||||
| please do not use, install, modify or redistribute this Apple software. | |||||
| In consideration of your agreement to abide by the following terms, and subject | |||||
| to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs | |||||
| copyrights in this original Apple software (the "Apple Software"), to use, | |||||
| reproduce, modify and redistribute the Apple Software, with or without | |||||
| modifications, in source and/or binary forms; provided that if you redistribute | |||||
| the Apple Software in its entirety and without modifications, you must retain | |||||
| this notice and the following text and disclaimers in all such redistributions of | |||||
| the Apple Software. Neither the name, trademarks, service marks or logos of | |||||
| Apple Computer, Inc. may be used to endorse or promote products derived from the | |||||
| Apple Software without specific prior written permission from Apple. Except as | |||||
| expressly stated in this notice, no other rights or licenses, express or implied, | |||||
| are granted by Apple herein, including but not limited to any patent rights that | |||||
| may be infringed by your derivative works or by other works in which the Apple | |||||
| Software may be incorporated. | |||||
| The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | |||||
| WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | |||||
| WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||||
| PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | |||||
| COMBINATION WITH YOUR PRODUCTS. | |||||
| IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | |||||
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |||||
| GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
| ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION | |||||
| OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT | |||||
| (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN | |||||
| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| */ | |||||
| /* pThreadUtilities.c */ | |||||
| #define THREAD_SET_PRIORITY 0 | |||||
| #define THREAD_SCHEDULED_PRIORITY 1 | |||||
| #include <mach/thread_policy.h> | |||||
| #include <mach/thread_act.h> | |||||
| #include <CoreAudio/HostTime.h> | |||||
| #include "pThreadUtilities.h" | |||||
| UInt32 _getThreadPriority (pthread_t inThread, int inWhichPriority); | |||||
| void setThreadToPriority(pthread_t inThread, UInt32 inPriority, Boolean inIsFixed, UInt64 inHALIOProcCycleDurationInNanoseconds) | |||||
| { | |||||
| if (inPriority == 96) | |||||
| { | |||||
| // REAL-TIME / TIME-CONSTRAINT THREAD | |||||
| thread_time_constraint_policy_data_t theTCPolicy; | |||||
| UInt64 theComputeQuanta; | |||||
| UInt64 thePeriod; | |||||
| UInt64 thePeriodNanos; | |||||
| thePeriodNanos = inHALIOProcCycleDurationInNanoseconds; | |||||
| theComputeQuanta = AudioConvertNanosToHostTime ( thePeriodNanos * 0.15 ); | |||||
| thePeriod = AudioConvertNanosToHostTime (thePeriodNanos); | |||||
| theTCPolicy.period = thePeriod; | |||||
| theTCPolicy.computation = theComputeQuanta; | |||||
| theTCPolicy.constraint = thePeriod; | |||||
| theTCPolicy.preemptible = true; | |||||
| thread_policy_set (pthread_mach_thread_np(inThread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&theTCPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT); | |||||
| } else { | |||||
| // OTHER THREADS | |||||
| thread_extended_policy_data_t theFixedPolicy; | |||||
| thread_precedence_policy_data_t thePrecedencePolicy; | |||||
| SInt32 relativePriority; | |||||
| // [1] SET FIXED / NOT FIXED | |||||
| theFixedPolicy.timeshare = !inIsFixed; | |||||
| thread_policy_set (pthread_mach_thread_np(inThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); | |||||
| // [2] SET PRECEDENCE | |||||
| // N.B.: We expect that if thread A created thread B, and the program wishes to change | |||||
| // the priority of thread B, then the call to change the priority of thread B must be | |||||
| // made by thread A. | |||||
| // This assumption allows us to use pthread_self() to correctly calculate the priority | |||||
| // of the feeder thread (since precedency policy's importance is relative to the | |||||
| // spawning thread's priority.) | |||||
| relativePriority = inPriority - getThreadSetPriority (pthread_self()); | |||||
| thePrecedencePolicy.importance = relativePriority; | |||||
| thread_policy_set (pthread_mach_thread_np(inThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); | |||||
| } | |||||
| } | |||||
| // returns the thread's priority as it was last set by the API | |||||
| UInt32 getThreadSetPriority(pthread_t inThread) | |||||
| { | |||||
| return _getThreadPriority (inThread, THREAD_SET_PRIORITY); | |||||
| } | |||||
| // returns the thread's priority as it was last scheduled by the Kernel | |||||
| UInt32 getThreadScheduledPriority(pthread_t inThread) | |||||
| { | |||||
| return _getThreadPriority (inThread, THREAD_SCHEDULED_PRIORITY); | |||||
| } | |||||
| UInt32 _getThreadPriority(pthread_t inThread, int inWhichPriority) | |||||
| { | |||||
| thread_basic_info_data_t threadInfo; | |||||
| policy_info_data_t thePolicyInfo; | |||||
| unsigned int count; | |||||
| // get basic info | |||||
| count = THREAD_BASIC_INFO_COUNT; | |||||
| thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (thread_info_t)&threadInfo, &count); | |||||
| switch (threadInfo.policy) { | |||||
| case POLICY_TIMESHARE: | |||||
| count = POLICY_TIMESHARE_INFO_COUNT; | |||||
| thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&(thePolicyInfo.ts), &count); | |||||
| if (inWhichPriority == THREAD_SCHEDULED_PRIORITY) { | |||||
| return thePolicyInfo.ts.cur_priority; | |||||
| } else { | |||||
| return thePolicyInfo.ts.base_priority; | |||||
| } | |||||
| break; | |||||
| case POLICY_FIFO: | |||||
| count = POLICY_FIFO_INFO_COUNT; | |||||
| thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (thread_info_t)&(thePolicyInfo.fifo), &count); | |||||
| if ( (thePolicyInfo.fifo.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) { | |||||
| return thePolicyInfo.fifo.depress_priority; | |||||
| } | |||||
| return thePolicyInfo.fifo.base_priority; | |||||
| break; | |||||
| case POLICY_RR: | |||||
| count = POLICY_RR_INFO_COUNT; | |||||
| thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (thread_info_t)&(thePolicyInfo.rr), &count); | |||||
| if ( (thePolicyInfo.rr.depressed) && (inWhichPriority == THREAD_SCHEDULED_PRIORITY) ) { | |||||
| return thePolicyInfo.rr.depress_priority; | |||||
| } | |||||
| return thePolicyInfo.rr.base_priority; | |||||
| break; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| @@ -1,50 +0,0 @@ | |||||
| /* Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved. | |||||
| Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. | |||||
| ("Apple") in consideration of your agreement to the following terms, and your | |||||
| use, installation, modification or redistribution of this Apple software | |||||
| constitutes acceptance of these terms. If you do not agree with these terms, | |||||
| please do not use, install, modify or redistribute this Apple software. | |||||
| In consideration of your agreement to abide by the following terms, and subject | |||||
| to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs | |||||
| copyrights in this original Apple software (the "Apple Software"), to use, | |||||
| reproduce, modify and redistribute the Apple Software, with or without | |||||
| modifications, in source and/or binary forms; provided that if you redistribute | |||||
| the Apple Software in its entirety and without modifications, you must retain | |||||
| this notice and the following text and disclaimers in all such redistributions of | |||||
| the Apple Software. Neither the name, trademarks, service marks or logos of | |||||
| Apple Computer, Inc. may be used to endorse or promote products derived from the | |||||
| Apple Software without specific prior written permission from Apple. Except as | |||||
| expressly stated in this notice, no other rights or licenses, express or implied, | |||||
| are granted by Apple herein, including but not limited to any patent rights that | |||||
| may be infringed by your derivative works or by other works in which the Apple | |||||
| Software may be incorporated. | |||||
| The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | |||||
| WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | |||||
| WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||||
| PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | |||||
| COMBINATION WITH YOUR PRODUCTS. | |||||
| IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | |||||
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |||||
| GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
| ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION | |||||
| OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT | |||||
| (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN | |||||
| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| */ | |||||
| /* pThreadUtilities.h */ | |||||
| #ifndef __PTHREADUTILITIES_H__ | |||||
| #define __PTHREADUTILITIES_H__ | |||||
| #import "pthread.h" | |||||
| #import <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> | |||||
| void setThreadToPriority(pthread_t inThread, UInt32 inPriority, Boolean inIsFixed, UInt64 inHALIOProcCycleDurationInNanoseconds); | |||||
| UInt32 getThreadSetPriority(pthread_t inThread); | |||||
| UInt32 getThreadScheduledPriority(pthread_t inThread); | |||||
| #endif /* __PTHREADUTILITIES_H__ */ | |||||
| @@ -1,133 +0,0 @@ | |||||
| Darwin/MacOSX port for Jack : architecture changes in the implementation | |||||
| ======================================================================== | |||||
| Shared memory | |||||
| ============= | |||||
| The system V shared memory is not very reliable on Darwin/MacOSX. The POSIX shared memory API is used instead. | |||||
| Jack server audio cycle | |||||
| ======================== | |||||
| On Linux, the jack server audio cycle (jack_run_cycle function) is called in a real-time SCHED_FIFO thread. | |||||
| On Darwin/MacOSX, the jack_run_cycle is directly called inside the CoreAudio audio callback. | |||||
| External client activation | |||||
| =========================== | |||||
| Jack Linux implementation use system fifo/pipe to trigger the clients real-time callback from the server : | |||||
| the first client of an external subgraph is triggered, does it's job and wakes up the next one in the list, | |||||
| and so on until the last client that wakes up the Jack server. This avoid uneeded context switches between | |||||
| the server and clients and thus is more efficient. | |||||
| This Linux implementation works also on Darwin/MacOSX but is not very efficient : audio gliches occur quite | |||||
| frequently. | |||||
| A more efficient system for external client activation has been developed. It use low-level mach messages | |||||
| system to implement fast IPC between the Jack server and the running clients. The Darwin/MacOSX has a very | |||||
| efficient Remote Procedure Call (RPC) implementation that can be used : the Jack server activate each external | |||||
| client in turn in a loop. | |||||
| On the client side, each client uses an additionnal thread only used for the real-time process callback, | |||||
| that will be triggered by the Jack server using this fast RPC mechanism. | |||||
| Real-time threads | |||||
| ================== | |||||
| The Darwin/MacOSX system use a special class of scheduling for real-time threads : | |||||
| Since the server audio cycle is called directly from the CoreAudio callback, there is nothing special | |||||
| to do on the server side. On the client side, the thread used to call the "process" callback from the | |||||
| server is made real-time, using the mach thread API. | |||||
| Compilation and installation | |||||
| ============================= | |||||
| - In the jack/jack folder, you'll have to produce the version.h manually from the version.h.in file ): | |||||
| Edit the version.h.in, replace the JACK_PROTOCOL_VERSION value with the one found in configure.in and | |||||
| save as a new version.h file. You should get something like "#define jack_protocol_version 6" in the file. | |||||
| Several packages need to be installed before compiling Jack : | |||||
| - Fink dlcompat (fink.sourceforge.net) : this package define the dlopen, dlsym... API used in Jack to | |||||
| load drivers and internal clients. The package has to be installed before compiling Jack. | |||||
| - fakepoll is a implementation of the poll function using select. The Fink version of poll does not | |||||
| work correctly, thus the public domain "fakepoll" code has been used instead. It is directly included | |||||
| in the Jack Darwin/MacOSX port. | |||||
| - PortAudio (www.portaudio.com) : PortAudio is a free, cross platform, open-source, audio I/O library. | |||||
| The Jack CoreAudio driver actually is implemented using PortAudio. The PortAudio source code for MacOSX | |||||
| has to be installed and compiled to produce a framework called "PortAudio.framework" that will be used | |||||
| in the Jack link phase. | |||||
| Several targets are avaiblable in the Project Builder project : | |||||
| - jackd : build the Jack server ("jackd" executable) | |||||
| - jack framework : build the "Jack.framework" library. | |||||
| - driver : build the PortAudio driver as a "jack_portaudio.so" shared library. | |||||
| - jack_metro : build the "jack_metro" executable. | |||||
| - jack_lsp : build the "jack_lsp" executable. | |||||
| - jack_connect : build the "jack_connect" executable. | |||||
| - jack_disconnect : build the "jack_disconnect" executable. | |||||
| Server, driver and library installation : | |||||
| ----------------------------------------- | |||||
| First copy the Jack.framework in /Library/Framework. Then as root : | |||||
| cp jack_portaudio /usr/local/lib | |||||
| cp jackd /usr/local/bin | |||||
| Launching Jack server : | |||||
| ----------------------- | |||||
| By default buffer size is 128 frames and sample rate is 44100. | |||||
| jackd -v -R -d coreaudio | |||||
| To setup a 32 frames buffer and a 4800 Hz sample rate : | |||||
| jackd -v -R -d coreaudio -p 32 -r 48000 | |||||
| Performances | |||||
| ============= | |||||
| The Darwin/MacOSX implementation is quite efficient : on a G4/867 Mhz, the Jack server can run with | |||||
| a 32 frames buffer size without noticable problems. | |||||
| Known problems or unimplemented features | |||||
| ========================================= | |||||
| - thread cancellation : the pthread API pthread_cancel is not completely available on Darwin/MacOSX. | |||||
| Thread cannot be cancelled in the general case : they must use explicit cancelation points like | |||||
| "pthread_testcancel" (see the "jack_client_thread" function) | |||||
| - xruns detection and report : not implemented. | |||||
| Possible improvements | |||||
| ====================== | |||||
| - The audio driver is built on top of PortAudio. It may be more efficient to directly use the | |||||
| CoreAudio API in order to avoid additionnal buffer copy and interleaving/desinterleaving operations. | |||||
| - The project uses Project Builder. It would be helpful to work on the autoconf, automake ... tools | |||||
| as in the Linux version. Is this case, the macosx/config.h file would have to be removed and generated | |||||
| by configure, and jack/version.h will be generated automatically from jack/version.h.in | |||||
| - Better separation of Linux and Darwin/MacOSX only code. | |||||
| The Jack port for Darwin/MacOSX version has be done by : | |||||
| Grame Research Laboratory | |||||
| 9, rue du Garet 69001 Lyon - France | |||||
| Mail : letz@grame.fr | |||||