A library that allows for simple porting of general purposed bio(blocked io) OSS/ALSA audio applications to Jack.
The sourceforge project page can be found here.
Projects that are currently using bio2jack:
- xmms-jack - Jack audio output plugin for XMMS (This plugin was developed in parallel with this library)
- mplayer - Popular media player for linux
- veejay - Video
editing software with an impressive number of video effects
- MythTV - PVR system(like TiVo). I've got one of these in my living room actually, works GREAT
How to use bio2jack
News:
6/17/2006- Released bio2jack 0.9
- 0.9 released - bugs fixed, bio2jack latency greatly reduced
- Update copyright date to 2006
- Fix incorrect parameters to ensure_buffer_size() that was causing us to ensure the size of a buffer that we weren't using. This was causing a crash in bio2jack when used with the Freebob jack driver. Issue reported by Peter Galiovsky.
- Change ringbuffer size from 16384 to 4096 samples to reduce the latency in bio2jack.
- Move volume function from JACK_Write() to JACK_Callback() so volume adjustment occurs without the latency of the ringbuffer size.
- Factor out demux() calls by having non-sample conversion code use callback_buffer2 just like the resample library does for its output data. This way the output data for jack is always in the same buffer and we can keep the volume and demux code outside of the if(resample) else don't resample code branches and reduce duplicate code.
- Fix handling of 8bit samples in JACK_Write(). We were falling
through the 8bit case due to a lack of a 'break' and
treating 8bit samples as 16bit ones.
Patch by Sean Meiners < sean.meiners@linspireinc.com > - Fix sample_move_char_float() and sample_move_float_char() to treat
8bit samples as unsigned instead of signed.
Patch by Sean Meiners < sean.meiners@linspireinc.com > - Fix deadlock between JACK_callback() and jack_client_close()
that can occur when jack_client_close() has grabbed the driver mutex
and JACK_callback() is called. Add tryGetDriver() that uses
pthread_mutex_trylock(). Use tryGetDriver() in JACK_callback()
instead of getDriver().
Patch by Sean Meiners < sean.meiners@linspireinc.com >
11/7/2005
- Released bio2jack 0.8
- 0.8 released
- Major changes in this release
- Broke api compatibility by removing a handful of functions that don't appear necessary, email me if you have trouble with this change so we can work things out
- Add large patch by Sean Meiners at Linspire that adds support for recording and resampling using libresample
- Add JACK_SetPortConnectionMode() api call that enables users of bio2jack to decide how they want port connections to work. The options are CONNECT_ALL(default), CONNECT_OUTPUT that only connects the ports used for output even if alsa may have a dozen ports available, or CONNECT_NONE that doesn't connect any ports. The primary use of this api is for users that need to perform connections at run-time and don't want to have to disconnect ports each time their bio2jack app starts up.
- Fix a few minor bugs, see the ChangeLog for more details
3/23/2005
- Released bio2jack 0.7
- 0.7 released
- Minor updates to README and INSTALL
- Bump revisions up to 0.7 for release
- Removed unused JACK_SendMessage() code, this can be retrieved from cvs at a later time if we start using messages.
- Received a great patch from Sean Meiners at Linspire. They are pushing to jack enable the desktop, the reason I wrote bio2jack.
- -Adds the JACK_GetJackBufferSize function that allows bio2jack clients to find out how big JACK's buffer size is. This makes it possible for the client to calculate latency much more accurately. So far this is mostly useful in programs like Xine where if the timing is off by more than ~10ms it makes all movies look like badly dubbed Hong Kong action flicks.
- -Switches bio2jack to use the very nice ring-buffer provided by the JACK API to improve performance. The linked-list method is good if you want to *never* loose audio data, but the down-side is that there is no (technical) upper-limit to how much memory it will use. Using a ring-buffer that's sufficiently big places an absolute limit on how much memory will be used and also eliminates the need to malloc new memory every time JACK_Write is called, thereby reducing the amount of time spent there. There is a risk that the ring-buffer will fill up, but if that were to happen JACK_Write simply refuses and returns 0, letting the client know that we ran out of ring-buffer space and (usually) causing them to just slow down. What prompted this is that we saw a few (admittedly, badly-behaved) apps that will keep writing data until it refuses to take anymore. When using a simple linked-list they never stop and the whole process starts chewing up so much CPU time that the system becomes unusable.
- -Builds bio2jack as a versioned, shared library so clients don't have to be rebuilt every time a fix/improvement is made to the library.
3/13/2005
- Released bio2jack 0.6
- 0.6 Released
- Implement JACK_SetClientName() that will let users of bio2jack set the name that bio2jack uses when creating jack clients - Suggestion and concept patch by Dirk Jagdmann
- Ran aspell on bio2jack.c and bio2jack.h to fix spelling mistakes
- Fix compile errors when JACK_CLOSE_HACK is disabled
- extern "C" patch to fix compiling with c++ code - Patch by Dirk Jagdmann
- Fix long standing bug where if no ports exist bio2jack will crash. - Patch by Ed Wildgoose
- Install bio2jack-configure to the local binary directory via bin_SCRIPTS automake directive - Bug reported by Pierre Delagrave
- Call gettimeofday() at the start of the jack callback routine rather than at two places in two branches of the callback. This apparently reduces jitter. - Patch by Ed Wildgoose
1/30/2005
- Released bio2jack 0.5
- Install bio2jack.h to $includedir during 'make install'
11/13/2004
- Released bio2jack 0.4
- Made JACK_GetBytesStored() return the real-time bytes stored using JACK_GetPositionFromDriver(). This way JACK_GetBytesStored() gives a smoother return value over time.
- JACK_Write() should early out if the user tells us to write
0 bytes. (Found by Ed Wildgoose) - JACK_GetJackLatency() should use jack_port_get_total_latency() instead of jack_port_get_latency() because we want to know the amount of latency from the output port until we've actually output the data to a physical device.
- JACK_GetBytesStoredFromDriver() should use JACK_GetPositionFromDriver() for the drv->played_client_bytes value so we get a more accurate real-time update of the bytes stored.
- Compiled bio2jack under C++ and decided to change 'this' to 'drv'. This makes more sense considering that jack_driver_t is the structure and it doesn't namespace conflict with the c++ 'this' keyword.
- Added a few casts to silence warnings
- Changed a few 'char*' to 'unsigned char*'
- Added support for 0 input channels.
- Fixed a few comparisons between 'unsigned int' and 'int'
- JACK_OpenEx() 'char **jack_port_name' can be 'const char **' because we never modify the port names
- Added #ifndef __cplusplus wrapper around the #define for bool. C++ has its own boolean type.
- JACK_Write() should take an unsigned char* instead of a char*.
9/12/2004
- Released bio2jack 0.3
- Bumped revision in configure.in and bio2jack-config up to 0.3
- JACK_Write() was missing a releaseDriver(this); in the out of space path so we were returning without unlocking the driver. This would no doubt cause a deadlock. Thanks to Ed Wildgoose for reporting this.
- Fix 3 signed/unsigned conversions. I'm not seeing these here using gcc 3.3.4 so I'll take Ed's word on this.
- Apply volume to the audio data after it has been converted into floating point values. This should improve the output quality by a minor amount as we will preserve more of the original data prior to the conversion to float. Float is of higher precision so we keep more information after applying the volume effect to it. Also suggested by Ed ;-)
- Add the ability to have the volume be either 'linear' or 'dbAttenuation'. JACK_SetVolumeEffectType() controls this setting, bio2jack defaults to 'linear' If you set dbAttenuation then the volume level is the number of dBs of attenuation to apply, 0 being 0dB or full volume.
- Fix a couple of warnings for unused values that were only used for tracing. Wrapped them in the TRACE_ENABLE conditional so they are only compiled in when we are tracing.
- Added checks in configure.in so if we don't find jack/jack.h or
if we don't find jack_activate in -ljack then we should report these
errors to the user and exit out of the configure script. Thanks
to Jim Snyder for reporting this issue.
- Released bio2jack 0.2, available here
- Bumped revision in configure.in up to 0.2
- Added bio2jack-config to allow configure scripts to retrieve information about bio2jack
- Modified Makefile.am to build bio2jack's library the same way
that xmms-jack builds its.
- Make bio2jack threadsafe(mostly). We now lock the jack_driver_t structure when functions enter. There are two sets of functions, the ones that expect things to be locked have "FromThis" at the end, the rest are the external api calls to the interface functions.
- Reconnect to jack if we lose our connection. We try at most every 250ms and inside of getDriver() which is called to lock the mutex before we can use the jack_driver_t structure. Added at the request of Paul Davis, a principle author of Jack and Ardour
- Ansi C fix by Michael Johnson
- Fix bug in JACK_GetPosition() where the position was advancing
even if we were paused
- JACK_callback() changes so everything is in terms of frames, simplifies the code a bit
- JACK_Open() now takes a pointer to a rate to try and if there is a mismatch between the requested and server rates sets this value to the server rate
- Added JACK_SetNumChannels() to support stereo/mono, rough
implementation thus far
12/27/3003
- Add a handful of error defines to bio2jack.h for JACK_Open()
- JACK_Callback() shouldn't print ERR when we have underruns because
- this is actually a pretty normal thing to do at the very end of
playing.
12/15/2003
- Added pid to the client name to prevent name collisions with
multiple bio2jack's running, patch from Kasper Souren
- Fixed JACK_SetPosition(), we only modify position_byte_offset now, and not other internal values like played_bytes and bytes_in_jack. This fixes a bug where JACK_GetBytesStore() was returning negative values, something that really should be impossible.
- Initialize this->previousTime in JACK_Init() from the current time
- JACK_GetBytesStored() should display error if returned time is going to be negative
- TRACE() should be conditional, ERR() should be unconditional so we always have error printing enabled
- JACK_Callback() now performs the flushing of any buffered data, this avoids zeroing pointers in JACK_Reset() that the callback routine could be using.
- Added a CMD_SET_POSITION command message as the first fix for
JACK_SetPosition(). This turned out to be a poor choice as the user
could call JACK_SetPosition() then immediately start sending new data
to be played. The set position command would be processed from
the callback at a later time but this is simply more complex than it
has to be. Simplified JACK_SetPosition() so this is all
unnecessary.
11/24/2003
- Committed latest changes to cvs
- Fixed a couple of outstanding issues with the xmms-jack driver
- Compatible with jack 0.90.0
10/26/2003 - Picked bio2jack up after letting in languish for far too long. Tons of fixes:
- Removed all mutexes, prevents any odd cases where the callback can possibly be blocked
- Fixed several bugs
- Made various small changes that make bio2jack compatible with the
latest release of Jack
1/1/2003 - CVS archive is setup.
12/31/2002 - Initial version of this webpage. Just got the sourceforge.net project page online. Code is almost in a presentable state ;-)
How to convert your player to output in jack using bio2jack
To convert your player you'll need to find the equivalent of these functions in whatever output system you are using.JACK_Init() - Must be called before any other interface function
JACK_Open()
JACK_Close()
JACK_Write()
JACK_GetPosition()
For most general purpose audio applications it is a straightforward approach to map the required functions to the library. The library takes care of buffering the written data and handling the jack callbacks.
To map OSS to bio2jack you'll want to find and replace these functions:
OSS call | bio2jack call |
fd = open(oss_device_name, O_RDONLY, 0) | JACK_Open(&deviceID,...) |
close(fd) | JACK_Close(deviceID) |
write(fd, buf, byteLength) | JACK_Write(deviceID, buf, byteLength) |
ioctl(fd, SNDCTL_DSP_GETISPACE, &tmp_info) | JACK_GetPosition(deviceID, MILLISECONDS, WRITTEN) |
Written by Chris Morgan<cmorgan@alum.wpi.edu>