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 | |||
| config.cache | |||
| config.h | |||
| config.h.in | |||
| stamp-h1 | |||
| config.log | |||
| aclocal.m4 | |||
| config.status | |||
| config.cache | |||
| libtool | |||
| *.pc | |||
| .deps | |||
| Makefile | |||
| Makefile.in | |||
| jack.spec | |||
| 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 \ | |||
| config.guess mkinstalldirs config.status \ | |||
| missing install-sh config.sub ltconfig \ | |||
| ltmain.sh | |||
| config.status | |||
| if HAVE_DOXYGEN | |||
| DOC_DIR = doc | |||
| @@ -16,14 +14,13 @@ dist-check-doxygen: | |||
| @false | |||
| 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 | |||
| pkgconfig_DATA = jack.pc | |||
| EXTRA_DIST = depcomp COPYING COPYING.GPL COPYING.LGPL | |||
| EXTRA_DIST = COPYING COPYING.GPL COPYING.LGPL | |||
| 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 | |||
| - add explanation of protocol versioning to README.developers (kaiv) | |||
| @@ -1,11 +1,25 @@ | |||
| #!/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..." | |||
| exit 1 | |||
| } | |||
| aclocal $ACLOCAL_FLAGS || { | |||
| aclocal $ACLOCAL_FLAGS -I config || { | |||
| echo "aclocal \$ACLOCAL_FLAGS where \$ACLOCAL_FLAGS= failed, exiting..." | |||
| 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 | |||
| it under the terms of the GNU General Public License as published by | |||
| 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 | |||
| 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 | |||
| $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__ | |||
| #define __jack_cycles_h__ | |||
| #if defined(__i386__) || defined(__x86_64__) | |||
| /* | |||
| * Standard way to access the cycle counter on i586+ CPUs. | |||
| * Currently only used on SMP. | |||
| @@ -53,76 +51,4 @@ static inline cycles_t get_cycles (void) | |||
| 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__ */ | |||
| @@ -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 | |||
| #include <limits.h> | |||
| #define FD_SETSIZE OPEN_MAX | |||
| #include <sys/types.h> | |||
| #include <sys/time.h> | |||
| #include <unistd.h> | |||
| @@ -19,13 +19,4 @@ | |||
| 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 | |||
| */ | |||
| #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 */ | |||
| int | |||
| static inline int | |||
| jack_client_resume(jack_client_internal_t *client) | |||
| { | |||
| mach_msg_header_t *head = &client->message.header; | |||
| int err; | |||
| 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) { | |||
| 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; | |||
| } | |||
| client->running = TRUE; | |||
| @@ -49,28 +79,34 @@ jack_client_resume(jack_client_internal_t *client) | |||
| head->msgh_local_port = MACH_PORT_NULL; | |||
| 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) { | |||
| /* | |||
| switch(err) { | |||
| 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; | |||
| 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; | |||
| 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; | |||
| } | |||
| */ | |||
| 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; | |||
| } | |||
| } | |||
| @@ -78,39 +114,44 @@ jack_client_resume(jack_client_internal_t *client) | |||
| return 0; | |||
| } | |||
| int | |||
| static inline int | |||
| jack_client_suspend(jack_client_t * client) | |||
| { | |||
| int err = 0; | |||
| 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_local_port = client->replyport; | |||
| head->msgh_size = sizeof(mach_msg_header_t); | |||
| 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) { | |||
| 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 0; | |||
| } | |||
| void | |||
| static inline void | |||
| allocate_mach_serverport(jack_engine_t * engine, jack_client_internal_t *client) | |||
| { | |||
| char buf[256]; | |||
| 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"); | |||
| } | |||
| 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"); | |||
| } | |||
| @@ -122,7 +163,7 @@ allocate_mach_serverport(jack_engine_t * engine, jack_client_internal_t *client) | |||
| engine->portnum++; | |||
| } | |||
| int | |||
| static inline int | |||
| allocate_mach_clientport(jack_client_t * client, int portnum) | |||
| { | |||
| char buf[256]; | |||
| @@ -133,7 +174,8 @@ allocate_mach_clientport(jack_client_t * client, int portnum) | |||
| 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"); | |||
| return -1; | |||
| } | |||
| @@ -141,4 +183,4 @@ allocate_mach_clientport(jack_client_t * client, int portnum) | |||
| 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 | |||
| 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 | |||
| @@ -18,12 +20,9 @@ | |||
| $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__ | |||
| #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> | |||
| extern void jack_init_time (); | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #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; | |||
| } | |||
| #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__ */ | |||
| @@ -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. | |||
| AC_INIT(jackd/jackd.c) | |||
| AC_CONFIG_AUX_DIR(.) | |||
| AC_CONFIG_AUX_DIR(config) | |||
| AC_CANONICAL_TARGET | |||
| dnl --- | |||
| @@ -14,8 +14,8 @@ dnl micro version = incremented when implementation-only | |||
| dnl changes are made | |||
| dnl --- | |||
| JACK_MAJOR_VERSION=0 | |||
| JACK_MINOR_VERSION=95 | |||
| JACK_MICRO_VERSION=11 | |||
| JACK_MINOR_VERSION=96 | |||
| JACK_MICRO_VERSION=0 | |||
| dnl --- | |||
| dnl HOWTO: updating the jack protocol version | |||
| @@ -68,63 +68,58 @@ AM_INIT_AUTOMAKE(jack-audio-connection-kit,${JACK_VERSION}) | |||
| AM_MAINTAINER_MODE | |||
| AM_CONFIG_HEADER(config.h) | |||
| AC_ENABLE_STATIC(no) | |||
| AC_ENABLE_SHARED(yes) | |||
| AC_PROG_CC | |||
| AC_PROG_CXX | |||
| AC_PROG_LD | |||
| AM_PROG_LIBTOOL | |||
| AC_PROG_LN_S | |||
| 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_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(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) | |||
| AC_CHECK_FUNC(connect, , AC_CHECK_LIB(inet, connect)) | |||
| 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 ], | |||
| 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" | |||
| 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 | |||
| echo ' JACK will use System V shm API (shmget() and friends)' | |||
| AC_MSG_RESULT([System V shmget().]) | |||
| 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_OPT_CFLAGS="$JACK_CORE_CFLAGS -g -march=pentium2 -mcpu=pentium4 -O3 -ffast-math -funroll-loops -fprefetch-loop-arrays" | |||
| dnl | |||
| dnl figure out how best to optimize | |||
| dnl JOQ: this should be done via config/configure.hosts | |||
| dnl | |||
| if test "$target_cpu" = "powerpc"; then | |||
| 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 | |||
| AC_DEFINE(HAVE_ALTIVEC_LINUX, 1, "Is there Altivec Support ?") | |||
| if test "$gcc_major_version" = "3"; then | |||
| @@ -164,8 +159,10 @@ elif echo $target_cpu | grep "i*86" >/dev/null; then | |||
| fi | |||
| 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) | |||
| @@ -387,8 +384,8 @@ fi | |||
| # on some systems, readline depends on termcap or ncurses, respectively | |||
| 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, | |||
| [HAVE_READLINE=true], [HAVE_READLINE=false], [$READLINE_DEPS] | |||
| ) | |||
| @@ -411,6 +408,8 @@ AM_CONDITIONAL(STRIPPED_JACKD, $STRIPPED_JACKD) | |||
| AC_OUTPUT( | |||
| Makefile | |||
| config/Makefile | |||
| config/sysdeps/Makefile | |||
| doc/Makefile | |||
| doc/reference.doxygen | |||
| drivers/Makefile | |||
| @@ -4,12 +4,12 @@ MAINTAINERCLEANFILES=Makefile.in | |||
| CLEANFILES=doxygen-build.stamp | |||
| 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/ringbuffer.h ../jack/port.h \ | |||
| ../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 | |||
| @@ -104,6 +104,14 @@ useful. It includes | |||
| - simple examples of wrapping a GUI around a JACK application. | |||
| - 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 | |||
| 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. | |||
| 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/types.h \ | |||
| @top_srcdir@/jack/transport.h \ | |||
| @@ -14,7 +14,6 @@ noinst_HEADERS = alsa_driver.h \ | |||
| generic.h \ | |||
| hammerfall.h \ | |||
| hdsp.h \ | |||
| ice1712.h \ | |||
| memops.h | |||
| ice1712.h | |||
| jack_alsa_la_LIBADD = $(ALSA_LIBS) | |||
| @@ -26,20 +26,22 @@ | |||
| #include <stdlib.h> | |||
| #include <errno.h> | |||
| #include <stdarg.h> | |||
| #include <getopt.h> | |||
| #include <signal.h> | |||
| #include <sys/types.h> | |||
| #include <regex.h> | |||
| #include <string.h> | |||
| #include "alsa_driver.h" | |||
| #include <jack/types.h> | |||
| #include <jack/internal.h> | |||
| #include <jack/engine.h> | |||
| #include GETOPT_H | |||
| #include <sysdeps/time.h> | |||
| #include "alsa_driver.h" | |||
| #include "hammerfall.h" | |||
| #include "hdsp.h" | |||
| #include "ice1712.h" | |||
| #include "generic.h" | |||
| #include <jack/time.h> | |||
| extern void store_work_time (int); | |||
| extern void store_wait_time (int); | |||
| @@ -36,7 +36,7 @@ | |||
| #include <jack/types.h> | |||
| #include <jack/hardware.h> | |||
| #include <jack/driver.h> | |||
| #include "memops.h" | |||
| #include <jack/memops.h> | |||
| #include <jack/jack.h> | |||
| typedef void (*ReadCopyFunction) (jack_default_audio_sample_t *dst, char *src, | |||
| @@ -31,7 +31,7 @@ | |||
| #include <stdlib.h> | |||
| #include <limits.h> | |||
| #include "memops.h" | |||
| #include <jack/memops.h> | |||
| #define SAMPLE_MAX_24BIT 8388608.0f | |||
| #define SAMPLE_MAX_16BIT 32768.0f | |||
| @@ -20,6 +20,8 @@ | |||
| $Id$ | |||
| */ | |||
| #include <sysdeps/os_defines.h> | |||
| #include GETOPT_H | |||
| #include <math.h> | |||
| #include <stdio.h> | |||
| #include <memory.h> | |||
| @@ -27,13 +29,12 @@ | |||
| #include <stdlib.h> | |||
| #include <errno.h> | |||
| #include <stdarg.h> | |||
| #include <getopt.h> | |||
| #include <sys/mman.h> | |||
| #include <jack/types.h> | |||
| #include <jack/internal.h> | |||
| #include <jack/engine.h> | |||
| #include <jack/time.h> | |||
| #include <sysdeps/time.h> | |||
| #include "dummy_driver.h" | |||
| @@ -20,9 +20,10 @@ | |||
| * | |||
| */ | |||
| #include <sysdeps/os_defines.h> | |||
| #include GETOPT_H | |||
| #include <unistd.h> | |||
| #include <stdarg.h> | |||
| #include <getopt.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <errno.h> | |||
| @@ -43,7 +43,7 @@ | |||
| #include <jack/types.h> | |||
| #include <jack/internal.h> | |||
| #include <jack/engine.h> | |||
| #include <jack/time.h> | |||
| #include <sysdeps/time.h> | |||
| #include "oss_driver.h" | |||
| @@ -30,7 +30,6 @@ | |||
| #include <jack/types.h> | |||
| #include <jack/jslist.h> | |||
| #include <jack/driver.h> | |||
| #include <jack/time.h> | |||
| #include <jack/jack.h> | |||
| @@ -19,13 +19,27 @@ | |||
| Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France | |||
| 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 <errno.h> | |||
| #include <string.h> | |||
| #include <getopt.h> | |||
| #include <jack/engine.h> | |||
| #include "portaudio_driver.h" | |||
| @@ -37,8 +51,8 @@ paCallback(void *inputBuffer, void *outputBuffer, | |||
| portaudio_driver_t * driver = (portaudio_driver_t*)userData; | |||
| 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); | |||
| } | |||
| @@ -48,7 +62,7 @@ portaudio_driver_attach (portaudio_driver_t *driver, jack_engine_t *engine) | |||
| jack_port_t *port; | |||
| int port_flags; | |||
| channel_t chn; | |||
| char buf[32]; | |||
| char buf[JACK_PORT_NAME_SIZE]; | |||
| 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++) { | |||
| 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) { | |||
| 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; | |||
| 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) { | |||
| 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 */ | |||
| 0, /* number of buffers = default min */ | |||
| paClipOff, /* we won't output out of | |||
| * range samples so don't | |||
| * bother clipping them */ | |||
| * range samples so don't | |||
| * bother clipping them */ | |||
| paCallback, | |||
| driver); | |||
| if (err == paNoError) { | |||
| if (err == paNoError) { | |||
| driver->period_usecs = (((float) driver->frames_per_cycle) | |||
| / driver->frame_rate) * 1000000.0f; | |||
| @@ -251,7 +265,7 @@ portaudio_driver_set_parameters (portaudio_driver_t* driver, | |||
| } else { | |||
| // JOQ: this driver is dead. How do we terminate it? | |||
| // Pa_Terminate(); | |||
| Pa_Terminate(); | |||
| fprintf(stderr, "Unable to set portaudio parameters\n"); | |||
| fprintf(stderr, "Error number: %d\n", err); | |||
| fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); | |||
| @@ -270,7 +284,7 @@ portaudio_driver_reset_parameters (portaudio_driver_t* driver, | |||
| return EINVAL; | |||
| } | |||
| Pa_CloseStream(driver->stream); | |||
| Pa_CloseStream(driver->stream); | |||
| 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 ============================================= | |||
| 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 | |||
| */ | |||
| static jack_driver_t * | |||
| 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; | |||
| 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)); | |||
| jack_driver_init ((jack_driver_t *) driver); | |||
| @@ -333,109 +476,106 @@ portaudio_driver_new (char *name, | |||
| } | |||
| driver->frames_per_cycle = frames_per_cycle; | |||
| driver->frame_rate = rate; | |||
| driver->frame_rate = rate; | |||
| driver->capturing = capturing; | |||
| driver->playing = playing; | |||
| driver->attach = (JackDriverAttachFunction) portaudio_driver_attach; | |||
| 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->null_cycle = (JackDriverNullCycleFunction) portaudio_driver_null_cycle; | |||
| 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->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: | |||
| 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 | |||
| @@ -461,7 +601,7 @@ driver_get_descriptor () | |||
| desc = calloc (1, sizeof (jack_driver_desc_t)); | |||
| strcpy (desc->name, "portaudio"); | |||
| desc->nparams = 7; | |||
| desc->nparams = 10; | |||
| desc->params = calloc (desc->nparams, | |||
| sizeof (jack_driver_param_desc_t)); | |||
| @@ -470,7 +610,23 @@ driver_get_descriptor () | |||
| desc->params[i].character = 'c'; | |||
| desc->params[i].type = JackDriverParamInt; | |||
| 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); | |||
| i++; | |||
| @@ -509,9 +665,17 @@ driver_get_descriptor () | |||
| strcpy (desc->params[i].name, "period"); | |||
| desc->params[i].character = 'p'; | |||
| 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].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++; | |||
| strcpy (desc->params[i].name, "dither"); | |||
| @@ -525,8 +689,6 @@ driver_get_descriptor () | |||
| " t : triangular\n" | |||
| " s : shaped\n" | |||
| " - : no dithering"); | |||
| return desc; | |||
| } | |||
| @@ -537,18 +699,25 @@ driver_initialize (jack_client_t *client, const JSList * params) | |||
| { | |||
| jack_nframes_t srate = 48000; | |||
| jack_nframes_t frames_per_interrupt = 1024; | |||
| int capture = FALSE; | |||
| int playback = FALSE; | |||
| int chan = -1; | |||
| int chan_in = -1; | |||
| int chan_out = -1; | |||
| DitherAlgorithm dither = None; | |||
| const JSList * node; | |||
| const jack_driver_param_t * param; | |||
| char *name = ""; | |||
| for (node = params; node; node = jack_slist_next (node)) { | |||
| param = (const jack_driver_param_t *) node->data; | |||
| switch (param->character) { | |||
| case 'n': | |||
| name = (char *) param->value.str; | |||
| printf("Driver name found %s\n",name); | |||
| break; | |||
| case 'D': | |||
| capture = TRUE; | |||
| @@ -556,15 +725,24 @@ driver_initialize (jack_client_t *client, const JSList * params) | |||
| break; | |||
| 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; | |||
| case 'C': | |||
| capture = TRUE; | |||
| capture = param->value.i; | |||
| break; | |||
| case 'P': | |||
| playback = TRUE; | |||
| playback = param->value.i; | |||
| break; | |||
| case 'r': | |||
| @@ -605,9 +783,11 @@ driver_initialize (jack_client_t *client, const JSList * params) | |||
| } | |||
| return portaudio_driver_new ("portaudio", client, frames_per_interrupt, | |||
| srate, capture, playback, chan, dither); | |||
| srate, capture, playback, chan_in, | |||
| chan_out, dither,name); | |||
| } | |||
| void | |||
| driver_finish (jack_driver_t *driver) | |||
| { | |||
| @@ -23,19 +23,14 @@ | |||
| #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/hardware.h> | |||
| #include <jack/driver.h> | |||
| #include <jack/jack.h> | |||
| #include <jack/internal.h> | |||
| #include <jack/memops.h> | |||
| typedef struct { | |||
| @@ -57,10 +52,12 @@ typedef struct { | |||
| JSList *playback_ports; | |||
| float *inPortAudio; | |||
| float *outPortAudio; | |||
| float *outPortAudio; | |||
| char driver_name[256]; | |||
| PortAudioStream* stream; | |||
| } portaudio_driver_t; | |||
| #define kVersion 101 | |||
| #endif /* __jack_portaudio_driver_h__ */ | |||
| @@ -48,55 +48,56 @@ AM_CFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||
| AM_CXXFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||
| 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_connect_SOURCES = connect.c | |||
| jack_connect_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_connect_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||
| jack_connect_LDADD = ../libjack/libjack.la | |||
| 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_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_metro_SOURCES = metro.c | |||
| jack_metro_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_metro_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||
| jack_metro_LDADD = ../libjack/libjack.la | |||
| 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_showtime_SOURCES = showtime.c | |||
| jack_showtime_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_showtime_LDFLAGS = -ldl -lpthread @OS_LDFLAGS@ | |||
| jack_showtime_LDADD = ../libjack/libjack.la | |||
| jack_bufsize_SOURCES = bufsize.c | |||
| jack_bufsize_LDFLAGS = | |||
| jack_bufsize_LDFLAGS = @OS_LDFLAGS@ | |||
| jack_bufsize_LDADD = ../libjack/libjack.la | |||
| jack_freewheel_SOURCES = freewheel.c | |||
| jack_freewheel_LDFLAGS = | |||
| jack_freewheel_LDFLAGS = @OS_LDFLAGS@ | |||
| jack_freewheel_LDADD = ../libjack/libjack.la | |||
| if HAVE_SNDFILE | |||
| 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 | |||
| endif | |||
| if HAVE_READLINE | |||
| 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 | |||
| endif | |||
| 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 | |||
| # | |||
| @@ -104,11 +105,11 @@ jack_impulse_grabber_LDADD = ../libjack/libjack.la | |||
| # | |||
| 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_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 | |||
| # | |||
| @@ -119,10 +120,10 @@ ip_clientdir = $(ADDON_DIR) | |||
| 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 | |||
| intime_la_LDFLAGS = -module -avoid-version | |||
| intime_la_LDFLAGS = -module -avoid-version @OS_LDFLAGS@ | |||
| intime_la_SOURCES = intime.c | |||
| dist-hook: dist-check-sndfile | |||
| @@ -22,6 +22,7 @@ | |||
| $Id$ | |||
| */ | |||
| #include <sysdeps/os_defines.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| @@ -29,7 +30,7 @@ | |||
| #include <unistd.h> | |||
| #include <sndfile.h> | |||
| #include <pthread.h> | |||
| #include <getopt.h> | |||
| #include GETOPT_H | |||
| #include <jack/jack.h> | |||
| #include <jack/ringbuffer.h> | |||
| @@ -45,7 +46,7 @@ typedef struct _thread_info { | |||
| volatile int can_capture; | |||
| volatile int can_process; | |||
| volatile int status; | |||
| } thread_info_t; | |||
| } jack_thread_info_t; | |||
| /* JACK data */ | |||
| unsigned int nports; | |||
| @@ -65,7 +66,7 @@ long overruns = 0; | |||
| void * | |||
| 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; | |||
| jack_nframes_t samples_per_frame = info->channels; | |||
| size_t bytes_per_frame = samples_per_frame * sample_size; | |||
| @@ -116,7 +117,7 @@ process (jack_nframes_t nframes, void *arg) | |||
| { | |||
| int chn; | |||
| 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. */ | |||
| if ((!info->can_process) || (!info->can_capture)) | |||
| @@ -158,7 +159,7 @@ jack_shutdown (void *arg) | |||
| } | |||
| void | |||
| setup_disk_thread (thread_info_t *info) | |||
| setup_disk_thread (jack_thread_info_t *info) | |||
| { | |||
| SF_INFO sf_info; | |||
| int short_mask; | |||
| @@ -195,7 +196,7 @@ setup_disk_thread (thread_info_t *info) | |||
| } | |||
| void | |||
| run_disk_thread (thread_info_t *info) | |||
| run_disk_thread (jack_thread_info_t *info) | |||
| { | |||
| info->can_capture = 1; | |||
| pthread_join (info->thread_id, NULL); | |||
| @@ -213,7 +214,7 @@ run_disk_thread (thread_info_t *info) | |||
| } | |||
| 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; | |||
| size_t in_size; | |||
| @@ -261,7 +262,7 @@ main (int argc, char *argv[]) | |||
| { | |||
| jack_client_t *client; | |||
| thread_info_t thread_info; | |||
| jack_thread_info_t thread_info; | |||
| int c; | |||
| int longopt_index = 0; | |||
| extern int optind, opterr; | |||
| @@ -18,12 +18,13 @@ | |||
| * $Id$ | |||
| */ | |||
| #include <sysdeps/os_defines.h> | |||
| #include <stdio.h> | |||
| #include <errno.h> | |||
| #include <unistd.h> | |||
| #include <stdlib.h> | |||
| #include <math.h> | |||
| #include <getopt.h> | |||
| #include GETOPT_H | |||
| #include <jack/jack.h> | |||
| @@ -4,7 +4,7 @@ | |||
| * that runs within the JACK server process. | |||
| * | |||
| * 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(). | |||
| */ | |||
| @@ -15,7 +15,7 @@ | |||
| /** | |||
| * 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(). | |||
| */ | |||
| typedef struct { | |||
| @@ -25,14 +25,15 @@ typedef struct { | |||
| /** | |||
| * 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 | |||
| * the client terminated immediately. | |||
| */ | |||
| int | |||
| process (jack_nframes_t nframes, void *arg) | |||
| inprocess (jack_nframes_t nframes, void *arg) | |||
| { | |||
| port_pair_t *pp = arg; | |||
| jack_default_audio_sample_t *out = | |||
| @@ -63,7 +64,7 @@ jack_initialize (jack_client_t *client, const char *so_data) | |||
| if (pp == NULL) | |||
| return 1; /* heap exhausted */ | |||
| jack_set_process_callback (client, process, pp); | |||
| jack_set_process_callback (client, inprocess, pp); | |||
| /* create a pair of ports */ | |||
| 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 | |||
| * is unloaded, which could happen due to a call to | |||
| * 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 | |||
| jack_finish (void *arg) | |||
| @@ -1,8 +1,9 @@ | |||
| #include <sysdeps/os_defines.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <unistd.h> | |||
| #include <string.h> | |||
| #include <getopt.h> | |||
| #include GETOPT_H | |||
| #include <config.h> | |||
| @@ -16,15 +16,17 @@ | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include <sysdeps/os_defines.h> | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <errno.h> | |||
| #include <unistd.h> | |||
| #include <math.h> | |||
| #include GETOPT_H | |||
| #include <string.h> | |||
| #include <jack/jack.h> | |||
| #include <jack/transport.h> | |||
| #include <getopt.h> | |||
| #include <string.h> | |||
| typedef jack_default_audio_sample_t sample_t; | |||
| @@ -6,5 +6,5 @@ includedir=@includedir@ | |||
| Name: jack | |||
| Description: the Jack Audio Connection Kit: a low-latency synchronous callback-based media server | |||
| Version: @JACK_VERSION@ | |||
| Libs: -L${libdir} -ljack -lpthread -ldl -lrt | |||
| Libs: -L${libdir} -ljack -lpthread -ldl | |||
| Cflags: -I${includedir} | |||
| @@ -10,19 +10,18 @@ libjackinclude_HEADERS = \ | |||
| types.h | |||
| noinst_HEADERS = \ | |||
| cycles.h \ | |||
| atomicity.h \ | |||
| driver.h \ | |||
| driver_interface.h \ | |||
| driver_parse.h \ | |||
| engine.h \ | |||
| hardware.h \ | |||
| internal.h \ | |||
| jslist.h \ | |||
| memops.h \ | |||
| pool.h \ | |||
| port.h \ | |||
| ringbuffer.h \ | |||
| shm.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 usecs_per_cycle; | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| /* specific resources for server/client real-time thread communication */ | |||
| mach_port_t servertask, bp; | |||
| int portnum; | |||
| @@ -27,29 +27,35 @@ | |||
| #ifndef __jack_internal_h__ | |||
| #define __jack_internal_h__ | |||
| #include <sysdeps/os_defines.h> | |||
| #include <stdlib.h> | |||
| #include <unistd.h> | |||
| #include <limits.h> | |||
| #include <dlfcn.h> | |||
| #include <pthread.h> | |||
| #include <sys/types.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/types.h> | |||
| #include <jack/port.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 | |||
| #define DEBUG(format,args...) \ | |||
| fprintf (stderr, "jack:%5d:%" PRIu64 " %s:%s:%d: " format "\n", getpid(), jack_get_microseconds(), __FILE__, __FUNCTION__, __LINE__ , ## args) | |||
| #else | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #if JACK_CPP_VARARGS_BROKEN | |||
| #define DEBUG(format...) | |||
| #else | |||
| #define DEBUG(format,args...) | |||
| @@ -92,7 +98,7 @@ typedef struct { | |||
| jack_position_t pending_time; /* position for next cycle */ | |||
| jack_position_t request_time; /* latest requested position */ | |||
| 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 pending_pos; /* new position request pending */ | |||
| jack_nframes_t pending_frame; /* pending frame number */ | |||
| @@ -112,7 +118,7 @@ typedef struct { | |||
| float cpu_load; | |||
| uint32_t port_max; | |||
| 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_shared_t ports[0]; | |||
| @@ -249,7 +255,7 @@ typedef struct { | |||
| jack_client_control_t *client_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 */ | |||
| int32_t portnum; | |||
| #endif | |||
| @@ -338,13 +344,13 @@ typedef struct _jack_client_internal { | |||
| void (*finish)(void *); /* internal clients only */ | |||
| int error; | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| /* specific resources for server/client real-time thread communication */ | |||
| mach_port_t serverport; | |||
| trivial_message message; | |||
| int running; | |||
| int portnum; | |||
| #endif | |||
| #endif /* JACK_USE_MACH_THREADS */ | |||
| } jack_client_internal_t; | |||
| @@ -364,8 +370,6 @@ extern char *jack_server_dir; | |||
| 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_type_info_t jack_builtin_port_types[]; | |||
| @@ -148,15 +148,16 @@ int jack_set_freewheel_callback (jack_client_t *client, | |||
| 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 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 | |||
| * 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; | |||
| #endif | |||
| /** | |||
| * jack_port_t is an opaque type. You may only access it using the | |||
| @@ -1,5 +1,7 @@ | |||
| /* | |||
| Copyright (C) 2003 Paul Davis | |||
| @configure_input@ | |||
| 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 | |||
| @@ -14,6 +16,5 @@ | |||
| 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. | |||
| */ | |||
| #define jack_protocol_version @JACK_PROTOCOL_VERSION@ | |||
| @@ -24,7 +24,7 @@ bin_PROGRAMS = jackd $(CAP_PROGS) | |||
| AM_CFLAGS = $(JACK_CFLAGS) -DJACK_LOCATION=\"$(bindir)\" | |||
| 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 | |||
| @@ -19,17 +19,11 @@ | |||
| $Id$ | |||
| */ | |||
| #include <config.h> | |||
| #include <math.h> | |||
| #include <unistd.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/stat.h> | |||
| #include <errno.h> | |||
| @@ -38,21 +32,22 @@ | |||
| #include <stdarg.h> | |||
| #include <stdint.h> | |||
| #include <dirent.h> | |||
| #include <sys/ipc.h> | |||
| #include <signal.h> | |||
| #include <sys/types.h> | |||
| #include <sys/mman.h> | |||
| #include <string.h> | |||
| #include <limits.h> | |||
| #include <config.h> | |||
| #include <jack/internal.h> | |||
| #include <jack/engine.h> | |||
| #include <jack/driver.h> | |||
| #include <jack/time.h> | |||
| #include <jack/version.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 | |||
| /* 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); | |||
| } | |||
| 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 | |||
| * Linux VM manager still allows newly allocated pages | |||
| @@ -471,6 +467,7 @@ jack_resize_port_segment (jack_engine_t *engine, | |||
| "%s", strerror(errno)); | |||
| } | |||
| } | |||
| #endif /* JACK_DO_NOT_MLOCK */ | |||
| /* Tell everybody about this segment. */ | |||
| event.type = AttachPortSegment; | |||
| @@ -577,7 +574,7 @@ jack_process_internal(jack_engine_t *engine, JSList *node, | |||
| return jack_slist_next (node); | |||
| } | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| static JSList * | |||
| 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->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); | |||
| } | |||
| #else | |||
| #else /* !JACK_USE_MACH_THREADS */ | |||
| static JSList * | |||
| 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_control_t *ctl; | |||
| jack_time_t now, then; | |||
| client = (jack_client_internal_t *) node->data; | |||
| ctl = client->control; | |||
| @@ -731,7 +731,7 @@ jack_process_external(jack_engine_t *engine, JSList *node) | |||
| return node; | |||
| } | |||
| #endif | |||
| #endif /* JACK_USE_MACH_THREADS */ | |||
| static int | |||
| @@ -1022,8 +1022,8 @@ setup_client (jack_engine_t *engine, int client_fd, | |||
| res->engine_shm = engine->control_shm; | |||
| res->realtime = engine->control->real_time; | |||
| res->realtime_priority = engine->rtpriority - 1; | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| /* specific resources for server/client real-time thread | |||
| * communication */ | |||
| res->portnum = client->portnum; | |||
| @@ -1840,9 +1840,9 @@ jack_server_thread (void *arg) | |||
| (engine, pfd[i].fd)) { | |||
| jack_error ("could not handle external" | |||
| " client request"); | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| /* poll is implemented using | |||
| select (see the fakepool | |||
| select (see the macosx/fakepoll | |||
| code). When the socket is closed | |||
| select does not return any error, | |||
| POLLIN is true and the next read | |||
| @@ -1854,7 +1854,7 @@ jack_server_thread (void *arg) | |||
| */ | |||
| handle_client_socket_error(engine, | |||
| 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; | |||
| #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 */ | |||
| engine->servertask = mach_task_self(); | |||
| 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; | |||
| } | |||
| engine->portnum = 0; | |||
| #endif | |||
| #endif /* JACK_USE_MACH_THREADS */ | |||
| #ifdef USE_CAPABILITIES | |||
| @@ -2131,18 +2131,16 @@ jack_become_real_time (jack_engine_t *engine, pthread_t thread, int priority) | |||
| return -1; | |||
| } | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| // To be implemented | |||
| #else | |||
| #ifndef JACK_DO_NOT_MLOCK | |||
| if (engine->control->do_mlock | |||
| && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | |||
| jack_error ("cannot lock down memory for RT thread (%s)", | |||
| strerror (errno)); | |||
| #ifdef ENSURE_MLOCK | |||
| return -1; | |||
| return -1; | |||
| #endif /* ENSURE_MLOCK */ | |||
| } | |||
| #endif | |||
| #endif /* JACK_DO_NOT_MLOCK */ | |||
| return 0; | |||
| } | |||
| @@ -2168,7 +2166,6 @@ jack_watchdog_thread (void *arg) | |||
| while (1) { | |||
| usleep (5000000); | |||
| pthread_testcancel(); | |||
| if ( engine->watchdog_check == 0) { | |||
| jack_error ("jackd watchdog: timeout - killing jackd"); | |||
| @@ -2183,6 +2180,11 @@ jack_watchdog_thread (void *arg) | |||
| kill (-getpgrp(), SIGABRT); | |||
| /*NOTREACHED*/ | |||
| exit (1); | |||
| #if 0 /* suppress watchdog message */ | |||
| } else { | |||
| VERBOSE(engine, "jackd watchdog: all is well.\n"); | |||
| #endif | |||
| } | |||
| engine->watchdog_check = 0; | |||
| } | |||
| @@ -2564,7 +2566,7 @@ jack_setup_client_control (jack_engine_t *engine, int fd, | |||
| jack_transport_client_new (client); | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| /* specific resources for server/client real-time thread | |||
| * communication */ | |||
| allocate_mach_serverport(engine, client); | |||
| @@ -19,9 +19,12 @@ | |||
| $Id$ | |||
| */ | |||
| #include <config.h> | |||
| #include <sysdeps/os_defines.h> | |||
| #include <stdio.h> | |||
| #include <signal.h> | |||
| #include <getopt.h> | |||
| #include GETOPT_H | |||
| #include <sys/types.h> | |||
| #include <sys/shm.h> | |||
| #include <sys/wait.h> | |||
| @@ -31,8 +34,6 @@ | |||
| #include <dirent.h> | |||
| #include <dlfcn.h> | |||
| #include <config.h> | |||
| #include <jack/engine.h> | |||
| #include <jack/internal.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"); | |||
| 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; | |||
| } | |||
| @@ -255,7 +257,6 @@ jack_drivers_get_descriptor (JSList * drivers, const char * sofile) | |||
| jack_error ("error closing driver .so '%s': %s\n", filename, dlerror ()); | |||
| } | |||
| /* check it doesn't exist already */ | |||
| for (node = drivers; node; node = jack_slist_next (node)) { | |||
| other_descriptor = (jack_driver_desc_t *) node->data; | |||
| @@ -377,7 +378,7 @@ int | |||
| main (int argc, char *argv[]) | |||
| { | |||
| jack_driver_desc_t * desc; | |||
| jack_driver_desc_t * desc; | |||
| const char *options = "-ad:P:vshVRTFl:t:m"; | |||
| struct option long_options[] = | |||
| { | |||
| @@ -6,6 +6,12 @@ | |||
| int jack_port_name_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> | |||
| * new ring buffer interface: <jack/ringbuffer.h> | |||
| @@ -20,6 +20,6 @@ AM_CXXFLAGS = $(JACK_CFLAGS) | |||
| libjack_la_CFLAGS = $(AM_CFLAGS) | |||
| 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@ | |||
| @@ -19,42 +19,40 @@ | |||
| $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 <errno.h> | |||
| #include <fcntl.h> | |||
| #include <sys/types.h> | |||
| #include <sys/ipc.h> | |||
| #include <sys/mman.h> | |||
| #include <stdarg.h> | |||
| #include <stdio.h> | |||
| #include <stdint.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/jack.h> | |||
| #include <jack/engine.h> | |||
| #include <jack/pool.h> | |||
| #include <jack/time.h> | |||
| #include <jack/jslist.h> | |||
| #include <jack/version.h> | |||
| #include <jack/shm.h> | |||
| #include <sysdeps/time.h> | |||
| JACK_TIME_GLOBAL_DECL; /* One instance per process. */ | |||
| #include "local.h" | |||
| #include <sysdeps/poll.h> | |||
| #include <sysdeps/ipc.h> | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| #include <sysdeps/pThreadUtilities.h> | |||
| #endif | |||
| #ifdef WITH_TIMESTAMPS | |||
| #include <jack/timestamps.h> | |||
| #endif /* WITH_TIMESTAMPS */ | |||
| @@ -168,6 +166,9 @@ jack_client_alloc () | |||
| client->engine = NULL; | |||
| client->control = NULL; | |||
| client->thread_ok = FALSE; | |||
| #if JACK_USE_MACH_THREADS | |||
| client->rt_thread_ok = FALSE; | |||
| #endif | |||
| client->first_active = TRUE; | |||
| client->on_shutdown = NULL; | |||
| client->n_port_types = 0; | |||
| @@ -433,7 +434,7 @@ _start_server (void) | |||
| } | |||
| 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"; | |||
| strncpy(arguments, JACK_LOCATION "/jackd -T -d portaudio -p 512", 255); | |||
| #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*) | |||
| realloc (client->port_segment, | |||
| sizeof (jack_shm_info_t) * (ptid+1)); | |||
| memset (&client->port_segment[client->n_port_types], | |||
| 0, | |||
| 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 */ | |||
| #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]); | |||
| #endif | |||
| } | |||
| /* get the index into the shm registry */ | |||
| @@ -747,7 +755,7 @@ jack_client_new (const char *client_name) | |||
| client->event_fd = ev_fd; | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| /* specific resources for server/client real-time thread | |||
| * communication */ | |||
| client->clienttask = mach_task_self(); | |||
| @@ -761,7 +769,7 @@ jack_client_new (const char *client_name) | |||
| jack_error("Can't allocate mach port"); | |||
| goto fail; | |||
| }; | |||
| #endif | |||
| #endif /* JACK_USE_MACH_THREADS */ | |||
| return client; | |||
| fail: | |||
| @@ -815,6 +823,24 @@ jack_internal_client_close (const char *client_name) | |||
| 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 | |||
| jack_drop_real_time_scheduling (pthread_t thread) | |||
| { | |||
| @@ -849,6 +875,8 @@ jack_acquire_real_time_scheduling (pthread_t thread, int priority) | |||
| return 0; | |||
| } | |||
| #endif | |||
| int | |||
| 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; | |||
| 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); | |||
| #endif | |||
| } | |||
| if (control->freewheel_cb) { | |||
| @@ -881,8 +913,13 @@ jack_stop_freewheel (jack_client_t* client) | |||
| } | |||
| 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, | |||
| 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 | |||
| * communicate with the server using fast mach RPC mechanism */ | |||
| @@ -1176,14 +1213,17 @@ jack_client_process_thread (void *arg) | |||
| int err = 0; | |||
| 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) { | |||
| 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(); | |||
| @@ -1192,6 +1232,9 @@ jack_client_process_thread (void *arg) | |||
| control->state = Running; | |||
| if (control->sync_cb) | |||
| jack_call_sync_client (client); | |||
| if (control->process) { | |||
| if (control->process (control->nframes, | |||
| control->process_arg) == 0) { | |||
| @@ -1200,6 +1243,9 @@ jack_client_process_thread (void *arg) | |||
| } else { | |||
| control->state = Finished; | |||
| } | |||
| if (control->timebase_cb) | |||
| jack_call_timebase_master (client); | |||
| control->finished_at = jack_get_microseconds(); | |||
| @@ -1226,27 +1272,31 @@ jack_client_process_thread (void *arg) | |||
| jack_error ("jack_client_process_thread : zombified"); | |||
| client->rt_thread_ok = FALSE; | |||
| if (client->on_shutdown) { | |||
| jack_error ("zombified - calling shutdown handler"); | |||
| client->on_shutdown (client->on_shutdown_arg); | |||
| } else { | |||
| 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); | |||
| /*NOTREACHED*/ | |||
| return 0; | |||
| } | |||
| #endif | |||
| #endif /* JACK_USE_MACH_THREADS */ | |||
| static int | |||
| jack_start_thread (jack_client_t *client) | |||
| { | |||
| pthread_attr_t *attributes = 0; | |||
| #ifndef JACK_USE_MACH_THREADS | |||
| int policy = SCHED_OTHER; | |||
| struct sched_param client_param, temp_param; | |||
| #endif | |||
| pthread_attr_t *attributes = 0; | |||
| if (client->engine->real_time) { | |||
| @@ -1282,9 +1332,7 @@ jack_start_thread (jack_client_t *client) | |||
| return -1; | |||
| } | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| // To be implemented | |||
| #else | |||
| #ifndef JACK_DO_NOT_MLOCK | |||
| if (client->engine->do_mlock | |||
| && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | |||
| jack_error ("cannot lock down memory for RT thread (%s)", | |||
| @@ -1293,23 +1341,17 @@ jack_start_thread (jack_client_t *client) | |||
| return -1; | |||
| #endif /* ENSURE_MLOCK */ | |||
| } | |||
| #endif | |||
| #endif /* JACK_DO_NOT_MLOCK */ | |||
| } | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| if (pthread_create (&client->thread, attributes, | |||
| 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; | |||
| } | |||
| #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 | |||
| * mach RPC mechanism */ | |||
| if (pthread_create (&client->process_thread, attributes, | |||
| @@ -1319,18 +1361,22 @@ jack_start_thread (jack_client_t *client) | |||
| } | |||
| if (client->engine->real_time){ | |||
| /* time constraint thread */ | |||
| setThreadToPriority(client->process_thread, 96, true, 10000000); | |||
| setThreadToPriority(client->process_thread, 96, TRUE, 10000000); | |||
| }else{ | |||
| /* 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 | |||
| 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; | |||
| } | |||
| @@ -1433,22 +1481,13 @@ jack_activate (jack_client_t *client) | |||
| * 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; | |||
| for (i = 0; i < BIG_ENOUGH_STACK; i++) { | |||
| for (i = 0; i < JACK_THREAD_STACK_TOUCH; i++) { | |||
| buf[i] = (char) (i & 0xff); | |||
| } | |||
| #undef BIG_ENOUGH_STACK | |||
| if (client->control->type == ClientInternal || | |||
| client->control->type == ClientDriver) { | |||
| goto startit; | |||
| @@ -1546,6 +1585,16 @@ jack_client_close (jack_client_t *client) | |||
| } | |||
| 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 | |||
| * server, only if it was actually running | |||
| @@ -1889,69 +1938,3 @@ jack_port_type_size(void) | |||
| { | |||
| 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$ | |||
| */ | |||
| #include <config.h> | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include <stdarg.h> | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <sys/mman.h> | |||
| #include <errno.h> | |||
| #include <config.h> | |||
| #include <jack/driver.h> | |||
| #include <jack/internal.h> | |||
| #include <jack/driver.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_detach (jack_driver_t *drv, jack_engine_t *eng) { return 0; } | |||
| 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; | |||
| } | |||
| #ifndef JACK_DO_NOT_MLOCK | |||
| if (driver->engine->control->do_mlock | |||
| && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) { | |||
| 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; | |||
| #endif /* ENSURE_MLOCK */ | |||
| } | |||
| #endif /* JACK_DO_NOT_MLOCK */ | |||
| return 0; | |||
| } | |||
| @@ -31,11 +31,12 @@ struct _jack_client { | |||
| char first_active : 1; | |||
| pthread_t thread_id; | |||
| #if defined(__APPLE__) && defined(__POWERPC__) | |||
| #ifdef JACK_USE_MACH_THREADS | |||
| /* specific ressources for server/client real-time thread communication */ | |||
| mach_port_t clienttask, bp, serverport, replyport; | |||
| trivial_message message; | |||
| pthread_t process_thread; | |||
| char rt_thread_ok : 1; | |||
| #endif | |||
| }; | |||
| @@ -18,18 +18,26 @@ | |||
| $Id$ | |||
| */ | |||
| #include <config.h> | |||
| #ifdef HAVE_POSIX_MEMALIGN | |||
| #define _XOPEN_SOURCE 600 | |||
| #endif | |||
| #include <stdlib.h> | |||
| #include <config.h> | |||
| #include <jack/pool.h> | |||
| /* XXX need RT-pool based allocator here */ | |||
| void * | |||
| jack_pool_alloc (size_t bytes) | |||
| { | |||
| /* XXX need RT-pool based allocator here */ | |||
| #ifdef HAVE_POSIX_MEMALIGN | |||
| void* m; | |||
| int err = posix_memalign (&m, 16, bytes); | |||
| return (!err) ? m : 0; | |||
| #else | |||
| return malloc (bytes); | |||
| #endif /* HAVE_POSIX_MEMALIGN */ | |||
| } | |||
| void | |||
| @@ -20,9 +20,12 @@ | |||
| This is safe for the case of one read thread and one write thread. | |||
| */ | |||
| #include <sysdeps/os_defines.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #ifndef JACK_DO_NOT_MLOCK | |||
| #include <sys/mman.h> | |||
| #endif /* JACK_DO_NOT_MLOCK */ | |||
| #include <jack/ringbuffer.h> | |||
| /* Create a new ringbuffer to hold at least `sz' bytes of data. The | |||
| @@ -54,9 +57,11 @@ jack_ringbuffer_create (size_t sz) | |||
| void | |||
| jack_ringbuffer_free (jack_ringbuffer_t * rb) | |||
| { | |||
| #ifndef JACK_DO_NOT_MLOCK | |||
| if (rb->mlocked) { | |||
| munlock (rb->buf, rb->size); | |||
| } | |||
| #endif /* JACK_DO_NOT_MLOCK */ | |||
| free (rb->buf); | |||
| } | |||
| @@ -65,9 +70,11 @@ jack_ringbuffer_free (jack_ringbuffer_t * rb) | |||
| int | |||
| jack_ringbuffer_mlock (jack_ringbuffer_t * rb) | |||
| { | |||
| #ifndef JACK_DO_NOT_MLOCK | |||
| if (mlock (rb->buf, rb->size)) { | |||
| return -1; | |||
| } | |||
| #endif /* JACK_DO_NOT_MLOCK */ | |||
| rb->mlocked = 1; | |||
| return 0; | |||
| } | |||
| @@ -17,6 +17,7 @@ | |||
| $Id$ | |||
| */ | |||
| #include <config.h> | |||
| #include <unistd.h> | |||
| #include <fcntl.h> | |||
| @@ -25,12 +26,10 @@ | |||
| #include <signal.h> | |||
| #include <limits.h> | |||
| #include <errno.h> | |||
| #include <dirent.h> | |||
| #include <sys/mman.h> | |||
| #include <sys/types.h> | |||
| #include <dirent.h> | |||
| #include <sys/ipc.h> | |||
| #include <sys/shm.h> | |||
| #include <config.h> | |||
| #include <jack/shm.h> | |||
| #include <jack/internal.h> | |||
| @@ -22,7 +22,7 @@ | |||
| #include <string.h> | |||
| #include <jack/timestamps.h> | |||
| #include <jack/internal.h> | |||
| #include <jack/time.h> | |||
| #include <sysdeps/time.h> | |||
| typedef struct { | |||
| jack_time_t when; | |||
| @@ -24,6 +24,7 @@ | |||
| #include <errno.h> | |||
| #include <math.h> | |||
| #include <stdio.h> | |||
| #include <jack/atomicity.h> | |||
| #include <jack/internal.h> | |||
| #include "local.h" | |||
| @@ -34,40 +35,8 @@ | |||
| jack_unique_t | |||
| 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 | |||
| @@ -226,7 +195,8 @@ jack_get_current_transport_frame (const jack_client_t *client) | |||
| */ | |||
| 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 | |||
| */ | |||
| @@ -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 | |||