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); | 
