From 387a56dc36a3b3b4cfc0de6530196d1fa5556bee Mon Sep 17 00:00:00 2001 From: Orcan Ogetbil Date: Tue, 20 Jul 2010 05:53:44 +0000 Subject: [PATCH] - Jack 2! --- .cvsignore | 2 +- jack-DSO-linking.patch | 11 + jack-audio-connection-kit-no_date_footer.html | 5 - ...-audio-connection-kit-no_date_footer.patch | 22 + jack-audio-connection-kit.spec | 209 +- jack-celt08.patch | 30 + jack-infrastructure.patch | 3365 +++++++++++++++++ jack-manpages.patch | 1215 ++++++ jack-realtime-compat.patch | 56 + sources | 2 +- 10 files changed, 4827 insertions(+), 90 deletions(-) create mode 100644 jack-DSO-linking.patch delete mode 100644 jack-audio-connection-kit-no_date_footer.html create mode 100644 jack-audio-connection-kit-no_date_footer.patch create mode 100644 jack-celt08.patch create mode 100644 jack-infrastructure.patch create mode 100644 jack-manpages.patch create mode 100644 jack-realtime-compat.patch diff --git a/.cvsignore b/.cvsignore index 6e87eb9..8545362 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1 +1 @@ -jack-audio-connection-kit-0.118.0.tar.gz +jack-1.9.5.tar.bz2 diff --git a/jack-DSO-linking.patch b/jack-DSO-linking.patch new file mode 100644 index 0000000..855e82f --- /dev/null +++ b/jack-DSO-linking.patch @@ -0,0 +1,11 @@ +--- jack-1.9.5/wscript~ 2010-02-12 05:58:08.000000000 -0500 ++++ jack-1.9.5/wscript 2010-05-18 14:14:27.000000000 -0400 +@@ -230,6 +230,8 @@ + print Logs.colors.NORMAL, + print + ++ conf.env.append_unique('LINKFLAGS', '-lm -lstdc++') ++ + if Options.options.mixed == True: + env_variant2 = conf.env.copy() + conf.set_env_name('lib32', env_variant2) diff --git a/jack-audio-connection-kit-no_date_footer.html b/jack-audio-connection-kit-no_date_footer.html deleted file mode 100644 index 6c9f46b..0000000 --- a/jack-audio-connection-kit-no_date_footer.html +++ /dev/null @@ -1,5 +0,0 @@ -
Generated for $projectname by  - -doxygen$doxygenversion
- - diff --git a/jack-audio-connection-kit-no_date_footer.patch b/jack-audio-connection-kit-no_date_footer.patch new file mode 100644 index 0000000..8509ee5 --- /dev/null +++ b/jack-audio-connection-kit-no_date_footer.patch @@ -0,0 +1,22 @@ +diff -rupN jack-1.9.5.old/doxyfile jack-1.9.5/doxyfile +--- jack-1.9.5.old/doxyfile 2010-02-12 05:57:30.000000000 -0500 ++++ jack-1.9.5/doxyfile 2010-07-19 23:18:57.000000000 -0400 +@@ -413,7 +413,7 @@ HTML_HEADER = + # each generated HTML page. If it is left blank doxygen will generate a + # standard footer. + +-HTML_FOOTER = ++HTML_FOOTER = no_date_footer.html + + # The HTML_STYLESHEET tag can be used to specify a user defined cascading + # style sheet that is used by each HTML page. It can be used to +diff -rupN jack-1.9.5.old/no_date_footer.html jack-1.9.5/no_date_footer.html +--- jack-1.9.5.old/no_date_footer.html 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/no_date_footer.html 2010-07-19 23:19:19.000000000 -0400 +@@ -0,0 +1,6 @@ ++
++Generated for $projectname by doxygen ++$doxygenversion
++ ++ diff --git a/jack-audio-connection-kit.spec b/jack-audio-connection-kit.spec index 7d50600..1ffc83b 100644 --- a/jack-audio-connection-kit.spec +++ b/jack-audio-connection-kit.spec @@ -1,42 +1,56 @@ -Summary: The Jack Audio Connection Kit -Name: jack-audio-connection-kit -Version: 0.118.0 -Release: 1%{?dist} -License: GPLv2 and LGPLv2 -Group: System Environment/Daemons -Source0: http://www.jackaudio.org/downloads/%{name}-%{version}.tar.gz -Source1: %{name}-README.Fedora -Source2: %{name}-script.pa -Source3: %{name}-no_date_footer.html -Source4: %{name}-limits.conf -URL: http://www.jackaudio.org -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +%global groupname jackuser +%global pagroup pulse-rt + +Summary: The Jack Audio Connection Kit +Name: jack-audio-connection-kit +Version: 1.9.5 +Release: 1%{?dist} +# The entire source (~500 files) is a mixture of these three licenses +License: GPLv2 and GPLv2+ and LGPLv2+ +Group: System Environment/Daemons +URL: http://www.jackaudio.org +Source0: http://www.grame.fr/~letz/jack-%{version}.tar.bz2 +Source1: %{name}-README.Fedora +Source2: %{name}-script.pa +Source3: %{name}-limits.conf +# No-date-footer hack to remove dates from doxygen documentation +Patch0: jack-audio-connection-kit-no_date_footer.patch +# Enables renaming of the jack ports based on a configuration file +# Under discussion upstream. We need it for CCRMA compatibility +Patch1: jack-infrastructure.patch +# Fix DSO linking +Patch2: jack-DSO-linking.patch +# Manpages. From ustream trunk +Patch3: jack-manpages.patch +# Make jack compatible with both the Fedora kernel and the realtime kernel +Patch4: jack-realtime-compat.patch +# Compile against celt-0.8.0 +Patch5: jack-celt08.patch + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: alsa-lib-devel -BuildRequires: libsndfile-devel >= 1.0.0 -BuildRequires: pkgconfig +BuildRequires: dbus-devel +BuildRequires: celt-devel BuildRequires: doxygen -BuildRequires: readline-devel, ncurses-devel -BuildRequires: autoconf >= 2.59, automake >= 1.9.3, libtool -%ifnarch s390 s390x -BuildRequires: libfreebob-devel >= 1.0.0 -%endif - -%define groupname jackuser -%define pagroup pulse-rt +BuildRequires: expat-devel +BuildRequires: libffado-devel +BuildRequires: libfreebob-devel +BuildRequires: libsamplerate-devel +BuildRequires: libsndfile-devel +BuildRequires: ncurses-devel +BuildRequires: pkgconfig +BuildRequires: python2 +BuildRequires: readline-devel Requires(pre): shadow-utils -Requires(post): /sbin/ldconfig -Requires: pam - -# To fix multilib conflicts take a basepoint as following -%define doxyfile doc/reference.doxygen.in +Requires: pam %description JACK is a low-latency audio server, written primarily for the Linux operating system. It can connect a number of different applications to an audio device, as well as allowing them to share audio between -themselves. Its clients can run in their own processes (ie. as a -normal application), or can they can run within a JACK server (ie. a +themselves. Its clients can run in their own processes (i.e. as a +normal application), or can they can run within a JACK server (i.e. a "plugin"). JACK is different from other audio server efforts in that it has been @@ -45,61 +59,58 @@ work. This means that it focuses on two key areas: synchronous execution of all clients, and low latency operation. %package devel -Summary: Header files for Jack -Group: Development/Libraries -Requires: %{name} = %{version} -Requires: pkgconfig +Summary: Header files for Jack +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig %description devel Header files for the Jack Audio Connection Kit. %package example-clients -Summary: Example clients that use Jack -Group: Applications/Multimedia -Requires: %{name} = %{version} +Summary: Example clients that use Jack +Group: Applications/Multimedia +Requires: %{name} = %{version}-%{release} %description example-clients Small example clients that use the Jack Audio Connection Kit. %prep -%setup -q - -# Put custom HTML_FOOTER to avoid timestamp inside -# (recipe was taken from http://fedoraproject.org/wiki/PackagingDrafts/MultilibTricks) -cp %{SOURCE3} doc/no_date_footer.html -# Fix Doxyfile: -# - apply custom html footer (#477718, #341621) -# - avoid font packaging (workaround for #477402, fix will come with #478747) -sed -e 's,^HTML_FOOTER[ \t]*=.*,HTML_FOOTER = no_date_footer.html,; - s,^GENERATE_LATEX[ \t]*=.*,GENERATE_LATEX = NO,;' %{doxyfile} > %{doxyfile}.new -touch -r %{doxyfile} %{doxyfile}.new -mv -f %{doxyfile}.new %{doxyfile} +%setup -q -n jack-%{version} +%patch0 -p1 -b .nodate +%patch1 -p1 -b .infra +%patch2 -p1 -b .linking +%patch3 -p1 +%patch4 -p1 +%if 0%{?fedora} > 13 +%patch5 -p1 -b .celt08 +%endif -%build -# x86_64 issue reported by Rudolf Kastl (not checked, but not bad). -autoreconf --force --install +# Fix encoding issues +for file in ChangeLog README TODO; do + sed 's|\r||' $file > $file.tmp + iconv -f ISO-8859-1 -t UTF8 $file.tmp > $file.tmp2 + touch -r $file $file.tmp2 + mv -f $file.tmp2 $file +done -%configure \ - --with-html-dir=%{_docdir} \ -%ifnarch s390 s390x - --enable-freebob \ -%endif - --disable-oss \ - --disable-portaudio \ - --with-default-tmpdir=/dev/shm -make %{?_smp_mflags} +%build +export CPPFLAGS="$RPM_OPT_FLAGS" +./waf configure --prefix=%{_prefix} --libdir=/%{_lib} --doxygen --dbus --classic +./waf build %{?_smp_mflags} -v %install rm -rf $RPM_BUILD_ROOT +./waf --destdir=$RPM_BUILD_ROOT install -# can't use the makeinstall macro, jack needs DESTDIR and prefix gets -# added to it and messes up part of the install -make install DESTDIR=$RPM_BUILD_ROOT +# move doxygen documentation to the right place +mv $RPM_BUILD_ROOT%{_datadir}/jack-audio-connection-kit/reference . +rm -rf $RPM_BUILD_ROOT%{_datadir}/jack-audio-connection-kit # install our limits to the /etc/security/limits.d mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/security/limits.d sed -e 's,@groupname@,%groupname,g; s,@pagroup@,%pagroup,g;' \ - %{SOURCE4} > $RPM_BUILD_ROOT%{_sysconfdir}/security/limits.d/99-jack.conf + %{SOURCE3} > $RPM_BUILD_ROOT%{_sysconfdir}/security/limits.d/99-jack.conf # prepare README.Fedora for documentation including install -p -m644 %{SOURCE1} README.Fedora @@ -107,15 +118,11 @@ install -p -m644 %{SOURCE1} README.Fedora # install pulseaudio script for jack (as documentation part) install -p -m644 %{SOURCE2} jack.pa -# remove extra install of the documentation -rm -fr $RPM_BUILD_ROOT%{_docdir} - -# remove *.la files -rm -f $RPM_BUILD_ROOT%{_libdir}/jack/*.la -rm -f $RPM_BUILD_ROOT%{_libdir}/*.la +# For compatibility with jack1 +mv $RPM_BUILD_ROOT%{_bindir}/jack_rec $RPM_BUILD_ROOT%{_bindir}/jackrec -# Fix timestamps to avoid multiarch conflicts -find doc/reference -type f | xargs touch -r %{doxyfile} +# Fix permissions of the modules +chmod 755 $RPM_BUILD_ROOT%{_libdir}/jack/*.so $RPM_BUILD_ROOT%{_libdir}/libjack*.so.*.*.* %clean rm -rf $RPM_BUILD_ROOT @@ -129,37 +136,56 @@ exit 0 %postun -p /sbin/ldconfig %files -%defattr(-,root,root) -%doc AUTHORS TODO COPYING* +%defattr(-,root,root,-) +%doc ChangeLog README README_NETJACK2 TODO %doc README.Fedora %doc jack.pa +%{_bindir}/alsa_in +%{_bindir}/alsa_out %{_bindir}/jackd %{_bindir}/jack_load %{_bindir}/jack_unload %{_bindir}/jack_freewheel +%exclude %{_bindir}/jackdbus +%exclude %{_bindir}/jack_control +%{_bindir}/jack_cpu +%{_bindir}/jack_cpu_load +%{_bindir}/jack_delay +%{_bindir}/jack_server_control +%{_bindir}/jack_test +%{_bindir}/jack_thru +%{_bindir}/jack_zombie +%{_datadir}/dbus-1/services/org.jackaudio.service %{_libdir}/jack/ -%{_mandir}/man1/jack*.1* %{_libdir}/libjack.so.* %{_libdir}/libjackserver.so.* -%{_sysconfdir}/security/limits.d/*.conf +%config(noreplace) %{_sysconfdir}/security/limits.d/*.conf +%{_mandir}/man1/alsa_*.1* +%{_mandir}/man1/jack_freewheel*.1* +%{_mandir}/man1/jack_load*.1* +%{_mandir}/man1/jack_unload*.1* +%{_mandir}/man1/jackd*.1* + %files devel -%defattr(-,root,root) -%doc doc/reference +%defattr(-,root,root,-) +%doc reference/* %{_includedir}/jack/ %{_libdir}/libjack.so %{_libdir}/libjackserver.so %{_libdir}/pkgconfig/jack.pc %files example-clients -%defattr(-,root,root) +%defattr(-,root,root,-) %{_bindir}/jackrec %{_bindir}/jack_alias %{_bindir}/jack_bufsize %{_bindir}/jack_connect %{_bindir}/jack_disconnect %{_bindir}/jack_evmon -%{_bindir}/jack_impulse_grabber +# These are not ready yet +#{_bindir}/jack_impulse_grabber +%exclude %{_mandir}/man1/jack_impulse_grabber.1* %{_bindir}/jack_lsp %{_bindir}/jack_metro %{_bindir}/jack_netsource @@ -169,11 +195,28 @@ exit 0 %{_bindir}/jack_wait %{_bindir}/jack_monitor_client %{_bindir}/jack_simple_client -%{_bindir}/jack_transport_client %{_bindir}/jack_midiseq %{_bindir}/jack_midisine +%{_bindir}/jack_multiple_metro +%{_mandir}/man1/jack_bufsize.1* +%{_mandir}/man1/jack_connect.1* +%{_mandir}/man1/jack_disconnect.1* +%{_mandir}/man1/jack_lsp.1* +%{_mandir}/man1/jack_metro.1* +%{_mandir}/man1/jack_monitor_client.1* +%{_mandir}/man1/jack_netsource.1* +%{_mandir}/man1/jack_samplerate.1* +%{_mandir}/man1/jack_showtime.1* +%{_mandir}/man1/jack_simple_client.1* +%{_mandir}/man1/jack_transport.1* +%{_mandir}/man1/jack_wait.1* +%{_mandir}/man1/jackrec.1* + %changelog +* Mon Jul 19 2010 Orcan Ogetbil - 1.9.5-1 +- Jack 2! + * Sat Nov 21 2009 Andy Shevchenko - 0.118.0-1 - update to 0.118.0 (should fix #533419) - remove upstreamed patch @@ -274,7 +317,7 @@ exit 0 - remove --enable-stripped-jackd and --enable-optimize (use default flags) * Fri May 19 2006 Andy Shevchenko 0.101.1-8 -- uniform directories items at %files section +- uniform directories items at %%files section * Wed May 17 2006 Andy Shevchenko 0.101.1-7 - change License tag to GPL/LGPL diff --git a/jack-celt08.patch b/jack-celt08.patch new file mode 100644 index 0000000..e728c94 --- /dev/null +++ b/jack-celt08.patch @@ -0,0 +1,30 @@ +diff -rupN jack-1.9.5.old/common/JackNetOneDriver.cpp jack-1.9.5/common/JackNetOneDriver.cpp +--- jack-1.9.5.old/common/JackNetOneDriver.cpp 2010-02-12 05:57:48.000000000 -0500 ++++ jack-1.9.5/common/JackNetOneDriver.cpp 2010-07-20 01:26:44.000000000 -0400 +@@ -709,9 +709,9 @@ JackNetOneDriver::render_payload_to_jack + + CELTDecoder *decoder = (CELTDecoder *)src_node->data; + if( !packet_payload ) +- celt_decode_float( decoder, NULL, net_period_down, buf ); ++ celt_decode_float( decoder, NULL, net_period_down, buf, NULL ); + else +- celt_decode_float( decoder, packet_bufX, net_period_down, buf ); ++ celt_decode_float( decoder, packet_bufX, net_period_down, buf, NULL ); + + src_node = jack_slist_next (src_node); + } +diff -rupN jack-1.9.5.old/common/netjack_packet.c jack-1.9.5/common/netjack_packet.c +--- jack-1.9.5.old/common/netjack_packet.c 2010-02-12 05:57:47.000000000 -0500 ++++ jack-1.9.5/common/netjack_packet.c 2010-07-20 01:12:42.000000000 -0400 +@@ -1428,9 +1428,9 @@ render_payload_to_jack_ports_celt (void + + CELTDecoder *decoder = src_node->data; + if( !packet_payload ) +- celt_decode_float( decoder, NULL, net_period_down, buf ); ++ celt_decode_float( decoder, NULL, net_period_down, buf, NULL ); + else +- celt_decode_float( decoder, packet_bufX, net_period_down, buf ); ++ celt_decode_float( decoder, packet_bufX, net_period_down, buf, NULL ); + + src_node = jack_slist_next (src_node); + } diff --git a/jack-infrastructure.patch b/jack-infrastructure.patch new file mode 100644 index 0000000..ed825b6 --- /dev/null +++ b/jack-infrastructure.patch @@ -0,0 +1,3365 @@ +diff -rupN jack-1.9.5.old/linux/alsa/JackAlsaDriver.cpp jack-1.9.5/linux/alsa/JackAlsaDriver.cpp +--- jack-1.9.5.old/linux/alsa/JackAlsaDriver.cpp 2010-02-12 05:58:07.000000000 -0500 ++++ jack-1.9.5/linux/alsa/JackAlsaDriver.cpp 2010-07-20 00:17:44.000000000 -0400 +@@ -49,6 +49,7 @@ Foundation, Inc., 675 Mass Ave, Cambridg + #include "generic.h" + #include "memops.h" + #include "JackServerGlobals.h" ++#include "port_names.h" + + + //#define DEBUG_WAKEUP 1 +@@ -2091,6 +2092,8 @@ int JackAlsaDriver::Attach() + + alsa_driver_t* alsa_driver = (alsa_driver_t*)fDriver; + ++ char **portnames; ++ + if (alsa_driver->has_hw_monitoring) + port_flags |= JackPortCanMonitor; + +@@ -2100,13 +2103,15 @@ int JackAlsaDriver::Attach() + + jack_log("JackAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); + ++ portnames = port_names_get_portnames(alsa_driver); ++ + for (int i = 0; i < fCaptureChannels; i++) { +- snprintf(alias, sizeof(alias) - 1, "%s:capture_%u", fAliasName, i + 1); +- snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); +- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { ++ snprintf(alias, sizeof(alias) - 1, "system:%s", portnames[i]); ++ if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, alias, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { + jack_error("driver: cannot register port for %s", name); + return -1; + } ++ free(portnames[i]); + port = fGraphManager->GetPort(port_index); + port->SetAlias(alias); + port->SetLatency(alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency); +@@ -2117,12 +2122,12 @@ int JackAlsaDriver::Attach() + port_flags = (unsigned long)PlaybackDriverFlags; + + for (int i = 0; i < fPlaybackChannels; i++) { +- snprintf(alias, sizeof(alias) - 1, "%s:playback_%u", fAliasName, i + 1); +- snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); +- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { ++ snprintf(alias, sizeof(alias) - 1, "system:%s", portnames[i+fCaptureChannels]); ++ if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, alias, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { + jack_error("driver: cannot register port for %s", name); + return -1; + } ++ free(portnames[i+fCaptureChannels]); + port = fGraphManager->GetPort(port_index); + port->SetAlias(alias); + // Add one buffer more latency if "async" mode is used... +@@ -2145,6 +2150,8 @@ int JackAlsaDriver::Attach() + } + } + ++ free(portnames); ++ + if (alsa_driver->midi) { + int err = (alsa_driver->midi->attach)(alsa_driver->midi); + if (err) +diff -rupN jack-1.9.5.old/linux/alsa/JackAlsaDriver.cpp.orig jack-1.9.5/linux/alsa/JackAlsaDriver.cpp.orig +--- jack-1.9.5.old/linux/alsa/JackAlsaDriver.cpp.orig 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/linux/alsa/JackAlsaDriver.cpp.orig 2010-02-12 05:58:07.000000000 -0500 +@@ -0,0 +1,2981 @@ ++/* ++Copyright (C) 2001 Paul Davis ++Copyright (C) 2004 Grame ++ ++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. ++ ++*/ ++ ++#define __STDC_FORMAT_MACROS // For inttypes.h to work in C++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "JackAlsaDriver.h" ++#include "JackEngineControl.h" ++#include "JackClientControl.h" ++#include "JackPort.h" ++#include "JackGraphManager.h" ++#include "JackLockedEngine.h" ++#include "JackPosixThread.h" ++#include "JackCompilerDeps.h" ++#include "hammerfall.h" ++#include "hdsp.h" ++#include "ice1712.h" ++#include "usx2y.h" ++#include "generic.h" ++#include "memops.h" ++#include "JackServerGlobals.h" ++ ++ ++//#define DEBUG_WAKEUP 1 ++ ++namespace Jack ++{ ++ ++#define jack_get_microseconds GetMicroSeconds ++ ++/* Delay (in process calls) before jackd will report an xrun */ ++#define XRUN_REPORT_DELAY 0 ++ ++void ++JackAlsaDriver::alsa_driver_release_channel_dependent_memory (alsa_driver_t *driver) ++{ ++ bitset_destroy (&driver->channels_done); ++ bitset_destroy (&driver->channels_not_done); ++ ++ if (driver->playback_addr) { ++ free (driver->playback_addr); ++ driver->playback_addr = 0; ++ } ++ ++ if (driver->capture_addr) { ++ free (driver->capture_addr); ++ driver->capture_addr = 0; ++ } ++ ++ if (driver->playback_interleave_skip) { ++ free (driver->playback_interleave_skip); ++ driver->playback_interleave_skip = NULL; ++ } ++ ++ if (driver->capture_interleave_skip) { ++ free (driver->capture_interleave_skip); ++ driver->capture_interleave_skip = NULL; ++ } ++ ++ if (driver->silent) { ++ free (driver->silent); ++ driver->silent = 0; ++ } ++ ++ if (driver->dither_state) { ++ free (driver->dither_state); ++ driver->dither_state = 0; ++ } ++} ++ ++int ++JackAlsaDriver::alsa_driver_check_capabilities (alsa_driver_t *driver) ++{ ++ return 0; ++} ++ ++static ++char * ++get_control_device_name (const char * device_name) ++{ ++ char * ctl_name; ++ regex_t expression; ++ ++ regcomp(&expression, "(plug)?hw:[0-9](,[0-9])?", REG_ICASE | REG_EXTENDED); ++ ++ if (!regexec(&expression, device_name, 0, NULL, 0)) { ++ /* the user wants a hw or plughw device, the ctl name ++ * should be hw:x where x is the card number */ ++ ++ char tmp[5]; ++ strncpy(tmp, strstr(device_name, "hw"), 4); ++ tmp[4] = '\0'; ++ //jack_log("control device %s", tmp); ++ ctl_name = strdup(tmp); ++ } else { ++ ctl_name = strdup(device_name); ++ } ++ ++ regfree(&expression); ++ ++ if (ctl_name == NULL) { ++ jack_error("strdup(\"%s\") failed.", ctl_name); ++ } ++ ++ return ctl_name; ++} ++ ++int ++JackAlsaDriver::alsa_driver_check_card_type (alsa_driver_t *driver) ++{ ++ int err; ++ snd_ctl_card_info_t *card_info; ++ char * ctl_name; ++ ++ snd_ctl_card_info_alloca (&card_info); ++ ++ ctl_name = get_control_device_name(driver->alsa_name_playback); ++ ++ // XXX: I don't know the "right" way to do this. Which to use ++ // driver->alsa_name_playback or driver->alsa_name_capture. ++ if ((err = snd_ctl_open (&driver->ctl_handle, ctl_name, 0)) < 0) { ++ jack_error ("control open \"%s\" (%s)", ctl_name, ++ snd_strerror(err)); ++ return -1; ++ } ++ ++ if ((err = snd_ctl_card_info(driver->ctl_handle, card_info)) < 0) { ++ jack_error ("control hardware info \"%s\" (%s)", ++ driver->alsa_name_playback, snd_strerror (err)); ++ snd_ctl_close (driver->ctl_handle); ++ return -1; ++ } ++ ++ driver->alsa_driver = strdup(snd_ctl_card_info_get_driver (card_info)); ++ jack_info("Using ALSA driver %s running on card %i - %s", driver->alsa_driver, snd_ctl_card_info_get_card(card_info), snd_ctl_card_info_get_longname(card_info)); ++ ++ free(ctl_name); ++ ++ return alsa_driver_check_capabilities (driver); ++} ++ ++int ++JackAlsaDriver::alsa_driver_hammerfall_hardware (alsa_driver_t *driver) ++{ ++ driver->hw = jack_alsa_hammerfall_hw_new (driver); ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_hdsp_hardware (alsa_driver_t *driver) ++{ ++ driver->hw = jack_alsa_hdsp_hw_new (driver); ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_ice1712_hardware (alsa_driver_t *driver) ++{ ++ driver->hw = jack_alsa_ice1712_hw_new (driver); ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_usx2y_hardware (alsa_driver_t *driver) ++{ ++ // TODO : will need so deeped redesign ++ // driver->hw = jack_alsa_usx2y_hw_new (driver); ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_generic_hardware (alsa_driver_t *driver) ++{ ++ driver->hw = jack_alsa_generic_hw_new (driver); ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_hw_specific (alsa_driver_t *driver, int hw_monitoring, ++ int hw_metering) ++{ ++ int err; ++ ++ if (!strcmp(driver->alsa_driver, "RME9652")) { ++ if ((err = alsa_driver_hammerfall_hardware (driver)) != 0) { ++ return err; ++ } ++ } else if (!strcmp(driver->alsa_driver, "H-DSP")) { ++ if ((err = alsa_driver_hdsp_hardware (driver)) != 0) { ++ return err; ++ } ++ } else if (!strcmp(driver->alsa_driver, "ICE1712")) { ++ if ((err = alsa_driver_ice1712_hardware (driver)) != 0) { ++ return err; ++ } ++ } /*else if (!strcmp(driver->alsa_driver, "USB US-X2Y")) { ++ if ((err = alsa_driver_usx2y_hardware (driver)) != 0) { ++ return err; ++ } ++ } */else { ++ if ((err = alsa_driver_generic_hardware (driver)) != 0) { ++ return err; ++ } ++ } ++ ++ if (driver->hw->capabilities & Cap_HardwareMonitoring) { ++ driver->has_hw_monitoring = TRUE; ++ /* XXX need to ensure that this is really FALSE or ++ * TRUE or whatever*/ ++ driver->hw_monitoring = hw_monitoring; ++ } else { ++ driver->has_hw_monitoring = FALSE; ++ driver->hw_monitoring = FALSE; ++ } ++ ++ if (driver->hw->capabilities & Cap_ClockLockReporting) { ++ driver->has_clock_sync_reporting = TRUE; ++ } else { ++ driver->has_clock_sync_reporting = FALSE; ++ } ++ ++ if (driver->hw->capabilities & Cap_HardwareMetering) { ++ driver->has_hw_metering = TRUE; ++ driver->hw_metering = hw_metering; ++ } else { ++ driver->has_hw_metering = FALSE; ++ driver->hw_metering = FALSE; ++ } ++ ++ return 0; ++} ++ ++void ++JackAlsaDriver::alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) ++{ ++ if (driver->playback_handle) { ++ if (SND_PCM_FORMAT_FLOAT_LE == driver->playback_sample_format) { ++ if (driver->playback_interleaved) { ++ driver->channel_copy = memcpy_interleave_d32_s32; ++ } else { ++ driver->channel_copy = memcpy_fake; ++ } ++ driver->read_via_copy = sample_move_floatLE_sSs; ++ driver->write_via_copy = sample_move_dS_floatLE; ++ } else { ++ ++ switch (driver->playback_sample_bytes) { ++ case 2: ++ if (driver->playback_interleaved) { ++ driver->channel_copy = memcpy_interleave_d16_s16; ++ } else { ++ driver->channel_copy = memcpy_fake; ++ } ++ ++ switch (driver->dither) { ++ case Rectangular: ++ jack_info("Rectangular dithering at 16 bits"); ++ driver->write_via_copy = driver->quirk_bswap? ++ sample_move_dither_rect_d16_sSs: ++ sample_move_dither_rect_d16_sS; ++ break; ++ ++ case Triangular: ++ jack_info("Triangular dithering at 16 bits"); ++ driver->write_via_copy = driver->quirk_bswap? ++ sample_move_dither_tri_d16_sSs: ++ sample_move_dither_tri_d16_sS; ++ break; ++ ++ case Shaped: ++ jack_info("Noise-shaped dithering at 16 bits"); ++ driver->write_via_copy = driver->quirk_bswap? ++ sample_move_dither_shaped_d16_sSs: ++ sample_move_dither_shaped_d16_sS; ++ break; ++ ++ default: ++ driver->write_via_copy = driver->quirk_bswap? ++ sample_move_d16_sSs : ++ sample_move_d16_sS; ++ break; ++ } ++ break; ++ ++ case 3: /* NO DITHER */ ++ if (driver->playback_interleaved) { ++ driver->channel_copy = memcpy_interleave_d24_s24; ++ } else { ++ driver->channel_copy = memcpy_fake; ++ } ++ ++ driver->write_via_copy = driver->quirk_bswap? ++ sample_move_d24_sSs: ++ sample_move_d24_sS; ++ ++ break; ++ ++ case 4: /* NO DITHER */ ++ if (driver->playback_interleaved) { ++ driver->channel_copy = memcpy_interleave_d32_s32; ++ } else { ++ driver->channel_copy = memcpy_fake; ++ } ++ ++ driver->write_via_copy = driver->quirk_bswap? ++ sample_move_d32u24_sSs: ++ sample_move_d32u24_sS; ++ break; ++ ++ default: ++ jack_error ("impossible sample width (%d) discovered!", ++ driver->playback_sample_bytes); ++ exit (1); ++ } ++ } ++ } ++ ++ if (driver->capture_handle) { ++ switch (driver->capture_sample_bytes) { ++ case 2: ++ driver->read_via_copy = driver->quirk_bswap? ++ sample_move_dS_s16s: ++ sample_move_dS_s16; ++ break; ++ case 3: ++ driver->read_via_copy = driver->quirk_bswap? ++ sample_move_dS_s24s: ++ sample_move_dS_s24; ++ break; ++ case 4: ++ driver->read_via_copy = driver->quirk_bswap? ++ sample_move_dS_s32u24s: ++ sample_move_dS_s32u24; ++ break; ++ } ++ } ++} ++ ++int ++JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name, ++ const char *stream_name, ++ snd_pcm_t *handle, ++ snd_pcm_hw_params_t *hw_params, ++ snd_pcm_sw_params_t *sw_params, ++ unsigned int *nperiodsp, ++ unsigned long *nchns, ++ unsigned long sample_width) ++{ ++ int err, format; ++ unsigned int frame_rate; ++ snd_pcm_uframes_t stop_th; ++ static struct { ++ char Name[32]; ++ snd_pcm_format_t format; ++ int swapped; ++ } formats[] = { ++ {"32bit float little-endian", SND_PCM_FORMAT_FLOAT_LE}, ++ {"32bit integer little-endian", SND_PCM_FORMAT_S32_LE, IS_LE}, ++ {"32bit integer big-endian", SND_PCM_FORMAT_S32_BE, IS_BE}, ++ {"24bit little-endian", SND_PCM_FORMAT_S24_3LE, IS_LE}, ++ {"24bit big-endian", SND_PCM_FORMAT_S24_3BE, IS_BE}, ++ {"16bit little-endian", SND_PCM_FORMAT_S16_LE, IS_LE}, ++ {"16bit big-endian", SND_PCM_FORMAT_S16_BE, IS_BE}, ++ }; ++#define NUMFORMATS (sizeof(formats)/sizeof(formats[0])) ++#define FIRST_16BIT_FORMAT 5 ++ ++ if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) { ++ jack_error ("ALSA: no playback configurations available (%s)", ++ snd_strerror (err)); ++ return -1; ++ } ++ ++ if ((err = snd_pcm_hw_params_set_periods_integer (handle, hw_params)) ++ < 0) { ++ jack_error ("ALSA: cannot restrict period size to integral" ++ " value."); ++ return -1; ++ } ++ ++ if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) < 0) { ++ if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) { ++ if ((err = snd_pcm_hw_params_set_access ( ++ handle, hw_params, ++ SND_PCM_ACCESS_MMAP_COMPLEX)) < 0) { ++ jack_error ("ALSA: mmap-based access is not possible" ++ " for the %s " ++ "stream of this audio interface", ++ stream_name); ++ return -1; ++ } ++ } ++ } ++ ++ format = (sample_width == 4) ? 0 : NUMFORMATS - 1; ++ ++ while (1) { ++ if ((err = snd_pcm_hw_params_set_format ( ++ handle, hw_params, formats[format].format)) < 0) { ++ ++ if ((sample_width == 4 ++ ? format++ >= NUMFORMATS - 1 ++ : format-- <= 0)) { ++ jack_error ("Sorry. The audio interface \"%s\"" ++ " doesn't support any of the" ++ " hardware sample formats that" ++ " JACK's alsa-driver can use.", ++ device_name); ++ return -1; ++ } ++ } else { ++ if (formats[format].swapped) { ++ driver->quirk_bswap = 1; ++ } else { ++ driver->quirk_bswap = 0; ++ } ++ jack_info ("ALSA: final selected sample format for %s: %s", stream_name, formats[format].Name); ++ break; ++ } ++ } ++ ++ frame_rate = driver->frame_rate ; ++ err = snd_pcm_hw_params_set_rate_near (handle, hw_params, ++ &frame_rate, NULL) ; ++ driver->frame_rate = frame_rate ; ++ if (err < 0) { ++ jack_error ("ALSA: cannot set sample/frame rate to %" ++ PRIu32 " for %s", driver->frame_rate, ++ stream_name); ++ return -1; ++ } ++ if (!*nchns) { ++ /*if not user-specified, try to find the maximum ++ * number of channels */ ++ unsigned int channels_max ; ++ err = snd_pcm_hw_params_get_channels_max (hw_params, ++ &channels_max); ++ *nchns = channels_max ; ++ ++ if (*nchns > 1024) { ++ ++ /* the hapless user is an unwitting victim of ++ the "default" ALSA PCM device, which can ++ support up to 16 million channels. since ++ they can't be bothered to set up a proper ++ default device, limit the number of ++ channels for them to a sane default. ++ */ ++ ++ jack_error ( ++"You appear to be using the ALSA software \"plug\" layer, probably\n" ++"a result of using the \"default\" ALSA device. This is less\n" ++"efficient than it could be. Consider using a hardware device\n" ++"instead rather than using the plug layer. Usually the name of the\n" ++"hardware device that corresponds to the first sound card is hw:0\n" ++ ); ++ *nchns = 2; ++ } ++ } ++ ++ if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, ++ *nchns)) < 0) { ++ jack_error ("ALSA: cannot set channel count to %u for %s", ++ *nchns, stream_name); ++ return -1; ++ } ++ ++ if ((err = snd_pcm_hw_params_set_period_size (handle, hw_params, ++ driver->frames_per_cycle, ++ 0)) ++ < 0) { ++ jack_error ("ALSA: cannot set period size to %" PRIu32 ++ " frames for %s", driver->frames_per_cycle, ++ stream_name); ++ return -1; ++ } ++ ++ *nperiodsp = driver->user_nperiods; ++ snd_pcm_hw_params_set_periods_min (handle, hw_params, nperiodsp, NULL); ++ if (*nperiodsp < driver->user_nperiods) ++ *nperiodsp = driver->user_nperiods; ++ if (snd_pcm_hw_params_set_periods_near (handle, hw_params, ++ nperiodsp, NULL) < 0) { ++ jack_error ("ALSA: cannot set number of periods to %u for %s", ++ *nperiodsp, stream_name); ++ return -1; ++ } ++ ++ if (*nperiodsp < driver->user_nperiods) { ++ jack_error ("ALSA: got smaller periods %u than %u for %s", ++ *nperiodsp, (unsigned int) driver->user_nperiods, ++ stream_name); ++ return -1; ++ } ++ jack_info ("ALSA: use %d periods for %s", *nperiodsp, stream_name); ++#if 0 ++ if (!jack_power_of_two(driver->frames_per_cycle)) { ++ jack_error("JACK: frames must be a power of two " ++ "(64, 512, 1024, ...)\n"); ++ return -1; ++ } ++#endif ++ ++ if ((err = snd_pcm_hw_params_set_buffer_size (handle, hw_params, ++ *nperiodsp * ++ driver->frames_per_cycle)) ++ < 0) { ++ jack_error ("ALSA: cannot set buffer length to %" PRIu32 ++ " for %s", ++ *nperiodsp * driver->frames_per_cycle, ++ stream_name); ++ return -1; ++ } ++ ++ if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) { ++ jack_error ("ALSA: cannot set hardware parameters for %s", ++ stream_name); ++ return -1; ++ } ++ ++ snd_pcm_sw_params_current (handle, sw_params); ++ ++ if ((err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, ++ 0U)) < 0) { ++ jack_error ("ALSA: cannot set start mode for %s", stream_name); ++ return -1; ++ } ++ ++ stop_th = *nperiodsp * driver->frames_per_cycle; ++ if (driver->soft_mode) { ++ stop_th = (snd_pcm_uframes_t)-1; ++ } ++ ++ if ((err = snd_pcm_sw_params_set_stop_threshold ( ++ handle, sw_params, stop_th)) < 0) { ++ jack_error ("ALSA: cannot set stop mode for %s", ++ stream_name); ++ return -1; ++ } ++ ++ if ((err = snd_pcm_sw_params_set_silence_threshold ( ++ handle, sw_params, 0)) < 0) { ++ jack_error ("ALSA: cannot set silence threshold for %s", ++ stream_name); ++ return -1; ++ } ++ ++#if 0 ++ jack_info ("set silence size to %lu * %lu = %lu", ++ driver->frames_per_cycle, *nperiodsp, ++ driver->frames_per_cycle * *nperiodsp); ++ ++ if ((err = snd_pcm_sw_params_set_silence_size ( ++ handle, sw_params, ++ driver->frames_per_cycle * *nperiodsp)) < 0) { ++ jack_error ("ALSA: cannot set silence size for %s", ++ stream_name); ++ return -1; ++ } ++#endif ++ ++ if (handle == driver->playback_handle) ++ err = snd_pcm_sw_params_set_avail_min ( ++ handle, sw_params, ++ driver->frames_per_cycle ++ * (*nperiodsp - driver->user_nperiods + 1)); ++ else ++ err = snd_pcm_sw_params_set_avail_min ( ++ handle, sw_params, driver->frames_per_cycle); ++ ++ if (err < 0) { ++ jack_error ("ALSA: cannot set avail min for %s", stream_name); ++ return -1; ++ } ++ ++ if ((err = snd_pcm_sw_params (handle, sw_params)) < 0) { ++ jack_error ("ALSA: cannot set software parameters for %s\n", ++ stream_name); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_set_parameters (alsa_driver_t *driver, ++ jack_nframes_t frames_per_cycle, ++ jack_nframes_t user_nperiods, ++ jack_nframes_t rate) ++{ ++ int dir; ++ snd_pcm_uframes_t p_period_size = 0; ++ snd_pcm_uframes_t c_period_size = 0; ++ channel_t chn; ++ unsigned int pr = 0; ++ unsigned int cr = 0; ++ int err; ++ ++ driver->frame_rate = rate; ++ driver->frames_per_cycle = frames_per_cycle; ++ driver->user_nperiods = user_nperiods; ++ ++ jack_info ("configuring for %" PRIu32 "Hz, period = %" ++ PRIu32 " frames (%.1f ms), buffer = %" PRIu32 " periods", ++ rate, frames_per_cycle, (((float)frames_per_cycle / (float) rate) * 1000.0f), user_nperiods); ++ ++ if (driver->capture_handle) { ++ if (alsa_driver_configure_stream ( ++ driver, ++ driver->alsa_name_capture, ++ "capture", ++ driver->capture_handle, ++ driver->capture_hw_params, ++ driver->capture_sw_params, ++ &driver->capture_nperiods, ++ (long unsigned int*)&driver->capture_nchannels, ++ driver->capture_sample_bytes)) { ++ jack_error ("ALSA: cannot configure capture channel"); ++ return -1; ++ } ++ } ++ ++ if (driver->playback_handle) { ++ if (alsa_driver_configure_stream ( ++ driver, ++ driver->alsa_name_playback, ++ "playback", ++ driver->playback_handle, ++ driver->playback_hw_params, ++ driver->playback_sw_params, ++ &driver->playback_nperiods, ++ (long unsigned int*)&driver->playback_nchannels, ++ driver->playback_sample_bytes)) { ++ jack_error ("ALSA: cannot configure playback channel"); ++ return -1; ++ } ++ } ++ ++ /* check the rate, since thats rather important */ ++ ++ if (driver->playback_handle) { ++ snd_pcm_hw_params_get_rate (driver->playback_hw_params, ++ &pr, &dir); ++ } ++ ++ if (driver->capture_handle) { ++ snd_pcm_hw_params_get_rate (driver->capture_hw_params, ++ &cr, &dir); ++ } ++ ++ if (driver->capture_handle && driver->playback_handle) { ++ if (cr != pr) { ++ jack_error ("playback and capture sample rates do " ++ "not match (%d vs. %d)", pr, cr); ++ } ++ ++ /* only change if *both* capture and playback rates ++ * don't match requested certain hardware actually ++ * still works properly in full-duplex with slightly ++ * different rate values between adc and dac ++ */ ++ if (cr != driver->frame_rate && pr != driver->frame_rate) { ++ jack_error ("sample rate in use (%d Hz) does not " ++ "match requested rate (%d Hz)", ++ cr, driver->frame_rate); ++ driver->frame_rate = cr; ++ } ++ ++ } else if (driver->capture_handle && cr != driver->frame_rate) { ++ jack_error ("capture sample rate in use (%d Hz) does not " ++ "match requested rate (%d Hz)", ++ cr, driver->frame_rate); ++ driver->frame_rate = cr; ++ } else if (driver->playback_handle && pr != driver->frame_rate) { ++ jack_error ("playback sample rate in use (%d Hz) does not " ++ "match requested rate (%d Hz)", ++ pr, driver->frame_rate); ++ driver->frame_rate = pr; ++ } ++ ++ ++ /* check the fragment size, since thats non-negotiable */ ++ ++ if (driver->playback_handle) { ++ snd_pcm_access_t access; ++ ++ err = snd_pcm_hw_params_get_period_size ( ++ driver->playback_hw_params, &p_period_size, &dir); ++ err = snd_pcm_hw_params_get_format ( ++ driver->playback_hw_params, ++ &(driver->playback_sample_format)); ++ err = snd_pcm_hw_params_get_access (driver->playback_hw_params, ++ &access); ++ driver->playback_interleaved = ++ (access == SND_PCM_ACCESS_MMAP_INTERLEAVED) ++ || (access == SND_PCM_ACCESS_MMAP_COMPLEX); ++ ++ if (p_period_size != driver->frames_per_cycle) { ++ jack_error ("alsa_pcm: requested an interrupt every %" ++ PRIu32 ++ " frames but got %u frames for playback", ++ driver->frames_per_cycle, p_period_size); ++ return -1; ++ } ++ } ++ ++ if (driver->capture_handle) { ++ snd_pcm_access_t access; ++ ++ err = snd_pcm_hw_params_get_period_size ( ++ driver->capture_hw_params, &c_period_size, &dir); ++ err = snd_pcm_hw_params_get_format ( ++ driver->capture_hw_params, ++ &(driver->capture_sample_format)); ++ err = snd_pcm_hw_params_get_access (driver->capture_hw_params, ++ &access); ++ driver->capture_interleaved = ++ (access == SND_PCM_ACCESS_MMAP_INTERLEAVED) ++ || (access == SND_PCM_ACCESS_MMAP_COMPLEX); ++ ++ ++ if (c_period_size != driver->frames_per_cycle) { ++ jack_error ("alsa_pcm: requested an interrupt every %" ++ PRIu32 ++ " frames but got %uc frames for capture", ++ driver->frames_per_cycle, p_period_size); ++ return -1; ++ } ++ } ++ ++ driver->playback_sample_bytes = ++ snd_pcm_format_physical_width (driver->playback_sample_format) ++ / 8; ++ driver->capture_sample_bytes = ++ snd_pcm_format_physical_width (driver->capture_sample_format) ++ / 8; ++ ++ if (driver->playback_handle) { ++ switch (driver->playback_sample_format) { ++ case SND_PCM_FORMAT_FLOAT_LE: ++ case SND_PCM_FORMAT_S32_LE: ++ case SND_PCM_FORMAT_S24_3LE: ++ case SND_PCM_FORMAT_S24_3BE: ++ case SND_PCM_FORMAT_S16_LE: ++ case SND_PCM_FORMAT_S32_BE: ++ case SND_PCM_FORMAT_S16_BE: ++ break; ++ ++ default: ++ jack_error ("programming error: unhandled format " ++ "type for playback"); ++ exit (1); ++ } ++ } ++ ++ if (driver->capture_handle) { ++ switch (driver->capture_sample_format) { ++ case SND_PCM_FORMAT_FLOAT_LE: ++ case SND_PCM_FORMAT_S32_LE: ++ case SND_PCM_FORMAT_S24_3LE: ++ case SND_PCM_FORMAT_S24_3BE: ++ case SND_PCM_FORMAT_S16_LE: ++ case SND_PCM_FORMAT_S32_BE: ++ case SND_PCM_FORMAT_S16_BE: ++ break; ++ ++ default: ++ jack_error ("programming error: unhandled format " ++ "type for capture"); ++ exit (1); ++ } ++ } ++ ++ if (driver->playback_interleaved) { ++ const snd_pcm_channel_area_t *my_areas; ++ snd_pcm_uframes_t offset, frames; ++ if (snd_pcm_mmap_begin(driver->playback_handle, ++ &my_areas, &offset, &frames) < 0) { ++ jack_error ("ALSA: %s: mmap areas info error", ++ driver->alsa_name_playback); ++ return -1; ++ } ++ driver->interleave_unit = ++ snd_pcm_format_physical_width ( ++ driver->playback_sample_format) / 8; ++ } else { ++ driver->interleave_unit = 0; /* NOT USED */ ++ } ++ ++ if (driver->capture_interleaved) { ++ const snd_pcm_channel_area_t *my_areas; ++ snd_pcm_uframes_t offset, frames; ++ if (snd_pcm_mmap_begin(driver->capture_handle, ++ &my_areas, &offset, &frames) < 0) { ++ jack_error ("ALSA: %s: mmap areas info error", ++ driver->alsa_name_capture); ++ return -1; ++ } ++ } ++ ++ if (driver->playback_nchannels > driver->capture_nchannels) { ++ driver->max_nchannels = driver->playback_nchannels; ++ driver->user_nchannels = driver->capture_nchannels; ++ } else { ++ driver->max_nchannels = driver->capture_nchannels; ++ driver->user_nchannels = driver->playback_nchannels; ++ } ++ ++ alsa_driver_setup_io_function_pointers (driver); ++ ++ /* Allocate and initialize structures that rely on the ++ channels counts. ++ ++ Set up the bit pattern that is used to record which ++ channels require action on every cycle. any bits that are ++ not set after the engine's process() call indicate channels ++ that potentially need to be silenced. ++ */ ++ ++ bitset_create (&driver->channels_done, driver->max_nchannels); ++ bitset_create (&driver->channels_not_done, driver->max_nchannels); ++ ++ if (driver->playback_handle) { ++ driver->playback_addr = (char **) ++ malloc (sizeof (char *) * driver->playback_nchannels); ++ memset (driver->playback_addr, 0, ++ sizeof (char *) * driver->playback_nchannels); ++ driver->playback_interleave_skip = (unsigned long *) ++ malloc (sizeof (unsigned long *) * driver->playback_nchannels); ++ memset (driver->playback_interleave_skip, 0, ++ sizeof (unsigned long *) * driver->playback_nchannels); ++ driver->silent = (unsigned long *) ++ malloc (sizeof (unsigned long) ++ * driver->playback_nchannels); ++ ++ for (chn = 0; chn < driver->playback_nchannels; chn++) { ++ driver->silent[chn] = 0; ++ } ++ ++ for (chn = 0; chn < driver->playback_nchannels; chn++) { ++ bitset_add (driver->channels_done, chn); ++ } ++ ++ driver->dither_state = (dither_state_t *) ++ calloc ( driver->playback_nchannels, ++ sizeof (dither_state_t)); ++ } ++ ++ if (driver->capture_handle) { ++ driver->capture_addr = (char **) ++ malloc (sizeof (char *) * driver->capture_nchannels); ++ memset (driver->capture_addr, 0, ++ sizeof (char *) * driver->capture_nchannels); ++ driver->capture_interleave_skip = (unsigned long *) ++ malloc (sizeof (unsigned long *) * driver->capture_nchannels); ++ memset (driver->capture_interleave_skip, 0, ++ sizeof (unsigned long *) * driver->capture_nchannels); ++ } ++ ++ driver->clock_sync_data = (ClockSyncStatus *) ++ malloc (sizeof (ClockSyncStatus) * driver->max_nchannels); ++ ++ driver->period_usecs = ++ (jack_time_t) floor ((((float) driver->frames_per_cycle) / ++ driver->frame_rate) * 1000000.0f); ++ driver->poll_timeout = (int) floor (1.5f * driver->period_usecs); ++ ++ // steph ++ /* ++ if (driver->engine) { ++ driver->engine->set_buffer_size (driver->engine, ++ driver->frames_per_cycle); ++ } ++ */ ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_reset_parameters (alsa_driver_t *driver, ++ jack_nframes_t frames_per_cycle, ++ jack_nframes_t user_nperiods, ++ jack_nframes_t rate) ++{ ++ /* XXX unregister old ports ? */ ++ alsa_driver_release_channel_dependent_memory (driver); ++ return alsa_driver_set_parameters (driver, ++ frames_per_cycle, ++ user_nperiods, rate); ++} ++ ++int ++JackAlsaDriver::alsa_driver_get_channel_addresses (alsa_driver_t *driver, ++ snd_pcm_uframes_t *capture_avail, ++ snd_pcm_uframes_t *playback_avail, ++ snd_pcm_uframes_t *capture_offset, ++ snd_pcm_uframes_t *playback_offset) ++{ ++ unsigned long err; ++ channel_t chn; ++ ++ if (capture_avail) { ++ if ((err = snd_pcm_mmap_begin ( ++ driver->capture_handle, &driver->capture_areas, ++ (snd_pcm_uframes_t *) capture_offset, ++ (snd_pcm_uframes_t *) capture_avail)) < 0) { ++ jack_error ("ALSA: %s: mmap areas info error", ++ driver->alsa_name_capture); ++ return -1; ++ } ++ ++ for (chn = 0; chn < driver->capture_nchannels; chn++) { ++ const snd_pcm_channel_area_t *a = ++ &driver->capture_areas[chn]; ++ driver->capture_addr[chn] = (char *) a->addr ++ + ((a->first + a->step * *capture_offset) / 8); ++ driver->capture_interleave_skip[chn] = (unsigned long ) (a->step / 8); ++ } ++ } ++ ++ if (playback_avail) { ++ if ((err = snd_pcm_mmap_begin ( ++ driver->playback_handle, &driver->playback_areas, ++ (snd_pcm_uframes_t *) playback_offset, ++ (snd_pcm_uframes_t *) playback_avail)) < 0) { ++ jack_error ("ALSA: %s: mmap areas info error ", ++ driver->alsa_name_playback); ++ return -1; ++ } ++ ++ for (chn = 0; chn < driver->playback_nchannels; chn++) { ++ const snd_pcm_channel_area_t *a = ++ &driver->playback_areas[chn]; ++ driver->playback_addr[chn] = (char *) a->addr ++ + ((a->first + a->step * *playback_offset) / 8); ++ driver->playback_interleave_skip[chn] = (unsigned long ) (a->step / 8); ++ } ++ } ++ ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_start (alsa_driver_t *driver) ++{ ++ int err; ++ snd_pcm_uframes_t poffset, pavail; ++ channel_t chn; ++ ++ driver->poll_last = 0; ++ driver->poll_next = 0; ++ ++ if (driver->playback_handle) { ++ if ((err = snd_pcm_prepare (driver->playback_handle)) < 0) { ++ jack_error ("ALSA: prepare error for playback on " ++ "\"%s\" (%s)", driver->alsa_name_playback, ++ snd_strerror(err)); ++ return -1; ++ } ++ } ++ ++ if ((driver->capture_handle && driver->capture_and_playback_not_synced) ++ || !driver->playback_handle) { ++ if ((err = snd_pcm_prepare (driver->capture_handle)) < 0) { ++ jack_error ("ALSA: prepare error for capture on \"%s\"" ++ " (%s)", driver->alsa_name_capture, ++ snd_strerror(err)); ++ return -1; ++ } ++ } ++ ++ if (driver->hw_monitoring) { ++ if (driver->input_monitor_mask || driver->all_monitor_in) { ++ if (driver->all_monitor_in) { ++ driver->hw->set_input_monitor_mask (driver->hw, ~0U); ++ } else { ++ driver->hw->set_input_monitor_mask ( ++ driver->hw, driver->input_monitor_mask); ++ } ++ } else { ++ driver->hw->set_input_monitor_mask (driver->hw, ++ driver->input_monitor_mask); ++ } ++ } ++ ++ if (driver->playback_handle) { ++ driver->playback_nfds = ++ snd_pcm_poll_descriptors_count (driver->playback_handle); ++ } else { ++ driver->playback_nfds = 0; ++ } ++ ++ if (driver->capture_handle) { ++ driver->capture_nfds = ++ snd_pcm_poll_descriptors_count (driver->capture_handle); ++ } else { ++ driver->capture_nfds = 0; ++ } ++ ++ if (driver->pfd) { ++ free (driver->pfd); ++ } ++ ++ driver->pfd = (struct pollfd *) ++ malloc (sizeof (struct pollfd) * ++ (driver->playback_nfds + driver->capture_nfds + 2)); ++ ++ if (driver->midi && !driver->xrun_recovery) ++ (driver->midi->start)(driver->midi); ++ ++ if (driver->playback_handle) { ++ /* fill playback buffer with zeroes, and mark ++ all fragments as having data. ++ */ ++ ++ pavail = snd_pcm_avail_update (driver->playback_handle); ++ ++ if (pavail != ++ driver->frames_per_cycle * driver->playback_nperiods) { ++ jack_error ("ALSA: full buffer not available at start"); ++ return -1; ++ } ++ ++ if (alsa_driver_get_channel_addresses (driver, ++ 0, &pavail, 0, &poffset)) { ++ return -1; ++ } ++ ++ /* XXX this is cheating. ALSA offers no guarantee that ++ we can access the entire buffer at any one time. It ++ works on most hardware tested so far, however, buts ++ its a liability in the long run. I think that ++ alsa-lib may have a better function for doing this ++ here, where the goal is to silence the entire ++ buffer. ++ */ ++ ++ for (chn = 0; chn < driver->playback_nchannels; chn++) { ++ alsa_driver_silence_on_channel ( ++ driver, chn, ++ driver->user_nperiods ++ * driver->frames_per_cycle); ++ } ++ ++ snd_pcm_mmap_commit (driver->playback_handle, poffset, ++ driver->user_nperiods ++ * driver->frames_per_cycle); ++ ++ if ((err = snd_pcm_start (driver->playback_handle)) < 0) { ++ jack_error ("ALSA: could not start playback (%s)", ++ snd_strerror (err)); ++ return -1; ++ } ++ } ++ ++ if ((driver->capture_handle && driver->capture_and_playback_not_synced) ++ || !driver->playback_handle) { ++ if ((err = snd_pcm_start (driver->capture_handle)) < 0) { ++ jack_error ("ALSA: could not start capture (%s)", ++ snd_strerror (err)); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_stop (alsa_driver_t *driver) ++{ ++ int err; ++ //JSList* node; ++ //int chn; ++ ++ /* silence all capture port buffers, because we might ++ be entering offline mode. ++ */ ++ ++ // steph ++ /* ++ for (chn = 0, node = driver->capture_ports; node; ++ node = jack_slist_next (node), chn++) { ++ ++ jack_port_t* port; ++ char* buf; ++ jack_nframes_t nframes = driver->engine->control->buffer_size; ++ ++ port = (jack_port_t *) node->data; ++ buf = jack_port_get_buffer (port, nframes); ++ memset (buf, 0, sizeof (jack_default_audio_sample_t) * nframes); ++ } ++ */ ++ ++ for (int i = 0; i < fPlaybackChannels; i++) { ++ jack_default_audio_sample_t* buf = ++ (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[i], fEngineControl->fBufferSize); ++ memset (buf, 0, sizeof (jack_default_audio_sample_t) * fEngineControl->fBufferSize); ++ } ++ ++ if (driver->playback_handle) { ++ if ((err = snd_pcm_drop (driver->playback_handle)) < 0) { ++ jack_error ("ALSA: channel flush for playback " ++ "failed (%s)", snd_strerror (err)); ++ return -1; ++ } ++ } ++ ++ if (!driver->playback_handle ++ || driver->capture_and_playback_not_synced) { ++ if (driver->capture_handle) { ++ if ((err = snd_pcm_drop (driver->capture_handle)) < 0) { ++ jack_error ("ALSA: channel flush for " ++ "capture failed (%s)", ++ snd_strerror (err)); ++ return -1; ++ } ++ } ++ } ++ ++ if (driver->hw_monitoring) { ++ driver->hw->set_input_monitor_mask (driver->hw, 0); ++ } ++ ++ if (driver->midi && !driver->xrun_recovery) ++ (driver->midi->stop)(driver->midi); ++ ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_restart (alsa_driver_t *driver) ++{ ++ int res; ++ ++ driver->xrun_recovery = 1; ++ if ((res = Stop()) == 0) ++ res = Start(); ++ driver->xrun_recovery = 0; ++ ++ if (res && driver->midi) ++ (driver->midi->stop)(driver->midi); ++ ++ return res; ++} ++ ++int ++JackAlsaDriver::alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs) ++{ ++ snd_pcm_status_t *status; ++ int res; ++ ++ jack_error("alsa_driver_xrun_recovery"); ++ ++ snd_pcm_status_alloca(&status); ++ ++ if (driver->capture_handle) { ++ if ((res = snd_pcm_status(driver->capture_handle, status)) ++ < 0) { ++ jack_error("status error: %s", snd_strerror(res)); ++ } ++ } else { ++ if ((res = snd_pcm_status(driver->playback_handle, status)) ++ < 0) { ++ jack_error("status error: %s", snd_strerror(res)); ++ } ++ } ++ ++ if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN ++ && driver->process_count > XRUN_REPORT_DELAY) { ++ struct timeval now, diff, tstamp; ++ driver->xrun_count++; ++ snd_pcm_status_get_tstamp(status,&now); ++ snd_pcm_status_get_trigger_tstamp(status, &tstamp); ++ timersub(&now, &tstamp, &diff); ++ *delayed_usecs = diff.tv_sec * 1000000.0 + diff.tv_usec; ++ jack_error("\n\n**** alsa_pcm: xrun of at least %.3f msecs\n\n", *delayed_usecs / 1000.0); ++ } ++ ++ if (alsa_driver_restart (driver)) { ++ return -1; ++ } ++ return 0; ++} ++ ++void ++JackAlsaDriver::alsa_driver_silence_untouched_channels (alsa_driver_t *driver, ++ jack_nframes_t nframes) ++{ ++ channel_t chn; ++ jack_nframes_t buffer_frames = ++ driver->frames_per_cycle * driver->playback_nperiods; ++ ++ for (chn = 0; chn < driver->playback_nchannels; chn++) { ++ if (bitset_contains (driver->channels_not_done, chn)) { ++ if (driver->silent[chn] < buffer_frames) { ++ alsa_driver_silence_on_channel_no_mark ( ++ driver, chn, nframes); ++ driver->silent[chn] += nframes; ++ } ++ } ++ } ++} ++ ++static int under_gdb = FALSE; ++ ++jack_nframes_t ++JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float ++ *delayed_usecs) ++{ ++ snd_pcm_sframes_t avail = 0; ++ snd_pcm_sframes_t capture_avail = 0; ++ snd_pcm_sframes_t playback_avail = 0; ++ int xrun_detected = FALSE; ++ int need_capture; ++ int need_playback; ++ unsigned int i; ++ jack_time_t poll_enter; ++ jack_time_t poll_ret = 0; ++ ++ *status = -1; ++ *delayed_usecs = 0; ++ ++ need_capture = driver->capture_handle ? 1 : 0; ++ ++ if (extra_fd >= 0) { ++ need_playback = 0; ++ } else { ++ need_playback = driver->playback_handle ? 1 : 0; ++ } ++ ++ again: ++ ++ while (need_playback || need_capture) { ++ ++ int poll_result; ++ unsigned int ci = 0; ++ unsigned int nfds; ++ unsigned short revents; ++ ++ nfds = 0; ++ ++ if (need_playback) { ++ snd_pcm_poll_descriptors (driver->playback_handle, ++ &driver->pfd[0], ++ driver->playback_nfds); ++ nfds += driver->playback_nfds; ++ } ++ ++ if (need_capture) { ++ snd_pcm_poll_descriptors (driver->capture_handle, ++ &driver->pfd[nfds], ++ driver->capture_nfds); ++ ci = nfds; ++ nfds += driver->capture_nfds; ++ } ++ ++ /* ALSA doesn't set POLLERR in some versions of 0.9.X */ ++ ++ for (i = 0; i < nfds; i++) { ++ driver->pfd[i].events |= POLLERR; ++ } ++ ++ if (extra_fd >= 0) { ++ driver->pfd[nfds].fd = extra_fd; ++ driver->pfd[nfds].events = ++ POLLIN|POLLERR|POLLHUP|POLLNVAL; ++ nfds++; ++ } ++ ++ poll_enter = jack_get_microseconds (); ++ ++ if (poll_enter > driver->poll_next) { ++ /* ++ * This processing cycle was delayed past the ++ * next due interrupt! Do not account this as ++ * a wakeup delay: ++ */ ++ driver->poll_next = 0; ++ driver->poll_late++; ++ } ++ ++ poll_result = poll (driver->pfd, nfds, driver->poll_timeout); ++ if (poll_result < 0) { ++ ++ if (errno == EINTR) { ++ jack_info ("poll interrupt"); ++ // this happens mostly when run ++ // under gdb, or when exiting due to a signal ++ if (under_gdb) { ++ goto again; ++ } ++ *status = -2; ++ return 0; ++ } ++ ++ jack_error ("ALSA: poll call failed (%s)", ++ strerror (errno)); ++ *status = -3; ++ return 0; ++ ++ } ++ ++ poll_ret = jack_get_microseconds (); ++ ++ // steph ++ fBeginDateUst = poll_ret; ++ ++ if (extra_fd < 0) { ++ if (driver->poll_next && poll_ret > driver->poll_next) { ++ *delayed_usecs = poll_ret - driver->poll_next; ++ } ++ driver->poll_last = poll_ret; ++ driver->poll_next = poll_ret + driver->period_usecs; ++ // steph ++ /* ++ driver->engine->transport_cycle_start (driver->engine, ++ poll_ret); ++ */ ++ } ++ ++#ifdef DEBUG_WAKEUP ++ jack_info ("%" PRIu64 ": checked %d fds, %" PRIu64 ++ " usecs since poll entered", poll_ret, nfds, ++ poll_ret - poll_enter); ++#endif ++ ++ /* check to see if it was the extra FD that caused us ++ * to return from poll */ ++ ++ if (extra_fd >= 0) { ++ ++ if (driver->pfd[nfds-1].revents == 0) { ++ /* we timed out on the extra fd */ ++ ++ *status = -4; ++ return -1; ++ } ++ ++ /* if POLLIN was the only bit set, we're OK */ ++ ++ *status = 0; ++ if (driver->pfd[nfds-1].revents == POLLIN) { ++ jack_error("driver->pfd[nfds-1].revents == POLLIN"); ++ } ++ return (driver->pfd[nfds-1].revents == POLLIN) ? 0 : -1; ++ } ++ ++ if (need_playback) { ++ if (snd_pcm_poll_descriptors_revents ++ (driver->playback_handle, &driver->pfd[0], ++ driver->playback_nfds, &revents) < 0) { ++ jack_error ("ALSA: playback revents failed"); ++ *status = -6; ++ return 0; ++ } ++ ++ if (revents & POLLERR) { ++ xrun_detected = TRUE; ++ } ++ ++ if (revents & POLLOUT) { ++ need_playback = 0; ++#ifdef DEBUG_WAKEUP ++ jack_info ("%" PRIu64 ++ " playback stream ready", ++ poll_ret); ++#endif ++ } ++ } ++ ++ if (need_capture) { ++ if (snd_pcm_poll_descriptors_revents ++ (driver->capture_handle, &driver->pfd[ci], ++ driver->capture_nfds, &revents) < 0) { ++ jack_error ("ALSA: capture revents failed"); ++ *status = -6; ++ return 0; ++ } ++ ++ if (revents & POLLERR) { ++ xrun_detected = TRUE; ++ } ++ ++ if (revents & POLLIN) { ++ need_capture = 0; ++#ifdef DEBUG_WAKEUP ++ jack_info ("%" PRIu64 ++ " capture stream ready", ++ poll_ret); ++#endif ++ } ++ } ++ ++ if (poll_result == 0) { ++ jack_error ("ALSA: poll time out, polled for %" PRIu64 ++ " usecs", ++ poll_ret - poll_enter); ++ *status = -5; ++ return 0; ++ } ++ ++ } ++ ++ if (driver->capture_handle) { ++ if ((capture_avail = snd_pcm_avail_update ( ++ driver->capture_handle)) < 0) { ++ if (capture_avail == -EPIPE) { ++ xrun_detected = TRUE; ++ } else { ++ jack_error ("unknown ALSA avail_update return" ++ " value (%u)", capture_avail); ++ } ++ } ++ } else { ++ /* odd, but see min() computation below */ ++ capture_avail = INT_MAX; ++ } ++ ++ if (driver->playback_handle) { ++ if ((playback_avail = snd_pcm_avail_update ( ++ driver->playback_handle)) < 0) { ++ if (playback_avail == -EPIPE) { ++ xrun_detected = TRUE; ++ } else { ++ jack_error ("unknown ALSA avail_update return" ++ " value (%u)", playback_avail); ++ } ++ } ++ } else { ++ /* odd, but see min() computation below */ ++ playback_avail = INT_MAX; ++ } ++ ++ if (xrun_detected) { ++ *status = alsa_driver_xrun_recovery (driver, delayed_usecs); ++ return 0; ++ } ++ ++ *status = 0; ++ driver->last_wait_ust = poll_ret; ++ ++ avail = capture_avail < playback_avail ? capture_avail : playback_avail; ++ ++#ifdef DEBUG_WAKEUP ++ jack_info ("wakeup complete, avail = %lu, pavail = %lu " ++ "cavail = %lu", ++ avail, playback_avail, capture_avail); ++#endif ++ ++ /* mark all channels not done for now. read/write will change this */ ++ ++ bitset_copy (driver->channels_not_done, driver->channels_done); ++ ++ /* constrain the available count to the nearest (round down) number of ++ periods. ++ */ ++ ++ return avail - (avail % driver->frames_per_cycle); ++} ++ ++ ++int JackAlsaDriver::SetBufferSize(jack_nframes_t buffer_size) ++{ ++ jack_log("JackAlsaDriver::SetBufferSize %ld", buffer_size); ++ int res = alsa_driver_reset_parameters((alsa_driver_t *)fDriver, buffer_size, ++ ((alsa_driver_t *)fDriver)->user_nperiods, ++ ((alsa_driver_t *)fDriver)->frame_rate); ++ ++ if (res == 0) { // update fEngineControl and fGraphManager ++ JackAudioDriver::SetBufferSize(buffer_size); // never fails ++ } else { ++ alsa_driver_reset_parameters((alsa_driver_t *)fDriver, fEngineControl->fBufferSize, ++ ((alsa_driver_t *)fDriver)->user_nperiods, ++ ((alsa_driver_t *)fDriver)->frame_rate); ++ } ++ ++ return res; ++} ++ ++int ++JackAlsaDriver::alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes) ++{ ++ snd_pcm_sframes_t contiguous; ++ snd_pcm_sframes_t nread; ++ snd_pcm_sframes_t offset; ++ jack_nframes_t orig_nframes; ++ jack_default_audio_sample_t* buf; ++ //channel_t chn; ++ //JSList *node; ++ //jack_port_t* port; ++ int err; ++ ++ // steph ++ /* ++ if (!driver->capture_handle || driver->engine->freewheeling) { ++ return 0; ++ } ++ */ ++ ++ if (nframes > driver->frames_per_cycle) { ++ return -1; ++ } ++ ++ if (driver->midi) ++ (driver->midi->read)(driver->midi, nframes); ++ ++ if (!driver->capture_handle) { ++ return 0; ++ } ++ ++ nread = 0; ++ contiguous = 0; ++ orig_nframes = nframes; ++ ++ while (nframes) { ++ ++ contiguous = nframes; ++ ++ if (alsa_driver_get_channel_addresses ( ++ driver, ++ (snd_pcm_uframes_t *) &contiguous, ++ (snd_pcm_uframes_t *) 0, ++ (snd_pcm_uframes_t *)&offset, 0) < 0) { ++ return -1; ++ } ++ ++ // steph ++ for (int chn = 0; chn < fCaptureChannels; chn++) { ++ if (fGraphManager->GetConnectionsNum(fCapturePortList[chn]) > 0) { ++ buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[chn], orig_nframes); ++ alsa_driver_read_from_channel (driver, chn, buf + nread, contiguous); ++ } ++ } ++ ++ /* // steph ++ for (chn = 0, node = driver->capture_ports; node; ++ node = jack_slist_next (node), chn++) { ++ ++ port = (jack_port_t *) node->data; ++ ++ if (!jack_port_connected (port)) { ++ // no-copy optimization ++ continue; ++ } ++ buf = jack_port_get_buffer (port, orig_nframes); ++ alsa_driver_read_from_channel (driver, chn, ++ buf + nread, contiguous); ++ } ++ */ ++ ++ if ((err = snd_pcm_mmap_commit (driver->capture_handle, ++ offset, contiguous)) < 0) { ++ ++ jack_error ("ALSA: could not complete read of %" ++ PRIu32 " frames: error = %d\n", contiguous, err); ++ jack_error ("ALSA: could not complete read of %d frames: error = %d", contiguous, err); ++ return -1; ++ } ++ ++ nframes -= contiguous; ++ nread += contiguous; ++ } ++ ++ return 0; ++} ++ ++int ++JackAlsaDriver::alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes) ++{ ++ //channel_t chn; ++ //JSList *node; ++ //JSList *mon_node; ++ jack_default_audio_sample_t* buf; ++ jack_default_audio_sample_t* monbuf; ++ jack_nframes_t orig_nframes; ++ snd_pcm_sframes_t nwritten; ++ snd_pcm_sframes_t contiguous; ++ snd_pcm_sframes_t offset; ++ JackPort* port; ++ //jack_port_t *port; ++ int err; ++ ++ driver->process_count++; ++ ++ // steph ++ /* ++ if (!driver->playback_handle || driver->engine->freewheeling) { ++ return 0; ++ } ++ */ ++ if (!driver->playback_handle) { ++ return 0; ++ } ++ ++ if (nframes > driver->frames_per_cycle) { ++ return -1; ++ } ++ ++ if (driver->midi) ++ (driver->midi->write)(driver->midi, nframes); ++ ++ nwritten = 0; ++ contiguous = 0; ++ orig_nframes = nframes; ++ ++ /* check current input monitor request status */ ++ ++ driver->input_monitor_mask = 0; ++ ++ // steph ++ /* ++ for (chn = 0, node = driver->capture_ports; node; ++ node = jack_slist_next (node), chn++) { ++ if (((jack_port_t *) node->data)->shared->monitor_requests) { ++ driver->input_monitor_mask |= (1<GetPort(fCapturePortList[chn]); ++ if (port->MonitoringInput()) { ++ driver->input_monitor_mask |= (1 << chn); ++ } ++ } ++ ++ if (driver->hw_monitoring) { ++ if ((driver->hw->input_monitor_mask ++ != driver->input_monitor_mask) ++ && !driver->all_monitor_in) { ++ driver->hw->set_input_monitor_mask ( ++ driver->hw, driver->input_monitor_mask); ++ } ++ } ++ ++ while (nframes) { ++ ++ contiguous = nframes; ++ ++ if (alsa_driver_get_channel_addresses ( ++ driver, ++ (snd_pcm_uframes_t *) 0, ++ (snd_pcm_uframes_t *) &contiguous, ++ 0, (snd_pcm_uframes_t *)&offset) < 0) { ++ return -1; ++ } ++ ++ // steph ++ for (int chn = 0; chn < fPlaybackChannels; chn++) { ++ // Ouput ports ++ if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chn]) > 0) { ++ buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[chn], orig_nframes); ++ alsa_driver_write_to_channel (driver, chn, buf + nwritten, contiguous); ++ // Monitor ports ++ if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[chn]) > 0) { ++ monbuf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[chn], orig_nframes); ++ memcpy(monbuf + nwritten, buf + nwritten, contiguous * sizeof(jack_default_audio_sample_t)); ++ } ++ } ++ } ++ ++ /* ++ for (chn = 0, node = driver->playback_ports, mon_node=driver->monitor_ports; ++ node; ++ node = jack_slist_next (node), chn++) { ++ ++ port = (jack_port_t *) node->data; ++ ++ if (!jack_port_connected (port)) { ++ continue; ++ } ++ buf = jack_port_get_buffer (port, orig_nframes); ++ alsa_driver_write_to_channel (driver, chn, ++ buf + nwritten, contiguous); ++ ++ if (mon_node) { ++ port = (jack_port_t *) mon_node->data; ++ if (!jack_port_connected (port)) { ++ continue; ++ } ++ monbuf = jack_port_get_buffer (port, orig_nframes); ++ memcpy (monbuf + nwritten, buf + nwritten, contiguous * sizeof(jack_default_audio_sample_t)); ++ mon_node = jack_slist_next (mon_node); ++ } ++ } ++ */ ++ ++ if (!bitset_empty (driver->channels_not_done)) { ++ alsa_driver_silence_untouched_channels (driver, ++ contiguous); ++ } ++ ++ if ((err = snd_pcm_mmap_commit (driver->playback_handle, ++ offset, contiguous)) < 0) { ++ jack_error ("ALSA: could not complete playback of %" ++ PRIu32 " frames: error = %d", contiguous, err); ++ jack_error ("ALSA: could not complete playback of %d frames: error = %d", contiguous, err); ++ if (err != EPIPE && err != ESTRPIPE) ++ return -1; ++ } ++ ++ nframes -= contiguous; ++ nwritten += contiguous; ++ } ++ return 0; ++} ++ ++void ++JackAlsaDriver::alsa_driver_delete (alsa_driver_t *driver) ++{ ++ JSList *node; ++ ++ if (driver->midi) ++ (driver->midi->destroy)(driver->midi); ++ ++ for (node = driver->clock_sync_listeners; node; ++ node = jack_slist_next (node)) { ++ free (node->data); ++ } ++ jack_slist_free (driver->clock_sync_listeners); ++ ++ if (driver->ctl_handle) { ++ snd_ctl_close (driver->ctl_handle); ++ driver->ctl_handle = 0; ++ } ++ ++ if (driver->ctl_handle) { ++ snd_ctl_close (driver->ctl_handle); ++ driver->ctl_handle = 0; ++ } ++ ++ if (driver->capture_handle) { ++ snd_pcm_close (driver->capture_handle); ++ driver->capture_handle = 0; ++ } ++ ++ if (driver->playback_handle) { ++ snd_pcm_close (driver->playback_handle); ++ driver->capture_handle = 0; ++ } ++ ++ if (driver->capture_hw_params) { ++ snd_pcm_hw_params_free (driver->capture_hw_params); ++ driver->capture_hw_params = 0; ++ } ++ ++ if (driver->playback_hw_params) { ++ snd_pcm_hw_params_free (driver->playback_hw_params); ++ driver->playback_hw_params = 0; ++ } ++ ++ if (driver->capture_sw_params) { ++ snd_pcm_sw_params_free (driver->capture_sw_params); ++ driver->capture_sw_params = 0; ++ } ++ ++ if (driver->playback_sw_params) { ++ snd_pcm_sw_params_free (driver->playback_sw_params); ++ driver->playback_sw_params = 0; ++ } ++ ++ if (driver->pfd) { ++ free (driver->pfd); ++ } ++ ++ if (driver->hw) { ++ driver->hw->release (driver->hw); ++ driver->hw = 0; ++ } ++ free(driver->alsa_name_playback); ++ free(driver->alsa_name_capture); ++ free(driver->alsa_driver); ++ ++ alsa_driver_release_channel_dependent_memory (driver); ++ // steph ++ //jack_driver_nt_finish ((jack_driver_nt_t *) driver); ++ free (driver); ++} ++ ++jack_driver_t * ++JackAlsaDriver::alsa_driver_new (const char *name, char *playback_alsa_device, ++ char *capture_alsa_device, ++ jack_client_t *client, ++ jack_nframes_t frames_per_cycle, ++ jack_nframes_t user_nperiods, ++ jack_nframes_t rate, ++ int hw_monitoring, ++ int hw_metering, ++ int capturing, ++ int playing, ++ DitherAlgorithm dither, ++ int soft_mode, ++ int monitor, ++ int user_capture_nchnls, ++ int user_playback_nchnls, ++ int shorts_first, ++ jack_nframes_t capture_latency, ++ jack_nframes_t playback_latency, ++ alsa_midi_t *midi) ++{ ++ int err; ++ ++ alsa_driver_t *driver; ++ ++ jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32 ++ "|%" PRIu32"|%" PRIu32"|%" PRIu32 "|%s|%s|%s|%s", ++ playing ? playback_alsa_device : "-", ++ capturing ? capture_alsa_device : "-", ++ frames_per_cycle, user_nperiods, rate, ++ user_capture_nchnls,user_playback_nchnls, ++ hw_monitoring ? "hwmon": "nomon", ++ hw_metering ? "hwmeter":"swmeter", ++ soft_mode ? "soft-mode":"-", ++ shorts_first ? "16bit":"32bit"); ++ ++ driver = (alsa_driver_t *) calloc (1, sizeof (alsa_driver_t)); ++ ++ jack_driver_nt_init ((jack_driver_nt_t *) driver); ++ ++ driver->midi = midi; ++ driver->xrun_recovery = 0; ++ ++ //driver->nt_attach = (JackDriverNTAttachFunction) alsa_driver_attach; ++ //driver->nt_detach = (JackDriverNTDetachFunction) alsa_driver_detach; ++ //driver->read = (JackDriverReadFunction) alsa_driver_read; ++ //driver->write = (JackDriverReadFunction) alsa_driver_write; ++ //driver->null_cycle = (JackDriverNullCycleFunction) alsa_driver_null_cycle; ++ //driver->nt_bufsize = (JackDriverNTBufSizeFunction) alsa_driver_bufsize; ++ //driver->nt_start = (JackDriverNTStartFunction) alsa_driver_start; ++ //driver->nt_stop = (JackDriverNTStopFunction) alsa_driver_stop; ++ //driver->nt_run_cycle = (JackDriverNTRunCycleFunction) alsa_driver_run_cycle; ++ ++ driver->playback_handle = NULL; ++ driver->capture_handle = NULL; ++ driver->ctl_handle = 0; ++ driver->hw = 0; ++ driver->capture_and_playback_not_synced = FALSE; ++ driver->max_nchannels = 0; ++ driver->user_nchannels = 0; ++ driver->playback_nchannels = user_playback_nchnls; ++ driver->capture_nchannels = user_capture_nchnls; ++ driver->playback_sample_bytes = (shorts_first ? 2 : 4); ++ driver->capture_sample_bytes = (shorts_first ? 2 : 4); ++ driver->capture_frame_latency = capture_latency; ++ driver->playback_frame_latency = playback_latency; ++ ++ driver->playback_addr = 0; ++ driver->capture_addr = 0; ++ driver->playback_interleave_skip = NULL; ++ driver->capture_interleave_skip = NULL; ++ ++ driver->silent = 0; ++ driver->all_monitor_in = FALSE; ++ driver->with_monitor_ports = monitor; ++ ++ driver->clock_mode = ClockMaster; /* XXX is it? */ ++ driver->input_monitor_mask = 0; /* XXX is it? */ ++ ++ driver->capture_ports = 0; ++ driver->playback_ports = 0; ++ driver->monitor_ports = 0; ++ ++ driver->pfd = 0; ++ driver->playback_nfds = 0; ++ driver->capture_nfds = 0; ++ ++ driver->dither = dither; ++ driver->soft_mode = soft_mode; ++ ++ pthread_mutex_init (&driver->clock_sync_lock, 0); ++ driver->clock_sync_listeners = 0; ++ ++ driver->poll_late = 0; ++ driver->xrun_count = 0; ++ driver->process_count = 0; ++ ++ driver->alsa_name_playback = strdup (playback_alsa_device); ++ driver->alsa_name_capture = strdup (capture_alsa_device); ++ ++ if (alsa_driver_check_card_type (driver)) { ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ ++ alsa_driver_hw_specific (driver, hw_monitoring, hw_metering); ++ ++ if (playing) { ++ if (snd_pcm_open (&driver->playback_handle, ++ playback_alsa_device, ++ SND_PCM_STREAM_PLAYBACK, ++ SND_PCM_NONBLOCK) < 0) { ++ switch (errno) { ++ case EBUSY: ++ jack_error ("the playback device \"%s\" is " ++ "already in use. Please stop the" ++ " application using it and " ++ "run JACK again", ++ playback_alsa_device); ++ alsa_driver_delete (driver); ++ return NULL; ++ break; ++ ++ case EPERM: ++ jack_error ("you do not have permission to open " ++ "the audio device \"%s\" for playback", ++ playback_alsa_device); ++ alsa_driver_delete (driver); ++ return NULL; ++ break; ++ } ++ ++ driver->playback_handle = NULL; ++ } ++ ++ if (driver->playback_handle) { ++ snd_pcm_nonblock (driver->playback_handle, 0); ++ } ++ } ++ ++ if (capturing) { ++ if (snd_pcm_open (&driver->capture_handle, ++ capture_alsa_device, ++ SND_PCM_STREAM_CAPTURE, ++ SND_PCM_NONBLOCK) < 0) { ++ switch (errno) { ++ case EBUSY: ++ jack_error ("the capture device \"%s\" is " ++ "already in use. Please stop the" ++ " application using it and " ++ "run JACK again", ++ capture_alsa_device); ++ alsa_driver_delete (driver); ++ return NULL; ++ break; ++ ++ case EPERM: ++ jack_error ("you do not have permission to open " ++ "the audio device \"%s\" for capture", ++ capture_alsa_device); ++ alsa_driver_delete (driver); ++ return NULL; ++ break; ++ } ++ ++ driver->capture_handle = NULL; ++ } ++ ++ if (driver->capture_handle) { ++ snd_pcm_nonblock (driver->capture_handle, 0); ++ } ++ } ++ ++ if (driver->playback_handle == NULL) { ++ if (playing) { ++ ++ /* they asked for playback, but we can't do it */ ++ ++ jack_error ("ALSA: Cannot open PCM device %s for " ++ "playback. Falling back to capture-only" ++ " mode", name); ++ ++ if (driver->capture_handle == NULL) { ++ /* can't do anything */ ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ ++ playing = FALSE; ++ } ++ } ++ ++ if (driver->capture_handle == NULL) { ++ if (capturing) { ++ ++ /* they asked for capture, but we can't do it */ ++ ++ jack_error ("ALSA: Cannot open PCM device %s for " ++ "capture. Falling back to playback-only" ++ " mode", name); ++ ++ if (driver->playback_handle == NULL) { ++ /* can't do anything */ ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ ++ capturing = FALSE; ++ } ++ } ++ ++ driver->playback_hw_params = 0; ++ driver->capture_hw_params = 0; ++ driver->playback_sw_params = 0; ++ driver->capture_sw_params = 0; ++ ++ if (driver->playback_handle) { ++ if ((err = snd_pcm_hw_params_malloc ( ++ &driver->playback_hw_params)) < 0) { ++ jack_error ("ALSA: could not allocate playback hw" ++ " params structure"); ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ ++ if ((err = snd_pcm_sw_params_malloc ( ++ &driver->playback_sw_params)) < 0) { ++ jack_error ("ALSA: could not allocate playback sw" ++ " params structure"); ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ } ++ ++ if (driver->capture_handle) { ++ if ((err = snd_pcm_hw_params_malloc ( ++ &driver->capture_hw_params)) < 0) { ++ jack_error ("ALSA: could not allocate capture hw" ++ " params structure"); ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ ++ if ((err = snd_pcm_sw_params_malloc ( ++ &driver->capture_sw_params)) < 0) { ++ jack_error ("ALSA: could not allocate capture sw" ++ " params structure"); ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ } ++ ++ if (alsa_driver_set_parameters (driver, frames_per_cycle, ++ user_nperiods, rate)) { ++ alsa_driver_delete (driver); ++ return NULL; ++ } ++ ++ driver->capture_and_playback_not_synced = FALSE; ++ ++ if (driver->capture_handle && driver->playback_handle) { ++ if (snd_pcm_link (driver->capture_handle, ++ driver->playback_handle) != 0) { ++ driver->capture_and_playback_not_synced = TRUE; ++ } ++ } ++ ++ driver->client = client; ++ return (jack_driver_t *) driver; ++} ++ ++int JackAlsaDriver::Attach() ++{ ++ JackPort* port; ++ int port_index; ++ unsigned long port_flags; ++ char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; ++ char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; ++ ++ assert(fCaptureChannels < DRIVER_PORT_NUM); ++ assert(fPlaybackChannels < DRIVER_PORT_NUM); ++ ++ port_flags = (unsigned long)CaptureDriverFlags; ++ ++ alsa_driver_t* alsa_driver = (alsa_driver_t*)fDriver; ++ ++ if (alsa_driver->has_hw_monitoring) ++ port_flags |= JackPortCanMonitor; ++ ++ // ALSA driver may have changed the values ++ JackAudioDriver::SetBufferSize(alsa_driver->frames_per_cycle); ++ JackAudioDriver::SetSampleRate(alsa_driver->frame_rate); ++ ++ jack_log("JackAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); ++ ++ for (int i = 0; i < fCaptureChannels; i++) { ++ snprintf(alias, sizeof(alias) - 1, "%s:capture_%u", fAliasName, i + 1); ++ snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); ++ if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { ++ jack_error("driver: cannot register port for %s", name); ++ return -1; ++ } ++ port = fGraphManager->GetPort(port_index); ++ port->SetAlias(alias); ++ port->SetLatency(alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency); ++ fCapturePortList[i] = port_index; ++ jack_log("JackAudioDriver::Attach fCapturePortList[i] %ld ", port_index); ++ } ++ ++ port_flags = (unsigned long)PlaybackDriverFlags; ++ ++ for (int i = 0; i < fPlaybackChannels; i++) { ++ snprintf(alias, sizeof(alias) - 1, "%s:playback_%u", fAliasName, i + 1); ++ snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); ++ if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { ++ jack_error("driver: cannot register port for %s", name); ++ return -1; ++ } ++ port = fGraphManager->GetPort(port_index); ++ port->SetAlias(alias); ++ // Add one buffer more latency if "async" mode is used... ++ port->SetLatency((alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) + ++ ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency); ++ fPlaybackPortList[i] = port_index; ++ jack_log("JackAudioDriver::Attach fPlaybackPortList[i] %ld ", port_index); ++ ++ // Monitor ports ++ if (fWithMonitorPorts) { ++ jack_log("Create monitor port "); ++ snprintf(name, sizeof(name) - 1, "%s:monitor_%d", fClientControl.fName, i + 1); ++ if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { ++ jack_error ("ALSA: cannot register monitor port for %s", name); ++ } else { ++ port = fGraphManager->GetPort(port_index); ++ port->SetLatency(alsa_driver->frames_per_cycle); ++ fMonitorPortList[i] = port_index; ++ } ++ } ++ } ++ ++ if (alsa_driver->midi) { ++ int err = (alsa_driver->midi->attach)(alsa_driver->midi); ++ if (err) ++ jack_error ("ALSA: cannot attach MIDI: %d", err); ++ } ++ ++ return 0; ++} ++ ++int JackAlsaDriver::Detach() ++{ ++ alsa_driver_t* alsa_driver = (alsa_driver_t*)fDriver; ++ if (alsa_driver->midi) ++ (alsa_driver->midi->detach)(alsa_driver->midi); ++ ++ return JackAudioDriver::Detach(); ++} ++ ++static int card_to_num(const char* device) ++{ ++ int err; ++ char* ctl_name; ++ snd_ctl_card_info_t *card_info; ++ snd_ctl_t* ctl_handle; ++ int i = -1; ++ ++ snd_ctl_card_info_alloca (&card_info); ++ ++ ctl_name = get_control_device_name(device); ++ if (ctl_name == NULL) { ++ jack_error("get_control_device_name() failed."); ++ goto fail; ++ } ++ ++ if ((err = snd_ctl_open (&ctl_handle, ctl_name, 0)) < 0) { ++ jack_error ("control open \"%s\" (%s)", ctl_name, ++ snd_strerror(err)); ++ goto free; ++ } ++ ++ if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) { ++ jack_error ("control hardware info \"%s\" (%s)", ++ device, snd_strerror (err)); ++ goto close; ++ } ++ ++ i = snd_ctl_card_info_get_card(card_info); ++ ++close: ++ snd_ctl_close(ctl_handle); ++ ++free: ++ free(ctl_name); ++ ++fail: ++ return i; ++} ++ ++int JackAlsaDriver::Open(jack_nframes_t nframes, ++ jack_nframes_t user_nperiods, ++ jack_nframes_t samplerate, ++ bool hw_monitoring, ++ bool hw_metering, ++ bool capturing, ++ bool playing, ++ DitherAlgorithm dither, ++ bool soft_mode, ++ bool monitor, ++ int inchannels, ++ int outchannels, ++ bool shorts_first, ++ const char* capture_driver_name, ++ const char* playback_driver_name, ++ jack_nframes_t capture_latency, ++ jack_nframes_t playback_latency, ++ const char* midi_driver_name) ++{ ++ // Generic JackAudioDriver Open ++ if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, ++ inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, ++ capture_latency, playback_latency) != 0) { ++ return -1; ++ } ++ ++ alsa_midi_t *midi = 0; ++ if (strcmp(midi_driver_name, "seq") == 0) ++ midi = alsa_seqmidi_new((jack_client_t*)this, 0); ++ else if (strcmp(midi_driver_name, "raw") == 0) ++ midi = alsa_rawmidi_new((jack_client_t*)this); ++ ++ if (JackServerGlobals::on_device_acquire != NULL) ++ { ++ int capture_card = card_to_num(capture_driver_name); ++ int playback_card = card_to_num(playback_driver_name); ++ char audio_name[32]; ++ ++ snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", capture_card); ++ if (!JackServerGlobals::on_device_acquire(audio_name)) { ++ jack_error("Audio device %s cannot be acquired, trying to open it anyway...", capture_driver_name); ++ } ++ ++ if (playback_card != capture_card) { ++ snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", playback_card); ++ if (!JackServerGlobals::on_device_acquire(audio_name)) { ++ jack_error("Audio device %s cannot be acquired, trying to open it anyway...", playback_driver_name); ++ } ++ } ++ } ++ ++ fDriver = alsa_driver_new ("alsa_pcm", (char*)playback_driver_name, (char*)capture_driver_name, ++ NULL, ++ nframes, ++ user_nperiods, ++ samplerate, ++ hw_monitoring, ++ hw_metering, ++ capturing, ++ playing, ++ dither, ++ soft_mode, ++ monitor, ++ inchannels, ++ outchannels, ++ shorts_first, ++ capture_latency, ++ playback_latency, ++ midi); ++ if (fDriver) { ++ // ALSA driver may have changed the in/out values ++ fCaptureChannels = ((alsa_driver_t *)fDriver)->capture_nchannels; ++ fPlaybackChannels = ((alsa_driver_t *)fDriver)->playback_nchannels; ++ return 0; ++ } else { ++ JackAudioDriver::Close(); ++ return -1; ++ } ++} ++ ++int JackAlsaDriver::Close() ++{ ++ JackAudioDriver::Close(); ++ alsa_driver_delete((alsa_driver_t*)fDriver); ++ ++ if (JackServerGlobals::on_device_release != NULL) ++ { ++ char audio_name[32]; ++ int capture_card = card_to_num(fCaptureDriverName); ++ if (capture_card >= 0) { ++ snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", capture_card); ++ JackServerGlobals::on_device_release(audio_name); ++ } ++ ++ int playback_card = card_to_num(fPlaybackDriverName); ++ if (playback_card >= 0 && playback_card != capture_card) { ++ snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", playback_card); ++ JackServerGlobals::on_device_release(audio_name); ++ } ++ } ++ ++ return 0; ++} ++ ++int JackAlsaDriver::Start() ++{ ++ JackAudioDriver::Start(); ++ return alsa_driver_start((alsa_driver_t *)fDriver); ++} ++ ++int JackAlsaDriver::Stop() ++{ ++ return alsa_driver_stop((alsa_driver_t *)fDriver); ++} ++ ++int JackAlsaDriver::Read() ++{ ++ /* Taken from alsa_driver_run_cycle */ ++ int wait_status; ++ jack_nframes_t nframes; ++ fDelayedUsecs = 0.f; ++ ++ nframes = alsa_driver_wait((alsa_driver_t *)fDriver, -1, &wait_status, &fDelayedUsecs); ++ ++ if (wait_status < 0) ++ return -1; /* driver failed */ ++ ++ if (nframes == 0) { ++ /* we detected an xrun and restarted: notify ++ * clients about the delay. ++ */ ++ jack_log("ALSA XRun wait_status = %d", wait_status); ++ NotifyXRun(fBeginDateUst, fDelayedUsecs); ++ return -1; ++ } ++ ++ if (nframes != fEngineControl->fBufferSize) ++ jack_log("JackAlsaDriver::Read error nframes = %ld", nframes); ++ ++ // Has to be done before read ++ JackDriver::CycleIncTime(); ++ ++ return alsa_driver_read((alsa_driver_t *)fDriver, fEngineControl->fBufferSize); ++} ++ ++int JackAlsaDriver::Write() ++{ ++ return alsa_driver_write((alsa_driver_t *)fDriver, fEngineControl->fBufferSize); ++} ++ ++void ++JackAlsaDriver::jack_driver_init (jack_driver_t *driver) ++{ ++ memset (driver, 0, sizeof (*driver)); ++ ++ driver->attach = 0; ++ driver->detach = 0; ++ driver->write = 0; ++ driver->read = 0; ++ driver->null_cycle = 0; ++ driver->bufsize = 0; ++ driver->start = 0; ++ driver->stop = 0; ++} ++ ++void ++JackAlsaDriver::jack_driver_nt_init (jack_driver_nt_t * driver) ++{ ++ memset (driver, 0, sizeof (*driver)); ++ ++ jack_driver_init ((jack_driver_t *) driver); ++ ++ driver->attach = 0; ++ driver->detach = 0; ++ driver->bufsize = 0; ++ driver->stop = 0; ++ driver->start = 0; ++ ++ driver->nt_bufsize = 0; ++ driver->nt_start = 0; ++ driver->nt_stop = 0; ++ driver->nt_attach = 0; ++ driver->nt_detach = 0; ++ driver->nt_run_cycle = 0; ++} ++ ++int JackAlsaDriver::is_realtime() const ++{ ++ return fEngineControl->fRealTime; ++} ++ ++int JackAlsaDriver::create_thread(pthread_t *thread, int priority, int realtime, void *(*start_routine)(void*), void *arg) ++{ ++ return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg); ++} ++ ++jack_port_id_t JackAlsaDriver::port_register(const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size) ++{ ++ jack_port_id_t port_index; ++ int res = fEngine->PortRegister(fClientControl.fRefNum, port_name, port_type, flags, buffer_size, &port_index); ++ return (res == 0) ? port_index : 0; ++} ++ ++int JackAlsaDriver::port_unregister(jack_port_id_t port_index) ++{ ++ return fEngine->PortUnRegister(fClientControl.fRefNum, port_index); ++} ++ ++void* JackAlsaDriver::port_get_buffer(int port, jack_nframes_t nframes) ++{ ++ return fGraphManager->GetBuffer(port, nframes); ++} ++ ++int JackAlsaDriver::port_set_alias(int port, const char* name) ++{ ++ return fGraphManager->GetPort(port)->SetAlias(name); ++} ++ ++jack_nframes_t JackAlsaDriver::get_sample_rate() const ++{ ++ return fEngineControl->fSampleRate; ++} ++ ++jack_nframes_t JackAlsaDriver::frame_time() const ++{ ++ JackTimer timer; ++ fEngineControl->ReadFrameTime(&timer); ++ return timer.Time2Frames(GetMicroSeconds(), fEngineControl->fBufferSize); ++} ++ ++jack_nframes_t JackAlsaDriver::last_frame_time() const ++{ ++ JackTimer timer; ++ fEngineControl->ReadFrameTime(&timer); ++ return timer.CurFrame(); ++} ++ ++} // end of namespace ++ ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++static ++void ++fill_device( ++ jack_driver_param_constraint_desc_t ** constraint_ptr_ptr, ++ uint32_t * array_size_ptr, ++ const char * device_id, ++ const char * device_description) ++{ ++ jack_driver_param_value_enum_t * possible_value_ptr; ++ ++ //jack_info("%6s - %s", device_id, device_description); ++ ++ if (*constraint_ptr_ptr == NULL) ++ { ++ *constraint_ptr_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); ++ *array_size_ptr = 0; ++ } ++ ++ if ((*constraint_ptr_ptr)->constraint.enumeration.count == *array_size_ptr) ++ { ++ *array_size_ptr += 10; ++ (*constraint_ptr_ptr)->constraint.enumeration.possible_values_array = ++ (jack_driver_param_value_enum_t *)realloc( ++ (*constraint_ptr_ptr)->constraint.enumeration.possible_values_array, ++ sizeof(jack_driver_param_value_enum_t) * *array_size_ptr); ++ } ++ ++ possible_value_ptr = (*constraint_ptr_ptr)->constraint.enumeration.possible_values_array + (*constraint_ptr_ptr)->constraint.enumeration.count; ++ (*constraint_ptr_ptr)->constraint.enumeration.count++; ++ strcpy(possible_value_ptr->value.str, device_id); ++ strcpy(possible_value_ptr->short_desc, device_description); ++} ++ ++static ++jack_driver_param_constraint_desc_t * ++enum_alsa_devices() ++{ ++ snd_ctl_t * handle; ++ snd_ctl_card_info_t * info; ++ snd_pcm_info_t * pcminfo_capture; ++ snd_pcm_info_t * pcminfo_playback; ++ int card_no = -1; ++ char card_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; ++ char device_id[JACK_DRIVER_PARAM_STRING_MAX + 1]; ++ char description[64]; ++ int device_no; ++ bool has_capture; ++ bool has_playback; ++ jack_driver_param_constraint_desc_t * constraint_ptr; ++ uint32_t array_size = 0; ++ ++ snd_ctl_card_info_alloca(&info); ++ snd_pcm_info_alloca(&pcminfo_capture); ++ snd_pcm_info_alloca(&pcminfo_playback); ++ ++ constraint_ptr = NULL; ++ ++ while(snd_card_next(&card_no) >= 0 && card_no >= 0) ++ { ++ sprintf(card_id, "hw:%d", card_no); ++ ++ if (snd_ctl_open(&handle, card_id, 0) >= 0 && ++ snd_ctl_card_info(handle, info) >= 0) ++ { ++ fill_device(&constraint_ptr, &array_size, card_id, snd_ctl_card_info_get_name(info)); ++ ++ device_no = -1; ++ ++ while (snd_ctl_pcm_next_device(handle, &device_no) >= 0 && device_no != -1) ++ { ++ sprintf(device_id, "%s,%d", card_id, device_no); ++ ++ snd_pcm_info_set_device(pcminfo_capture, device_no); ++ snd_pcm_info_set_subdevice(pcminfo_capture, 0); ++ snd_pcm_info_set_stream(pcminfo_capture, SND_PCM_STREAM_CAPTURE); ++ has_capture = snd_ctl_pcm_info(handle, pcminfo_capture) >= 0; ++ ++ snd_pcm_info_set_device(pcminfo_playback, device_no); ++ snd_pcm_info_set_subdevice(pcminfo_playback, 0); ++ snd_pcm_info_set_stream(pcminfo_playback, SND_PCM_STREAM_PLAYBACK); ++ has_playback = snd_ctl_pcm_info(handle, pcminfo_playback) >= 0; ++ ++ if (has_capture && has_playback) ++ { ++ snprintf(description, sizeof(description),"%s (duplex)", snd_pcm_info_get_name(pcminfo_capture)); ++ } ++ else if (has_capture) ++ { ++ snprintf(description, sizeof(description),"%s (capture)", snd_pcm_info_get_name(pcminfo_capture)); ++ } ++ else if (has_playback) ++ { ++ snprintf(description, sizeof(description),"%s (playback)", snd_pcm_info_get_name(pcminfo_playback)); ++ } ++ else ++ { ++ continue; ++ } ++ ++ fill_device(&constraint_ptr, &array_size, device_id, description); ++ } ++ ++ snd_ctl_close(handle); ++ } ++ } ++ ++ return constraint_ptr; ++} ++ ++static ++jack_driver_param_constraint_desc_t * ++get_midi_driver_constraint() ++{ ++ jack_driver_param_constraint_desc_t * constraint_ptr; ++ jack_driver_param_value_enum_t * possible_value_ptr; ++ ++ //jack_info("%6s - %s", device_id, device_description); ++ ++ constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); ++ constraint_ptr->flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; ++ ++ constraint_ptr->constraint.enumeration.possible_values_array = (jack_driver_param_value_enum_t *)malloc(3 * sizeof(jack_driver_param_value_enum_t)); ++ constraint_ptr->constraint.enumeration.count = 3; ++ ++ possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array; ++ ++ strcpy(possible_value_ptr->value.str, "none"); ++ strcpy(possible_value_ptr->short_desc, "no MIDI driver"); ++ ++ possible_value_ptr++; ++ ++ strcpy(possible_value_ptr->value.str, "seq"); ++ strcpy(possible_value_ptr->short_desc, "ALSA Sequencer driver"); ++ ++ possible_value_ptr++; ++ ++ strcpy(possible_value_ptr->value.str, "raw"); ++ strcpy(possible_value_ptr->short_desc, "ALSA RawMIDI driver"); ++ ++ return constraint_ptr; ++} ++ ++static ++jack_driver_param_constraint_desc_t * ++get_dither_constraint() ++{ ++ jack_driver_param_constraint_desc_t * constraint_ptr; ++ jack_driver_param_value_enum_t * possible_value_ptr; ++ ++ //jack_info("%6s - %s", device_id, device_description); ++ ++ constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t)); ++ constraint_ptr->flags = JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; ++ ++ constraint_ptr->constraint.enumeration.possible_values_array = (jack_driver_param_value_enum_t *)malloc(4 * sizeof(jack_driver_param_value_enum_t)); ++ constraint_ptr->constraint.enumeration.count = 4; ++ ++ possible_value_ptr = constraint_ptr->constraint.enumeration.possible_values_array; ++ ++ possible_value_ptr->value.c = 'n'; ++ strcpy(possible_value_ptr->short_desc, "none"); ++ ++ possible_value_ptr++; ++ ++ possible_value_ptr->value.c = 'r'; ++ strcpy(possible_value_ptr->short_desc, "rectangular"); ++ ++ possible_value_ptr++; ++ ++ possible_value_ptr->value.c = 's'; ++ strcpy(possible_value_ptr->short_desc, "shaped"); ++ ++ possible_value_ptr++; ++ ++ possible_value_ptr->value.c = 't'; ++ strcpy(possible_value_ptr->short_desc, "triangular"); ++ ++ return constraint_ptr; ++} ++ ++ static int ++ dither_opt (char c, DitherAlgorithm* dither) ++ { ++ switch (c) { ++ case '-': ++ case 'n': ++ *dither = None; ++ break; ++ ++ case 'r': ++ *dither = Rectangular; ++ break; ++ ++ case 's': ++ *dither = Shaped; ++ break; ++ ++ case 't': ++ *dither = Triangular; ++ break; ++ ++ default: ++ fprintf (stderr, "ALSA driver: illegal dithering mode %c\n", c); ++ return -1; ++ } ++ return 0; ++ } ++ ++ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () ++ { ++ jack_driver_desc_t * desc; ++ jack_driver_param_desc_t * params; ++ unsigned int i; ++ ++ desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); ++ ++ strcpy(desc->name, "alsa"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 ++ strcpy(desc->desc, "Linux ALSA API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 ++ ++ desc->nparams = 18; ++ params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); ++ ++ i = 0; ++ strcpy (params[i].name, "capture"); ++ params[i].character = 'C'; ++ params[i].type = JackDriverParamString; ++ strcpy (params[i].value.str, "none"); ++ strcpy (params[i].short_desc, ++ "Provide capture ports. Optionally set device"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "playback"); ++ params[i].character = 'P'; ++ params[i].type = JackDriverParamString; ++ strcpy (params[i].value.str, "none"); ++ strcpy (params[i].short_desc, ++ "Provide playback ports. Optionally set device"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "device"); ++ params[i].character = 'd'; ++ params[i].type = JackDriverParamString; ++ strcpy (params[i].value.str, "hw:0"); ++ strcpy (params[i].short_desc, "ALSA device name"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ params[i].constraint = enum_alsa_devices(); ++ ++ i++; ++ strcpy (params[i].name, "rate"); ++ params[i].character = 'r'; ++ params[i].type = JackDriverParamUInt; ++ params[i].value.ui = 48000U; ++ strcpy (params[i].short_desc, "Sample rate"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "period"); ++ params[i].character = 'p'; ++ params[i].type = JackDriverParamUInt; ++ params[i].value.ui = 1024U; ++ strcpy (params[i].short_desc, "Frames per period"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "nperiods"); ++ params[i].character = 'n'; ++ params[i].type = JackDriverParamUInt; ++ params[i].value.ui = 2U; ++ strcpy (params[i].short_desc, "Number of periods of playback latency"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "hwmon"); ++ params[i].character = 'H'; ++ params[i].type = JackDriverParamBool; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, "Hardware monitoring, if available"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "hwmeter"); ++ params[i].character = 'M'; ++ params[i].type = JackDriverParamBool; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, "Hardware metering, if available"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "duplex"); ++ params[i].character = 'D'; ++ params[i].type = JackDriverParamBool; ++ params[i].value.i = 1; ++ strcpy (params[i].short_desc, ++ "Provide both capture and playback ports"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "softmode"); ++ params[i].character = 's'; ++ params[i].type = JackDriverParamBool; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, "Soft-mode, no xrun handling"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "monitor"); ++ params[i].character = 'm'; ++ params[i].type = JackDriverParamBool; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, "Provide monitor ports for the output"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "dither"); ++ params[i].character = 'z'; ++ params[i].type = JackDriverParamChar; ++ params[i].value.c = 'n'; ++ strcpy (params[i].short_desc, "Dithering mode"); ++ strcpy (params[i].long_desc, ++ "Dithering mode:\n" ++ " n - none\n" ++ " r - rectangular\n" ++ " s - shaped\n" ++ " t - triangular"); ++ params[i].constraint = get_dither_constraint(); ++ ++ i++; ++ strcpy (params[i].name, "inchannels"); ++ params[i].character = 'i'; ++ params[i].type = JackDriverParamUInt; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, ++ "Number of capture channels (defaults to hardware max)"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "outchannels"); ++ params[i].character = 'o'; ++ params[i].type = JackDriverParamUInt; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, ++ "Number of playback channels (defaults to hardware max)"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "shorts"); ++ params[i].character = 'S'; ++ params[i].type = JackDriverParamBool; ++ params[i].value.i = FALSE; ++ strcpy (params[i].short_desc, "Try 16-bit samples before 32-bit"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "input-latency"); ++ params[i].character = 'I'; ++ params[i].type = JackDriverParamUInt; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, "Extra input latency (frames)"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "output-latency"); ++ params[i].character = 'O'; ++ params[i].type = JackDriverParamUInt; ++ params[i].value.i = 0; ++ strcpy (params[i].short_desc, "Extra output latency (frames)"); ++ strcpy (params[i].long_desc, params[i].short_desc); ++ ++ i++; ++ strcpy (params[i].name, "midi-driver"); ++ params[i].character = 'X'; ++ params[i].type = JackDriverParamString; ++ strcpy (params[i].value.str, "none"); ++ strcpy (params[i].short_desc, "ALSA MIDI driver name (seq|raw)"); ++ strcpy (params[i].long_desc, ++ "ALSA MIDI driver:\n" ++ " none - no MIDI driver\n" ++ " seq - ALSA Sequencer driver\n" ++ " raw - ALSA RawMIDI driver\n"); ++ params[i].constraint = get_midi_driver_constraint(); ++ ++ desc->params = params; ++ return desc; ++ } ++ ++ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) ++ { ++ jack_nframes_t srate = 48000; ++ jack_nframes_t frames_per_interrupt = 1024; ++ unsigned long user_nperiods = 2; ++ const char *playback_pcm_name = "hw:0"; ++ const char *capture_pcm_name = "hw:0"; ++ int hw_monitoring = FALSE; ++ int hw_metering = FALSE; ++ int capture = FALSE; ++ int playback = FALSE; ++ int soft_mode = FALSE; ++ int monitor = FALSE; ++ DitherAlgorithm dither = None; ++ int user_capture_nchnls = 0; ++ int user_playback_nchnls = 0; ++ int shorts_first = FALSE; ++ jack_nframes_t systemic_input_latency = 0; ++ jack_nframes_t systemic_output_latency = 0; ++ const JSList * node; ++ const jack_driver_param_t * param; ++ const char *midi_driver = "none"; ++ ++ for (node = params; node; node = jack_slist_next (node)) { ++ param = (const jack_driver_param_t *) node->data; ++ ++ switch (param->character) { ++ ++ case 'C': ++ capture = TRUE; ++ if (strcmp (param->value.str, "none") != 0) { ++ capture_pcm_name = strdup (param->value.str); ++ jack_log("capture device %s", capture_pcm_name); ++ } ++ break; ++ ++ case 'P': ++ playback = TRUE; ++ if (strcmp (param->value.str, "none") != 0) { ++ playback_pcm_name = strdup (param->value.str); ++ jack_log("playback device %s", playback_pcm_name); ++ } ++ break; ++ ++ case 'D': ++ playback = TRUE; ++ capture = TRUE; ++ break; ++ ++ case 'd': ++ playback_pcm_name = strdup (param->value.str); ++ capture_pcm_name = strdup (param->value.str); ++ jack_log("playback device %s", playback_pcm_name); ++ jack_log("capture device %s", capture_pcm_name); ++ break; ++ ++ case 'H': ++ hw_monitoring = param->value.i; ++ break; ++ ++ case 'm': ++ monitor = param->value.i; ++ break; ++ ++ case 'M': ++ hw_metering = param->value.i; ++ break; ++ ++ case 'r': ++ srate = param->value.ui; ++ jack_log("apparent rate = %d", srate); ++ break; ++ ++ case 'p': ++ frames_per_interrupt = param->value.ui; ++ jack_log("frames per period = %d", frames_per_interrupt); ++ break; ++ ++ case 'n': ++ user_nperiods = param->value.ui; ++ if (user_nperiods < 2) /* enforce minimum value */ ++ user_nperiods = 2; ++ break; ++ ++ case 's': ++ soft_mode = param->value.i; ++ break; ++ ++ case 'z': ++ if (dither_opt (param->value.c, &dither)) { ++ return NULL; ++ } ++ break; ++ ++ case 'i': ++ user_capture_nchnls = param->value.ui; ++ break; ++ ++ case 'o': ++ user_playback_nchnls = param->value.ui; ++ break; ++ ++ case 'S': ++ shorts_first = param->value.i; ++ break; ++ ++ case 'I': ++ systemic_input_latency = param->value.ui; ++ break; ++ ++ case 'O': ++ systemic_output_latency = param->value.ui; ++ break; ++ ++ case 'X': ++ midi_driver = strdup(param->value.str); ++ break; ++ } ++ } ++ ++ /* duplex is the default */ ++ if (!capture && !playback) { ++ capture = TRUE; ++ playback = TRUE; ++ } ++ ++ Jack::JackAlsaDriver* alsa_driver = new Jack::JackAlsaDriver("system", "alsa_pcm", engine, table); ++ Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(alsa_driver); ++ // Special open for ALSA driver... ++ if (alsa_driver->Open(frames_per_interrupt, user_nperiods, srate, hw_monitoring, hw_metering, capture, playback, dither, soft_mode, monitor, ++ user_capture_nchnls, user_playback_nchnls, shorts_first, capture_pcm_name, playback_pcm_name, ++ systemic_input_latency, systemic_output_latency, midi_driver) == 0) { ++ return threaded_driver; ++ } else { ++ delete threaded_driver; // Delete the decorated driver ++ return NULL; ++ } ++ } ++ ++#ifdef __cplusplus ++} ++#endif ++ ++ +diff -rupN jack-1.9.5.old/linux/alsa/port_names.c jack-1.9.5/linux/alsa/port_names.c +--- jack-1.9.5.old/linux/alsa/port_names.c 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/linux/alsa/port_names.c 2010-07-20 00:17:44.000000000 -0400 +@@ -0,0 +1,176 @@ ++/* -*- mode: c; c-file-style: "linux"; -*- */ ++/* ++ Copyright (C) 2010 Florian Faber, faber@faberman.de ++ ++ 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. ++ ++*/ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "alsa_driver.h" ++ ++ ++static int port_names_load_portfile(alsa_driver_t *driver, const char *filename, char **buf, const unsigned int offset, const unsigned int num) { ++ int fh, i, ret, lineno, id, res=0; ++ char line[256]; ++ ++ fh = open(filename, O_RDONLY); ++ if (-1!=fh) { ++ res = 1; ++ i = 0; ++ lineno = 1; ++ for (;;) { ++ ret = read(fh, &line[i], 1); ++ if (0==ret) { ++ break; ++ } else if (-1==ret) { ++ sprintf(stderr, "Error while reading \"%s\": %s", filename, strerror(errno)); ++ break; ++ } ++ if (0x0A==line[i]) { ++ /* new line, parse input */ ++ line[i] = 0; ++ ++ if ('#' != line[0]) { ++ i=0; ++ while ((i<255) && (line[i]!='=')) i++; ++ if (255==i) { ++ sprintf(stderr, "Error while reading \"%s\": Line %d has no key=value syntax!", filename, lineno); ++ } else { ++ line[i] = 0; ++ id = atoi(line); ++ if ((id>=1) && (id<=num)) { ++ if (NULL==buf[id-1+offset]) { ++ /* don't overwrite existing names */ ++ buf[id-1+offset] = strdup(&line[i+1]); ++ } ++ } else { ++ sprintf(stderr, "Error while reading \"%s\": Key %d out of range in line %d (1..%d)", filename, id, lineno, num); ++ } ++ } ++ } ++ ++ i = 0; ++ lineno++; ++ } else { ++ i++; ++ if (i==255) { ++ sprintf(stderr, "Error while reading \"%s\": Line %d is too long", filename, lineno); ++ break; ++ } ++ } ++ } ++ ++ (void) close(fh); ++ } ++ ++ return res; ++} ++ ++ ++static void port_names_default_portnames(char **buf, const unsigned int offset, const unsigned int num, const char *defaultname) { ++ unsigned int i; ++ char line[256]; ++ ++ /* Fill in default names */ ++ for (i=0; iframe_rate > 96000) { ++ speed="qs"; ++ } else if (driver->frame_rate > 48000) { ++ speed="ds"; ++ } else { ++ speed="ss"; ++ } ++ ++ snd_ctl_card_info_alloca(&card_info); ++ err = snd_ctl_card_info(driver->ctl_handle, card_info); ++ if (err >= 0) { ++ card_name = snd_ctl_card_info_get_name(card_info); ++ } ++ ++ buf = malloc(sizeof(char *)*(driver->capture_nchannels + driver->playback_nchannels)); ++ if (NULL==buf) { ++ sprintf(stderr, "ALSA: Not enough memory for %d port names", driver->capture_nchannels + driver->playback_nchannels); ++ return NULL; ++ } ++ bzero(buf, sizeof(char *)*(driver->capture_nchannels + driver->playback_nchannels)); ++ ++ /* Read port names from special to general: ++ * Begin with user and speed specific port names */ ++ snprintf(filename, 255, "%s/.config/jack/cards/%s.%s.ports.in", getenv("HOME"), card_name, speed); ++ (void) port_names_load_portfile(driver, filename, buf, 0, driver->capture_nchannels); ++ ++ /* Now user general */ ++ snprintf(filename, 255, "%s/.config/jack/cards/%s.ports.in", getenv("HOME"), card_name); ++ (void) port_names_load_portfile(driver, filename, buf, 0, driver->capture_nchannels); ++ ++ /* System speed specific */ ++ snprintf(filename, 255, "/etc/jack/cards/%s.%s.ports.in", card_name, speed); ++ (void) port_names_load_portfile(driver, filename, buf, 0, driver->capture_nchannels); ++ ++ /* System general */ ++ snprintf(filename, 255, "/etc/jack/cards/%s.ports.in", card_name); ++ (void) port_names_load_portfile(driver, filename, buf, 0, driver->capture_nchannels); ++ ++ /* Fill all still unnamed ports with default names */ ++ port_names_default_portnames(buf, 0, driver->capture_nchannels, "capture_%lu"); ++ ++ ++ /* Same procedure for the playback channels */ ++ snprintf(filename, 255, "%s/.config/jack/cards/%s.%s.ports.out", getenv("HOME"), card_name, speed); ++ (void) port_names_load_portfile(driver, filename, buf, driver->capture_nchannels, driver->playback_nchannels); ++ ++ snprintf(filename, 255, "%s/.config/jack/cards/%s.ports.out", getenv("HOME"), card_name); ++ (void) port_names_load_portfile(driver, filename, buf, driver->capture_nchannels, driver->playback_nchannels); ++ ++ snprintf(filename, 255, "/etc/jack/cards/%s.%s.ports.out", card_name, speed); ++ (void) port_names_load_portfile(driver, filename, buf, driver->capture_nchannels, driver->playback_nchannels); ++ ++ snprintf(filename, 255, "/etc/jack/cards/%s.ports.out", card_name); ++ (void) port_names_load_portfile(driver, filename, buf, driver->capture_nchannels, driver->playback_nchannels); ++ ++ port_names_default_portnames(buf, driver->capture_nchannels, driver->playback_nchannels, "playback_%lu"); ++ ++ return buf; ++} +diff -rupN jack-1.9.5.old/linux/alsa/port_names.h jack-1.9.5/linux/alsa/port_names.h +--- jack-1.9.5.old/linux/alsa/port_names.h 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/linux/alsa/port_names.h 2010-07-20 00:17:44.000000000 -0400 +@@ -0,0 +1,34 @@ ++/* ++ Copyright (C) 2010 Florian Faber, faber@faberman.de ++ ++ 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. ++ ++*/ ++ ++#ifndef __jack_port_names_h__ ++#define __jack_port_names_h__ ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++char** port_names_get_portnames(alsa_driver_t *driver); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __jack_port_names_h__ */ +diff -rupN jack-1.9.5.old/linux/wscript jack-1.9.5/linux/wscript +--- jack-1.9.5.old/linux/wscript 2010-02-12 05:58:07.000000000 -0500 ++++ jack-1.9.5/linux/wscript 2010-07-20 00:17:44.000000000 -0400 +@@ -52,7 +52,8 @@ def build(bld): + 'alsa/generic_hw.c', + 'alsa/hdsp.c', + 'alsa/hammerfall.c', +- 'alsa/ice1712.c' ++ 'alsa/ice1712.c', ++ 'alsa/port_names.c' + ] + + ffado_driver_src = ['firewire/JackFFADODriver.cpp', +diff -rupN jack-1.9.5.old/linux/wscript.orig jack-1.9.5/linux/wscript.orig +--- jack-1.9.5.old/linux/wscript.orig 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/linux/wscript.orig 2010-02-12 05:58:07.000000000 -0500 +@@ -0,0 +1,81 @@ ++#! /usr/bin/env python ++# encoding: utf-8 ++ ++def configure(conf): ++ conf.check_cfg(package='alsa', atleast_version='1.0.18', args='--cflags --libs') ++ conf.env['BUILD_DRIVER_ALSA'] = conf.is_defined('HAVE_ALSA') ++ ++ conf. check_cfg(package='libfreebob', atleast_version='1.0.0', args='--cflags --libs') ++ conf.env['BUILD_DRIVER_FREEBOB'] = conf.is_defined('HAVE_LIBFREEBOB') ++ ++ conf. check_cfg(package='libffado', atleast_version='1.999.17', args='--cflags --libs') ++ conf.env['BUILD_DRIVER_FFADO'] = conf.is_defined('HAVE_LIBFFADO') ++ ++ conf.define('HAVE_PPOLL', 1 ) ++ ++ ++def create_jack_driver_obj(bld, target, sources, uselib = None): ++ driver = bld.new_task_gen('cxx', 'shlib') ++ driver.features.append('cc') ++ driver.env['shlib_PATTERN'] = 'jack_%s.so' ++ driver.defines = ['HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL'] ++ driver.includes = ['.', '../linux', '../posix', '../common', '../common/jack', '../dbus'] ++ driver.target = target ++ driver.source = sources ++ driver.install_path = '${ADDON_DIR}/' ++ if uselib: ++ driver.uselib = uselib ++ driver.uselib_local = 'serverlib' ++ return driver ++ ++def build(bld): ++ if bld.env['BUILD_JACKD'] == True: ++ jackd = bld.new_task_gen('cxx', 'program') ++ jackd.includes = ['../linux', '../posix', '../common/jack', '../common', '../dbus'] ++ jackd.defines = 'HAVE_CONFIG_H' ++ jackd.source = ['../common/Jackdmp.cpp'] ++ if bld.env['IS_LINUX'] and bld.env['BUILD_JACKDBUS']: ++ jackd.source += ['../dbus/reserve.c', '../dbus/audio_reserve.c'] ++ jackd.uselib = 'PTHREAD DL RT DBUS-1' ++ else: ++ jackd.uselib = 'PTHREAD DL RT' ++ jackd.uselib_local = 'serverlib' ++ jackd.target = 'jackd' ++ ++ create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') ++ ++ alsa_driver_src = ['alsa/JackAlsaDriver.cpp', ++ 'alsa/alsa_rawmidi.c', ++ 'alsa/alsa_seqmidi.c', ++ 'alsa/alsa_midi_jackmp.cpp', ++ '../common/memops.c', ++ 'alsa/generic_hw.c', ++ 'alsa/hdsp.c', ++ 'alsa/hammerfall.c', ++ 'alsa/ice1712.c' ++ ] ++ ++ ffado_driver_src = ['firewire/JackFFADODriver.cpp', ++ 'firewire/JackFFADOMidiInput.cpp', ++ 'firewire/JackFFADOMidiOutput.cpp', ++ '../common/JackPhysicalMidiInput.cpp', ++ '../common/JackPhysicalMidiOutput.cpp' ++ ] ++ ++ if bld.env['BUILD_DRIVER_ALSA'] == True: ++ create_jack_driver_obj(bld, 'alsa', alsa_driver_src, "ALSA") ++ ++ if bld.env['BUILD_DRIVER_FREEBOB'] == True: ++ create_jack_driver_obj(bld, 'freebob', 'freebob/JackFreebobDriver.cpp', "LIBFREEBOB") ++ ++ if bld.env['BUILD_DRIVER_FFADO'] == True: ++ create_jack_driver_obj(bld, 'firewire', ffado_driver_src, "LIBFFADO") ++ ++ create_jack_driver_obj(bld, 'net', '../common/JackNetDriver.cpp') ++ ++ create_jack_driver_obj(bld, 'loopback', '../common/JackLoopbackDriver.cpp') ++ ++ create_jack_driver_obj(bld, 'netone', [ '../common/JackNetOneDriver.cpp', ++ '../common/netjack.c', ++ '../common/netjack_packet.c' ], "SAMPLERATE CELT" ) ++ diff --git a/jack-manpages.patch b/jack-manpages.patch new file mode 100644 index 0000000..ba80750 --- /dev/null +++ b/jack-manpages.patch @@ -0,0 +1,1215 @@ +diff -rupN jack-1.9.5.old/man/alsa_in.0 jack-1.9.5/man/alsa_in.0 +--- jack-1.9.5.old/man/alsa_in.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/alsa_in.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,97 @@ ++.TH ALSA_IO "1" "!DATE!" "!VERSION!" ++.SH NAME ++\fBalsa_in\fR, \fBalsa_out\fR \- Jack clients that perform I/O with an alternate audio interface ++.SH SYNOPSIS ++\fBalsa_in\fR [\fIoptions\fR] ++.br ++\fBalsa_out\fR [\fIoptions\fR] ++ ++.SH DESCRIPTION ++A JACK client that opens a specified audio interface (different to the ++one used by the JACK server, if any) and moves audio data between its ++JACK ports and the interface. alsa_in will provide data from the ++interface (potentially for capture); alsa_out will deliver data to it ++(for playback). ++ ++The audio interface used by alsa_in/alsa_out does not need to be ++synchronized with JACK backend (or the hardware it might be using). ++alsa_in/alsa_out tries to resample the output stream in an attempt to ++compensate for drift between the two clocks. ++ ++As of jack-0.116.3 this works almost perfectly. It takes some time, to reach ++absolute resample-rate stability. So give it some minutes (its intended to be ++running permanently anyways) ++ ++.SH OPTIONS ++.TP ++\fB\-j \fI jack_client_name\fR ++.br ++Set Client Name. ++.TP ++\fB\-d \fI alsa_device\fR ++.br ++Use this Soundcard. ++.TP ++\fB\-v\fR ++.br ++Verbose, prints out resample coefficient and other parameters useful for debugging, every 500ms. ++also reports soft xruns. ++.TP ++\fB\-i\fR ++.br ++Instrumentation. This logs the 4 important parameters of the samplerate control algorithm every 1ms. ++You can pipe this into a file, and plot it. Should only be necessary, if it does not work as ++expected, and we need to adjust some of the obscure parameters, to make it work. ++Find me on irc.freenode.org #jack in order to set this up correctly. ++.TP ++\fB\-c \fI channels\fR ++.br ++Set Number of channels. ++.TP ++\fB\-r \fI sample_rate\fR ++.br ++Set sample_rate. The program resamples as necessary. ++So you can connect a 44k1 jackd to a soundcard only supporting ++48k. (default is jack sample_rate) ++.TP ++\fB\-p \fI period_size\fR ++.br ++Set the period size. It is not related to the jackd period_size. ++Sometimes it affects the quality of the delay measurements. ++Setting this lower than the jackd period_size will only work, if you ++use a higher number of periods. ++.TP ++\fB\-n \fI num_period\fR ++.br ++Set number of periods. See note for period_size. ++.TP ++\fB\-q \fI quality\fR ++.br ++Set the quality of the resampler from 0 to 4. can significanly reduce cpu usage. ++.TP ++\fB\-m \fI max_diff\fR ++.br ++The value when a soft xrun occurs. Basically the window, in which ++the dma pointer may jitter. I don't think its necessary to play with this anymore. ++.TP ++\fB\-t \fI target_delay\fR ++.br ++The delay alsa_io should try to approach. Same as for max_diff. It will be setup based on \-p and \-n ++which is generally sufficient. ++.TP ++\fB\-s \fI smooth_array_size\fR ++.br ++This parameter controls the size of the array used for smoothing the delay measurement. Its default is 256. ++If you use a pretty low period size, you can lower the CPU usage a bit by decreasing this parameter. ++However most CPU time is spent in the resampling so this will not be much. ++.TP ++\fB\-C \fI P Control Clamp\fR ++.br ++If you have a PCI card, then the default value (15) of this parameter is too high for \-p64 \-n2... Setting it to 5 should fix that. ++Be aware that setting this parameter too low, lets the hf noise on the delay measurement come through onto the resamplerate, so this ++might degrade the quality of the output. (but its a threshold value, and it has been chosen, to mask the noise of a USB card, ++which has an amplitude which is 50 times higher than that of a PCI card, so 5 wont loose you any quality on a PCI card) ++ ++.SH AUTHOR ++Torben Hohn ++ +diff -rupN jack-1.9.5.old/man/alsa_out.0 jack-1.9.5/man/alsa_out.0 +--- jack-1.9.5.old/man/alsa_out.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/alsa_out.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1 @@ ++.so man1/alsa_in.1 +diff -rupN jack-1.9.5.old/man/fill_template jack-1.9.5/man/fill_template +--- jack-1.9.5.old/man/fill_template 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/fill_template 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,5 @@ ++#!/bin/sh ++ ++for i in *.0 ; do ++ sed -e "s/!VERSION!/${1}/g" -e "s/!DATE!/`date '+%B %Y'`/g" < ${i} > ${i%%0}1 ++done +diff -rupN jack-1.9.5.old/man/jack_bufsize.0 jack-1.9.5/man/jack_bufsize.0 +--- jack-1.9.5.old/man/jack_bufsize.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_bufsize.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,14 @@ ++.TH JACK_BUFSIZE "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_bufsize \- JACK toolkit client to change the JACK buffer size ++.SH SYNOPSIS ++.B jack_bufsize bufsize ++.SH DESCRIPTION ++.B jack_bufsize ++jack_bufsize sets the size of the buffer (frames per period) used in JACK. ++This change happens on-line (the JACK server and its clients do not need to be ++restarted). ++.br ++When invoked without arguments, it prints the current bufsize, and exits. ++ ++ +diff -rupN jack-1.9.5.old/man/jack_connect.0 jack-1.9.5/man/jack_connect.0 +--- jack-1.9.5.old/man/jack_connect.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_connect.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,11 @@ ++.TH JACK_CONNECT "1" "!DATE!" "!VERSION!" ++.SH NAME ++\fBjack_connect\fR, \fBjack_disconnect\fR \- JACK toolkit clients for connecting & disconnecting ports ++.SH SYNOPSIS ++\fB jack_connect\fR [ \fI-s\fR | \fI--server servername\fR ] [\fI-h\fR | \fI--help\fR ] port1 port2 ++\fB jack_disconnect\fR [ \fI-s\fR | \fI--server servername\fR ] [\fI-h\fR | \fI--help\fR ] port1 port2 ++.SH DESCRIPTION ++\fBjack_connect\fR connects the two named ports. \fBjack_connect\fR disconnects the two named ports. ++.SH RETURNS ++The exit status is zero if successful, 1 otherwise ++ +diff -rupN jack-1.9.5.old/man/jackd.0 jack-1.9.5/man/jackd.0 +--- jack-1.9.5.old/man/jackd.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jackd.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,547 @@ ++.TH "JACKD" "1" "!VERSION!" "!DATE!" "" ++.SH "NAME" ++jackd \- JACK Audio Connection Kit sound server ++.SH "SYNOPSIS" ++\fBjackd\fR [\fIoptions\fR] \fB\-d\fI backend \fR ++[\fIbackend\-parameters\fR] ++.br ++\fBjackd \-\-help\fR ++.SH "DESCRIPTION" ++\fBjackd\fR is the JACK audio server daemon, a low\-latency audio ++server. Originally written for the ++GNU/Linux operating system, it also supports Mac OS X and various Unix ++platforms. JACK can connect a number of different client applications ++to an audio device and also to each other. Most clients are external, ++running in their own processes as normal applications. JACK also ++supports internal clients, which run within the \fBjackd\fR process ++using a loadable "plugin" interface. ++ ++JACK differs from other audio servers in being designed from the ++ground up for professional audio work. It focuses on two key areas: ++synchronous execution of all clients, and low latency operation. ++ ++For the latest JACK information, please consult the web site, ++<\fBhttp://www.jackaudio.org\fR>. ++.SH "OPTIONS" ++.TP ++\fB\-d, \-\-driver \fIbackend\fR [\fIbackend\-parameters\fR ] ++.br ++Select the audio interface backend. The current list of supported ++backends is: \fBalsa\fR, \fBcoreaudio\fR, \fBdummy\fR, \fBfreebob\fR, ++\fBoss\fR \fBsun\fR and \fBportaudio\fR. They are not all available ++on all platforms. All \fIbackend\-parameters\fR are optional. ++ ++.TP ++\fB\-h, \-\-help\fR ++.br ++Print a brief usage message describing the main \fBjackd\fR options. ++These do not include \fIbackend\-parameters\fR, which are listed using ++the \fB\-\-help\fR option for each specific backend. Examples below ++show how to list them. ++.TP ++\fB\-m, \-\-no\-mlock\fR ++Do not attempt to lock memory, even if \fB\-\-realtime\fR. ++.TP ++\fB\-n, \-\-name\fR \fIserver\-name\fR ++Name this \fBjackd\fR instance \fIserver\-name\fR. If unspecified, ++this name comes from the \fB$JACK_DEFAULT_SERVER\fR environment ++variable. It will be "default" if that is not defined. ++.TP ++\fB\-p, \-\-port\-max \fI n\fR ++Set the maximum number of ports the JACK server can manage. ++The default value is 256. ++.TP ++\fB\-\-replace-registry\fR ++.br ++Remove the shared memory registry used by all JACK server instances ++before startup. This should rarely be used, and is intended only ++for occasions when the structure of this registry changes in ways ++that are incompatible across JACK versions (which is rare). ++.TP ++\fB\-R, \-\-realtime\fR ++.br ++Use realtime scheduling (default = true). This is needed for reliable low\-latency ++performance. On many systems, it requires \fBjackd\fR to run with ++special scheduler and memory allocation privileges, which may be ++obtained in several ways. ++.TP ++\fB\-r, \-\-no-realtime\fR ++.br ++Do not use realtime scheduling. ++.TP ++\fB\-P, \-\-realtime\-priority \fIint\fR ++When running \fB\-\-realtime\fR, set the scheduler priority to ++\fIint\fR. ++.TP ++\fB\-\-silent\fR ++Silence any output during operation. ++.TP ++\fB\-T, \-\-temporary\fR ++Exit once all clients have closed their connections. ++.TP ++\fB\-t, \-\-timeout \fIint\fR ++.br ++Set client timeout limit in milliseconds. The default is 500 msec. ++In realtime mode the client timeout must be smaller than the watchdog timeout (5000 msec). ++.TP ++\fB\-Z, \-\-nozombies\fR ++.br ++Prevent JACK from ever kicking out clients because they were too slow. ++This cancels the effect any specified timeout value, but JACK and its clients are ++still subject to the supervision of the watchdog thread or its equivalent. ++.TP ++\fB\-u, \-\-unlock\fR ++.br ++Unlock libraries GTK+, QT, FLTK, Wine. ++.TP ++\fB\-v, \-\-verbose\fR ++Give verbose output. ++.TP ++\fB\-c, \-\-clocksource\fR (\fI c(ycle)\fR | \fI h(pet) \fR | \fI s(ystem) \fR) ++Select a specific wall clock (Cycle Counter, HPET timer, System timer). ++.TP ++\fB\-V, \-\-version\fR ++Print the current JACK version number and exit. ++.SS ALSA BACKEND OPTIONS ++.TP ++\fB\-C, \-\-capture\fR [ \fIname\fR ] ++Provide only capture ports, unless combined with \-D or \-P. Parameterally set ++capture device name. ++.TP ++\fB\-d, \-\-device \fIname\fR ++.br ++The ALSA pcm device \fIname\fR to use. If none is specified, JACK will ++use "hw:0", the first hardware card defined in \fB/etc/modules.conf\fR. ++.TP ++\fB\-z, \-\-dither [rectangular,triangular,shaped,none] ++Set dithering mode. If \fBnone\fR or unspecified, dithering is off. ++Only the first letter of the mode name is required. ++.TP ++\fB\-D, \-\-duplex\fR ++Provide both capture and playback ports. Defaults to on unless only one ++of \-P or \-C is specified. ++.TP ++\fB\-h, \-\-help\fR Print a brief usage message describing only the ++\fBalsa\fR backend parameters. ++.TP ++\fB\-M, \-\-hwmeter\fR ++.br ++Enable hardware metering for devices that support it. Otherwise, use ++software metering. ++.TP ++\fB\-H, \-\-hwmon\fR ++.br ++Enable hardware monitoring of capture ports. This is a method for ++obtaining "zero latency" monitoring of audio input. It requires ++support in hardware and from the underlying ALSA device driver. ++ ++When enabled, requests to monitor capture ports will be satisfied by ++creating a direct signal path between audio interface input and output ++connectors, with no processing by the host computer at all. This ++offers the lowest possible latency for the monitored signal. ++ ++Presently (March 2003), only the RME Hammerfall series and cards based ++on the ICE1712 chipset (M\-Audio Delta series, Terratec, and others) ++support \fB\-\-hwmon\fR. In the future, some consumer cards may also ++be supported by modifying their mixer settings. ++ ++Without \fB\-\-hwmon\fR, port monitoring requires JACK to read audio ++into system memory, then copy it back out to the hardware again, ++imposing the basic JACK system latency determined by the ++\fB\-\-period\fR and \fB\-\-nperiods\fR parameters. ++.TP ++\fB\-i, \-\-inchannels \fIint\fR ++.br ++Number of capture channels. Default is maximum supported by hardware. ++.TP ++\fB\-n, \-\-nperiods \fIint\fR ++.br ++Specify the number of periods of playback latency. In seconds, this ++corresponds to \fB\-\-nperiods\fR times \fB\-\-period\fR divided by ++\fB\-\-rate\fR. The default is 2, the minimum allowable. For most ++devices, there is no need for any other value with the ++\fB\-\-realtime\fR option. Without realtime privileges or with boards ++providing unreliable interrupts (like ymfpci), a larger value may ++yield fewer xruns. This can also help if the system is not tuned for ++reliable realtime scheduling. ++ ++For most ALSA devices, the hardware buffer has exactly ++\fB\-\-period\fR times \fB\-\-nperiods\fR frames. Some devices demand ++a larger buffer. If so, JACK will use the smallest possible buffer ++containing at least \fB\-\-nperiods\fR, but the playback latency does ++not increase. ++ ++For USB audio devices it is recommended to use \fB\-n 3\fR. Firewire ++devices supported by FFADO (formerly Freebob) are configured with ++\fB\-n 3\fR by default. ++.TP ++\fB\-o, \-\-outchannels \fIint\fR ++.br ++Number of playback channels. Default is maximum supported by hardware. ++.TP ++\fB\-P, \-\-playback\fR [ \fIname\fR ] ++Provide only playback ports, unless combined with \-D or \-C. Optionally set ++playback device name. ++.TP ++\fB\-p, \-\-period \fIint\fR ++.br ++Specify the number of frames between JACK \fBprocess()\fR calls. This ++value must be a power of 2, and the default is 1024. If you need low ++latency, set \fB\-p\fR as low as you can go without seeing xruns. A larger ++period size yields higher latency, but makes xruns less likely. The JACK ++capture latency in seconds is \fB\-\-period\fR divided by \fB\-\-rate\fR. ++.TP ++\fB\-r, \-\-rate \fIint\fR ++Specify the sample rate. The default is 48000. ++.TP ++\fB\-S, \-\-shorts ++.br ++Try to configure card for 16\-bit samples first, only trying 32\-bits if ++unsuccessful. Default is to prefer 32\-bit samples. ++.TP ++\fB\-s, \-\-softmode\fR ++.br ++Ignore xruns reported by the ALSA driver. This makes JACK less likely ++to disconnect unresponsive ports when running without \fB\-\-realtime\fR. ++.TP ++\fB\-X, \-\-midi \fR[\fIseq\fR|\fIraw\fR] ++.br ++Specify which ALSA MIDI system to provide access to. Using \fBraw\fR ++will provide a set of JACK MIDI ports that correspond to each raw ALSA ++device on the machine. Using \fBseq\fR will provide a set of JACK MIDI ++ports that correspond to each ALSA "sequencer" client (which includes ++each hardware MIDI port on the machine). \fBraw\fR provides slightly ++better performance but does not permit JACK MIDI communication with ++software written to use the ALSA "sequencer" API. ++.SS COREAUDIO BACKEND PARAMETERS ++.TP ++\fB\-c \-\-channel\fR ++Maximum number of channels (default: 2) ++.TP ++\fB\-i \-\-channelin\fR ++Maximum number of input channels (default: 2) ++.TP ++\fB\-o \-\-channelout\fR ++Maximum number of output channels (default: 2) ++.TP ++\fB\-C \-\-capture\fR ++Whether or not to capture (default: true) ++.TP ++\fB\-P \-\-playback\fR ++Whether or not to playback (default: true) ++.TP ++\fB\-D \-\-duplex\fR ++Capture and playback (default: true) ++.TP ++\fB\-r \-\-rate\fR ++Sample rate (default: 44100) ++.TP ++\fB\-p \-\-period\fR ++Frames per period (default: 128). Must be a power of 2. ++.TP ++\fB\-n \-\-name\fR ++Driver name (default: none) ++.TP ++\fB\-I \-\-id\fR ++Audio Device ID (default: 0) ++.SS DUMMY BACKEND PARAMETERS ++.TP ++\fB\-C, \-\-capture \fIint\fR ++Specify number of capture ports. The default value is 2. ++.TP ++\fB\-P, \-\-playback \fIint\fR ++Specify number of playback ports. The default value is 2. ++.TP ++\fB\-r, \-\-rate \fIint\fR ++Specify sample rate. The default value is 48000. ++.TP ++\fB\-p, \-\-period \fIint\fR ++Specify the number of frames between JACK \fBprocess()\fR calls. This ++value must be a power of 2, and the default is 1024. If you need low ++latency, set \fB\-p\fR as low as you can go without seeing xruns. A larger ++period size yields higher latency, but makes xruns less likely. The JACK ++capture latency in seconds is \fB\-\-period\fR divided by \fB\-\-rate\fR. ++.TP ++\fB\-w, \-\-wait \fIint\fR ++Specify number of usecs to wait between engine processes. ++The default value is 21333. ++ ++ ++.SS NET BACKEND PARAMETERS ++ ++.TP ++ \fB\-i, \-\-audio\-ins \fIint\fR ++Number of capture channels (default: 2) ++.TP ++ \fB\-o, \-\-audio\-outs \fIint\fR ++Number of playback channels (default: 2) ++.TP ++ \fB\-I, \-\-midi\-ins \fIint\fR ++Number of midi capture channels (default: 1) ++.TP ++\fB\-O, \-\-midi\-outs \fIint\fR ++Number of midi playback channels (default: 1) ++.TP ++ \fB\-r, \-\-rate \fIint\fR ++Sample rate (default: 48000) ++.TP ++\fB\-p, \-\-period \fIint\fR ++Frames per period (default: 1024) ++.TP ++\fB\-n, \-\-num\-periods \fIint\fR ++Network latency setting in no. of periods (default: 5) ++.TP ++\fB\-l, \-\-listen\-port \fIint\fR ++The socket port we are listening on for sync packets (default: 3000) ++.TP ++\fB\-f, \-\-factor \fIint\fR ++Factor for sample rate reduction (default: 1) ++.TP ++\fB\-u, \-\-upstream\-factor \fIint\fR ++Factor for sample rate reduction on the upstream (default: 0) ++.TP ++\fB\-c, \-\-celt \fIint\fR ++sets celt encoding and number of kbits per channel (default: 0) ++.TP ++\fB\-b, \-\-bit\-depth \fIint\fR ++Sample bit\-depth (0 for float, 8 for 8bit and 16 for 16bit) (default: 0) ++.TP ++\fB\-t, \-\-transport\-sync \fIint\fR ++Whether to slave the transport to the master transport (default: true) ++.TP ++\fB\-a, \-\-autoconf \fIint\fR ++Whether to use Autoconfig, or just start. (default: true) ++.TP ++\fB\-R, \-\-redundancy \fIint\fR ++Send packets N times (default: 1) ++.TP ++\fB\-e, \-\-native\-endian \fIint\fR ++Dont convert samples to network byte order. (default: false) ++.TP ++\fB\-J, \-\-jitterval \fIint\fR ++attempted jitterbuffer microseconds on master (default: 0) ++.TP ++\fB\-D, \-\-always\-deadline \fIint\fR ++always use deadline (default: false) ++ ++ ++.SS OSS BACKEND PARAMETERS ++.TP ++\fB\-r, \-\-rate \fIint\fR ++Specify the sample rate. The default is 48000. ++.TP ++\fB\-p, \-\-period \fIint\fR ++Specify the number of frames between JACK \fBprocess()\fR calls. This ++value must be a power of 2, and the default is 1024. If you need low ++latency, set \fB\-p\fR as low as you can go without seeing xruns. A larger ++period size yields higher latency, but makes xruns less likely. The JACK ++capture latency in seconds is \fB\-\-period\fR divided by \fB\-\-rate\fR. ++.TP ++\fB\-n, \-\-nperiods \fIint\fR ++Specify the number of periods in the hardware buffer. The default is ++2. The period size (\fB\-p\fR) times \fB\-\-nperiods\fR times four is ++the JACK buffer size in bytes. The JACK output latency in seconds is ++\fB\-\-nperiods\fR times \fB\-\-period\fR divided by \fB\-\-rate\fR. ++.TP ++\fB\-w, \-\-wordlength \fIint\fR ++Specify the sample size in bits. The default is 16. ++.TP ++\fB\-i, \-\-inchannels \fIint\fR ++Specify how many channels to capture (default: 2) ++.TP ++\fB\-o, \-\-outchannels \fIint\fR ++Specify number of playback channels (default: 2) ++.TP ++\fB\-C, \-\-capture \fIdevice_file\fR ++Specify input device for capture (default: /dev/dsp) ++.TP ++\fB\-P, \-\-playback \fIdevice_file\fR ++Specify output device for playback (default: /dev/dsp) ++.TP ++\fB\-b, \-\-ignorehwbuf \fIboolean\fR ++Specify, whether to ignore hardware period size (default: false) ++.SS SUN BACKEND PARAMETERS ++.TP ++\fB\-r, \-\-rate \fIint\fR ++Specify the sample rate. The default is 48000. ++.TP ++\fB\-p, \-\-period \fIint\fR ++Specify the number of frames between JACK \fBprocess()\fR calls. This ++value must be a power of 2, and the default is 1024. If you need low ++latency, set \fB\-p\fR as low as you can go without seeing xruns. A larger ++period size yields higher latency, but makes xruns less likely. The JACK ++capture latency in seconds is \fB\-\-period\fR divided by \fB\-\-rate\fR. ++.TP ++\fB\-n, \-\-nperiods \fIint\fR ++Specify the number of periods in the hardware buffer. The default is ++2. The period size (\fB\-p\fR) times \fB\-\-nperiods\fR times four ++(assuming 2 channels 16-bit samples) is the JACK buffer size in bytes. ++The JACK output latency in seconds is \fB\-\-nperiods\fR times ++\fB\-\-period\fR divided by \fB\-\-rate\fR. ++.TP ++\fB\-w, \-\-wordlength \fIint\fR ++Specify the sample size in bits. The default is 16. ++.TP ++\fB\-i, \-\-inchannels \fIint\fR ++Specify how many channels to capture (default: 2) ++.TP ++\fB\-o, \-\-outchannels \fIint\fR ++Specify number of playback channels (default: 2) ++.TP ++\fB\-C, \-\-capture \fIdevice_file\fR ++Specify input device for capture (default: /dev/audio) ++.TP ++\fB\-P, \-\-playback \fIdevice_file\fR ++Specify output device for playback (default: /dev/audio) ++.TP ++\fB\-b, \-\-ignorehwbuf \fIboolean\fR ++Specify, whether to ignore hardware period size (default: false) ++.SS PORTAUDIO BACKEND PARAMETERS ++.TP ++\fB\-c \-\-channel\fR ++Maximum number of channels (default: all available hardware channels) ++.TP ++\fB\-i \-\-channelin\fR ++Maximum number of input channels (default: all available hardware channels) ++.TP ++\fB\-o \-\-channelout\fR ++Maximum number of output channels (default: all available hardware channels) ++.TP ++\fB\-C \-\-capture\fR ++Whether or not to capture (default: true) ++.TP ++\fB\-P \-\-playback\fR ++Whether or not to playback (default: true) ++.TP ++\fB\-D \-\-duplex\fR ++Capture and playback (default: true) ++.TP ++\fB\-r \-\-rate\fR ++Sample rate (default: 48000) ++.TP ++\fB\-p \-\-period\fR ++Frames per period (default: 1024). Must be a power of 2. ++.TP ++\fB\-n \-\-name\fR ++Driver name (default: none) ++.TP ++\fB\-z \-\-dither\fR ++Dithering mode (default: none) ++.SH "EXAMPLES" ++.PP ++Print usage message for the parameters specific to each backend. ++.IP ++\fBjackd \-d alsa \-\-help\fR ++.br ++\fBjackd \-d coreaudio \-\-help\fR ++.br ++\fBjackd \-d net \-\-help\fR ++.br ++\fBjackd \-d dummy \-\-help\fR ++.br ++\fBjackd \-d firewire \-\-help\fR ++.br ++\fBjackd \-d freebob \-\-help\fR ++.br ++\fBjackd \-d oss \-\-help\fR ++.br ++\fBjackd \-d sun \-\-help\fR ++.br ++\fBjackd \-d portaudio \-\-help\fR ++.PP ++Run the JACK daemon with realtime priority using the first ALSA ++hardware card defined in \fB/etc/modules.conf\fR. ++.IP ++\fBjackstart \-\-realtime \-\-driver=alsa\fR ++.PP ++Run the JACK daemon with low latency giving verbose output, which can ++be helpful for trouble\-shooting system latency problems. A ++reasonably well\-tuned system with a good sound card and a ++low\-latency kernel can handle these values reliably. Some can do ++better. If you get xrun messages, try a larger buffer. Tuning a ++system for low latency can be challenging. The JACK FAQ, ++.I http://jackit.sourceforge.net/docs/faq.php\fR ++has some useful suggestions. ++.IP ++\fBjackstart \-Rv \-d alsa \-p 128 \-n 2 \-r 44100\fR ++.PP ++Run \fBjackd\fR with realtime priority using the "sblive" ALSA device ++defined in ~/.asoundrc. Apply shaped dithering to playback audio. ++.IP ++\fBjackd \-R \-d alsa \-d sblive \-\-dither=shaped\fR ++.PP ++Run \fBjackd\fR with no special privileges using the second ALSA ++hardware card defined in \fB/etc/modules.conf\fR. Any xruns reported ++by the ALSA backend will be ignored. The larger buffer helps reduce ++data loss. Rectangular dithering will be used for playback. ++.IP ++\fBjackd \-d alsa \-d hw:1 \-p2048 \-n3 \-\-softmode \-zr\fR ++.PP ++Run \fBjackd\fR in full\-duplex mode using the ALSA hw:0,0 device for ++playback and the hw:0,2 device for capture. ++.IP ++\fBjackd \-d alsa \-P hw:0,0 \-C hw:0,2\fR ++.PP ++Run \fBjackd\fR in playback\-only mode using the ALSA hw:0,0 device. ++.IP ++\fBjackd \-d alsa \-P hw:0,0\fR ++.SH "ENVIRONMENT" ++.br ++JACK is evolving a mechanism for automatically starting the server ++when needed. Any client started without a running JACK server will ++attempt to start one itself using the command line found in the first ++line of \fB$HOME/.jackdrc\fR if it exists, or \fB/etc/jackdrc\fR if it ++does not. If neither file exists, a built\-in default command will be ++used, including the \fB\-T\fR flag, which causes the server to shut ++down when all clients have exited. ++ ++As a transition, this only happens when \fB$JACK_START_SERVER\fR is ++defined in the environment of the calling process. In the future this ++will become normal behavior. In either case, defining ++\fB$JACK_NO_START_SERVER\fR disables this feature. ++ ++To change where JACK looks for the backend drivers, set ++\fB$JACK_DRIVER_DIR\fR. ++ ++\fB$JACK_DEFAULT_SERVER\fR specifies the default server name. If not ++defined, the string "default" is used. If set in their respective ++environments, this affects \fBjackd\fR unless its \fB\-\-name\fR ++parameter is set, and all JACK clients unless they pass an explicit ++name to \fBjack_client_open()\fR. ++ ++.SH "SEE ALSO:" ++.PP ++.I http://www.jackaudio.org ++.br ++The official JACK website with news, docs and a list of JACK clients. ++.PP ++.I http://jackaudio.org/email ++.br ++The JACK developers' mailing list. Subscribe, to take part in ++development of JACK or JACK clients. User questions are also welcome, ++there is no user-specific mailing list. ++.PP ++.I http://www.jackosx.com/ ++.br ++Tools specific to the Mac OS X version of JACK. ++.PP ++.I http://www.alsa\-project.org ++.br ++The Advanced Linux Sound Architecture. ++.SH "BUGS" ++Please report bugs to ++.br ++.I http://trac.jackaudio.org/ ++.SH "AUTHORS" ++Architect and original implementor: Paul Davis ++.PP ++Original design Group: Paul Davis, David Olofson, Kai Vehmanen, Benno Sennoner, ++Richard Guenther, and other members of the Linux Audio Developers group. ++.PP ++Programming: Paul Davis, Jack O'Quin, Taybin Rutkin, Stephane Letz, Fernando ++Pablo Lopez-Lezcano, Steve Harris, Jeremy Hall, Andy Wingo, Kai ++Vehmanen, Melanie Thielker, Jussi Laako, Tilman Linneweh, Johnny ++Petrantoni, Torben Hohn. ++.PP ++Manpage written by Stefan Schwandter, Jack O'Quin and Alexandre ++Prokoudine. +diff -rupN jack-1.9.5.old/man/jack_disconnect.0 jack-1.9.5/man/jack_disconnect.0 +--- jack-1.9.5.old/man/jack_disconnect.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_disconnect.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1 @@ ++.so man1/jack_connect.1 +diff -rupN jack-1.9.5.old/man/jack_freewheel.0 jack-1.9.5/man/jack_freewheel.0 +--- jack-1.9.5.old/man/jack_freewheel.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_freewheel.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,16 @@ ++.TH JACK_FREEWHEEL "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_freewheel \- JACK toolkit client to control freewheeling mode ++.SH SYNOPSIS ++.B jack_freewheel [y|n] ++.SH DESCRIPTION ++.B jack_freewheel ++Turns freewheeling mode on (y) or off (n). While in freewheeling mode, ++the JACK server does not wait in between process() calls, and does not ++read or write data from/to any audio interface. That results in the JACK graph ++processing data as fast as possible. Freewheeling makes fast exports to ++files possible. ++.PP ++There is no useful reason to use this tool other than testing. JACK ++clients that use freewheeling will turn it on and off themselves. ++ +diff -rupN jack-1.9.5.old/man/jack_impulse_grabber.0 jack-1.9.5/man/jack_impulse_grabber.0 +--- jack-1.9.5.old/man/jack_impulse_grabber.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_impulse_grabber.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,11 @@ ++.TH JACK_IMPULSE_GRABBER "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_impulse_grabber \- JACK toolkit client to grab an impulse (response) ++.SH SYNOPSIS ++\fBjack_impulse_grabber\fR \fB-d\fR \fIduration\fR [\fI-f\fR (C|gnuplot)] ++.SH DESCRIPTION ++\fBjack_impulse_grabber\fR is a JACK example client for collecting ++impulses recordings from JACK ports. ++ ++ ++ +diff -rupN jack-1.9.5.old/man/jack_load.0 jack-1.9.5/man/jack_load.0 +--- jack-1.9.5.old/man/jack_load.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_load.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,28 @@ ++.TH JACK_LOAD "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_load \- JACK toolkit client for loading in-process clients ++.SH SYNOPSIS ++\fBjack_load\fR [ \fI-i\fR initstring ] [ \fI-s\fR servername ] [\fI-w\fR ] client-name so-name [ initstring ] ++.SH DESCRIPTION ++\fBjack_load\fR is a JACK toolkit client. It loads the specified plugin and creates an in-process client. ++.SH ARGUMENTS ++.PP ++The client-name must be a currently unused client name. ++.PP ++The so-name is the name of file that client code is stored in (typically, \fIclientname.so\fR) ++.SH OPTIONS ++.TP ++\fB-i\fR, \fB--init\fR init-string ++.br ++initialization string passed to the in-process client. Note that this can also be specified as the last argument on the command line. ++.TP ++\fB-s\fR, \fB--server\fR servername ++.br ++Name of JACK server to connect to ++.TP ++\fB-w\fR, \fB--wait\fR ++Wait for a signal (eg. from Ctrl-c) and then unload the client. ++.SH AUTHOR ++Jeremy Hall ++ ++ +diff -rupN jack-1.9.5.old/man/jack_lsp.0 jack-1.9.5/man/jack_lsp.0 +--- jack-1.9.5.old/man/jack_lsp.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_lsp.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,47 @@ ++.TH JACK_LSP "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_lsp \- JACK toolkit client to list informtion on ports ++.SH SYNOPSIS ++\fBjack_lsp\fR [ \fI-s\fR | \fI--server\fR servername ] [ \fI-AclLptvh\fR ] ++.SH DESCRIPTION ++\fBjack_lsp\fR lists all known ports associated with a JACK ++server. It can also optionally list various kinds of information about each port. ++.SH OPTIONS ++.TP ++\fB-s\fR, \fB--server\fR \fIservername\fR ++.br ++Connect to the jack server named \fIservername\fR ++.TP ++\fB-A\fR, \fB--aliases\fR ++.br ++List aliases for each port ++.TP ++\fB-c\fR, \fB--connections\fR ++.br ++List connections to/from each port ++.TP ++\fB-l\fR, \fB--latency\fR ++.br ++Display per-port latency in frames at each port ++.TP ++\fB-L\fR, \fI--latency\fR ++.br ++Display total latency in frames at each port ++.TP ++\fB-p\fR, \fB--properties\fR ++.br ++Display port properties. Output may include input|output, can-monitor, physical, terminal ++.TP ++\fB-t\fR, \fB--type\fR ++.br ++Display port type ++.TP ++\fB-h\fR, \fB--help\fR ++.br ++Display help/usage message ++.TP ++\fB-v\fR, \fB--version\fR ++.br ++Output version information and exit ++ ++ +diff -rupN jack-1.9.5.old/man/jack_metro.0 jack-1.9.5/man/jack_metro.0 +--- jack-1.9.5.old/man/jack_metro.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_metro.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,40 @@ ++.TH JACK_METRO "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_metro \- JACK toolkit metronome ++.SH SYNOPSIS ++\fBjack_metro\fR [ \fI-n\fR name ] [ \fI-f\fR hz ] [ \fI-D\fR msecs ] [\fI-a\fR % ] [ \fI-d\fR % ] \fI-b\fR bpm ++.SH DESCRIPTION ++\fBjack_metro\fR is a simple metronome for JACK. It generates a ++synthetic "tick" sound for every beat. Note that is does \fBnot\fR ++connect its output port by default - to hear the sound it makes you must ++connect them using some other tool. ++.SH OPTIONS ++.TP ++\fB-n\fR, \fB--name\fR ++.br ++Specify a name for this instance of the metronome. ++.TP ++\fB-f\fR, \fB--frequency\fR Hz ++.br ++Define the frequency of the "tick" in Hz. ++.TP ++\fB-D\fR, \fB--duration\fR msecs ++.br ++Define the duration of the "tick" in milliseconds. ++.TP ++\fB-a\fR, \fB--attack\fR %-age ++.br ++Define the duration of the attack phase of the "tick" as a percentage ++of the duration. ++.TP ++\fB-d\fR, \fB--decay\fR %-age ++.br ++Define the duration of the decay phase of the "tick" as a percentage ++of the duration. ++.TP ++\fB--b\fR, \fB--bpm\fR bpm ++.br ++Define the number of beats per minute. ++.SH AUTHOR ++Anthony Van Groningen ++ +diff -rupN jack-1.9.5.old/man/jack_monitor_client.0 jack-1.9.5/man/jack_monitor_client.0 +--- jack-1.9.5.old/man/jack_monitor_client.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_monitor_client.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,18 @@ ++.TH JACK_CONNECT "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_monitor_client \- The JACK Audio Connection Kit example client ++.SH SYNOPSIS ++.B jack_monitor_client ++client-name ++.PP ++The client-name must be the name of a existing client that monitoring is ++to be enabled for. ++.SH DESCRIPTION ++.B jack_monitor_client ++is an example client for the JACK Audio Connection Kit. It enables ++monitoring for the specified client. ++.SH AUTHOR ++Jeremy Hall ++.PP ++This manpage was written by Robert Jordens for Debian. ++ +diff -rupN jack-1.9.5.old/man/jack_netsource.0 jack-1.9.5/man/jack_netsource.0 +--- jack-1.9.5.old/man/jack_netsource.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_netsource.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,109 @@ ++.TH JACK_NETSOURCE "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_netsource \- Netjack Master client for one slave ++.SH SYNOPSIS ++\fBjack_netsource\fR [ \fI-H\fR hostname ] [ \fIoptions\fR ] ++ ++.SH DESCRIPTION ++\fBjack_netsource\fR The Master side of a netjack connection. Represents the slave jackd -dnet in the master jack graph. ++Most connection parameters are configured via the netsource, and the slave will set itself up according to the commandline ++option given to jack_netsource. ++.br ++Netjack allows low latency audio connections over general IP networks. When using celt for compression, it is even possible ++to establish transatlantic links, with latencies not much over the actual ping time. ++.br ++But the main usecase is of course a LAN, where it can achieve one jack period of latency. ++ ++.SH OPTIONS ++.TP ++\fB-h\fR this help text ++.TP ++\fB-H\fR \fIslave host\fR ++.br ++Host name of the slave JACK ++.TP ++\fB-o\fR \fInum channels\fR ++.br ++Number of audio playback channels ++.TP ++\fB-i\fR \fInum channels\fR ++.br ++Number of audio capture channels ++.TP ++\fB-O\fR \fInum channels\fR ++.br ++Number of midi playback channels ++.TP ++\fB-I\fR \fInum channels\fR ++.br ++Number of midi capture channels ++.TP ++\fB-n\fR \fIperiods\fR ++.br ++Network latency in JACK periods ++.TP ++\fB-p\fR \fIport\fR ++.br ++UDP port that the slave is listening on ++.TP ++\fB-r\fR \fIreply port\fR ++.br ++UDP port that we are listening on ++.TP ++\fB-B\fR \fIbind port\fR ++.br ++reply port, for use in NAT environments ++.TP ++\fB-b\fR \fIbitdepth\fR ++.br ++Set transport to use 16bit or 8bit ++.TP ++\fB-c\fR \fIbytes\fR ++.br ++Use CELT encoding with per period and channel ++.TP ++\fB-m\fR \fImtu\fR ++.br ++Assume this mtu for the link ++.TP ++\fB-R\fR \fIN\fR ++.br ++Redundancy: send out packets N times. ++.TP ++\fB-e\fR ++.br ++skip host-to-network endianness conversion ++.TP ++\fB-N\fR \fIjack name\fR ++.br ++Reports a different client name to jack ++.TP ++.TP ++\fB-s\fR, \fB--server\fR \fIservername\fR ++.br ++Connect to the jack server named \fIservername\fR ++.TP ++\fB-h\fR, \fB--help\fR ++.br ++Display help/usage message ++.TP ++\fB-v\fR, \fB--version\fR ++.br ++Output version information and exit ++ ++ ++.SH EXAMPLES ++ ++.PP ++run a 4 audio channel bidirectional link with one period of latency and no midi channels. Audio data is flowing uncompressed over the wire: ++.br ++On \fIhostA\fR: ++.IP ++\fBjackd \-d alsa \fR ++.br ++\fBjack_netsource \-H hostB -n1 -i4 -o4 -I0 -O0 \fR ++.PP ++On \fIhostB\fR: ++.IP ++\fBjackd \-d net \fR ++ +diff -rupN jack-1.9.5.old/man/jackrec.0 jack-1.9.5/man/jackrec.0 +--- jack-1.9.5.old/man/jackrec.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jackrec.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,23 @@ ++.TH JACKREC "1" "!DATE!" "!VERSION!" ++.SH NAME ++jackrec \- JACK toolkit client for recording audio ++.SH SYNOPSIS ++.B jackrec ++\-f filename \-d seconds [ \-b bitdepth ] port1 [ port2 ... ] ++.SH DESCRIPTION ++.B jackrec is a basic, but useful, audio recorder that will record ++audio from 1 or more JACK ports to a file on disk. The file format is ++always RIFF/WAV, with samples stored as signed integers. The sample ++bit depth can be selected using the \fI-b\fR option. The file will ++have as many channels as there are ports specified on the command line ++- each channel will contain the data recorded from one port. The user ++should generally specify the duration (in seconds) using the \fI-d\fR ++option. If not specified, jackrec will record until terminated by a ++signal (eg. from Ctrl-c). ++.PP ++This application is not intended to be a heavy duty audio recorder, ++and originated as an example client to show how to handle threading ++and disk I/O in a JACK client. However, it is a useful, simple ++recorder and is included in the JACK toolkit as a result. ++ ++ +diff -rupN jack-1.9.5.old/man/jack_samplerate.0 jack-1.9.5/man/jack_samplerate.0 +--- jack-1.9.5.old/man/jack_samplerate.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_samplerate.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,9 @@ ++.TH JACK_SAMPLERATE "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_samplerate \- JACK toolkit client to print current samplerate ++.SH SYNOPSIS ++.B jack_samplerate ++.SH DESCRIPTION ++.B jack_samplerate prints the current samplerate, and exits. ++ ++ +diff -rupN jack-1.9.5.old/man/jack_showtime.0 jack-1.9.5/man/jack_showtime.0 +--- jack-1.9.5.old/man/jack_showtime.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_showtime.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,13 @@ ++.TH JACK_SHOWTIME "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_showtime \- The JACK Audio Connection Kit example client ++.SH SYNOPSIS ++.B jack_showtime ++.SH DESCRIPTION ++.B jack_showtime ++prints the current timebase information to stdout ++.SH AUTHOR ++Paul Davis ++.PP ++This manpage was written by Stefan Schwandter ++ +diff -rupN jack-1.9.5.old/man/jack_simple_client.0 jack-1.9.5/man/jack_simple_client.0 +--- jack-1.9.5.old/man/jack_simple_client.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_simple_client.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,20 @@ ++.TH JACK_CONNECT "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_simple_client \- The JACK Audio Connection Kit example client ++.SH SYNOPSYS ++.B jack_simple_client ++client-name ++.PP ++The client-name must be a yet unused client name. ++.SH DESCRIPTION ++.B jack_simple_client ++is an example client for the JACK Audio Connection Kit. It creates two ++ports (client-name:input and client-name:output) that pass the data ++unmodified. ++.SH EXAMPLE ++jack_simple_client in_process_test ++.SH AUTHOR ++Jeremy Hall ++.PP ++This manpage was written by Robert Jordens for Debian. ++ +diff -rupN jack-1.9.5.old/man/jack_transport.0 jack-1.9.5/man/jack_transport.0 +--- jack-1.9.5.old/man/jack_transport.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_transport.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,13 @@ ++.TH JACK_TRANSPORT "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_transport \- JACK toolkit client for transport control ++.SH SYNOPSIS ++.B jack_transport ++.SH DESCRIPTION ++.B jack_transport ++is a toolkit client for the JACK Audio Connection Kit. It provides command-line ++control over the JACK transport system. Type help at jack_transport's ++command prompt to see the available commands. ++.SH AUTHOR ++Jeremy Hall ++ +diff -rupN jack-1.9.5.old/man/jack_unload.0 jack-1.9.5/man/jack_unload.0 +--- jack-1.9.5.old/man/jack_unload.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_unload.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,19 @@ ++.TH JACK_UNLOAD "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_unload \- The JACK Audio Connection Kit example client ++.SH SYNOPSIS ++.B jack_unload ++client-name ++.PP ++The client-name must be the name of a loaded client that can be unloaded. ++.SH DESCRIPTION ++.B jack_unload ++is the counterpart to ++.B jack_load ++and unloads the specified client. ++.SH EXAMPLE ++.B jack_unload in_process_test ++.SH AUTHOR ++Jeremy Hall ++.PP ++This manpage was written by Robert Jordens for Debian. +diff -rupN jack-1.9.5.old/man/jack_wait.0 jack-1.9.5/man/jack_wait.0 +--- jack-1.9.5.old/man/jack_wait.0 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/jack_wait.0 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,41 @@ ++.TH JACK_WAIT "1" "!DATE!" "!VERSION!" ++.SH NAME ++jack_wait \- JACK toolkit client to check and wait for existence/exit of jackd. ++.SH SYNOPSIS ++\fBjack_wait\fR [ \fI-s\fR | \fI--server\fR servername ] [ \fI-t\fR | \fI--timeout\fR timeout_seconds [ \fI-cqwhv\fR ] ++.SH DESCRIPTION ++\fBjack_wait\fR When invoked with \fI-c\fR it only checks for the existence of a jack server. When invoked with \fI-w\fR the ++program will wait for a jackd to be available. ++The \fI-q\fR makes it wait for the jackd to exit. ++ ++.SH OPTIONS ++.TP ++\fB-w\fR, \fB--wait\fR ++.br ++Wait for jackd to be available. ++.TP ++\fB-q\fR, \fB--quit\fR ++.br ++Wait for jackd quit. ++.TP ++\fB-c\fR, \fB--check\fR ++.br ++Only check for existence of jackd, and exit. ++.TP ++\fB-s\fR, \fB--server\fR \fIservername\fR ++.br ++Connect to the jack server named \fIservername\fR ++.TP ++\fB-t\fR, \fB--timeout\fR \fItimeout_seconds\fR ++.br ++Only wait \fItimeout_seconds\fR. ++.TP ++\fB-h\fR, \fB--help\fR ++.br ++Display help/usage message ++.TP ++\fB-v\fR, \fB--version\fR ++.br ++Output version information and exit ++ ++ +diff -rupN jack-1.9.5.old/man/wscript jack-1.9.5/man/wscript +--- jack-1.9.5.old/man/wscript 1969-12-31 19:00:00.000000000 -0500 ++++ jack-1.9.5/man/wscript 2010-05-17 05:30:11.000000000 -0400 +@@ -0,0 +1,13 @@ ++#! /usr/bin/env python ++# encoding: utf-8 ++ ++import Build ++import re ++import os ++import misc ++ ++ ++def build(bld): ++ bld.exec_command("cd man ; sh fill_template %s" % bld.env['JACK_VERSION']) ++ bld.install_files(bld.env['MANDIR'], '*.1') ++ +diff -rupN jack-1.9.5.old/wscript jack-1.9.5/wscript +--- jack-1.9.5.old/wscript 2010-02-12 05:58:08.000000000 -0500 ++++ jack-1.9.5/wscript 2010-06-04 22:00:04.000000000 -0400 +@@ -62,6 +62,7 @@ def set_options(opt): + + opt.add_option('--libdir', type='string', help="Library directory [Default: /lib]") + opt.add_option('--libdir32', type='string', help="32bit Library directory [Default: /lib32]") ++ opt.add_option('--mandir', type='string', help="Manpage directory [Default: /share/man/man1]") + opt.add_option('--dbus', action='store_true', default=False, help='Enable D-Bus JACK (jackdbus)') + opt.add_option('--classic', action='store_true', default=False, help='Force enable standard JACK (jackd) even if D-Bus JACK (jackdbus) is enabled too') + opt.add_option('--doxygen', action='store_true', default=False, help='Enable build of doxygen documentation') +@@ -150,6 +151,11 @@ def configure(conf): + conf.env['LIBDIR'] = conf.env['PREFIX'] + Options.options.libdir + else: + conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib' ++ ++ if Options.options.mandir: ++ conf.env['MANDIR'] = conf.env['PREFIX'] + Options.options.mandir ++ else: ++ conf.env['MANDIR'] = conf.env['PREFIX'] + '/share/man/man1' + + if conf.env['BUILD_DEBUG']: + conf.env.append_unique('CXXFLAGS', '-g') +@@ -255,6 +261,7 @@ def build(bld): + bld.add_subdirs('linux') + bld.add_subdirs('example-clients') + bld.add_subdirs('tests') ++ bld.add_subdirs('man') + if bld.env['BUILD_JACKDBUS'] == True: + bld.add_subdirs('dbus') + diff --git a/jack-realtime-compat.patch b/jack-realtime-compat.patch new file mode 100644 index 0000000..8ab34b4 --- /dev/null +++ b/jack-realtime-compat.patch @@ -0,0 +1,56 @@ +diff -rupN jack-1.9.5.old/common/JackControlAPI.cpp jack-1.9.5/common/JackControlAPI.cpp +--- jack-1.9.5.old/common/JackControlAPI.cpp 2010-02-12 05:57:47.000000000 -0500 ++++ jack-1.9.5/common/JackControlAPI.cpp 2010-07-20 00:42:55.000000000 -0400 +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #include "jslist.h" + #include "driver_interface.h" +@@ -675,7 +676,13 @@ EXPORT jackctl_server_t * jackctl_server + goto fail_free_parameters; + } + +- value.i = 10; ++ struct utsname utsname; ++ int success; ++ success = uname( &utsname ); ++ if( success == 0 && strstr( utsname.version, "ccrma" ) ) ++ value.i = 60; ++ else ++ value.i = 20; + if (jackctl_add_parameter( + &server_ptr->parameters, + "realtime-priority", +diff -rupN jack-1.9.5.old/common/JackServerGlobals.cpp jack-1.9.5/common/JackServerGlobals.cpp +--- jack-1.9.5.old/common/JackServerGlobals.cpp 2010-02-12 05:57:47.000000000 -0500 ++++ jack-1.9.5/common/JackServerGlobals.cpp 2010-07-20 00:40:43.000000000 -0400 +@@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridg + #include "shm.h" + #include + #include ++#include + + static char* server_name = NULL; + +@@ -67,9 +68,17 @@ void JackServerGlobals::Delete() + + bool JackServerGlobals::Init() + { ++ struct utsname utsname; ++ int success; ++ success = uname( &utsname ); ++ + int realtime = 0; + int client_timeout = 0; /* msecs; if zero, use period size. */ +- int realtime_priority = 10; ++ int realtime_priority; ++ if( success == 0 && strstr( utsname.version, "ccrma" ) ) ++ realtime_priority = 60; ++ else ++ realtime_priority = 20; + int verbose_aux = 0; + int do_mlock = 1; + unsigned int port_max = 128; diff --git a/sources b/sources index e5be2fc..e545201 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -d58e29a55f285d54e75134cec8e02a10 jack-audio-connection-kit-0.118.0.tar.gz +fdb86434b57255139b72c7f91e827fea jack-1.9.5.tar.bz2