Browse Source

[0.96.0] merge MacOSX EXP tree into HEAD

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@673 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
joq 21 years ago
parent
commit
64930746f2
94 changed files with 3872 additions and 1786 deletions
  1. +13
    -19
      .cvsignore
  2. +5
    -8
      Makefile.am
  3. +9
    -0
      TODO
  4. +16
    -2
      autogen.sh
  5. +10
    -0
      config/.cvsignore
  6. +14
    -0
      config/Makefile.am
  7. +41
    -0
      config/acinclude.m4
  8. +159
    -0
      config/configure.host
  9. +76
    -0
      config/cpu/alpha/atomicity.h
  10. +35
    -0
      config/cpu/alpha/cycles.h
  11. +78
    -0
      config/cpu/cris/atomicity.h
  12. +80
    -0
      config/cpu/generic/atomicity.h
  13. +20
    -16
      config/cpu/generic/cycles.h
  14. +90
    -0
      config/cpu/hppa/atomicity.h
  15. +76
    -0
      config/cpu/i386/atomicity.h
  16. +24
    -0
      config/cpu/i386/cycles.h
  17. +54
    -0
      config/cpu/i486/atomicity.h
  18. +0
    -74
      config/cpu/i486/cycles.h
  19. +51
    -0
      config/cpu/ia64/atomicity.h
  20. +36
    -0
      config/cpu/ia64/cycles.h
  21. +130
    -0
      config/cpu/ia64/ia64intrin.h
  22. +139
    -0
      config/cpu/m68k/atomicity.h
  23. +83
    -0
      config/cpu/mips/atomicity.h
  24. +78
    -0
      config/cpu/powerpc/atomicity.h
  25. +55
    -0
      config/cpu/powerpc/cycles.h
  26. +60
    -0
      config/cpu/s390/atomicity.h
  27. +131
    -0
      config/cpu/sparc/atomicity.h
  28. +59
    -0
      config/os/aix/atomicity.h
  29. +28
    -0
      config/os/generic/ipc.h
  30. +30
    -0
      config/os/generic/os_defines.h
  31. +28
    -0
      config/os/generic/poll.h
  32. +42
    -0
      config/os/generic/time.h
  33. +97
    -0
      config/os/gnu-linux/time.h
  34. +50
    -0
      config/os/irix/atomicity.h
  35. +183
    -0
      config/os/macosx/README
  36. +0
    -1
      config/os/macosx/fakepoll.h
  37. +1
    -10
      config/os/macosx/getopt.h
  38. +66
    -24
      config/os/macosx/ipc.h
  39. +503
    -746
      config/os/macosx/jack.xcode/project.pbxproj
  40. +0
    -0
      config/os/macosx/mach_port.h
  41. +39
    -0
      config/os/macosx/os_defines.h
  42. +203
    -0
      config/os/macosx/pThreadUtilities.h
  43. +29
    -0
      config/os/macosx/poll.h
  44. +8
    -9
      config/os/macosx/portaudio.h
  45. +18
    -19
      config/os/macosx/time.h
  46. +3
    -0
      config/sysdeps/.cvsignore
  47. +23
    -0
      config/sysdeps/Makefile.am
  48. +32
    -33
      configure.in
  49. +2
    -2
      doc/Makefile.am
  50. +8
    -0
      doc/mainpage.dox
  51. +119
    -0
      doc/porting.dox
  52. +2
    -1
      doc/reference.doxygen.in
  53. +1
    -2
      drivers/alsa/Makefile.am
  54. +6
    -4
      drivers/alsa/alsa_driver.c
  55. +1
    -1
      drivers/alsa/alsa_driver.h
  56. +1
    -1
      drivers/alsa/memops.c
  57. +3
    -2
      drivers/dummy/dummy_driver.c
  58. +2
    -1
      drivers/iec61883/iec61883_driver.c
  59. +1
    -1
      drivers/oss/oss_driver.c
  60. +0
    -1
      drivers/oss/oss_driver.h
  61. +307
    -127
      drivers/portaudio/portaudio_driver.c
  62. +6
    -9
      drivers/portaudio/portaudio_driver.h
  63. +17
    -16
      example-clients/Makefile.am
  64. +9
    -8
      example-clients/capture_client.c
  65. +2
    -1
      example-clients/impulse_grabber.c
  66. +9
    -8
      example-clients/inprocess.c
  67. +2
    -1
      example-clients/lsp.c
  68. +4
    -2
      example-clients/metro.c
  69. +1
    -1
      jack.pc.in
  70. +5
    -6
      jack/Makefile.am
  71. +39
    -0
      jack/atomicity.h
  72. +1
    -1
      jack/engine.h
  73. +17
    -13
      jack/internal.h
  74. +8
    -7
      jack/jack.h
  75. +97
    -0
      jack/memops.h
  76. +0
    -8
      jack/types.h
  77. +2
    -1
      jack/version.h.in
  78. +1
    -1
      jackd/Makefile.am
  79. +36
    -34
      jackd/engine.c
  80. +7
    -6
      jackd/jackd.c
  81. +6
    -0
      libjack/ChangeLog
  82. +1
    -1
      libjack/Makefile.am
  83. +110
    -127
      libjack/client.c
  84. +8
    -4
      libjack/driver.c
  85. +2
    -1
      libjack/local.h
  86. +9
    -1
      libjack/pool.c
  87. +7
    -0
      libjack/ringbuffer.c
  88. +2
    -3
      libjack/shm.c
  89. +1
    -1
      libjack/timestamps.c
  90. +5
    -35
      libjack/transclient.c
  91. +0
    -53
      macosx/fakepoll.h
  92. +0
    -150
      macosx/pThreadUtilities.c
  93. +0
    -50
      macosx/pThreadUtilities.h
  94. +0
    -133
      macosx/readme.txt

+ 13
- 19
.cvsignore View File

@@ -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

+ 5
- 8
Makefile.am View File

@@ -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



+ 9
- 0
TODO View File

@@ -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)


+ 16
- 2
autogen.sh View File

@@ -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
}


+ 10
- 0
config/.cvsignore View File

@@ -0,0 +1,10 @@
Makefile
Makefile.in
compile
config.guess
config.sub
depcomp
install-sh
ltmain.sh
missing
mkinstalldirs

+ 14
- 0
config/Makefile.am View File

@@ -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

+ 41
- 0
config/acinclude.m4 View File

@@ -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
])


+ 159
- 0
config/configure.host View File

@@ -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

+ 76
- 0
config/cpu/alpha/atomicity.h View File

@@ -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 */

+ 35
- 0
config/cpu/alpha/cycles.h View File

@@ -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__ */

+ 78
- 0
config/cpu/cris/atomicity.h View File

@@ -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 */

+ 80
- 0
config/cpu/generic/atomicity.h View File

@@ -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 */

macosx/ipc.h → config/cpu/generic/cycles.h View File

@@ -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__ */

+ 90
- 0
config/cpu/hppa/atomicity.h View File

@@ -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

+ 76
- 0
config/cpu/i386/atomicity.h View File

@@ -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 */

+ 24
- 0
config/cpu/i386/cycles.h View File

@@ -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>

+ 54
- 0
config/cpu/i486/atomicity.h View File

@@ -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 */

jack/cycles.h → config/cpu/i486/cycles.h View File

@@ -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__ */

+ 51
- 0
config/cpu/ia64/atomicity.h View File

@@ -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 */

+ 36
- 0
config/cpu/ia64/cycles.h View File

@@ -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__ */

+ 130
- 0
config/cpu/ia64/ia64intrin.h View File

@@ -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

+ 139
- 0
config/cpu/m68k/atomicity.h View File

@@ -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 */

+ 83
- 0
config/cpu/mips/atomicity.h View File

@@ -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 */

+ 78
- 0
config/cpu/powerpc/atomicity.h View File

@@ -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 */

+ 55
- 0
config/cpu/powerpc/cycles.h View File

@@ -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__ */

+ 60
- 0
config/cpu/s390/atomicity.h View File

@@ -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 */



+ 131
- 0
config/cpu/sparc/atomicity.h View File

@@ -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 */

+ 59
- 0
config/os/aix/atomicity.h View File

@@ -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 */

+ 28
- 0
config/os/generic/ipc.h View File

@@ -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 */

+ 30
- 0
config/os/generic/os_defines.h View File

@@ -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 */

+ 28
- 0
config/os/generic/poll.h View File

@@ -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 */

+ 42
- 0
config/os/generic/time.h View File

@@ -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__ */

+ 97
- 0
config/os/gnu-linux/time.h View File

@@ -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__ */

+ 50
- 0
config/os/irix/atomicity.h View File

@@ -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 */

+ 183
- 0
config/os/macosx/README View File

@@ -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

macosx/fakepoll.c → config/os/macosx/fakepoll.h View File

@@ -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>

macosx/getopt.h → config/os/macosx/getopt.h View File

@@ -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"

macosx/ipc.c → config/os/macosx/ipc.h View File

@@ -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__ */

config/os/macosx/jack.xcode/project.pbxproj
File diff suppressed because it is too large
View File


macosx/mach_port.h → config/os/macosx/mach_port.h View File


+ 39
- 0
config/os/macosx/os_defines.h View File

@@ -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 */

+ 203
- 0
config/os/macosx/pThreadUtilities.h View File

@@ -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__ */

+ 29
- 0
config/os/macosx/poll.h View File

@@ -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__ */

macosx/config.h → config/os/macosx/portaudio.h View File

@@ -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 */

jack/time.h → config/os/macosx/time.h View File

@@ -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__ */

+ 3
- 0
config/sysdeps/.cvsignore View File

@@ -0,0 +1,3 @@
Makefile
Makefile.in
*.h

+ 23
- 0
config/sysdeps/Makefile.am View File

@@ -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

+ 32
- 33
configure.in View File

@@ -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


+ 2
- 2
doc/Makefile.am View File

@@ -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



+ 8
- 0
doc/mainpage.dox View File

@@ -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.


+ 119
- 0
doc/porting.dox View File

@@ -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.

*/

+ 2
- 1
doc/reference.doxygen.in View File

@@ -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 \


+ 1
- 2
drivers/alsa/Makefile.am View File

@@ -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)

+ 6
- 4
drivers/alsa/alsa_driver.c View File

@@ -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);


+ 1
- 1
drivers/alsa/alsa_driver.h View File

@@ -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,


+ 1
- 1
drivers/alsa/memops.c View File

@@ -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


+ 3
- 2
drivers/dummy/dummy_driver.c View File

@@ -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"



+ 2
- 1
drivers/iec61883/iec61883_driver.c View File

@@ -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>


+ 1
- 1
drivers/oss/oss_driver.c View File

@@ -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"



+ 0
- 1
drivers/oss/oss_driver.h View File

@@ -30,7 +30,6 @@
#include <jack/types.h>
#include <jack/jslist.h>
#include <jack/driver.h>
#include <jack/time.h>
#include <jack/jack.h>




+ 307
- 127
drivers/portaudio/portaudio_driver.c View File

@@ -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)
{


+ 6
- 9
drivers/portaudio/portaudio_driver.h View File

@@ -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__ */

+ 17
- 16
example-clients/Makefile.am View File

@@ -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

+ 9
- 8
example-clients/capture_client.c View File

@@ -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;


+ 2
- 1
example-clients/impulse_grabber.c View File

@@ -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>



+ 9
- 8
example-clients/inprocess.c View File

@@ -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)


+ 2
- 1
example-clients/lsp.c View File

@@ -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>



+ 4
- 2
example-clients/metro.c View File

@@ -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;



+ 1
- 1
jack.pc.in View File

@@ -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}

+ 5
- 6
jack/Makefile.am View File

@@ -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

+ 39
- 0
jack/atomicity.h View File

@@ -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__ */

+ 1
- 1
jack/engine.h View File

@@ -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;


+ 17
- 13
jack/internal.h View File

@@ -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[];


+ 8
- 7
jack/jack.h View File

@@ -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


+ 97
- 0
jack/memops.h View File

@@ -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__ */

+ 0
- 8
jack/types.h View File

@@ -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


+ 2
- 1
jack/version.h.in View File

@@ -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@

+ 1
- 1
jackd/Makefile.am View File

@@ -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



+ 36
- 34
jackd/engine.c View File

@@ -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);


+ 7
- 6
jackd/jackd.c View File

@@ -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
- 0
libjack/ChangeLog View File

@@ -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>


+ 1
- 1
libjack/Makefile.am View File

@@ -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@


+ 110
- 127
libjack/client.c View File

@@ -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

+ 8
- 4
libjack/driver.c View File

@@ -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;
}


+ 2
- 1
libjack/local.h View File

@@ -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

};


+ 9
- 1
libjack/pool.c View File

@@ -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


+ 7
- 0
libjack/ringbuffer.c View File

@@ -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;
}


+ 2
- 3
libjack/shm.c View File

@@ -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>


+ 1
- 1
libjack/timestamps.c View File

@@ -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;


+ 5
- 35
libjack/transclient.c View File

@@ -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
*/


+ 0
- 53
macosx/fakepoll.h View File

@@ -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

+ 0
- 150
macosx/pThreadUtilities.c View File

@@ -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;
}


+ 0
- 50
macosx/pThreadUtilities.h View File

@@ -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__ */

+ 0
- 133
macosx/readme.txt View File

@@ -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


Loading…
Cancel
Save