diff options
Diffstat (limited to 'recordmydesktop')
-rw-r--r-- | recordmydesktop/configure.ac | 44 | ||||
-rw-r--r-- | recordmydesktop/doc/recordmydesktop.1 | 29 | ||||
-rw-r--r-- | recordmydesktop/include/rmdfunc.h | 104 | ||||
-rw-r--r-- | recordmydesktop/include/rmdmacro.h | 43 | ||||
-rw-r--r-- | recordmydesktop/include/rmdtypes.h | 37 | ||||
-rw-r--r-- | recordmydesktop/src/Makefile.am | 3 | ||||
-rw-r--r-- | recordmydesktop/src/cache_audio.c | 72 | ||||
-rw-r--r-- | recordmydesktop/src/encode_sound_buffer.c | 114 | ||||
-rw-r--r-- | recordmydesktop/src/get_frame.c | 1 | ||||
-rw-r--r-- | recordmydesktop/src/initialize_data.c | 85 | ||||
-rw-r--r-- | recordmydesktop/src/load_cache.c | 5 | ||||
-rw-r--r-- | recordmydesktop/src/opendev.c | 1 | ||||
-rw-r--r-- | recordmydesktop/src/parseargs.c | 82 | ||||
-rw-r--r-- | recordmydesktop/src/recordmydesktop.c | 6 | ||||
-rw-r--r-- | recordmydesktop/src/register_callbacks.c | 24 | ||||
-rw-r--r-- | recordmydesktop/src/rmd_jack.c | 208 | ||||
-rw-r--r-- | recordmydesktop/src/rmdthreads.c | 24 |
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); |