Darkice is a really good free product when talking about live encoding and streaming. It is the best friend of Icecast, which is the deflector module (ie : the link between live stream and customers).

I used to use Darkice directly from ALSA, the Linux sound layer, and encode my live audio from the soundcard to MP3. But for my new radio project I had to use Jack. I already talked about Jack earlier. It is so damn easy you won’t believe it :
Start jack (or have Jack start automaticaly when you start something using jack – see /etc/jackd.conf)
Start your favorite app, let’s say Darkice
Connect your Darkice plug to the soundcard
and you’re done !

In the special case of Darkice, you can’t specify the name of the Jack plug you will get. This is hardcoded to « darkice-$PID » where $PID is the Darkice process number once started.
This means your Darkice plug name will change at every restart… not really conveniant.
Reading the Darkice Track, I found an opened bug related to this. The writer gives a solution to change that changing name to a static name, which is fine if you don’t have to run multiple Darkice on the same host. I do !
In fact, having a static name is also easyer when you are on a server (not a desktop) and you want to have Darkice connected to another Jack plug automaticaly. Else, you’ll have to find the PID of Darkice, then connect it. Ugly !

So I made another (dirty) patch to achieve that. As Darkice is C++ and is programmed in a way I even can’t read it I wasn’t able to add a new config parameter. Digging in the code showed me that only the first 4 letters of the name in the config file was used to detect the « jack » device.
So you have plenty of room to add anything you like after that !
In fact it seems the code already use this feature to detect if Darkice have to auto connect to the first 2 Jack inputs -> don’t name your device as « jack_auto » so :)

My change keeps the same code. I just add something so the « name » defined in the « device » config parameter is accessible by the « open » function of the Jack layer of Darkice.

diff -ru darkice-0.18.1/src/JackDspSource.cpp darkice-0.18.1-new-rbsize/src/JackDspSource.cpp
--- darkice-0.18.1/src/JackDspSource.cpp        2007-02-19 08:56:49.000000000 +0100
+++ darkice-0.18.1-new-rbsize/src/JackDspSource.cpp     2008-03-07 10:21:40.000000000 +0100
@@ -99,6 +99,7 @@
     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
+    snprintf(jack_name, 255, "%s", name);

     // Auto connect the ports ?
     if ( Util::strEq( name, "jack_auto", 9) ) {
@@ -188,7 +189,7 @@
     }

     // Register client with Jack
-    snprintf(client_name, 255, "darkice-%d", getpid());
+    snprintf(client_name, 255, "darkice-%s", jack_name);
     if ((client = jack_client_new(client_name)) == NULL) {
         throw Exception( __FILE__, __LINE__, "JACK server not running?");
     }
@@ -236,7 +237,7 @@

     // Create a ring buffer for each channel
-    rb_size = 2
+    rb_size = 32
             * jack_get_sample_rate(client)
             * sizeof (jack_default_audio_sample_t);
     for (c=0; c
@@ -277,26 +278,42 @@
 JackDspSource :: canRead ( unsigned int   sec,
                            unsigned int   usec )    throw ( Exception )
 {
-    size_t available=0;
-
+    const unsigned int max_wait_time = sec * 1000000;
+    const unsigned int wait_increment = 10000;
+
     if ( !isOpen() ) {
         return false;
     }

-    // How many bytes available in ring buffer ?
-    available = jack_ringbuffer_read_space( rb[0] );
-    if (available)    return true;
-
-    // Sleep and check again
-    // FIXME: should we really sleep the full duration ?
-    usleep( (sec*1000000) + usec );
-
-    available = jack_ringbuffer_read_space( rb[0] );
-    if (available) {
-        return true;
-    } else {
-        return false;
+    unsigned int cur_wait = 0;
+
+    // wait for the buffer to be filled
+    while ( max_wait_time > cur_wait ){
+       bool canRead = true;
+       for (unsigned int c = 0 ; c < getChannel() ; c++)
+               if ( jack_ringbuffer_read_space( rb[c] ) <= 2048 )
+                       canRead = false;
+
+       if (canRead)
+               return true;
+
+       cur_wait += wait_increment;
+       usleep ( wait_increment );
+     }
+
+    // impossible to get the buffer after max_wait_time
+    Reporter::reportEvent( 1, "Jack ringbuffer still not ready, waiting ", usec);
+    usleep( usec );
+
+    // check one last time
+    bool canRead = true;
+    for (unsigned int c = 0 ; c < getChannel() ; c++) {
+       if ( jack_ringbuffer_read_space( rb[c] ) <= 0 ) {
+               canRead = false;
+               Reporter::reportEvent( 1, "Jack ringbuffer still not ready on channel", c);
+       }
     }
+    return canRead;
 }

@@ -324,6 +341,14 @@
         throw Exception( __FILE__, __LINE__, "realloc on tmp_buffer failed");
     }

+    // We must be sure to fetch as many data on both channels
+    // get minBytesAvailable samples or a smaller size available
+    int minBytesAvailable = samples * sizeof( jack_default_audio_sample_t );
+    for (c=0; c
+       int readable = jack_ringbuffer_read_space( rb[c] );
+       if (readable < minBytesAvailable)
+               minBytesAvailable = readable;
+    }

     for (c=0; c
     {
@@ -331,7 +356,7 @@
         // and then convert samples to output buffer
         int bytes_read = jack_ringbuffer_read(rb[c],
                                              (char*)tmp_buffer,
-                              samples * sizeof( jack_default_audio_sample_t ));
+                               minBytesAvailable);
         samples_read[c] = bytes_read / sizeof( jack_default_audio_sample_t );

@@ -418,7 +443,8 @@
         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");
+            Reporter::reportEvent( 1, "failed to write to ring ruffer. wrote on channel ", len, to_write, c);
+           usleep( 1000000 );
             return 1;
          }
     }
root@dorado:/opt/src# diff -u darkice-0.18.1/src/JackDspSource.h darkice-0.18.1-new/src/JackDspSource.h
--- darkice-0.18.1/src/JackDspSource.h  2007-02-19 08:56:49.000000000 +0100
+++ darkice-0.18.1-new/src/JackDspSource.h      2007-09-03 19:21:39.000000000 +0200
@@ -93,6 +93,9 @@
          */
         bool                auto_connect;

+
+       char                    jack_name[255];
+
     protected:

         /**

Compile Darkice and install it.
Change your config file so the « device » name start by « jack » and add anything you want the name to be.
For exemple, if the input section is :

[input]
device          = jack_in_1
sampleRate      = 48000
bitsPerSample   = 16        # bits per sample. try 16
channel         = 2         # channels. 1 = mono, 2 = stereo

The resulting Jack plugs will be :

darkice-jack_in_1:left
darkice-jack_in_1:right