From 9c05582a007788295d872172c5109ae9bccfcf68 Mon Sep 17 00:00:00 2001 From: iovar Date: Wed, 7 Feb 2007 18:44:02 +0000 Subject: Added support for recording audio through jack. libjack is dlopened so there's no runtime dependency on it. Ports must be connected at startup. New files: src/rmd_jack.c git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@273 f606c939-3180-4ac9-a4b8-4b8779d57d0a --- recordmydesktop/include/rmdfunc.h | 104 +++++++++++++++++++++++++++++++++++++ recordmydesktop/include/rmdmacro.h | 43 ++++++++++----- recordmydesktop/include/rmdtypes.h | 37 +++++++++++-- 3 files changed, 168 insertions(+), 16 deletions(-) (limited to 'recordmydesktop/include') 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 #endif +#ifdef HAVE_JACK_H + #include + #include + #include +#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 -- cgit v1.2.1