summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a>2007-02-07 18:44:02 +0000
committeriovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a>2007-02-07 18:44:02 +0000
commit9c05582a007788295d872172c5109ae9bccfcf68 (patch)
tree6c2275255f4c38d819b27da2978e7f74715c8050
parentf39f779f299cd78a574999830699e30f92932f06 (diff)
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
-rw-r--r--recordmydesktop/configure.ac44
-rw-r--r--recordmydesktop/doc/recordmydesktop.129
-rw-r--r--recordmydesktop/include/rmdfunc.h104
-rw-r--r--recordmydesktop/include/rmdmacro.h43
-rw-r--r--recordmydesktop/include/rmdtypes.h37
-rw-r--r--recordmydesktop/src/Makefile.am3
-rw-r--r--recordmydesktop/src/cache_audio.c72
-rw-r--r--recordmydesktop/src/encode_sound_buffer.c114
-rw-r--r--recordmydesktop/src/get_frame.c1
-rw-r--r--recordmydesktop/src/initialize_data.c85
-rw-r--r--recordmydesktop/src/load_cache.c5
-rw-r--r--recordmydesktop/src/opendev.c1
-rw-r--r--recordmydesktop/src/parseargs.c82
-rw-r--r--recordmydesktop/src/recordmydesktop.c6
-rw-r--r--recordmydesktop/src/register_callbacks.c24
-rw-r--r--recordmydesktop/src/rmd_jack.c208
-rw-r--r--recordmydesktop/src/rmdthreads.c24
17 files changed, 753 insertions, 129 deletions
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
@@ -271,6 +284,15 @@ Sound Options:
.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.
.br
@@ -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
@@ -36,36 +36,66 @@ void *CacheSoundBuffer(ProgData *pdata){
#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
@@ -138,6 +138,11 @@ void *LoadCache(ProgData *pdata){
#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);
u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES],
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);
© All Rights Reserved