From 09e7e0ab53e2e5a25ce008b64843868f3b9b03b4 Mon Sep 17 00:00:00 2001 From: darkeye Date: Mon, 4 Apr 2005 08:36:18 +0000 Subject: [PATCH] commited changes to enable Jack support thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk --- darkice/trunk/AUTHORS | 1 + darkice/trunk/ChangeLog | 3 + darkice/trunk/configure.in | 32 +- darkice/trunk/man/darkice.1 | 1 + darkice/trunk/man/darkice.cfg.5 | 8 +- darkice/trunk/src/AlsaDspSource.cpp | 6 +- darkice/trunk/src/AudioSource.cpp | 21 +- darkice/trunk/src/AudioSource.h | 31 +- darkice/trunk/src/DarkIce.cpp | 20 +- darkice/trunk/src/DarkIce.h | 6 +- .../src/{Config.cpp => DarkIceConfig.cpp} | 8 +- .../trunk/src/{Config.h => DarkIceConfig.h} | 6 +- darkice/trunk/src/JackDspSource.cpp | 454 ++++++++++++++++++ darkice/trunk/src/JackDspSource.h | 289 +++++++++++ darkice/trunk/src/Makefile.am | 10 +- darkice/trunk/src/Reporter.h | 6 +- darkice/trunk/src/aflibConverter.cc | 50 +- darkice/trunk/src/aflibConverter.h | 6 +- 18 files changed, 900 insertions(+), 58 deletions(-) rename darkice/trunk/src/{Config.cpp => DarkIceConfig.cpp} (96%) rename darkice/trunk/src/{Config.h => DarkIceConfig.h} (97%) create mode 100644 darkice/trunk/src/JackDspSource.cpp create mode 100644 darkice/trunk/src/JackDspSource.h diff --git a/darkice/trunk/AUTHORS b/darkice/trunk/AUTHORS index 2e62584..97c400e 100644 --- a/darkice/trunk/AUTHORS +++ b/darkice/trunk/AUTHORS @@ -22,4 +22,5 @@ with contributions by: Robert Lunnon Enrico Ardizzoni Deti Fliegl + Nicholas J. Humfrey diff --git a/darkice/trunk/ChangeLog b/darkice/trunk/ChangeLog index fb91463..a423e70 100644 --- a/darkice/trunk/ChangeLog +++ b/darkice/trunk/ChangeLog @@ -4,6 +4,9 @@ DarkIce next release since it is not implemented in OpenBSD / NetBSD o added possibility to downsample from stereo to mono when encoding to Ogg Vorbis, thanks to Deti Fliegl, + o added support for Jack inputs, enabling a lot of interesting usage, + including support for MacOS X. + Thanks to Nicholas J. Humfrey 15-02-2004: DarkIce 0.14 released diff --git a/darkice/trunk/configure.in b/darkice/trunk/configure.in index 1e63198..ae91a07 100644 --- a/darkice/trunk/configure.in +++ b/darkice/trunk/configure.in @@ -1,9 +1,11 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(src/DarkIce.cpp) -AM_INIT_AUTOMAKE(darkice, 0.15beta) +AC_INIT(darkice, 0.15beta) +AC_CONFIG_SRCDIR(src/DarkIce.cpp) +AM_CONFIG_HEADER(src/config.h) -AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE +AC_PROG_CC AC_PROG_CXX AC_PROG_INSTALL @@ -155,6 +157,24 @@ else fi +dnl----------------------------------------------------------------------------- +dnl link JACK sound server if requested +dnl----------------------------------------------------------------------------- +AC_SUBST(JACK_CFLAGS) +AC_SUBST(JACK_LIBS) +AC_ARG_WITH( jack, +[ --with-jack use JACK audio server [yes] ], + USE_JACK=${withval}, USE_JACK="yes" ) + +if test "x${USE_JACK}" = "xyes" ; then + PKG_CHECK_MODULES(JACK, jack, + AC_DEFINE( HAVE_JACK_LIB, 1, [build with JACK audio server support] ) + ) +else + AC_MSG_RESULT( [building without JACK support] ) +fi + + dnl----------------------------------------------------------------------------- dnl check for MSG_NOSIGNAL for the send() function in libsocket dnl----------------------------------------------------------------------------- @@ -171,6 +191,12 @@ AC_TRY_COMPILE([#include ], [ ]) +dnl----------------------------------------------------------------------------- +dnl check for POSIX real-time scheduling +dnl----------------------------------------------------------------------------- +AC_CHECK_FUNCS( sched_getscheduler sched_getparam ) + + dnl----------------------------------------------------------------------------- dnl enable compilation with debug flags dnl----------------------------------------------------------------------------- diff --git a/darkice/trunk/man/darkice.1 b/darkice/trunk/man/darkice.1 index 3eb2983..e50f032 100644 --- a/darkice/trunk/man/darkice.1 +++ b/darkice/trunk/man/darkice.1 @@ -90,6 +90,7 @@ Developed with contributions by Robert Lunnon Enrico Ardizzoni Deti Fliegl + Nicholas J. Humfrey .SH LINKS Project homepage: diff --git a/darkice/trunk/man/darkice.cfg.5 b/darkice/trunk/man/darkice.cfg.5 index 62cc90f..ca1c76c 100644 --- a/darkice/trunk/man/darkice.cfg.5 +++ b/darkice/trunk/man/darkice.cfg.5 @@ -60,8 +60,12 @@ Required values: .TP .I device -OSS DSP audio device to record from (e.g. /dev/dsp) or ALSA DSP device name -(e.g. hwplug:0,0) +Specify the device to record from, which can be an OSS DSP device, +an ALSA source or you can use Jack audio. +- OSS DSP audio device to record from (e.g. /dev/dsp) +- ALSA DSP device name (e.g. hwplug:0,0) +- the string 'jack', to have an unconnected Jack port, or + 'jack_auto' to automatically make Jack connect to the first source. .TP .I sampleRate The sample rate to record with, samples per second diff --git a/darkice/trunk/src/AlsaDspSource.cpp b/darkice/trunk/src/AlsaDspSource.cpp index 46cd11a..94eef6d 100644 --- a/darkice/trunk/src/AlsaDspSource.cpp +++ b/darkice/trunk/src/AlsaDspSource.cpp @@ -260,7 +260,7 @@ AlsaDspSource :: read ( void * buf, } while (ret == -EAGAIN); if ( ret < 0 ) { - throw new Exception(__FILE__, __LINE__, snd_strerror(ret)); + throw Exception(__FILE__, __LINE__, snd_strerror(ret)); } running = true; @@ -292,6 +292,10 @@ AlsaDspSource :: close ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.4 2005/04/04 08:36:16 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.3 2005/04/03 05:00:14 jbebel Fixing code documentation of buffer overruns diff --git a/darkice/trunk/src/AudioSource.cpp b/darkice/trunk/src/AudioSource.cpp index 3a26819..e9e63d7 100644 --- a/darkice/trunk/src/AudioSource.cpp +++ b/darkice/trunk/src/AudioSource.cpp @@ -65,6 +65,7 @@ AudioSource :: createDspSource( const char * deviceName, int channel) throw ( Exception ) { + if ( Util::strEq( deviceName, "/dev", 4) ) { #if defined( SUPPORT_OSS_DSP ) Reporter::reportEvent( 1, "Using OSS DSP input device:", deviceName); @@ -79,9 +80,21 @@ AudioSource :: createDspSource( const char * deviceName, bitsPerSample, channel); #else - throw new Exception( __FILE__, __LINE__, + throw Exception( __FILE__, __LINE__, "trying to open OSS or Solaris DSP device " "without support compiled", deviceName); +#endif + } else if ( Util::strEq( deviceName, "jack", 4) ) { +#if defined( SUPPORT_JACK_DSP ) + Reporter::reportEvent( 1, "Using JACK audio server as input device."); + return new JackDspSource( deviceName, + sampleRate, + bitsPerSample, + channel); +#else + throw Exception( __FILE__, __LINE__, + "trying to open JACK device without " + "support compiled", deviceName); #endif } else { #if defined( SUPPORT_ALSA_DSP ) @@ -91,7 +104,7 @@ AudioSource :: createDspSource( const char * deviceName, bitsPerSample, channel); #else - throw new Exception( __FILE__, __LINE__, + throw Exception( __FILE__, __LINE__, "trying to open ALSA DSP device without " "support compiled", deviceName); #endif @@ -104,6 +117,10 @@ AudioSource :: createDspSource( const char * deviceName, $Source$ $Log$ + Revision 1.3 2005/04/04 08:36:16 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.2 2004/02/15 22:26:16 darkeye fixed typo, minimal cosmetic change diff --git a/darkice/trunk/src/AudioSource.h b/darkice/trunk/src/AudioSource.h index c89cc18..d6da9ce 100644 --- a/darkice/trunk/src/AudioSource.h +++ b/darkice/trunk/src/AudioSource.h @@ -33,6 +33,9 @@ #error This is a C++ include file #endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* ============================================================ include files */ @@ -50,21 +53,27 @@ *----------------------------------------------------------------------------*/ #if defined( HAVE_ALSA_LIB ) // we have an ALSA sound system available -#define SUPPORT_ALSA_DSP +#define SUPPORT_ALSA_DSP 1 #endif #if defined( HAVE_SYS_SOUNDCARD_H ) // we have an OSS DSP sound source device available -#define SUPPORT_OSS_DSP +#define SUPPORT_OSS_DSP 1 #endif #if defined( HAVE_SYS_AUDIO_H ) || defined( HAVE_SYS_AUDIOIO_H ) // we have a Solaris DSP sound device available (same for OpenBSD) -#define SUPPORT_SOLARIS_DSP +#define SUPPORT_SOLARIS_DSP 1 +#endif + +#if defined( HAVE_JACK_LIB ) +// we have JACK audio server +#define SUPPORT_JACK_DSP 1 #endif #if !defined( SUPPORT_ALSA_DSP ) \ && !defined( SUPPORT_OSS_DSP ) \ + && !defined( SUPPORT_JACK_DSP ) \ && !defined( SUPPORT_SOLARIS_DSP ) // there was no DSP audio system found #error No DSP audio input device found on system @@ -212,7 +221,14 @@ class AudioSource : public Source, public virtual Reporter * @return true if the data is big endian, false if little endian */ virtual bool - isBigEndian ( void ) const throw () = 0; + isBigEndian ( void ) const throw () + { +#ifdef WORDS_BIGENDIAN + return true; +#else + return false; +#endif + } /** * Get the sample rate per seconds for this AudioSource. @@ -275,6 +291,9 @@ class AudioSource : public Source, public virtual Reporter #include "SolarisDspSource.h" #endif +#if defined( SUPPORT_JACK_DSP ) +#include "JackDspSource.h" +#endif /* ====================================================== function prototypes */ @@ -288,6 +307,10 @@ class AudioSource : public Source, public virtual Reporter $Source$ $Log$ + Revision 1.8 2005/04/04 08:36:16 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.7 2004/02/18 21:08:11 darkeye ported to OpenBSD (real-time scheduling not yet supported) diff --git a/darkice/trunk/src/DarkIce.cpp b/darkice/trunk/src/DarkIce.cpp index cb525a1..9c642e0 100644 --- a/darkice/trunk/src/DarkIce.cpp +++ b/darkice/trunk/src/DarkIce.cpp @@ -873,9 +873,8 @@ DarkIce :: configFileCast ( const Config & config ) void DarkIce :: setRealTimeScheduling ( void ) throw ( Exception ) { -// don't include the following on OpenBSD / NetBSD, as the scheduling -// functions are not implemented. -#if !defined( __OpenBSD__ ) && !defined( __NetBSD__ ) +// Only if the OS has the POSIX real-time scheduling functions implemented. +#if defined( HAVE_SCHED_GETSCHEDULER ) && defined( HAVE_SCHED_GETPARAM ) uid_t euid; euid = geteuid(); @@ -921,9 +920,9 @@ DarkIce :: setRealTimeScheduling ( void ) throw ( Exception ) "It is recommended that you run this program as super-user"); } #else - reportEvent( 1, "POSIX scheduling not supported on OpenBSD / NetBSD, " + reportEvent( 1, "POSIX scheduling not supported on this system, " "this may cause recording skips"); -#endif // !__OpenBSD__ && !__NetBSD__ +#endif // HAVE_SCHED_GETSCHEDULER && HAVE_SCHED_GETPARAM } @@ -935,9 +934,8 @@ DarkIce :: setRealTimeScheduling ( void ) throw ( Exception ) void DarkIce :: setOriginalScheduling ( void ) throw ( Exception ) { -// don't include the following on OpenBSD / NetBSD, as the scheduling -// functions are not implemented. -#if !defined( __OpenBSD__ ) && !defined( __NetBSD__ ) +// Only if the OS has the POSIX real-time scheduling functions implemented. +#if defined( HAVE_SCHED_GETSCHEDULER ) && defined( HAVE_SCHED_GETPARAM ) uid_t euid; euid = geteuid(); @@ -957,7 +955,7 @@ DarkIce :: setOriginalScheduling ( void ) throw ( Exception ) reportEvent( 5, "reverted to original scheduling"); } -#endif // !__OpenBSD__ && !__NetBSD__ +#endif // HAVE_SCHED_GETSCHEDULER && HAVE_SCHED_GETPARAM } @@ -1010,6 +1008,10 @@ DarkIce :: run ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.42 2005/04/04 08:36:17 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.41 2005/04/03 05:12:20 jbebel Changed mechanism for testing the presence of the quality value such that zero is a valid option. diff --git a/darkice/trunk/src/DarkIce.h b/darkice/trunk/src/DarkIce.h index 19a3181..b87ef2a 100644 --- a/darkice/trunk/src/DarkIce.h +++ b/darkice/trunk/src/DarkIce.h @@ -58,7 +58,7 @@ #include "AudioEncoder.h" #include "TcpSocket.h" #include "CastSink.h" -#include "Config.h" +#include "DarkIceConfig.h" /* ================================================================ constants */ @@ -309,6 +309,10 @@ class DarkIce : public virtual Referable, public virtual Reporter $Source$ $Log$ + Revision 1.15 2005/04/04 08:36:17 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.14 2002/05/28 12:35:41 darkeye code cleanup: compiles under gcc-c++ 3.1, using -pedantic option diff --git a/darkice/trunk/src/Config.cpp b/darkice/trunk/src/DarkIceConfig.cpp similarity index 96% rename from darkice/trunk/src/Config.cpp rename to darkice/trunk/src/DarkIceConfig.cpp index 9286278..1584a45 100644 --- a/darkice/trunk/src/Config.cpp +++ b/darkice/trunk/src/DarkIceConfig.cpp @@ -4,7 +4,7 @@ Tyrell Config - File : Config.cpp + File : DarkIceConfig.cpp Version : $Revision$ Author : $Author$ Location : $Source$ @@ -38,7 +38,7 @@ #include -#include "Config.h" +#include "DarkIceConfig.h" /* =================================================== local data structures */ @@ -170,6 +170,10 @@ Config :: read ( std::istream & is ) throw ( Exception ) $Source$ $Log$ + Revision 1.1 2005/04/04 08:36:17 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.7 2002/05/28 12:35:41 darkeye code cleanup: compiles under gcc-c++ 3.1, using -pedantic option diff --git a/darkice/trunk/src/Config.h b/darkice/trunk/src/DarkIceConfig.h similarity index 97% rename from darkice/trunk/src/Config.h rename to darkice/trunk/src/DarkIceConfig.h index 0259af6..2b64a23 100644 --- a/darkice/trunk/src/Config.h +++ b/darkice/trunk/src/DarkIceConfig.h @@ -4,7 +4,7 @@ Tyrell Config - File : Config.h + File : DarkIceConfig.h Version : $Revision$ Author : $Author$ Location : $Source$ @@ -213,6 +213,10 @@ class Config : public virtual Referable $Source$ $Log$ + Revision 1.1 2005/04/04 08:36:17 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.5 2002/05/28 12:35:41 darkeye code cleanup: compiles under gcc-c++ 3.1, using -pedantic option diff --git a/darkice/trunk/src/JackDspSource.cpp b/darkice/trunk/src/JackDspSource.cpp new file mode 100644 index 0000000..9420e90 --- /dev/null +++ b/darkice/trunk/src/JackDspSource.cpp @@ -0,0 +1,454 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2005 Nicholas Humfrey. All rights reserved. + + Tyrell DarkIce + + File : JackDspSource.cpp + Version : $Revision$ + Author : $Author$ + Location : $Source$ + + Copyright notice: + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#include "AudioSource.h" + +#ifdef SUPPORT_JACK_DSP +// only compile this code if there is support for it + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + +#ifdef HAVE_STRING_H +#include +#else +#error need string.h +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#else +#error need sys/types.h +#endif + +#ifdef HAVE_MATH_H +#include +#else +#error need math.h +#endif + +#include "Util.h" +#include "Exception.h" +#include "JackDspSource.h" + + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * File identity + *----------------------------------------------------------------------------*/ +static const char fileid[] = "$Id$"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Initialize the object + *----------------------------------------------------------------------------*/ +void +JackDspSource :: init ( const char* name ) throw ( Exception ) +{ + // Set defaults + ports[0] = NULL; // Left Port + ports[1] = NULL; // Right Port + rb[0] = NULL; // Left Ring Buffer + rb[1] = NULL; // Right Ring Buffer + client = NULL; + auto_connect = false; // Default is to not auto connect the JACK ports + tmp_buffer = NULL; // Buffer big enough for one 'read' of audio + + // Auto connect the ports ? + if ( Util::strEq( name, "jack_auto", 9) ) { + auto_connect = true; + } + + // Check the sample size + if (getBitsPerSample() != 16) { + throw Exception( __FILE__, __LINE__, + "JackDspSource doesn't support non 16-bit samples"); + } +} + + + +/*------------------------------------------------------------------------------ + * De-initialize the object + *----------------------------------------------------------------------------*/ +void +JackDspSource :: strip ( void ) throw ( Exception ) +{ + if ( isOpen() ) { + close(); + } + + // Free the temporary buffer + if (tmp_buffer) { + free(tmp_buffer); + tmp_buffer = NULL; + } + +} + +/*------------------------------------------------------------------------------ + * Attempt to connect up the JACK ports automatically + * - Just connect left&right to the first two output ports we find + *----------------------------------------------------------------------------*/ +void +JackDspSource :: do_auto_connect ( void ) throw ( Exception ) +{ + const char **all_ports; + unsigned int ch = 0; + int i; + + Reporter::reportEvent( 10, "JackDspSource :: do_auto_connect"); + + // Get a list of all the jack ports + all_ports = jack_get_ports (client, NULL, NULL, JackPortIsOutput); + if (!ports) { + throw Exception( __FILE__, __LINE__, "jack_get_ports() returned NULL."); + } + + // Step through each port name + for (i = 0; all_ports[i]; ++i) { + + const char* in = all_ports[i]; + const char* out = jack_port_name( ports[ch] ); + + Reporter::reportEvent( 2, "Connecting", in, "to", out); + + if (jack_connect(client, in, out)) { + throw Exception( __FILE__, __LINE__, + "Failed to jack_connect() ports", in, out); + } + + // Found enough ports ? + if (++ch >= getChannel()) break; + } + + free( all_ports ); + +} + + +/*------------------------------------------------------------------------------ + * Open the audio source + *----------------------------------------------------------------------------*/ +bool +JackDspSource :: open ( void ) throw ( Exception ) +{ + char client_name[255]; + size_t rb_size; + unsigned int c; + + if ( isOpen() ) { + return false; + } + + // Register client with Jack + snprintf(client_name, 255, "darkice-%d", getpid()); + if ((client = jack_client_new(client_name)) == NULL) { + throw Exception( __FILE__, __LINE__, "JACK server not running?"); + } + Reporter::reportEvent( 1, "Registering as JACK client", client_name); + + + // Check the sample rate is correct + if (jack_get_sample_rate( client ) != (jack_nframes_t)getSampleRate()) { + throw Exception( __FILE__, __LINE__, + "JACK server sample rate is different than " + "sample rate in darkice config file"); + } + + + // Register ports with Jack + if (getChannel() == 1) { + if (!(ports[0] = jack_port_register(client, + "mono", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0))) { + throw Exception( __FILE__, __LINE__, + "Cannot register input port", "mono"); + } + } else if (getChannel() == 2) { + if (!(ports[0] = jack_port_register(client, + "left", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, + 0))) { + throw Exception( __FILE__, __LINE__, + "Cannot register input port", "left"); + } + if (!(ports[1] = jack_port_register(client, + "right", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, 0))) { + throw Exception( __FILE__, __LINE__, + "Cannot register input port", "right"); + } + } else { + throw Exception( __FILE__, __LINE__, + "Invalid number of channels", getChannel()); + } + + + // Create a ring buffer for each channel + rb_size = 2 + * jack_get_sample_rate(client) + * sizeof (jack_default_audio_sample_t); + for (c=0; c SHRT_MAX) { + output[n*getChannel()+c] = SHRT_MAX; + } else if (tmp < SHRT_MIN) { + output[n*getChannel()+c] = SHRT_MIN; + } else { + output[n*getChannel()+c] = (short) tmp; + } + } + } + + // Didn't get as many samples as we wanted ? + if (getChannel() == 2 && samples_read[0] != samples_read[1]) { + Reporter::reportEvent( 2, + "Warning: Read a different number of samples " + "for left and right channels"); + } + + // Return the number of bytes put in the output buffer + return samples_read[0] * 2 * getChannel(); +} + + +/*------------------------------------------------------------------------------ + * Close the audio source + *----------------------------------------------------------------------------*/ +void +JackDspSource :: close ( void ) throw ( Exception ) +{ + unsigned int i; + + if ( !isOpen() ) { + return; + } + + for(i = 0; i < getChannel(); i++) { + // Close the port for channel + if ( ports[i] ) { + jack_port_unregister( client, ports[i] ); + ports[i] = NULL; + } + + // Free up the ring buffer for channel + if ( rb[i] ) { + jack_ringbuffer_free( rb[i] ); + rb[i] = NULL; + } + } + + /* Leave the jack graph */ + if (client) { + jack_client_close(client); + client = NULL; + } + +} + + +/*------------------------------------------------------------------------------ + * Callback called by JACK when audio is available + * + * Don't do anything too expensive here + * - just shove audio samples in ring buffer + *----------------------------------------------------------------------------*/ +int +JackDspSource :: process_callback( jack_nframes_t nframes, void *arg ) +{ + JackDspSource* self = (JackDspSource*)arg; + size_t to_write = sizeof (jack_default_audio_sample_t) * nframes; + unsigned int c; + + // Wait until it is ready + if (self->client == NULL) { + return 0; + } + + /* copy data to ringbuffer; one per channel */ + for (c=0; c < self->getChannel(); c++) { + char *buf = (char*)jack_port_get_buffer(self->ports[c], nframes); + size_t len = jack_ringbuffer_write(self->rb[c], buf, to_write); + if (len < to_write) { + Reporter::reportEvent( 1, "failed to write to ring ruffer"); + return 1; + } + } + + // Success + return 0; +} + +/*------------------------------------------------------------------------------ + * Callback called when + *----------------------------------------------------------------------------*/ +void +JackDspSource :: shutdown_callback( void *arg ) +{ + //JackDspSource* self = (JackDspSource*)arg; + + Reporter::reportEvent( 1, "JackDspSource :: shutdown_callback"); +} + + +#endif // SUPPORT_JACK_DSP + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2005/04/04 08:36:17 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + + +------------------------------------------------------------------------------*/ + diff --git a/darkice/trunk/src/JackDspSource.h b/darkice/trunk/src/JackDspSource.h new file mode 100644 index 0000000..fb687fe --- /dev/null +++ b/darkice/trunk/src/JackDspSource.h @@ -0,0 +1,289 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2005 Nicholas Humfrey. All rights reserved. + + Tyrell DarkIce + + File : JackDspSource.h + Version : $Revision$ + Author : $Author$ + Location : $Source$ + + Copyright notice: + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +------------------------------------------------------------------------------*/ +#ifndef JACK_DSP_SOURCE_H +#define JACK_DSP_SOURCE_H + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + + +#include "Reporter.h" +#include "AudioSource.h" + +#if defined( HAVE_JACK_LIB ) +#include +#include +#else +#error configure for JACK +#endif + + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An audio input based on JACK + * + * @author $Author$ + * @version $Revision$ + */ +class JackDspSource : public AudioSource, public virtual Reporter +{ + private: + + /** + * The jack port + */ + jack_port_t * ports[2]; + + /** + * The jack ring buffer. + */ + jack_ringbuffer_t * rb[2]; + + /** + * The jack client. + */ + jack_client_t * client; + + /** + * The jack audio sample buffer. + */ + jack_default_audio_sample_t * tmp_buffer; + + /** + * Automatically connect the jack ports ? (default is to not) + */ + bool auto_connect; + + protected: + + /** + * Default constructor. Always throws an Exception. + * + * @exception Exception + */ + inline + JackDspSource ( void ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__); + } + + /** + * Initialize the object + * + * @exception Exception + */ + void + init ( const char* name ) throw ( Exception ); + + /** + * De-initialize the object + * + * @exception Exception + */ + void + strip ( void ) throw ( Exception ); + + + /** + * Attempt to connect up the JACK ports automatically + */ + void + do_auto_connect( ) throw ( Exception ); + + /** + * Callback called by JACK when audio is available + */ + static int + process_callback( jack_nframes_t nframes, void *arg ); + + + /** + * Callback called by JACK when jackd is shutting down + */ + static void + shutdown_callback( void *arg ); + + public: + + /** + * Constructor. + * + * @param name the name of the jack device + * @param sampleRate samples per second (e.g. 44100 for 44.1kHz). + * @param bitsPerSample bits per sample (e.g. 16 bits). + * @param channels number of channels of the audio source + * (e.g. 1 for mono, 2 for stereo, etc.). + * @exception Exception + */ + inline + JackDspSource ( const char * name, + int sampleRate = 44100, + int bitsPerSample = 16, + int channels = 2 ) + throw ( Exception ) + + : AudioSource( sampleRate, bitsPerSample, channels ) + { + init( name ); + } + + /** + * Copy Constructor. + * + * @param source the object to copy. + * @exception Exception + */ + inline + JackDspSource ( const JackDspSource & ds ) throw ( Exception ) + : AudioSource( ds ) + { + throw Exception( __FILE__, __LINE__, "JackDspSource doesn't copy"); + } + + /** + * Destructor. + * + * @exception Exception + */ + inline virtual + ~JackDspSource ( void ) throw ( Exception ) + { + strip(); + } + + /** + * Assignment operator. + * + * @param ds the object to assign to this one. + * @return a reference to this object. + * @exception Exception + */ + inline virtual JackDspSource & + operator= ( const JackDspSource & ds ) throw ( Exception ) + { + throw Exception( __FILE__, __LINE__, "JackDspSource doesn't assign"); + } + + /** + * Open the JackDspSource. + * This does not put the Jack DSP device into recording mode. + * To start getting samples, call either canRead() or read(). + * + * @return true if opening was successful, false otherwise + * @exception Exception + * + * @see #canRead + * @see #read + */ + virtual bool + open ( void ) throw ( Exception ); + + /** + * Check if the JackDspSource is registered + * + * @return true if Jack client is setup + */ + inline virtual bool + isOpen ( void ) const throw () + { + return client != NULL; + } + + /** + * Check if the JackDspSource can be read from. + * Blocks until the specified time for data to be available. + * Puts the Jack DSP device into recording mode. + * + * @param sec the maximum seconds to block. + * @param usec micro seconds to block after the full seconds. + * @return true if the JackDspSource is ready to be read from, + * false otherwise. + * @exception Exception + */ + virtual bool + canRead ( unsigned int sec, + unsigned int usec ) throw ( Exception ); + + /** + * Read from the JackDspSource. + * Puts the Jack DSP device into recording mode. + * + * @param buf the buffer to read into. + * @param len the number of bytes to read into buf + * @return the number of bytes read (may be less than len). + * @exception Exception + */ + virtual unsigned int + read ( void * buf, + unsigned int len ) throw ( Exception ); + + /** + * Close the JackDspSource. + * + * @exception Exception + */ + virtual void + close ( void ) throw ( Exception ); + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + + +#endif /* JACK_DSP_SOURCE_H */ + + +/*------------------------------------------------------------------------------ + + $Source$ + + $Log$ + Revision 1.1 2005/04/04 08:36:17 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + + +------------------------------------------------------------------------------*/ + diff --git a/darkice/trunk/src/Makefile.am b/darkice/trunk/src/Makefile.am index 3add294..f3bb7bd 100644 --- a/darkice/trunk/src/Makefile.am +++ b/darkice/trunk/src/Makefile.am @@ -1,7 +1,7 @@ bin_PROGRAMS = darkice -CXXFLAGS = -O2 -pedantic -Wall @DEBUG_CXXFLAGS@ @PTHREAD_CFLAGS@ +AM_CXXFLAGS = -O2 -pedantic -Wall @DEBUG_CXXFLAGS@ @PTHREAD_CFLAGS@ @JACK_CFLAGS@ INCLUDES = @LAME_INCFLAGS@ @VORBIS_INCFLAGS@ @ALSA_INCFLAGS@ -LDADD = @PTHREAD_LIBS@ @LAME_LDFLAGS@ @VORBIS_LDFLAGS@ @ALSA_LDFLAGS@ +LDADD = @PTHREAD_LIBS@ @LAME_LDFLAGS@ @VORBIS_LDFLAGS@ @ALSA_LDFLAGS@ @JACK_LIBS@ darkice_SOURCES = AudioEncoder.h\ AudioSource.h\ @@ -52,11 +52,13 @@ darkice_SOURCES = AudioEncoder.h\ Util.h\ ConfigSection.h\ ConfigSection.cpp\ - Config.h\ - Config.cpp\ + DarkIceConfig.h\ + DarkIceConfig.cpp\ Reporter.h\ Reporter.cpp\ AlsaDspSource.h\ AlsaDspSource.cpp\ + JackDspSource.h\ + JackDspSource.cpp\ main.cpp diff --git a/darkice/trunk/src/Reporter.h b/darkice/trunk/src/Reporter.h index 4384568..e9cbf97 100644 --- a/darkice/trunk/src/Reporter.h +++ b/darkice/trunk/src/Reporter.h @@ -43,7 +43,7 @@ #ifdef HAVE_UNISTD_H #include #else -#error need unistdt.h +#error need unistd.h #endif #ifdef HAVE_TIME_H @@ -309,6 +309,10 @@ class Reporter $Source$ $Log$ + Revision 1.9 2005/04/04 08:36:17 darkeye + commited changes to enable Jack support + thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk + Revision 1.8 2005/04/03 05:14:07 jbebel Changed timestamp on reported events to include date in addition to time. diff --git a/darkice/trunk/src/aflibConverter.cc b/darkice/trunk/src/aflibConverter.cc index 27ca8e4..99bdffe 100644 --- a/darkice/trunk/src/aflibConverter.cc +++ b/darkice/trunk/src/aflibConverter.cc @@ -123,8 +123,8 @@ aflibConverter::aflibConverter( largeFilter = high_quality; linearInterp = linear_interpolation; - _I = NULL; - _J = NULL; + _II = NULL; + _JJ = NULL; _vol = 1.0; } @@ -140,19 +140,19 @@ aflibConverter::deleteMemory() int i; // Delete memory for the input and output arrays - if (_I != NULL) + if (_II != NULL) { for (i = 0; i < _nChans; i++) { - delete [] _I[i]; - _I[i] = NULL; - delete [] _J[i]; - _J[i] = NULL; + delete [] _II[i]; + _II[i] = NULL; + delete [] _JJ[i]; + _JJ[i] = NULL; } - delete [] _I; - _I = NULL; - delete [] _J; - _J = NULL; + delete [] _II; + _II = NULL; + delete [] _JJ; + _JJ = NULL; } } @@ -180,15 +180,15 @@ aflibConverter::initialize( _vol = volume; // Allocate all new memory - _I = new short * [_nChans]; - _J = new short * [_nChans]; + _II = new short * [_nChans]; + _JJ = new short * [_nChans]; for (i = 0; i < _nChans; i++) { // Add extra to allow of offset of input data (Xoff in main routine) - _I[i] = new short[IBUFFSIZE + 256]; - _J[i] = new short[(int)(((double)IBUFFSIZE)*_factor)]; - memset(_I[i], 0, sizeof(short) * (IBUFFSIZE + 256)); + _II[i] = new short[IBUFFSIZE + 256]; + _JJ[i] = new short[(int)(((double)IBUFFSIZE)*_factor)]; + memset(_II[i], 0, sizeof(short) * (IBUFFSIZE + 256)); } } @@ -467,7 +467,7 @@ aflibConverter::resampleFast( /* number of output samples returned */ do { if (!last) /* If haven't read last sample yet */ { - last = readData(inCount, inArray, _I, + last = readData(inCount, inArray, _II, IBUFFSIZE, (int)Xread,first_pass); first_pass = FALSE; if (last && (last-Xoff= 1) { /* SrcUp() is faster if we can use it */ - Nout=SrcUp(_I[c],_J[c],_factor, + Nout=SrcUp(_II[c],_JJ[c],_factor, &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); } else { - Nout=SrcUD(_I[c],_J[c],_factor, + Nout=SrcUD(_II[c],_JJ[c],_factor, &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); } } @@ -642,7 +642,7 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */ { for (i = 0; i < Nout; i++) { - outArray[c * outCount + i + Ycount - Nout] = _J[c][i]; + outArray[c * outCount + i + Ycount - Nout] = _JJ[c][i]; } } @@ -651,7 +651,7 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */ for (c = 0; c < _nChans; c++) { for (i=0; i +#include "config.h" #endif #ifndef MAX @@ -222,8 +222,8 @@ static short LARGE_FILTER_IMP[]; bool interpFilt; bool largeFilter; bool linearInterp; -short ** _I; -short ** _J; +short ** _II; +short ** _JJ; unsigned int _Time; double _factor; int _nChans;