|  | diff --git a/RtAudio.cpp b/RtAudio.cpp
index 2ac2179..5fce9b2 100644
--- a/RtAudio.cpp
+++ b/RtAudio.cpp
@@ -76,7 +76,7 @@ const unsigned int RtApi::SAMPLE_RATES[] = {
     return s;
   }
 
-#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
+#elif defined(__LINUX_ALSA__) || defined(__UNIX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) || defined(__HAIKU__)
   // pthread API
   #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
   #define MUTEX_DESTROY(A)    pthread_mutex_destroy(A)
@@ -110,8 +110,8 @@ void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis )
 #if defined(__LINUX_ALSA__)
   apis.push_back( LINUX_ALSA );
 #endif
-#if defined(__LINUX_PULSE__)
-  apis.push_back( LINUX_PULSE );
+#if defined(__UNIX_PULSE__)
+  apis.push_back( UNIX_PULSE );
 #endif
 #if defined(__LINUX_OSS__)
   apis.push_back( LINUX_OSS );
@@ -147,8 +147,8 @@ void RtAudio :: openRtApi( RtAudio::Api api )
   if ( api == LINUX_ALSA )
     rtapi_ = new RtApiAlsa();
 #endif
-#if defined(__LINUX_PULSE__)
-  if ( api == LINUX_PULSE )
+#if defined(__UNIX_PULSE__)
+  if ( api == UNIX_PULSE )
     rtapi_ = new RtApiPulse();
 #endif
 #if defined(__LINUX_OSS__)
@@ -222,11 +222,12 @@ void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,
                             unsigned int *bufferFrames,
                             RtAudioCallback callback, void *userData,
                             RtAudio::StreamOptions *options,
+                            RtAudioBufferSizeCallback bufSizeCallback,
                             RtAudioErrorCallback errorCallback )
 {
   return rtapi_->openStream( outputParameters, inputParameters, format,
                              sampleRate, bufferFrames, callback,
-                             userData, options, errorCallback );
+                             userData, options, bufSizeCallback, errorCallback );
 }
 
 // *************************************************** //
@@ -259,6 +260,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
                           unsigned int *bufferFrames,
                           RtAudioCallback callback, void *userData,
                           RtAudio::StreamOptions *options,
+                          RtAudioBufferSizeCallback bufSizeCallback,
                           RtAudioErrorCallback errorCallback )
 {
   if ( stream_.state != STREAM_CLOSED ) {
@@ -282,7 +284,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
     return;
   }
 
-  if ( oParams == NULL && iParams == NULL ) {
+  if ( oParams == NULL && iParams == NULL && getCurrentApi() != RtAudio::RTAUDIO_DUMMY ) {
     errorText_ = "RtApi::openStream: input and output StreamParameters structures are both NULL!";
     error( RtAudioError::INVALID_USE );
     return;
@@ -340,6 +342,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
 
   stream_.callbackInfo.callback = (void *) callback;
   stream_.callbackInfo.userData = userData;
+  stream_.callbackInfo.bufSizeCallback = (void *) bufSizeCallback;
   stream_.callbackInfo.errorCallback = (void *) errorCallback;
 
   if ( options ) options->numberOfBuffers = stream_.nBuffers;
@@ -1587,6 +1590,8 @@ static void *coreStopStream( void *ptr )
 
   object->stopStream();
   pthread_exit( NULL );
+
+  return NULL;
 }
 
 bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
@@ -1925,7 +1930,7 @@ const char* RtApiCore :: getErrorCode( OSStatus code )
 // devices are available (i.e., the JACK server is not running), a
 // stream cannot be opened.
 
-#include <jack/jack.h>
+#include "jackbridge/JackBridge.hpp"
 #include <unistd.h>
 #include <cstdio>
 
@@ -1934,7 +1939,6 @@ const char* RtApiCore :: getErrorCode( OSStatus code )
 struct JackHandle {
   jack_client_t *client;
   jack_port_t **ports[2];
-  std::string deviceName[2];
   bool xrun[2];
   pthread_cond_t condition;
   int drainCounter;       // Tracks callback counts when draining
@@ -1944,17 +1948,9 @@ struct JackHandle {
     :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; }
 };
 
-#if !defined(__RTAUDIO_DEBUG__)
-static void jackSilentError( const char * ) {};
-#endif
-
 RtApiJack :: RtApiJack()
     :shouldAutoconnect_(true) {
   // Nothing to do here.
-#if !defined(__RTAUDIO_DEBUG__)
-  // Turn off Jack's internal error reporting.
-  jack_set_error_function( &jackSilentError );
-#endif
 }
 
 RtApiJack :: ~RtApiJack()
@@ -1964,128 +1960,40 @@ RtApiJack :: ~RtApiJack()
 
 unsigned int RtApiJack :: getDeviceCount( void )
 {
-  // See if we can become a jack client.
-  jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption;
-  jack_status_t *status = NULL;
-  jack_client_t *client = jack_client_open( "RtApiJackCount", options, status );
-  if ( client == 0 ) return 0;
-
-  const char **ports;
-  std::string port, previousPort;
-  unsigned int nChannels = 0, nDevices = 0;
-  ports = jack_get_ports( client, NULL, NULL, 0 );
-  if ( ports ) {
-    // Parse the port names up to the first colon (:).
-    size_t iColon = 0;
-    do {
-      port = (char *) ports[ nChannels ];
-      iColon = port.find(":");
-      if ( iColon != std::string::npos ) {
-        port = port.substr( 0, iColon + 1 );
-        if ( port != previousPort ) {
-          nDevices++;
-          previousPort = port;
-        }
-      }
-    } while ( ports[++nChannels] );
-    free( ports );
-  }
-
-  jack_client_close( client );
-  return nDevices;
+  return 2;
 }
 
 RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
 {
-  RtAudio::DeviceInfo info;
-  info.probed = false;
+  static RtAudio::DeviceInfo devInfo[3];
 
-  jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption
-  jack_status_t *status = NULL;
-  jack_client_t *client = jack_client_open( "RtApiJackInfo", options, status );
-  if ( client == 0 ) {
-    errorText_ = "RtApiJack::getDeviceInfo: Jack server not found or connection error!";
-    error( RtAudioError::WARNING );
-    return info;
-  }
-
-  const char **ports;
-  std::string port, previousPort;
-  unsigned int nPorts = 0, nDevices = 0;
-  ports = jack_get_ports( client, NULL, NULL, 0 );
-  if ( ports ) {
-    // Parse the port names up to the first colon (:).
-    size_t iColon = 0;
-    do {
-      port = (char *) ports[ nPorts ];
-      iColon = port.find(":");
-      if ( iColon != std::string::npos ) {
-        port = port.substr( 0, iColon );
-        if ( port != previousPort ) {
-          if ( nDevices == device ) info.name = port;
-          nDevices++;
-          previousPort = port;
-        }
-      }
-    } while ( ports[++nPorts] );
-    free( ports );
-  }
-
-  if ( device >= nDevices ) {
-    jack_client_close( client );
-    errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!";
-    error( RtAudioError::INVALID_USE );
-    return info;
-  }
-
-  // Get the current jack server sample rate.
-  info.sampleRates.clear();
-
-  info.preferredSampleRate = jack_get_sample_rate( client );
-  info.sampleRates.push_back( info.preferredSampleRate );
-
-  // Count the available ports containing the client name as device
-  // channels.  Jack "input ports" equal RtAudio output channels.
-  unsigned int nChannels = 0;
-  ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsInput );
-  if ( ports ) {
-    while ( ports[ nChannels ] ) nChannels++;
-    free( ports );
-    info.outputChannels = nChannels;
-  }
-
-  // Jack "output ports" equal RtAudio input channels.
-  nChannels = 0;
-  ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsOutput );
-  if ( ports ) {
-    while ( ports[ nChannels ] ) nChannels++;
-    free( ports );
-    info.inputChannels = nChannels;
+  if (! devInfo[0].probed)
+  {
+      devInfo[0].probed          = devInfo[1].probed          = true;
+      devInfo[0].outputChannels  = devInfo[1].outputChannels  = 2;
+      devInfo[0].inputChannels   = devInfo[1].inputChannels   = 2;
+      devInfo[0].duplexChannels  = devInfo[1].duplexChannels  = 2;
+      devInfo[0].isDefaultOutput = devInfo[1].isDefaultOutput = true;
+      devInfo[0].isDefaultInput  = devInfo[1].isDefaultInput  = true;
+      devInfo[0].nativeFormats   = devInfo[1].nativeFormats   = RTAUDIO_FLOAT32;
+      devInfo[0].name = "Auto-connect ON";
+      devInfo[1].name = "Auto-connect OFF";
   }
 
-  if ( info.outputChannels == 0 && info.inputChannels == 0 ) {
-    jack_client_close(client);
-    errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!";
-    error( RtAudioError::WARNING );
-    return info;
-  }
+  if (device > 2)
+      device = 2;
 
-  // If device opens for both playback and capture, we determine the channels.
-  if ( info.outputChannels > 0 && info.inputChannels > 0 )
-    info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
+  return devInfo[device];
+}
 
-  // Jack always uses 32-bit floats.
-  info.nativeFormats = RTAUDIO_FLOAT32;
+static int jackBufferSizeHandler( jack_nframes_t nframes, void *infoPointer )
+{
+  CallbackInfo *info = (CallbackInfo *) infoPointer;
 
-  // Jack doesn't provide default devices so we'll use the first available one.
-  if ( device == 0 && info.outputChannels > 0 )
-    info.isDefaultOutput = true;
-  if ( device == 0 && info.inputChannels > 0 )
-    info.isDefaultInput = true;
+  RtApiJack *object = (RtApiJack *) info->object;
+  if ( object->bufferSizeEvent( (unsigned long) nframes ) == false ) return 1;
 
-  jack_client_close(client);
-  info.probed = true;
-  return info;
+  return 0;
 }
 
 static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )
@@ -2101,7 +2009,7 @@ static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )
 // This function will be called by a spawned thread when the Jack
 // server signals that it is shutting down.  It is necessary to handle
 // it this way because the jackShutdown() function must return before
-// the jack_deactivate() function (in closeStream()) will return.
+// the jackbridge_deactivate() function (in closeStream()) will return.
 static void *jackCloseStream( void *ptr )
 {
   CallbackInfo *info = (CallbackInfo *) ptr;
@@ -2110,6 +2018,8 @@ static void *jackCloseStream( void *ptr )
   object->closeStream();
 
   pthread_exit( NULL );
+
+  return NULL;
 }
 static void jackShutdown( void *infoPointer )
 {
@@ -2139,7 +2049,7 @@ static int jackXrun( void *infoPointer )
 }
 
 bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
-                                   unsigned int firstChannel, unsigned int sampleRate,
+                                   unsigned int firstChannel, unsigned int,
                                    RtAudioFormat format, unsigned int *bufferSize,
                                    RtAudio::StreamOptions *options )
 {
@@ -2151,9 +2061,9 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     jack_options_t jackoptions = (jack_options_t) ( JackNoStartServer ); //JackNullOption;
     jack_status_t *status = NULL;
     if ( options && !options->streamName.empty() )
-      client = jack_client_open( options->streamName.c_str(), jackoptions, status );
+      client = jackbridge_client_open( options->streamName.c_str(), jackoptions, status );
     else
-      client = jack_client_open( "RtApiJack", jackoptions, status );
+      client = jackbridge_client_open( "Carla", jackoptions, status );
     if ( client == 0 ) {
       errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!";
       error( RtAudioError::WARNING );
@@ -2165,75 +2075,24 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     client = handle->client;
   }
 
-  const char **ports;
-  std::string port, previousPort, deviceName;
-  unsigned int nPorts = 0, nDevices = 0;
-  ports = jack_get_ports( client, NULL, NULL, 0 );
-  if ( ports ) {
-    // Parse the port names up to the first colon (:).
-    size_t iColon = 0;
-    do {
-      port = (char *) ports[ nPorts ];
-      iColon = port.find(":");
-      if ( iColon != std::string::npos ) {
-        port = port.substr( 0, iColon );
-        if ( port != previousPort ) {
-          if ( nDevices == device ) deviceName = port;
-          nDevices++;
-          previousPort = port;
-        }
-      }
-    } while ( ports[++nPorts] );
-    free( ports );
-  }
-
-  if ( device >= nDevices ) {
-    errorText_ = "RtApiJack::probeDeviceOpen: device ID is invalid!";
-    return FAILURE;
-  }
-
-  // Count the available ports containing the client name as device
-  // channels.  Jack "input ports" equal RtAudio output channels.
-  unsigned int nChannels = 0;
-  unsigned long flag = JackPortIsInput;
-  if ( mode == INPUT ) flag = JackPortIsOutput;
-  ports = jack_get_ports( client, deviceName.c_str(), NULL, flag );
-  if ( ports ) {
-    while ( ports[ nChannels ] ) nChannels++;
-    free( ports );
-  }
-
-  // Compare the jack ports for specified client to the requested number of channels.
-  if ( nChannels < (channels + firstChannel) ) {
-    errorStream_ << "RtApiJack::probeDeviceOpen: requested number of channels (" << channels << ") + offset (" << firstChannel << ") not found for specified device (" << device << ":" << deviceName << ").";
-    errorText_ = errorStream_.str();
-    return FAILURE;
-  }
-
   // Check the jack server sample rate.
-  unsigned int jackRate = jack_get_sample_rate( client );
-  if ( sampleRate != jackRate ) {
-    jack_client_close( client );
-    errorStream_ << "RtApiJack::probeDeviceOpen: the requested sample rate (" << sampleRate << ") is different than the JACK server rate (" << jackRate << ").";
-    errorText_ = errorStream_.str();
-    return FAILURE;
-  }
-  stream_.sampleRate = jackRate;
+  stream_.sampleRate = jackbridge_get_sample_rate( client );
 
   // Get the latency of the JACK port.
-  ports = jack_get_ports( client, deviceName.c_str(), NULL, flag );
+  const char **ports;
+  ports = jackbridge_get_ports( client, "system:", NULL, JackPortIsInput );
   if ( ports[ firstChannel ] ) {
     // Added by Ge Wang
     jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency);
     // the range (usually the min and max are equal)
     jack_latency_range_t latrange; latrange.min = latrange.max = 0;
     // get the latency range
-    jack_port_get_latency_range( jack_port_by_name( client, ports[firstChannel] ), cbmode, &latrange );
+    jackbridge_port_get_latency_range( jackbridge_port_by_name( client, ports[firstChannel] ), cbmode, &latrange );
     // be optimistic, use the min!
     stream_.latency[mode] = latrange.min;
-    //stream_.latency[mode] = jack_port_get_latency( jack_port_by_name( client, ports[ firstChannel ] ) );
+    //stream_.latency[mode] = jack_port_get_latency( jackbridge_port_by_name( client, ports[ firstChannel ] ) );
   }
-  free( ports );
+  jackbridge_free( ports );
 
   // The jack server always uses 32-bit floating-point data.
   stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
@@ -2250,7 +2109,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
 
   // Get the buffer size.  The buffer size and number of buffers
   // (periods) is set when the jack server is started.
-  stream_.bufferSize = (int) jack_get_buffer_size( client );
+  stream_.bufferSize = (int) jackbridge_get_buffer_size( client );
   *bufferSize = stream_.bufferSize;
 
   stream_.nDeviceChannels[mode] = channels;
@@ -2281,11 +2140,10 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     stream_.apiHandle = (void *) handle;
     handle->client = client;
   }
-  handle->deviceName[mode] = deviceName;
 
   // Allocate necessary internal buffers.
   unsigned long bufferBytes;
-  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
+  bufferBytes = stream_.nUserChannels[mode] * 8192 * formatBytes( stream_.userFormat );
   stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
   if ( stream_.userBuffer[mode] == NULL ) {
     errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory.";
@@ -2306,7 +2164,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     }
 
     if ( makeBuffer ) {
-      bufferBytes *= *bufferSize;
+      bufferBytes *= 8192;
       if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
       stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
       if ( stream_.deviceBuffer == NULL ) {
@@ -2333,28 +2191,34 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     stream_.mode = DUPLEX;
   else {
     stream_.mode = mode;
-    jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo );
-    jack_set_xrun_callback( handle->client, jackXrun, (void *) &stream_.apiHandle );
-    jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo );
+    jackbridge_set_buffer_size_callback( handle->client, jackBufferSizeHandler, (void *) &stream_.callbackInfo );
+    jackbridge_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo );
+    jackbridge_set_xrun_callback( handle->client, jackXrun, (void *) &stream_.apiHandle );
+    jackbridge_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo );
   }
 
   // Register our ports.
   char label[64];
   if ( mode == OUTPUT ) {
     for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
-      snprintf( label, 64, "outport %d", i );
-      handle->ports[0][i] = jack_port_register( handle->client, (const char *)label,
+      snprintf( label, 64, "audio-out%d", i+1 );
+      handle->ports[0][i] = jackbridge_port_register( handle->client, (const char *)label,
                                                 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
     }
   }
   else {
     for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
-      snprintf( label, 64, "inport %d", i );
-      handle->ports[1][i] = jack_port_register( handle->client, (const char *)label,
+      snprintf( label, 64, "audio-in%d", i+1 );
+      handle->ports[1][i] = jackbridge_port_register( handle->client, (const char *)label,
                                                 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
     }
   }
 
+  // auto-connect-off "device" is at index 1
+  shouldAutoconnect_ = (device != 1 &&
+                        std::getenv("LADISH_APP_NAME") == nullptr &&
+                        std::getenv("NSM_URL") == nullptr);
+
   // Setup the buffer conversion information structure.  We don't use
   // buffers to do channel offsets, so we override that parameter
   // here.
@@ -2367,7 +2231,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
  error:
   if ( handle ) {
     pthread_cond_destroy( &handle->condition );
-    jack_client_close( handle->client );
+    jackbridge_client_close( handle->client );
 
     if ( handle->ports[0] ) free( handle->ports[0] );
     if ( handle->ports[1] ) free( handle->ports[1] );
@@ -2403,9 +2267,9 @@ void RtApiJack :: closeStream( void )
   if ( handle ) {
 
     if ( stream_.state == STREAM_RUNNING )
-      jack_deactivate( handle->client );
+      jackbridge_deactivate( handle->client );
 
-    jack_client_close( handle->client );
+    jackbridge_client_close( handle->client );
   }
 
   if ( handle ) {
@@ -2442,8 +2306,8 @@ void RtApiJack :: startStream( void )
   }
 
   JackHandle *handle = (JackHandle *) stream_.apiHandle;
-  int result = jack_activate( handle->client );
-  if ( result ) {
+  bool result = jackbridge_activate( handle->client );
+  if ( ! result ) {
     errorText_ = "RtApiJack::startStream(): unable to activate JACK client!";
     goto unlock;
   }
@@ -2452,8 +2316,8 @@ void RtApiJack :: startStream( void )
 
   // Get the list of available ports.
   if ( shouldAutoconnect_ && (stream_.mode == OUTPUT || stream_.mode == DUPLEX) ) {
-    result = 1;
-    ports = jack_get_ports( handle->client, handle->deviceName[0].c_str(), NULL, JackPortIsInput);
+    result = false;
+    ports = jackbridge_get_ports( handle->client, "system:", NULL, JackPortIsInput);
     if ( ports == NULL) {
       errorText_ = "RtApiJack::startStream(): error determining available JACK input ports!";
       goto unlock;
@@ -2463,21 +2327,21 @@ void RtApiJack :: startStream( void )
     // allow the user to select particular channels of a device, we'll
     // just open the first "nChannels" ports with offset.
     for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
-      result = 1;
+      result = false;
       if ( ports[ stream_.channelOffset[0] + i ] )
-        result = jack_connect( handle->client, jack_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] );
-      if ( result ) {
-        free( ports );
+        result = jackbridge_connect( handle->client, jackbridge_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] );
+      if ( ! result ) {
+        jackbridge_free( ports );
         errorText_ = "RtApiJack::startStream(): error connecting output ports!";
         goto unlock;
       }
     }
-    free(ports);
+    jackbridge_free(ports);
   }
 
   if ( shouldAutoconnect_ && (stream_.mode == INPUT || stream_.mode == DUPLEX) ) {
-    result = 1;
-    ports = jack_get_ports( handle->client, handle->deviceName[1].c_str(), NULL, JackPortIsOutput );
+    result = false;
+    ports = jackbridge_get_ports( handle->client, "system:", NULL, JackPortIsOutput );
     if ( ports == NULL) {
       errorText_ = "RtApiJack::startStream(): error determining available JACK output ports!";
       goto unlock;
@@ -2485,16 +2349,16 @@ void RtApiJack :: startStream( void )
 
     // Now make the port connections.  See note above.
     for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
-      result = 1;
+      result = false;
       if ( ports[ stream_.channelOffset[1] + i ] )
-        result = jack_connect( handle->client, ports[ stream_.channelOffset[1] + i ], jack_port_name( handle->ports[1][i] ) );
-      if ( result ) {
-        free( ports );
+        result = jackbridge_connect( handle->client, ports[ stream_.channelOffset[1] + i ], jackbridge_port_name( handle->ports[1][i] ) );
+      if ( ! result ) {
+        jackbridge_free( ports );
         errorText_ = "RtApiJack::startStream(): error connecting input ports!";
         goto unlock;
       }
     }
-    free(ports);
+    jackbridge_free(ports);
   }
 
   handle->drainCounter = 0;
@@ -2502,7 +2366,7 @@ void RtApiJack :: startStream( void )
   stream_.state = STREAM_RUNNING;
 
  unlock:
-  if ( result == 0 ) return;
+  if ( result ) return;
   error( RtAudioError::SYSTEM_ERROR );
 }
 
@@ -2524,7 +2388,7 @@ void RtApiJack :: stopStream( void )
     }
   }
 
-  jack_deactivate( handle->client );
+  jackbridge_deactivate( handle->client );
   stream_.state = STREAM_STOPPED;
 }
 
@@ -2546,7 +2410,7 @@ void RtApiJack :: abortStream( void )
 // This function will be called by a spawned thread when the user
 // callback function signals that the stream should be stopped or
 // aborted.  It is necessary to handle it this way because the
-// callbackEvent() function must return before the jack_deactivate()
+// callbackEvent() function must return before the jackbridge_deactivate()
 // function will return.
 static void *jackStopStream( void *ptr )
 {
@@ -2555,6 +2419,8 @@ static void *jackStopStream( void *ptr )
 
   object->stopStream();
   pthread_exit( NULL );
+
+  return NULL;
 }
 
 bool RtApiJack :: callbackEvent( unsigned long nframes )
@@ -2565,8 +2431,8 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
     error( RtAudioError::WARNING );
     return FAILURE;
   }
-  if ( stream_.bufferSize != nframes ) {
-    errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!";
+  if ( nframes > 8192 ) {
+    errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size is too big ... cannot process!";
     error( RtAudioError::WARNING );
     return FAILURE;
   }
@@ -2600,7 +2466,7 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
       handle->xrun[1] = false;
     }
     int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
-                                  stream_.bufferSize, streamTime, status, info->userData );
+                                  nframes, streamTime, status, info->userData );
     if ( cbReturnValue == 2 ) {
       stream_.state = STREAM_STOPPING;
       handle->drainCounter = 2;
@@ -2621,7 +2487,7 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
     if ( handle->drainCounter > 1 ) { // write zeros to the output stream
 
       for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {
-        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
+        jackbuffer = (jack_default_audio_sample_t *) jackbridge_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
         memset( jackbuffer, 0, bufferBytes );
       }
 
@@ -2631,13 +2497,13 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
       convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );
 
       for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {
-        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
+        jackbuffer = (jack_default_audio_sample_t *) jackbridge_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
         memcpy( jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes );
       }
     }
     else { // no buffer conversion
       for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
-        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
+        jackbuffer = (jack_default_audio_sample_t *) jackbridge_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
         memcpy( jackbuffer, &stream_.userBuffer[0][i*bufferBytes], bufferBytes );
       }
     }
@@ -2653,14 +2519,14 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
 
     if ( stream_.doConvertBuffer[1] ) {
       for ( unsigned int i=0; i<stream_.nDeviceChannels[1]; i++ ) {
-        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
+        jackbuffer = (jack_default_audio_sample_t *) jackbridge_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
         memcpy( &stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes );
       }
       convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
     }
     else { // no buffer conversion
       for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
-        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
+        jackbuffer = (jack_default_audio_sample_t *) jackbridge_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
         memcpy( &stream_.userBuffer[1][i*bufferBytes], jackbuffer, bufferBytes );
       }
     }
@@ -2670,6 +2536,26 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
   RtApi::tickStreamTime();
   return SUCCESS;
 }
+
+bool RtApiJack :: bufferSizeEvent( unsigned long nframes )
+{
+  if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
+  if ( stream_.state == STREAM_CLOSED ) {
+    errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
+    error( RtAudioError::WARNING );
+    return FAILURE;
+  }
+  if ( nframes > 8192 ) {
+    errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size is too big ... cannot process!";
+    error( RtAudioError::WARNING );
+    return FAILURE;
+  }
+
+  CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
+
+  RtAudioBufferSizeCallback callback = (RtAudioBufferSizeCallback) info->bufSizeCallback;
+  return callback( nframes, info->userData );
+}
   //******************** End of __UNIX_JACK__ *********************//
 #endif
 
@@ -2691,10 +2577,10 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
 // on information found in
 // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html.
 
-#include "asiosys.h"
-#include "asio.h"
-#include "iasiothiscallresolver.h"
-#include "asiodrivers.h"
+#include "asio.cpp"
+#include "asiodrivers.cpp"
+#include "asiolist.cpp"
+#include "iasiothiscallresolver.cpp"
 #include <cmath>
 
 static AsioDrivers drivers;
@@ -5487,8 +5373,8 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned
   // two.  This is a judgement call and a value of two is probably too
   // low for capture, but it should work for playback.
   int nBuffers = 0;
-  if ( options ) nBuffers = options->numberOfBuffers;
   if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) nBuffers = 2;
+  if ( options && options->numberOfBuffers > 0 ) nBuffers = options->numberOfBuffers;
   if ( nBuffers < 2 ) nBuffers = 3;
 
   // Check the lower range of the user-specified buffer size and set
@@ -6795,7 +6681,9 @@ unsigned int RtApiAlsa :: getDeviceCount( void )
       nDevices++;
     }
   nextcard:
-    snd_ctl_close( handle );
+    if (result == 0) {
+      snd_ctl_close( handle );
+    }
     snd_card_next( &card );
   }
 
@@ -8012,12 +7900,14 @@ static void *alsaCallbackHandler( void *ptr )
   }
 
   pthread_exit( NULL );
+
+  return NULL;
 }
 
 //******************** End of __LINUX_ALSA__ *********************//
 #endif
 
-#if defined(__LINUX_PULSE__)
+#if defined(__UNIX_PULSE__)
 
 // Code written by Peter Meerwald, pmeerw@pmeerw.net
 // and Tristan Matthews.
@@ -8092,6 +7982,8 @@ static void *pulseaudio_callback( void * user )
   }
 
   pthread_exit( NULL );
+
+  return NULL;
 }
 
 void RtApiPulse::closeStream( void )
@@ -8502,7 +8394,7 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
   return FAILURE;
 }
 
-//******************** End of __LINUX_PULSE__ *********************//
+//******************** End of __UNIX_PULSE__ *********************//
 #endif
 
 #if defined(__LINUX_OSS__)
@@ -9446,6 +9338,8 @@ static void *ossCallbackHandler( void *ptr )
   }
 
   pthread_exit( NULL );
+
+  return NULL;
 }
 
 //******************** End of __LINUX_OSS__ *********************//
diff --git a/RtAudio.h b/RtAudio.h
index 34a2534..289e254 100644
--- a/RtAudio.h
+++ b/RtAudio.h
@@ -46,16 +46,7 @@
 #define __RTAUDIO_H
 
 #define RTAUDIO_VERSION "5.0.0"
-
-#if defined _WIN32 || defined __CYGWIN__
-  #define RTAUDIO_DLL_PUBLIC
-#else
-  #if __GNUC__ >= 4
-    #define RTAUDIO_DLL_PUBLIC __attribute__( (visibility( "default" )) )
-  #else
-    #define RTAUDIO_DLL_PUBLIC
-  #endif
-#endif
+#define RTAUDIO_DLL_PUBLIC
 
 #include <string>
 #include <vector>
@@ -255,6 +246,9 @@ class RTAUDIO_DLL_PUBLIC RtAudioError : public std::runtime_error
  */
 typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText );
 
+//! RtAudio buffer size change callback.
+typedef bool (*RtAudioBufferSizeCallback)( unsigned int bufferSize, void* userData );
+
 // **************************************************************** //
 //
 // RtAudio class declaration.
@@ -278,8 +272,8 @@ class RTAUDIO_DLL_PUBLIC RtAudio
   enum Api {
     UNSPECIFIED,    /*!< Search for a working compiled API. */
     LINUX_ALSA,     /*!< The Advanced Linux Sound Architecture API. */
-    LINUX_PULSE,    /*!< The Linux PulseAudio API. */
     LINUX_OSS,      /*!< The Linux Open Sound System API. */
+    UNIX_PULSE,     /*!< The PulseAudio API. */
     UNIX_JACK,      /*!< The Jack Low-Latency Audio Server API. */
     MACOSX_CORE,    /*!< Macintosh OS-X Core Audio API. */
     WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */
@@ -416,7 +410,7 @@ class RTAUDIO_DLL_PUBLIC RtAudio
   ~RtAudio();
 
   //! Returns the audio API specifier for the current instance of RtAudio.
-  RtAudio::Api getCurrentApi( void );
+  RtAudio::Api getCurrentApi( void ) const;
 
   //! A public function that queries for the number of audio devices available.
   /*!
@@ -503,7 +497,9 @@ class RTAUDIO_DLL_PUBLIC RtAudio
                    RtAudio::StreamParameters *inputParameters,
                    RtAudioFormat format, unsigned int sampleRate,
                    unsigned int *bufferFrames, RtAudioCallback callback,
-                   void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL );
+                   void *userData = NULL, RtAudio::StreamOptions *options = NULL,
+                   RtAudioBufferSizeCallback bufSizeCallback = NULL,
+                   RtAudioErrorCallback errorCallback = NULL );
 
   //! A function that closes a stream and frees any associated stream memory.
   /*!
@@ -597,7 +593,7 @@ class RTAUDIO_DLL_PUBLIC RtAudio
   typedef uintptr_t ThreadHandle;
   typedef CRITICAL_SECTION StreamMutex;
 
-#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
+#elif defined(__LINUX_ALSA__) || defined(__UNIX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) || defined(__HAIKU__)
   // Using pthread library for various flavors of unix.
   #include <pthread.h>
 
@@ -620,6 +616,7 @@ struct CallbackInfo {
   ThreadHandle thread;
   void *callback;
   void *userData;
+  void *bufSizeCallback;
   void *errorCallback;
   void *apiInfo;   // void pointer for API specific callback information
   bool isRunning;
@@ -628,7 +625,7 @@ struct CallbackInfo {
 
   // Default constructor.
   CallbackInfo()
-  :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {}
+  :object(0), callback(0), userData(0), bufSizeCallback(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {}
 };
 
 // **************************************************************** //
@@ -687,7 +684,7 @@ public:
 
   RtApi();
   virtual ~RtApi();
-  virtual RtAudio::Api getCurrentApi( void ) = 0;
+  virtual RtAudio::Api getCurrentApi( void ) const = 0;
   virtual unsigned int getDeviceCount( void ) = 0;
   virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0;
   virtual unsigned int getDefaultInputDevice( void );
@@ -697,6 +694,7 @@ public:
                    RtAudioFormat format, unsigned int sampleRate,
                    unsigned int *bufferFrames, RtAudioCallback callback,
                    void *userData, RtAudio::StreamOptions *options,
+                   RtAudioBufferSizeCallback bufSizeCallback,
                    RtAudioErrorCallback errorCallback );
   virtual void closeStream( void );
   virtual void startStream( void ) = 0;
@@ -836,7 +834,7 @@ protected:
 //
 // **************************************************************** //
 
-inline RtAudio::Api RtAudio :: getCurrentApi( void ) { return rtapi_->getCurrentApi(); }
+inline RtAudio::Api RtAudio :: getCurrentApi( void ) const { return rtapi_->getCurrentApi(); }
 inline unsigned int RtAudio :: getDeviceCount( void ) { return rtapi_->getDeviceCount(); }
 inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); }
 inline unsigned int RtAudio :: getDefaultInputDevice( void ) { return rtapi_->getDefaultInputDevice(); }
@@ -865,7 +863,7 @@ public:
 
   RtApiCore();
   ~RtApiCore();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; }
+  RtAudio::Api getCurrentApi( void ) const { return RtAudio::MACOSX_CORE; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   unsigned int getDefaultOutputDevice( void );
@@ -903,7 +901,7 @@ public:
 
   RtApiJack();
   ~RtApiJack();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; }
+  RtAudio::Api getCurrentApi( void ) const { return RtAudio::UNIX_JACK; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -918,6 +916,9 @@ public:
   // will most likely produce highly undesireable results!
   bool callbackEvent( unsigned long nframes );
 
+  // Buffer size change callback
+  bool bufferSizeEvent( unsigned long nframes );
+
   private:
 
   bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 
@@ -938,7 +939,7 @@ public:
 
   RtApiAsio();
   ~RtApiAsio();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; }
+  RtAudio::Api getCurrentApi( void ) const { return RtAudio::WINDOWS_ASIO; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -974,7 +975,7 @@ public:
 
   RtApiDs();
   ~RtApiDs();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; }
+  RtAudio::Api getCurrentApi( void ) const { return RtAudio::WINDOWS_DS; }
   unsigned int getDeviceCount( void );
   unsigned int getDefaultOutputDevice( void );
   unsigned int getDefaultInputDevice( void );
@@ -1015,7 +1016,7 @@ public:
   RtApiWasapi();
   ~RtApiWasapi();
 
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; }
+  RtAudio::Api getCurrentApi( void ) const { return RtAudio::WINDOWS_WASAPI; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   unsigned int getDefaultOutputDevice( void );
@@ -1050,7 +1051,7 @@ public:
 
   RtApiAlsa();
   ~RtApiAlsa();
-  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; }
+  RtAudio::Api getCurrentApi() const { return RtAudio::LINUX_ALSA; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -1076,13 +1077,13 @@ public:
 
 #endif
 
-#if defined(__LINUX_PULSE__)
+#if defined(__UNIX_PULSE__)
 
 class RtApiPulse: public RtApi
 {
 public:
   ~RtApiPulse();
-  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; }
+  RtAudio::Api getCurrentApi() const { return RtAudio::UNIX_PULSE; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -1116,7 +1117,7 @@ public:
 
   RtApiOss();
   ~RtApiOss();
-  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; }
+  RtAudio::Api getCurrentApi() const { return RtAudio::LINUX_OSS; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -1147,7 +1148,7 @@ class RtApiDummy: public RtApi
 public:
 
   RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtAudioError::WARNING ); }
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; }
+  RtAudio::Api getCurrentApi( void ) const { return RtAudio::RTAUDIO_DUMMY; }
   unsigned int getDeviceCount( void ) { return 0; }
   RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; }
   void closeStream( void ) {}
diff --git a/include/asio.h b/include/asio.h
index 8ec811f..656f681 100644
--- a/include/asio.h
+++ b/include/asio.h
@@ -3,11 +3,12 @@
 
 /*
 	Steinberg Audio Stream I/O API
-	(c) 1997 - 2005, Steinberg Media Technologies GmbH
+	(c) 1997 - 2013, Steinberg Media Technologies GmbH
 
-	ASIO Interface Specification v 2.1
+	ASIO Interface Specification v 2.3
 
 	2005 - Added support for DSD sample data (in cooperation with Sony)
+	2012 - Added support for drop out detection
 
 
 	basic concept is an i/o synchronous double-buffer scheme:
@@ -916,6 +917,7 @@ enum
 	kAsioCanInputMeter,
 	kAsioCanOutputGain,
 	kAsioCanOutputMeter,
+	kAsioOptionalOne,
 
 	//	DSD support
 	//	The following extensions are required to allow switching
@@ -923,6 +925,9 @@ enum
 	kAsioSetIoFormat			= 0x23111961,		/* ASIOIoFormat * in params.			*/
 	kAsioGetIoFormat			= 0x23111983,		/* ASIOIoFormat * in params.			*/
 	kAsioCanDoIoFormat			= 0x23112004,		/* ASIOIoFormat * in params.			*/
+	// Extension for drop out detection
+	kAsioCanReportOverload			= 0x24042012,	/* return ASE_SUCCESS if driver can detect and report overloads */
+	kAsioGetInternalBufferSamples	= 0x25042012	/* ASIOInternalBufferInfo * in params. Deliver size of driver internal buffering, return ASE_SUCCESS if supported */
 };
 
 typedef struct ASIOInputMonitor
@@ -1003,6 +1008,14 @@ typedef struct ASIOIoFormat_s
 	char				future[512-sizeof(ASIOIoFormatType)];
 } ASIOIoFormat;
 
+// Extension for drop detection
+// Note: Refers to buffering that goes beyond the double buffer e.g. used by USB driver designs
+typedef struct ASIOInternalBufferInfo
+{
+	long inputSamples;			// size of driver's internal input buffering which is included in getLatencies
+	long outputSamples;			// size of driver's internal output buffering which is included in getLatencies
+} ASIOInternalBufferInfo;
+
 
 ASIOError ASIOOutputReady(void);
 /* Purpose:
diff --git a/include/asiosys.h b/include/asiosys.h
index 37f7a48..c974fc3 100644
--- a/include/asiosys.h
+++ b/include/asiosys.h
@@ -1,7 +1,7 @@
 #ifndef __asiosys__
 	#define __asiosys__
 
-	#ifdef WIN32
+	#if defined(WIN32) || defined(_WIN64)
 		#undef MAC 
 		#define PPC 0
 		#define WINDOWS 1
diff --git a/include/ginclude.h b/include/ginclude.h
index b627dc2..8c609c7 100644
--- a/include/ginclude.h
+++ b/include/ginclude.h
@@ -8,7 +8,7 @@
 	//
 	#define ASIO_BIG_ENDIAN 1
 	#define ASIO_CPU_MIPS 1
-#elif defined WIN32
+#elif defined(WIN32) || defined(_WIN64)
 	#undef BEOS 
 	#undef MAC 
 	#undef SGI
diff --git a/include/iasiodrv.h b/include/iasiodrv.h
index 64d2dbb..860675c 100644
--- a/include/iasiodrv.h
+++ b/include/iasiodrv.h
@@ -1,3 +1,4 @@
+#pragma once
 #include "asiosys.h"
 #include "asio.h"
 
 |