From 9c05582a007788295d872172c5109ae9bccfcf68 Mon Sep 17 00:00:00 2001
From: iovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a>
Date: Wed, 7 Feb 2007 18:44:02 +0000
Subject: Added support for recording audio through jack. libjack is dlopened
 so there's no runtime dependency on it. Ports must be connected at startup.
 New files: src/rmd_jack.c

git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@273 f606c939-3180-4ac9-a4b8-4b8779d57d0a
---
 recordmydesktop/configure.ac              |  44 +++++--
 recordmydesktop/doc/recordmydesktop.1     |  29 ++++-
 recordmydesktop/include/rmdfunc.h         | 104 +++++++++++++++
 recordmydesktop/include/rmdmacro.h        |  43 ++++--
 recordmydesktop/include/rmdtypes.h        |  37 +++++-
 recordmydesktop/src/Makefile.am           |   3 +-
 recordmydesktop/src/cache_audio.c         |  72 ++++++++---
 recordmydesktop/src/encode_sound_buffer.c | 114 +++++++++++-----
 recordmydesktop/src/get_frame.c           |   1 -
 recordmydesktop/src/initialize_data.c     |  85 ++++++++----
 recordmydesktop/src/load_cache.c          |   5 +
 recordmydesktop/src/opendev.c             |   1 -
 recordmydesktop/src/parseargs.c           |  82 ++++++++++--
 recordmydesktop/src/recordmydesktop.c     |   6 +-
 recordmydesktop/src/register_callbacks.c  |  24 +++-
 recordmydesktop/src/rmd_jack.c            | 208 ++++++++++++++++++++++++++++++
 recordmydesktop/src/rmdthreads.c          |  24 +++-
 17 files changed, 753 insertions(+), 129 deletions(-)
 create mode 100644 recordmydesktop/src/rmd_jack.c

(limited to 'recordmydesktop')

diff --git a/recordmydesktop/configure.ac b/recordmydesktop/configure.ac
index cfd413d..1826d5f 100644
--- a/recordmydesktop/configure.ac
+++ b/recordmydesktop/configure.ac
@@ -33,13 +33,21 @@ if test "x$x_includes" != "x" && test "x$x_includes" != xNONE ; then
 fi
 
 AC_ARG_ENABLE(oss,
-     [  --enable-oss[=yes]    compile with OSS(don't check for ALSA))],
+     [  --enable-oss[=yes]    compile with OSS(don't check for ALSA)],
      [case "${enableval}" in
        yes) oss=true ;;
        no)  oss=false ;;
        *) AC_MSG_ERROR(bad value ${enableval} for --enable-oss) ;;
      esac],[oss=false])
 
+AC_ARG_ENABLE(jack,
+     [  --enable-jack[=yes]    compile with Jack support],
+     [case "${enableval}" in
+       yes) jack=true ;;
+       no)  jack=false ;;
+       *) AC_MSG_ERROR(bad value ${enableval} for --enable-jack) ;;
+     esac],[jack=true])
+
 AC_CHECK_HEADER([alsa/asoundlib.h])
 AC_CHECK_HEADER([endian.h],default_endian=true)
 if test x$default_endian != xtrue; then
@@ -47,7 +55,14 @@ AC_CHECK_HEADER([machine/endian.h],
                 AC_DEFINE([HAVE_MACHINE_ENDIAN_H],1,
                             endian.h in $include_path/machine/ subdirectory))
 fi
+
 AC_CHECK_HEADER([sys/soundcard.h])
+AC_CHECK_HEADER([dlfcn.h],[dlfcn_header=true])
+
+if test x$jack = xtrue && test x$dlfcn_header = xtrue; then
+AC_CHECK_HEADER([jack/jack.h],
+                jack_headers_present=true)
+fi
 AC_CHECK_HEADERS([sys/time.h unistd.h vorbis/vorbisfile.h fcntl.h])
 
 
@@ -80,6 +95,7 @@ AC_CHECK_LIB([theora],[theora_encode_YUVin],,
              AC_MSG_ERROR([Can't find libtheora]))
 AC_CHECK_LIB([pthread],[pthread_mutex_lock],,
              AC_MSG_ERROR([Can't find libpthread]))
+
 if test x$oss = xfalse; then
     AC_CHECK_LIB([asound],[snd_pcm_drain],,
                 audio_backend="OSS")
@@ -87,6 +103,14 @@ else
     audio_backend="OSS"
 fi
 
+if test x$jack_headers_present = xtrue; then
+    AC_CHECK_LIB([dl],[dlopen],,libdl_np=true)
+    if test x$libdl_np != xtrue; then
+        AC_DEFINE([HAVE_JACK_H],1,
+                define to 1 if <jack/jack.h> exists)
+    fi
+fi
+
 
 # Checks for typedefs, structures, and compiler characteristics.
 
@@ -100,17 +124,21 @@ AC_CONFIG_FILES([Makefile
         doc/Makefile ])
 AC_OUTPUT
 
-echo ""
-echo ""
+if test x$audio_backend != xOSS; then
+    audio_backend="ALSA"
+fi
+if test x$jack_headers_present = xtrue && test x$libdl_np != xtrue; then
+    jack_support="Enabled"
+else
+    jack_support="Disabled"
+fi
 echo ""
 echo ""
 echo "****************************************"
 echo ""
-if test x$audio_backend = xOSS; then
-    echo "Audio driver that will be used: OSS"
-else
-    echo "Audio driver that will be used: ALSA"
-fi
+echo "Audio driver that will be used: $audio_backend"
+echo ""
+echo "Compile with Jack support: $jack_support"
 echo ""
 echo "****************************************"
 echo ""
diff --git a/recordmydesktop/doc/recordmydesktop.1 b/recordmydesktop/doc/recordmydesktop.1
index 1e2d0c2..01e265b 100644
--- a/recordmydesktop/doc/recordmydesktop.1
+++ b/recordmydesktop/doc/recordmydesktop.1
@@ -149,6 +149,14 @@ The following error codes indicate the nature of the error:
 .br
 13 Cannot open file for writting.
 .br
+14 Cannot load the Jack library (dlopen/dlsym error on libjack.so).
+.br
+15 Cannot create new client.
+.br
+16 Cannot activate client.
+.br
+17 Port registration/connection failure.
+.br
 .br
 .SH OPTIONS
 .PP
@@ -165,6 +173,11 @@ Generic Options:
     \-\-version
     Print program version and exit.
 .br
+.TP
+.B
+    \-\-print\-config
+    Print info about options selected during compilation and exit.
+.br
 .PP
 .br
 .B
@@ -270,6 +283,15 @@ Sound Options:
     Sound device(default hw0:0 or /dev/dsp, depending on whether ALSA or OSS is used).
 .br
 .TP
+.B
+    \-use\-jack port1 port2... portn
+    Record audio from the specified list of
+.B
+space-separated
+jack ports.
+    When using this option, all the rest audio related ones(except --no-sound) are not taken into account.
+.br
+.TP
 .B
     \-\-no\-sound
     Do not record sound.
@@ -356,7 +378,7 @@ If no other option is specified, filename can be given without the \-o switch.
 .TP
 .B        recordmydesktop
 .br
-[\-h| \-\-help| \-\-version| \-delay n[H|h|M|m]| \-windowid id_of_window|
+[\-h| \-\-help| \-\-version| \-\-print\-config| \-delay n[H|h|M|m]| \-windowid id_of_window|
 .br
 \-display DISPLAY| \-x X| \-y Y|\-width N| \-height N| \-fps N(number>0)| \-\-on\-the\-fly\-encoding|
 .br
@@ -364,7 +386,7 @@ If no other option is specified, filename can be given without the \-o switch.
 .br
 \-\-no\-cursor| \-freq N(number>0)| \-channels N(number>0)| \-buffer\-size N(number>0)| \-device SOUND_DEVICE|
 .br
-\-\-no\-sound| \-\-with\-shared| \-\-no\-cond\-shared| \-shared\-threshold n| \-\-full\-shots|
+\-use\-jack port1 port2... portn| \-\-no\-sound| \-\-with\-shared| \-\-no\-cond\-shared| \-shared\-threshold n| \-\-full\-shots|
 .br
 \-\-quick\-subsampling| \-workdir DIR| \-\-zero\-compression| \-\-no\-wm\-check| \-\-overwrite| \-o filename]^filename
 .br
@@ -441,4 +463,5 @@ John Varouhakis(johnvarouhakis@gmail.com)
 .br
 .BR ffmpeg2theora(1)
 .br
-
+.BR jack_lsp(1)
+.br
diff --git a/recordmydesktop/include/rmdfunc.h b/recordmydesktop/include/rmdfunc.h
index 2f41c4d..b4d3ef6 100644
--- a/recordmydesktop/include/rmdfunc.h
+++ b/recordmydesktop/include/rmdfunc.h
@@ -521,5 +521,109 @@ int InitializeData(ProgData *pdata,
                    EncData *enc_data,
                    CacheData *cache_data);
 
+#ifdef HAVE_JACK_H
+/**
+*
+*   Global Fuction Pointers To Jack API Calls
+*
+*/
+jack_client_t *(*jack_client_new_p)(const char *client_name);
+jack_nframes_t (*jack_get_sample_rate_p)(jack_client_t * client);
+int (*jack_set_buffer_size_p)(jack_client_t *client, jack_nframes_t nframes);
+jack_nframes_t (*jack_get_buffer_size_p)(jack_client_t *client);
+int (*jack_set_process_callback_p)(jack_client_t *client,
+                                   JackProcessCallback process_callback,
+                                   void *arg);
+void (*jack_on_shutdown_p)(jack_client_t *client,
+                           void(*function)(void *arg),
+                           void *arg);
+int (*jack_activate_p)(jack_client_t *client);
+int (*jack_client_close_p)(jack_client_t *client);
+void *(*jack_port_get_buffer_p)(jack_port_t *port,jack_nframes_t);
+jack_port_t *(*jack_port_register_p)(jack_client_t *client,
+                                     const char *port_name,
+                                     const char *port_type,
+                                     unsigned long flags,
+                                     unsigned long buffer_size);
+int (*jack_connect_p)(jack_client_t *client,
+                      const char *source_port,
+                      const char *destination_port);
+const char *(*jack_port_name_p)(const jack_port_t *port);
+int (*jack_port_name_size_p)(void);
+jack_ringbuffer_t *(*jack_ringbuffer_create_p)(size_t sz);
+void (*jack_ringbuffer_free_p)(jack_ringbuffer_t *rb);
+size_t (*jack_ringbuffer_read_p)(jack_ringbuffer_t *rb,
+                                 char *dest, size_t cnt);
+size_t (*jack_ringbuffer_read_space_p)(const jack_ringbuffer_t *rb);
+size_t (*jack_ringbuffer_write_p)(jack_ringbuffer_t *rb,
+                                  const char *src,
+                                  size_t cnt);
+/**
+*   End Of Function Pointers
+*/
+
+/**
+*   Callback for capture through jack
+*
+*   \param  nframes Number of frames captured
+*
+*   \param jdata_t  Pointer to JackData struct containing port
+*                   and client information
+*
+*   \returns Zero always
+*/
+int JackCapture(jack_nframes_t nframes,void *jdata_t);
+
+/**
+*   Callback for jack server shutdown
+*
+*   \param jdata_t  Pointer to JackData struct containing port
+*                   and client information
+*/
+void JackShutdown(void *jdata_t);
+
+/**
+*   Register and Activate specified ports
+*
+*   \param jdata_t  Pointer to JackData struct containing port
+*                   and client information
+*
+*   \returns 0 on Success, 1 on failure
+*/
+int SetupPorts(JackData *jdata);
+
+/**
+*   dlopen libjack and dlsym all needed functions
+*
+*   \param jack_lib_handle  Pointer to handle for jack library
+*
+*   \returns 0 on Success, 1 on failure
+*/
+int LoadJackLib(void *jack_lib_handle);
+
+/**
+*   Load libjack, create and activate client,register ports
+*
+*   \param jdata_t  Pointer to JackData struct containing port
+*                   and client information
+*
+*   \returns 0 on Success, error code on failure
+*            (depending on where the error occured)
+*/
+int StartJackClient(JackData *jdata);
+
+/**
+*   Close Jack Client
+*
+*   \param jdata_t  Pointer to JackData struct containing port
+*                   and client information
+*
+*   \returns 0 on Success, 1 on failure
+*/
+int StopJackClient(JackData *jdata);
+
+#endif
+
+
 #endif
 
diff --git a/recordmydesktop/include/rmdmacro.h b/recordmydesktop/include/rmdmacro.h
index 1fe06a4..982f986 100644
--- a/recordmydesktop/include/rmdmacro.h
+++ b/recordmydesktop/include/rmdmacro.h
@@ -105,6 +105,11 @@
     #define DEFAULT_AUDIO_DEVICE "/dev/dsp"
 #endif
 
+#ifdef HAVE_JACK_H
+    #define BUFFERS_IN_RING 0x0020
+#endif
+
+
 #define CLIP_EVENT_AREA(e,brwin,wgeom){\
     if(((e)->area.x<=(brwin)->rgeom.x)&&((e)->area.y<=(brwin)->rgeom.y)&&\
         ((e)->area.width>=(brwin)->rgeom.width)&&\
@@ -204,7 +209,10 @@
     (args)->nowmcheck=\
     (args)->dropframes=\
     (args)->overwrite=\
+    (args)->use_jack=\
+    (args)->jack_nports=\
     (args)->nocondshared=0;\
+    (args)->jack_port_names=NULL;\
     (args)->no_quick_subsample=\
     (args)->noshared=1;\
     (args)->filename=(char *)malloc(8);\
@@ -251,13 +259,13 @@
     t3=*datapi_next;\
     t4=*(datapi_next+1);\
     t_val=((((t1&0xff000000) +(t2&0xff000000)+\
-    (t3&0xff000000)+(t4&0xff000000))/4)&0xff000000) \
-    +((((t1&0x00ff0000) +(t2&0x00ff0000)+\
-    (t3&0x00ff0000)+(t4&0x00ff0000))/4)&0x00ff0000)\
-    +((((t1&0x0000ff00) +(t2&0x0000ff00)+\
-    (t3&0x0000ff00)+(t4&0x0000ff00))/4)&0x0000ff00)\
-    +((((t1&0x000000ff) +(t2&0x000000ff)+\
-    (t3&0x000000ff)+(t4&0x000000ff))/4)&0x000000ff);\
+            (t3&0xff000000)+(t4&0xff000000))/4)&0xff000000)+\
+          ((((t1&0x00ff0000) +(t2&0x00ff0000)+\
+            (t3&0x00ff0000)+(t4&0x00ff0000))/4)&0x00ff0000)+\
+          ((((t1&0x0000ff00) +(t2&0x0000ff00)+\
+            (t3&0x0000ff00)+(t4&0x0000ff00))/4)&0x0000ff00)+\
+          ((((t1&0x000000ff) +(t2&0x000000ff)+\
+            (t3&0x000000ff)+(t4&0x000000ff))/4)&0x000000ff);\
 }
 
 #define CALC_TVAL_AVG_16(t_val,datapi,datapi_next){\
@@ -267,11 +275,11 @@
     t3=*datapi_next;\
     t4=*(datapi_next+1);\
     t_val=((((t1&__R16_MASK) +(t2&__R16_MASK)+\
-    (t3&__R16_MASK)+(t4&__R16_MASK))/4)&__R16_MASK) \
-    +((((t1&__G16_MASK) +(t2&__G16_MASK)+\
-    (t3&__G16_MASK)+(t4&__G16_MASK))/4)&__G16_MASK)\
-    +((((t1&__B16_MASK) +(t2&__B16_MASK)+\
-    (t3&__B16_MASK)+(t4&__B16_MASK))/4)&__B16_MASK);\
+             (t3&__R16_MASK)+(t4&__R16_MASK))/4)&__R16_MASK)+\
+          ((((t1&__G16_MASK) +(t2&__G16_MASK)+\
+             (t3&__G16_MASK)+(t4&__G16_MASK))/4)&__G16_MASK)+\
+          ((((t1&__B16_MASK) +(t2&__B16_MASK)+\
+             (t3&__B16_MASK)+(t4&__B16_MASK))/4)&__B16_MASK);\
 }
 
 #define UPDATE_Y_PLANE(data,\
@@ -494,8 +502,19 @@
     free((frame_t)->VData);\
 };
 
+#ifdef HAVE_JACK_H
 
+#define CHECK_DLERRORS_FATAL(__error_p)\
+    if((__error_p=dlerror())!=NULL){\
+        fprintf(stderr,"%s\n",__error_p);\
+        return 1;\
+    }
 
+#define DLSYM_AND_CHECK(lib_handle,__call_name__,__error_p)\
+    __call_name__##_p=dlsym(lib_handle,#__call_name__);\
+    CHECK_DLERRORS_FATAL(__error_p)
+
+#endif
 
 #endif
 
diff --git a/recordmydesktop/include/rmdtypes.h b/recordmydesktop/include/rmdtypes.h
index c97216d..005ae5a 100644
--- a/recordmydesktop/include/rmdtypes.h
+++ b/recordmydesktop/include/rmdtypes.h
@@ -72,6 +72,13 @@
     #include <sys/soundcard.h>
 #endif
 
+#ifdef HAVE_JACK_H
+    #include <jack/jack.h>
+    #include <jack/ringbuffer.h>
+    #include <dlfcn.h>
+#endif
+
+
 //this type exists only
 //for comparing the planes at caching.
 //u_int64_t mught not be available everywhere.
@@ -167,9 +174,11 @@ typedef struct _ProgArgs{
     int zerocompression;//image data are always flushed uncompressed
     int overwrite;      //overwite a previously existing file
                         //(do not add a .number postfix)
+    int use_jack;       //record audio with jack
+    unsigned int jack_nports;
+    char **jack_port_names;
 }ProgArgs;
 
-
 //this struct holds anything related to encoding AND
 //writting out to file.
 typedef struct _EncData{
@@ -231,6 +240,23 @@ typedef struct _SndBuffer{
     struct _SndBuffer *next;
 }SndBuffer;
 
+#ifdef HAVE_JACK_H
+typedef struct _JackData{
+    void *jack_lib_handle;      //handle for jack library (loaded with dlopen).
+    jack_client_t   *client;
+    unsigned int    buffersize, //buffer size for every port in frames.
+                    frequency,  //samplerate with which jack server was started.
+                    nports;     //number of ports.
+    char **port_names;          //names of ports(as specified in args).
+    jack_port_t **ports;        //connections to thes ports.
+    jack_default_audio_sample_t **portbuf;  //retrieval of audio buffers.
+    pthread_mutex_t *snd_buff_ready_mutex;  //mutex and cond_var
+    pthread_cond_t *sound_data_read;        //in the pdata struct
+    jack_ringbuffer_t *sound_buffer;        //data exchange happens through this
+    int capture_started;        //used to hold recording in the beginning
+}JackData;
+#endif
+
 //this structure holds any data related to the program
 //It's usage is mostly to be given as an argument to the
 //threads,so they will have access to the program data, avoiding
@@ -262,9 +288,12 @@ typedef struct _ProgData{
         damage_event,       //damage event base code
         damage_error,       //damage error base code
         running;
-    SndBuffer *sound_buffer;
-    EncData *enc_data;
-    CacheData *cache_data;
+    SndBuffer   *sound_buffer;
+    EncData     *enc_data;
+    CacheData   *cache_data;
+#ifdef HAVE_JACK_H
+    JackData    *jdata;
+#endif
     int hard_pause;         //if sound device doesn't support pause
                             //we have to close and reopen
     int avd;                //syncronization among audio and video
diff --git a/recordmydesktop/src/Makefile.am b/recordmydesktop/src/Makefile.am
index 98ddda2..879c7b7 100644
--- a/recordmydesktop/src/Makefile.am
+++ b/recordmydesktop/src/Makefile.am
@@ -27,7 +27,8 @@ recordmydesktop_SOURCES=	recordmydesktop.c\
 							wm_check.c\
 							encode_cache.c\
 							rmdthreads.c\
-							initialize_data.c
+							initialize_data.c\
+							rmd_jack.c
 
 INCLUDES= $(all_includes) -I../include
 
diff --git a/recordmydesktop/src/cache_audio.c b/recordmydesktop/src/cache_audio.c
index bff4df2..7896df7 100644
--- a/recordmydesktop/src/cache_audio.c
+++ b/recordmydesktop/src/cache_audio.c
@@ -35,37 +35,67 @@ void *CacheSoundBuffer(ProgData *pdata){
                   pdata->args.channels;
 #else
     int framesize=pdata->args.channels<<1;//Always signed 16 bit data
+#endif
+#ifdef HAVE_JACK_H
+    void *jackbuf=NULL;
+    if(pdata->args.use_jack){
+        framesize=sizeof(jack_default_audio_sample_t)*
+                  pdata->jdata->nports;
+        jackbuf=malloc(framesize*pdata->jdata->buffersize);
+    }
 #endif
     while((pdata->running)){
-        SndBuffer *buff;
+        SndBuffer *buff=NULL;
 
         if(Paused){
             pthread_mutex_lock(&pause_mutex);
             pthread_cond_wait(&pdata->pause_cond,&pause_mutex);
             pthread_mutex_unlock(&pause_mutex);
         }
-        if(pdata->sound_buffer==NULL){
-            pdata->v_enc_thread_waiting=1;
-            pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
-            pthread_cond_wait(&pdata->sound_data_read,
-                              &pdata->snd_buff_ready_mutex);
-            pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
-            pdata->v_enc_thread_waiting=0;
+        if(!pdata->args.use_jack){
+            if(pdata->sound_buffer==NULL){
+                pdata->v_enc_thread_waiting=1;
+                pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+                pthread_cond_wait(&pdata->sound_data_read,
+                                &pdata->snd_buff_ready_mutex);
+                pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+                pdata->v_enc_thread_waiting=0;
+            }
+            if(pdata->sound_buffer==NULL || !pdata->running){
+                break;
+            }
+            pthread_mutex_lock(&pdata->sound_buffer_mutex);
+            buff=pdata->sound_buffer;
+            //advance the list
+            pdata->sound_buffer=pdata->sound_buffer->next;
+            pthread_mutex_unlock(&pdata->sound_buffer_mutex);
+            fwrite(buff->data,1,pdata->periodsize*framesize,
+                   pdata->cache_data->afp);
+            free(buff->data);
+            free(buff);
+        }
+        else{
+#ifdef HAVE_JACK_H
+            if((*jack_ringbuffer_read_space_p)(pdata->jdata->sound_buffer)>=
+               (framesize*pdata->jdata->buffersize)){
+                (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer,
+                                          jackbuf,
+                                          (framesize*pdata->jdata->buffersize));
+                fwrite(jackbuf,1,(framesize*pdata->jdata->buffersize),
+                       pdata->cache_data->afp);
+            }
+            else{
+                pdata->v_enc_thread_waiting=1;
+                pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+                pthread_cond_wait(&pdata->sound_data_read,
+                                &pdata->snd_buff_ready_mutex);
+                pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+                pdata->v_enc_thread_waiting=0;
+                continue;
+            }
+#endif
         }
-        if(pdata->sound_buffer==NULL || !pdata->running)
-            break;
-
-        pthread_mutex_lock(&pdata->sound_buffer_mutex);
-        buff=pdata->sound_buffer;
-        //advance the list
-        pdata->sound_buffer=pdata->sound_buffer->next;
-        pthread_mutex_unlock(&pdata->sound_buffer_mutex);
-        fwrite(buff->data,1,pdata->periodsize*framesize,
-               pdata->cache_data->afp);
         pdata->avd-=pdata->periodtime;
-
-        free(buff->data);
-        free(buff);
     }
 
     fclose(pdata->cache_data->afp);
diff --git a/recordmydesktop/src/encode_sound_buffer.c b/recordmydesktop/src/encode_sound_buffer.c
index c8a8781..7945567 100644
--- a/recordmydesktop/src/encode_sound_buffer.c
+++ b/recordmydesktop/src/encode_sound_buffer.c
@@ -29,43 +29,84 @@
 
 void *EncodeSoundBuffer(ProgData *pdata){
     int sampread=pdata->periodsize;
-
+#ifdef HAVE_JACK_H
+    void *jackbuf=NULL;
+    int framesize=sizeof(jack_default_audio_sample_t)*
+                         pdata->jdata->nports;
+    if(pdata->args.use_jack){
+        framesize=sizeof(jack_default_audio_sample_t)*
+                  pdata->jdata->nports;
+        jackbuf=malloc(framesize*pdata->jdata->buffersize);
+    }
+#endif
     pdata->v_encoding_clean=0;
     while((pdata->running)){
         float **vorbis_buffer;
         int count=0,i,j;
-        SndBuffer *buff;
+        SndBuffer *buff=NULL;
 
         if(Paused){
             pthread_mutex_lock(&pause_mutex);
             pthread_cond_wait(&pdata->pause_cond,&pause_mutex);
             pthread_mutex_unlock(&pause_mutex);
         }
-
-        if(pdata->sound_buffer==NULL){
-            pdata->v_enc_thread_waiting=1;
-            pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
-            pthread_cond_wait(&pdata->sound_data_read,
-                              &pdata->snd_buff_ready_mutex);
-            pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
-            pdata->v_enc_thread_waiting=0;
+        if(!pdata->args.use_jack){
+            if(pdata->sound_buffer==NULL){
+                pdata->v_enc_thread_waiting=1;
+                pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+                pthread_cond_wait(&pdata->sound_data_read,
+                                &pdata->snd_buff_ready_mutex);
+                pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+                pdata->v_enc_thread_waiting=0;
+            }
+            if(pdata->sound_buffer==NULL || !pdata->running)
+                break;
+            pthread_mutex_lock(&pdata->sound_buffer_mutex);
+            buff=pdata->sound_buffer;
+            //advance the list
+            pdata->sound_buffer=pdata->sound_buffer->next;
+            pthread_mutex_unlock(&pdata->sound_buffer_mutex);
+
+            vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,
+                                                 sampread);
+
+            for(i=0;i<sampread;i++){
+                for(j=0;j<pdata->args.channels;j++){
+                    vorbis_buffer[j][i]=((buff->data[count+1]<<8)|
+                                        (0x00ff&(int)buff->data[count]))/
+                                        32768.f;
+                    count+=2;
+                }
+            }
+            free(buff->data);
+            free(buff);
         }
-        if(pdata->sound_buffer==NULL || !pdata->running)
-            break;
-        pthread_mutex_lock(&pdata->sound_buffer_mutex);
-        buff=pdata->sound_buffer;
-        //advance the list
-        pdata->sound_buffer=pdata->sound_buffer->next;
-        pthread_mutex_unlock(&pdata->sound_buffer_mutex);
-
-        vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,
-                                             sampread);
-        for(i=0;i<sampread;i++){
-            for(j=0;j<pdata->args.channels;j++){
-                vorbis_buffer[j][i]=((buff->data[count+1]<<8)|
-                                     (0x00ff&(int)buff->data[count]))/32768.f;
-                count+=2;
+        else{
+#ifdef HAVE_JACK_H
+            if((*jack_ringbuffer_read_space_p)(pdata->jdata->sound_buffer)>=
+               (framesize*pdata->jdata->buffersize)){
+                (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer,
+                                          jackbuf,
+                                          (framesize*pdata->jdata->buffersize));
+                vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,
+                                                    sampread);
+                for(j=0;j<pdata->args.channels;j++){
+                    for(i=0;i<sampread;i++){
+                        vorbis_buffer[j][i]=((float*)jackbuf)[count];
+                        count++;
+                    }
+                }
+            }
+            else{
+                pdata->v_enc_thread_waiting=1;
+                pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+                pthread_cond_wait(&pdata->sound_data_read,
+                                &pdata->snd_buff_ready_mutex);
+                pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+                pdata->v_enc_thread_waiting=0;
+                continue;
             }
+#endif
         }
         vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread);
 
@@ -86,8 +127,7 @@ void *EncodeSoundBuffer(ProgData *pdata){
 
         pdata->avd-=pdata->periodtime;
 
-        free(buff->data);
-        free(buff);
+
     }
 
     pdata->v_encoding_clean=1;
@@ -103,11 +143,23 @@ void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){
     int sampread=(buff!=NULL)?pdata->periodsize:0;
 
     vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread);
-    for(i=0;i<sampread;i++){
+
+    if(!pdata->args.use_jack){
+        for(i=0;i<sampread;i++){
+            for(j=0;j<pdata->args.channels;j++){
+                vorbis_buffer[j][i]=((buff[count+1]<<8)|
+                                        (0x00ff&(int)buff[count]))/
+                                    32768.f;
+                count+=2;
+            }
+        }
+    }
+    else{
         for(j=0;j<pdata->args.channels;j++){
-            vorbis_buffer[j][i]=((buff[count+1]<<8)|
-                                    (0x00ff&(int)buff[count]))/32768.f;
-            count+=2;
+            for(i=0;i<sampread;i++){
+                vorbis_buffer[j][i]=((float*)buff)[count];
+                count++;
+            }
         }
     }
 
diff --git a/recordmydesktop/src/get_frame.c b/recordmydesktop/src/get_frame.c
index 31dba8d..87e71aa 100644
--- a/recordmydesktop/src/get_frame.c
+++ b/recordmydesktop/src/get_frame.c
@@ -58,7 +58,6 @@ void *GetFrame(ProgData *pdata){
             }
         }
         capture_busy=1;
-
         //mutexes and lists with changes are useless when full_shots is enabled
         if(!pdata->args.full_shots){
             tlist_sel=pdata->list_selector;
diff --git a/recordmydesktop/src/initialize_data.c b/recordmydesktop/src/initialize_data.c
index d8f52c0..74d32cf 100644
--- a/recordmydesktop/src/initialize_data.c
+++ b/recordmydesktop/src/initialize_data.c
@@ -27,6 +27,22 @@
 
 #include <recordmydesktop.h>
 
+#ifdef HAVE_LIBASOUND
+void FixBufferSize(snd_pcm_uframes_t *buffsize){
+    snd_pcm_uframes_t buffsize_t=*buffsize,
+#else
+void FixBufferSize(u_int32_t *buffsize){
+    u_int32_t buffsize_t=*buffsize,
+#endif
+                          buffsize_ret=1;
+    while(buffsize_t>1){
+        buffsize_t>>=1;
+        buffsize_ret<<=1;
+    }
+    fprintf(stderr,"Buffer size adjusted to %d from %d frames.\n",
+                   (int)buffsize_ret,(int)*buffsize);
+}
+
 int InitializeData(ProgData *pdata,
                    EncData *enc_data,
                    CacheData *cache_data){
@@ -124,30 +140,56 @@ int InitializeData(ProgData *pdata,
                      AllPlanes);
     }
     if(!pdata->args.nosound){
+        if(!pdata->args.use_jack){
+            FixBufferSize(&pdata->args.buffsize);
 #ifdef HAVE_LIBASOUND
-        pdata->sound_handle=OpenDev( pdata->args.device,
-                                    &pdata->args.channels,
-                                    &pdata->args.frequency,
-                                    &pdata->args.buffsize,
-                                    &pdata->periodsize,
-                                    &pdata->periodtime,
-                                    &pdata->hard_pause);
-        if(pdata->sound_handle==NULL){
+            pdata->sound_handle=OpenDev( pdata->args.device,
+                                        &pdata->args.channels,
+                                        &pdata->args.frequency,
+                                        &pdata->args.buffsize,
+                                        &pdata->periodsize,
+                                        &pdata->periodtime,
+                                        &pdata->hard_pause);
+            if(pdata->sound_handle==NULL){
 #else
-        pdata->sound_handle=OpenDev(pdata->args.device,
-                                    pdata->args.channels,
-                                    pdata->args.frequency);
-        pdata->periodtime=(1000000*pdata->args.buffsize)/
-                          ((pdata->args.channels<<1)*pdata->args.frequency);
-        //when using OSS periodsize serves as an alias of buffsize
-        pdata->periodsize=pdata->args.buffsize;
-        if(pdata->sound_handle<0){
+            pdata->sound_handle=OpenDev(pdata->args.device,
+                                        pdata->args.channels,
+                                        pdata->args.frequency);
+            pdata->periodtime=(1000000*pdata->args.buffsize)/
+                            ((pdata->args.channels<<1)*pdata->args.frequency);
+            //when using OSS periodsize serves as an alias of buffsize
+            pdata->periodsize=pdata->args.buffsize;
+            if(pdata->sound_handle<0){
+#endif
+                fprintf(stderr,"Error while opening/configuring soundcard %s\n"
+                            "Try running with the --no-sound or specify a "
+                            "correct device.\n",
+                            pdata->args.device);
+                return 3;
+            }
+        }
+        else{
+#ifdef HAVE_JACK_H
+            int jack_error=0;
+            pdata->jdata->port_names=pdata->args.jack_port_names;
+            pdata->jdata->nports=pdata->args.jack_nports;
+            pdata->jdata->snd_buff_ready_mutex=&pdata->snd_buff_ready_mutex;
+            pdata->jdata->sound_data_read=&pdata->sound_data_read;
+            pdata->jdata->capture_started=0;
+
+            if((jack_error=StartJackClient(pdata->jdata))!=0)
+                return jack_error;
+
+            pdata->args.buffsize=pdata->jdata->buffersize;
+            pdata->periodsize=pdata->args.buffsize;
+            pdata->args.frequency=pdata->jdata->frequency;
+            pdata->args.channels=pdata->jdata->nports;
+            pdata->periodtime=(1000000*pdata->args.buffsize)/
+                              pdata->args.frequency;
+#else
+            fprintf(stderr,"Should not be here!\n");
+            exit(-1);
 #endif
-            fprintf(stderr,"Error while opening/configuring soundcard %s\n"
-                           "Try running with the --no-sound or specify a "
-                           "correct device.\n",
-                           pdata->args.device);
-            return 3;
         }
     }
 
@@ -176,7 +218,6 @@ int InitializeData(ProgData *pdata,
             pdata->specs.depth);
 
     pdata->frametime=(1000000)/pdata->args.fps;
-
     return 0;
 
 }
diff --git a/recordmydesktop/src/load_cache.c b/recordmydesktop/src/load_cache.c
index f75c375..78c81c5 100644
--- a/recordmydesktop/src/load_cache.c
+++ b/recordmydesktop/src/load_cache.c
@@ -137,6 +137,11 @@ void *LoadCache(ProgData *pdata){
                   pdata->args.channels;//audio frame size
 #else
     int framesize=pdata->args.channels<<1;//Always signed 16 bit data
+#endif
+#ifdef HAVE_JACK_H
+    if(pdata->args.use_jack)
+        framesize=sizeof(jack_default_audio_sample_t)*
+                  pdata->jdata->nports;
 #endif
     signed char *sound_data=(signed char *)malloc(pdata->periodsize*framesize);
 
diff --git a/recordmydesktop/src/opendev.c b/recordmydesktop/src/opendev.c
index 7810ec6..ea6f436 100644
--- a/recordmydesktop/src/opendev.c
+++ b/recordmydesktop/src/opendev.c
@@ -109,7 +109,6 @@ snd_pcm_t *OpenDev( const char *pcm_dev,
         snd_pcm_hw_params_get_period_time(hwparams,periodtime,0);
     fprintf(stderr,"Recording on device %s is set to:\n%d channels at %dHz\n",
                    pcm_dev,*channels,*frequency);
-    fprintf(stderr,"Buffer size set to %d frames.\n",(int)(*buffsize));
     snd_pcm_prepare(mhandle);
 
     return mhandle;
diff --git a/recordmydesktop/src/parseargs.c b/recordmydesktop/src/parseargs.c
index 9cda42b..4643bf1 100644
--- a/recordmydesktop/src/parseargs.c
+++ b/recordmydesktop/src/parseargs.c
@@ -27,11 +27,26 @@
 
 #include <recordmydesktop.h>
 
+void PrintConfig(void){
+    fprintf(stderr,"\nrecordMyDesktop was compiled with"
+                   " the following options:\n\n");
+#ifdef HAVE_JACK_H
+    fprintf(stdout,"Jack\t\t\t:Enabled\n");
+#else
+    fprintf(stdout,"Jack\t\t\t:Disabled\n");
+#endif
+#ifdef HAVE_LIBASOUND
+    fprintf(stdout,"Default Audio Backend\t:ALSA\n");
+#else
+    fprintf(stdout,"Default Audio Backend\t:OSS\n");
+#endif
+    fprintf(stderr,"\n\n");
+}
 
 int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
     int i;
     char *usage="\nUsage:\n"
-    "\trecordmydesktop [-h| --help| --version|"
+    "\trecordmydesktop [-h| --help| --version| --print-config|"
     " -delay n[H|h|M|m]| -windowid id_of_window|\n"
     "\t-display DISPLAY| -x X| -y Y|-width N| -height N|"
     " -fps N(number>0)| --on-the-fly-encoding|\n"
@@ -39,14 +54,17 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
     " -dummy-cursor color|\n"
     "\t --no-cursor| -freq N(number>0)| -channels N(number>0)|"
     " -buffer-size N(number>0)| -device SOUND_DEVICE|\n"
-    "\t --no-sound| --with-shared| --no-cond-shared| -shared-threshold n|"
+    "\t -use-jack port1 port2... portn| --no-sound| --with-shared|"
+    " --no-cond-shared| -shared-threshold n|"
     " --full-shots|\n"
     "\t --quick-subsampling| -workdir DIR| --zero-compression| --no-wm-check|"
     " --overwite| -o filename]^filename\n\n\n"
 
     "General Options:\n"
     "\t-h or --help\t\tPrint this help and exit.\n"
-    "\t--version\t\tPrint program version and exit.\n\n"
+    "\t--version\t\tPrint program version and exit.\n"
+    "\t--print-config\t\tPrint info about options "
+    "selected during compilation and exit.\n\n"
 
     "Image Options:\n"
     "\t-windowid id_of_window\tid of window to be recorded.\n"
@@ -74,17 +92,19 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
     "\t-fps N(number>0.0)\tA positive number denoting desired framerate.\n\n"
 
     "Sound Options:\n"
-    "\t-channels N\t\tA positive number denoting"
+    "\t-channels N\t\t\tA positive number denoting"
     " desired sound channels in recording.\n"
 
-    "\t-freq N\t\t\tA positive number denoting desired sound frequency.\n"
-    "\t-buffer-size N\t\tA positive number denoting the desired"
+    "\t-freq N\t\t\t\tA positive number denoting desired sound frequency.\n"
+    "\t-buffer-size N\t\t\tA positive number denoting the desired"
     " sound buffer size(in frames)\n"
 
-    "\t-device SOUND_DEVICE\tSound device(default "
+    "\t-device SOUND_DEVICE\t\tSound device(default "
     DEFAULT_AUDIO_DEVICE
     ").\n"
-    "\t--no-sound\t\tDo not record sound.\n\n"
+    "\t-use-jack port1 port2... portn\tRecord audio from the specified\n"
+    "\t\t\t\t\tlist of space-separated jack ports.\n"
+    "\t--no-sound\t\t\tDo not record sound.\n\n"
 
     "Encoding Options\n"
     "\t--on-the-fly-encoding\tEncode the audio-video data, while recording.\n"
@@ -446,6 +466,44 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
             }
             i++;
         }
+        else if(!strcmp(argv[i],"-use-jack")){
+            if(i+1<argc){
+#ifdef HAVE_JACK_H
+                int k=i+1;
+                arg_return->jack_nports=0;
+                while((k<argc)&&(argv[k][0]!='-')){
+                    arg_return->jack_nports++;
+                    k++;
+                }
+                if(arg_return->jack_nports>0){
+                    arg_return->jack_port_names=malloc(sizeof(char*)*
+                                                       arg_return->jack_nports);
+                    for(k=i+1;k<i+1+arg_return->jack_nports;k++){
+                        arg_return->jack_port_names[k-i-1]=
+                            malloc(strlen(argv[k])+1);
+                        strcpy(arg_return->jack_port_names[k-i-1],
+                               argv[k]);
+                    }
+                    i+=arg_return->jack_nports;
+                    arg_return->use_jack=1;
+                }
+                else{
+                    fprintf(stderr,"Argument Usage: -use-jack port1"
+                                   " port2... portn\n");
+                    return 1;
+                }
+#else
+                fprintf(stderr,"recordMyDesktop is not compiled"
+                               " with Jack support!\n");
+                return 1;
+#endif
+            }
+            else{
+                fprintf(stderr,"Argument Usage: -use-jack port1"
+                               " port2... portn\n");
+                return 1;
+            }
+        }
         else if(!strcmp(argv[i],"--no-sound"))
             arg_return->nosound=1;
         else if(!strcmp(argv[i],"--drop-frames"))
@@ -475,11 +533,15 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
         }
         else if(!strcmp(argv[i],"--help")||!strcmp(argv[i],"-h")){
             fprintf(stderr,"%s",usage);
-            return 1;
+            exit(0);
         }
         else if(!strcmp(argv[i],"--version")){
             fprintf(stderr,"recordMyDesktop v%s\n\n",VERSION);
-            return 1;
+            exit(0);
+        }
+        else if(!strcmp(argv[i],"--print-config")){
+            PrintConfig();
+            exit(0);
         }
         else{
             fprintf(stderr,"\n\tError parsing arguments.\n\t"
diff --git a/recordmydesktop/src/recordmydesktop.c b/recordmydesktop/src/recordmydesktop.c
index c832a3e..f30485c 100644
--- a/recordmydesktop/src/recordmydesktop.c
+++ b/recordmydesktop/src/recordmydesktop.c
@@ -30,6 +30,7 @@
 
 int main(int argc,char **argv){
     ProgData pdata;
+
     int exit_status=0;
     if(XInitThreads ()==0){
         fprintf(stderr,"Couldn't initialize thread support!\n");
@@ -52,7 +53,10 @@ int main(int argc,char **argv){
     else{
         EncData enc_data;
         CacheData cache_data;
-
+#ifdef HAVE_JACK_H
+        JackData jdata;
+        pdata.jdata=&jdata;
+#endif
         QUERY_DISPLAY_SPECS(pdata.dpy,&pdata.specs);
         if((pdata.specs.depth!=32)&&
            (pdata.specs.depth!=24)&&
diff --git a/recordmydesktop/src/register_callbacks.c b/recordmydesktop/src/register_callbacks.c
index 7f8d04f..2c5a8a3 100644
--- a/recordmydesktop/src/register_callbacks.c
+++ b/recordmydesktop/src/register_callbacks.c
@@ -32,14 +32,16 @@ void SetExpired(int signum){
         if(capture_busy){
             frames_lost++;
         }
+/*FIXME */
+//This is not safe.
+//cond_var signaling must move away from signal handlers
+//alltogether (JackCapture, SetExpired, SetPaused).
+//Better would be a set of pipes for each of these.
+//The callback should write on the pipe and the main thread
+//should perform a select over the fd's, signaling afterwards the
+//appropriate cond_var.
         pthread_mutex_lock(&time_mutex);
-        pthread_cond_broadcast(time_cond);  //sig handlers should
-                                            //not call this func
-                                            //could be a set_expired
-                                            // and main thread
-                                            //doing a while(running)
-                                            //if set_expired broadcast
-                                            //else usleep(n)
+        pthread_cond_broadcast(time_cond);
         pthread_mutex_unlock(&time_mutex);
     }
 }
@@ -49,6 +51,14 @@ void SetPaused(int signum){
         Paused=1;
     else{
         Paused=0;
+/*FIXME */
+//This is not safe.
+//cond_var signaling must move away from signal handlers
+//alltogether (JackCapture, SetExpired, SetPaused).
+//Better would be a set of pipes for each of these.
+//The callback should write on the pipe and the main thread
+//should perform a select over the fd's, signaling afterwards the
+//appropriate cond_var.
         pthread_mutex_lock(&pause_mutex);
         pthread_cond_broadcast(pause_cond);
         pthread_mutex_unlock(&pause_mutex);
diff --git a/recordmydesktop/src/rmd_jack.c b/recordmydesktop/src/rmd_jack.c
new file mode 100644
index 0000000..6d846a1
--- /dev/null
+++ b/recordmydesktop/src/rmd_jack.c
@@ -0,0 +1,208 @@
+/******************************************************************************
+*                            recordMyDesktop                                  *
+*******************************************************************************
+*                                                                             *
+*            Copyright (C) 2006,2007 John Varouhakis                          *
+*                                                                             *
+*                                                                             *
+*   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  *
+*                                                                             *
+*                                                                             *
+*                                                                             *
+*   For further information contact me at johnvarouhakis@gmail.com            *
+******************************************************************************/
+
+
+#include <recordmydesktop.h>
+
+#ifdef HAVE_JACK_H
+int JackCapture(jack_nframes_t nframes,void *jdata_t){
+    int i=0;
+    JackData *jdata=(JackData *)jdata_t;
+
+    if((!*Running)||(Paused) || (!jdata->capture_started))
+        return 0;
+    for(i= 0;i<jdata->nports;i++)
+        jdata->portbuf[i]=jack_port_get_buffer_p(jdata->ports[i],nframes);
+//vorbis analysis buffer wants uninterleaved data
+//so we are simply placing the buffers for every channel
+//sequentially on the ringbuffer
+    for(i=0;i<jdata->nports;i++)
+        (*jack_ringbuffer_write_p)(jdata->sound_buffer,
+                                   (void *)(jdata->portbuf[i]),
+                                   nframes*
+                                   sizeof(jack_default_audio_sample_t));
+/*FIXME */
+//This is not safe.
+//cond_var signaling must move away from signal handlers
+//alltogether (JackCapture, SetExpired, SetPaused).
+//Better would be a set of pipes for each of these.
+//The callback should write on the pipe and the main thread
+//should perform a select over the fd's, signaling afterwards the
+//appropriate cond_var.
+    pthread_mutex_lock(jdata->snd_buff_ready_mutex);
+    pthread_cond_signal(jdata->sound_data_read);
+    pthread_mutex_unlock(jdata->snd_buff_ready_mutex);
+
+    return 0;
+}
+
+int SetupPorts(JackData *jdata){
+    int i=0;
+    jdata->ports=malloc(sizeof(jack_port_t *)*
+                               jdata->nports);
+    jdata->portbuf=malloc(sizeof(jack_default_audio_sample_t*)*
+                          jdata->nports);
+    memset(jdata->portbuf,0,sizeof(jack_default_audio_sample_t*)*
+                            jdata->nports);
+
+    for(i=0;i<jdata->nports;i++){
+        char name[64];//recordMyDesktop:input_n<64 is enough for full name
+        char num[8];
+        strcpy(name,"input_");
+        I16TOA((i+1),num);
+        strcat(name,num);
+        if((jdata->ports[i]=jack_port_register_p(jdata->client,
+                                                 name,
+                                                 JACK_DEFAULT_AUDIO_TYPE,
+                                                 JackPortIsInput,
+                                                 0))==0){
+            fprintf(stderr,"Cannot register input port \"%s\"!\n",name);
+            return 1;
+        }
+        if(jack_connect_p(jdata->client,
+                          jdata->port_names[i],
+                          jack_port_name_p(jdata->ports[i]))){
+            fprintf(stderr,"Cannot connect input port %s to %s\n",
+                           jack_port_name_p(jdata->ports[i]),
+                           jdata->port_names[i]);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+int LoadJackLib(void *jack_lib_handle){
+    char *error;
+    jack_lib_handle=dlopen("libjack.so",RTLD_LAZY);
+    if(!jack_lib_handle){
+        fprintf(stderr,"%s\n",dlerror());
+        return 1;
+    }
+    if((error=dlerror())!=NULL){
+        fprintf(stderr,"%s\n",dlerror());
+    }
+//this macro will call return with status 1 on failure
+    DLSYM_AND_CHECK(jack_lib_handle,jack_client_new,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_get_sample_rate,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_set_buffer_size,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_get_buffer_size,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_set_process_callback,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_on_shutdown,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_activate,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_client_close,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_port_get_buffer,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_port_register,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_connect,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_port_name,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_port_name_size,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_create,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_free,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_read,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_read_space,error)
+    DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_write,error)
+
+    return 0;
+}
+//in case the jack server shuts down
+//the program should stop recording,
+//encode the result(if not on the fly)
+//an exit cleanly.
+void JackShutdown(void *jdata_t){
+    fprintf (stderr, "JACK shutdown\n");
+    *Running=0;
+}
+
+int StartJackClient(JackData *jdata){
+
+    if(LoadJackLib(jdata->jack_lib_handle)){
+        fprintf (stderr,"Couldn't load the Jack library (libjack.so)!\n");
+        return 14;
+    }
+    if ((jdata->client=(*jack_client_new_p)("recordMyDesktop"))==0){
+        fprintf(stderr,"Could not create new client!\n"
+                       "Make sure that Jack server is running!\n");
+        return 15;
+    }
+//in contrast to ALSA and OSS, Jack dictates frequency
+//and buffersize to the values it was launched with.
+//Supposedly jack_set_buffer_size can set the buffersize
+//but that causes some kind of halt and keeps giving me
+//zero buffers.
+//recordMyDesktop cannot handle buffer size changes.
+//FIXME
+//There is a callback for buffer size changes that I should use.
+//It will provide clean exits, instead of ?segfaults? .
+//Continuing though is not possible, with the current layout
+//(it might be in some cases, but it will certainly be the cause
+//of unpredicted problems). A clean exit is preferable
+//and any recording up to that point will be encoded and saved.
+    jdata->frequency=jack_get_sample_rate_p(jdata->client);
+    jdata->buffersize=jack_get_buffer_size_p(jdata->client);
+    jdata->sound_buffer=
+        (*jack_ringbuffer_create_p)(jdata->nports*
+                                    sizeof(jack_default_audio_sample_t)*
+                                    jdata->buffersize*
+                                    BUFFERS_IN_RING);
+    jack_set_process_callback_p(jdata->client,JackCapture,jdata);
+    jack_on_shutdown_p(jdata->client,JackShutdown,jdata);
+
+    if (jack_activate_p(jdata->client)) {
+        fprintf(stderr,"cannot activate client!\n");
+        return 16;
+    }
+    if(SetupPorts(jdata)){
+        jack_client_close_p(jdata->client);
+        return 17;
+    }
+
+    return 0;
+}
+
+int StopJackClient(JackData *jdata){
+    int ret=0;
+
+    (*jack_ringbuffer_free_p)(jdata->sound_buffer);
+    if(jack_client_close_p(jdata->client)){
+        fprintf(stderr,"Cannot close Jack client!\n");
+        ret=1;
+    }
+
+/*TODO*/
+//I need to make some kind of program/thread
+//flow diagram to see where it's safe to dlclose
+//because here it causes a segfault.
+
+//     if(dlclose(jdata->jack_lib_handle)){
+//         fprintf(stderr,"Cannot unload Jack library!\n");
+//         ret=1;
+//     }
+//     else fprintf(stderr,"Unloaded Jack library.\n");
+
+    return ret;
+}
+
+#endif
+
diff --git a/recordmydesktop/src/rmdthreads.c b/recordmydesktop/src/rmdthreads.c
index 4199472..014a1d6 100644
--- a/recordmydesktop/src/rmdthreads.c
+++ b/recordmydesktop/src/rmdthreads.c
@@ -65,10 +65,11 @@ void rmdThreads(ProgData *pdata){
                        (void *)pdata);
 
     if(!pdata->args.nosound){
-        pthread_create(&sound_capture_t,
-                       NULL,
-                       (void *)CaptureSound,
-                       (void *)pdata);
+        if(!pdata->args.use_jack)
+            pthread_create(&sound_capture_t,
+                        NULL,
+                        (void *)CaptureSound,
+                        (void *)pdata);
         if(pdata->args.encOnTheFly)
             pthread_create(&sound_encode_t,
                            NULL,
@@ -88,7 +89,11 @@ void rmdThreads(ProgData *pdata){
 
     RegisterCallbacks(&pdata->args);
     fprintf(stderr,"Capturing!\n");
-
+#ifdef HAVE_JACK_H
+    if(pdata->args.use_jack){
+        pdata->jdata->capture_started=1;
+    }
+#endif
     //wait all threads to finish
 
     pthread_join(image_capture_t,NULL);
@@ -108,9 +113,14 @@ void rmdThreads(ProgData *pdata){
         pthread_join(image_cache_t,NULL);
     fprintf(stderr,".");
     if(!pdata->args.nosound){
-        pthread_join(sound_capture_t,NULL);
+#ifdef HAVE_JACK_H
+        if(pdata->args.use_jack)
+            StopJackClient(pdata->jdata);
+#endif
+        if(!pdata->args.use_jack)
+            pthread_join(sound_capture_t,NULL);
         fprintf(stderr,".");
-        while(!pdata->v_enc_thread_waiting && !pdata->v_encoding_clean){
+        while(pdata->v_enc_thread_waiting || !pdata->v_encoding_clean){
             usleep(10000);
             pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
             pthread_cond_signal(&pdata->sound_data_read);
-- 
cgit v1.2.3