summaryrefslogtreecommitdiff
path: root/recordmydesktop
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 /recordmydesktop
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
Diffstat (limited to 'recordmydesktop')
-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