summaryrefslogtreecommitdiff
path: root/recordmydesktop/src
diff options
context:
space:
mode:
authoriovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a>2007-02-07 18:44:02 +0000
committeriovar <iovar@f606c939-3180-4ac9-a4b8-4b8779d57d0a>2007-02-07 18:44:02 +0000
commit9c05582a007788295d872172c5109ae9bccfcf68 (patch)
tree6c2275255f4c38d819b27da2978e7f74715c8050 /recordmydesktop/src
parentf39f779f299cd78a574999830699e30f92932f06 (diff)
Added support for recording audio through jack.
libjack is dlopened so there's no runtime dependency on it. Ports must be connected at startup. New files: src/rmd_jack.c git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@273 f606c939-3180-4ac9-a4b8-4b8779d57d0a
Diffstat (limited to 'recordmydesktop/src')
-rw-r--r--recordmydesktop/src/Makefile.am3
-rw-r--r--recordmydesktop/src/cache_audio.c72
-rw-r--r--recordmydesktop/src/encode_sound_buffer.c114
-rw-r--r--recordmydesktop/src/get_frame.c1
-rw-r--r--recordmydesktop/src/initialize_data.c85
-rw-r--r--recordmydesktop/src/load_cache.c5
-rw-r--r--recordmydesktop/src/opendev.c1
-rw-r--r--recordmydesktop/src/parseargs.c82
-rw-r--r--recordmydesktop/src/recordmydesktop.c6
-rw-r--r--recordmydesktop/src/register_callbacks.c24
-rw-r--r--recordmydesktop/src/rmd_jack.c208
-rw-r--r--recordmydesktop/src/rmdthreads.c24
12 files changed, 523 insertions, 102 deletions
diff --git a/recordmydesktop/src/Makefile.am b/recordmydesktop/src/Makefile.am
index 98ddda2..879c7b7 100644
--- a/recordmydesktop/src/Makefile.am
+++ b/recordmydesktop/src/Makefile.am
@@ -27,7 +27,8 @@ recordmydesktop_SOURCES= recordmydesktop.c\
wm_check.c\
encode_cache.c\
rmdthreads.c\
- initialize_data.c
+ initialize_data.c\
+ rmd_jack.c
INCLUDES= $(all_includes) -I../include
diff --git a/recordmydesktop/src/cache_audio.c b/recordmydesktop/src/cache_audio.c
index bff4df2..7896df7 100644
--- a/recordmydesktop/src/cache_audio.c
+++ b/recordmydesktop/src/cache_audio.c
@@ -36,36 +36,66 @@ void *CacheSoundBuffer(ProgData *pdata){
#else
int framesize=pdata->args.channels<<1;//Always signed 16 bit data
#endif
+#ifdef HAVE_JACK_H
+ void *jackbuf=NULL;
+ if(pdata->args.use_jack){
+ framesize=sizeof(jack_default_audio_sample_t)*
+ pdata->jdata->nports;
+ jackbuf=malloc(framesize*pdata->jdata->buffersize);
+ }
+#endif
while((pdata->running)){
- SndBuffer *buff;
+ SndBuffer *buff=NULL;
if(Paused){
pthread_mutex_lock(&pause_mutex);
pthread_cond_wait(&pdata->pause_cond,&pause_mutex);
pthread_mutex_unlock(&pause_mutex);
}
- if(pdata->sound_buffer==NULL){
- pdata->v_enc_thread_waiting=1;
- pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
- pthread_cond_wait(&pdata->sound_data_read,
- &pdata->snd_buff_ready_mutex);
- pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
- pdata->v_enc_thread_waiting=0;
+ if(!pdata->args.use_jack){
+ if(pdata->sound_buffer==NULL){
+ pdata->v_enc_thread_waiting=1;
+ pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+ pthread_cond_wait(&pdata->sound_data_read,
+ &pdata->snd_buff_ready_mutex);
+ pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+ pdata->v_enc_thread_waiting=0;
+ }
+ if(pdata->sound_buffer==NULL || !pdata->running){
+ break;
+ }
+ pthread_mutex_lock(&pdata->sound_buffer_mutex);
+ buff=pdata->sound_buffer;
+ //advance the list
+ pdata->sound_buffer=pdata->sound_buffer->next;
+ pthread_mutex_unlock(&pdata->sound_buffer_mutex);
+ fwrite(buff->data,1,pdata->periodsize*framesize,
+ pdata->cache_data->afp);
+ free(buff->data);
+ free(buff);
+ }
+ else{
+#ifdef HAVE_JACK_H
+ if((*jack_ringbuffer_read_space_p)(pdata->jdata->sound_buffer)>=
+ (framesize*pdata->jdata->buffersize)){
+ (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer,
+ jackbuf,
+ (framesize*pdata->jdata->buffersize));
+ fwrite(jackbuf,1,(framesize*pdata->jdata->buffersize),
+ pdata->cache_data->afp);
+ }
+ else{
+ pdata->v_enc_thread_waiting=1;
+ pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+ pthread_cond_wait(&pdata->sound_data_read,
+ &pdata->snd_buff_ready_mutex);
+ pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+ pdata->v_enc_thread_waiting=0;
+ continue;
+ }
+#endif
}
- if(pdata->sound_buffer==NULL || !pdata->running)
- break;
-
- pthread_mutex_lock(&pdata->sound_buffer_mutex);
- buff=pdata->sound_buffer;
- //advance the list
- pdata->sound_buffer=pdata->sound_buffer->next;
- pthread_mutex_unlock(&pdata->sound_buffer_mutex);
- fwrite(buff->data,1,pdata->periodsize*framesize,
- pdata->cache_data->afp);
pdata->avd-=pdata->periodtime;
-
- free(buff->data);
- free(buff);
}
fclose(pdata->cache_data->afp);
diff --git a/recordmydesktop/src/encode_sound_buffer.c b/recordmydesktop/src/encode_sound_buffer.c
index c8a8781..7945567 100644
--- a/recordmydesktop/src/encode_sound_buffer.c
+++ b/recordmydesktop/src/encode_sound_buffer.c
@@ -29,43 +29,84 @@
void *EncodeSoundBuffer(ProgData *pdata){
int sampread=pdata->periodsize;
-
+#ifdef HAVE_JACK_H
+ void *jackbuf=NULL;
+ int framesize=sizeof(jack_default_audio_sample_t)*
+ pdata->jdata->nports;
+ if(pdata->args.use_jack){
+ framesize=sizeof(jack_default_audio_sample_t)*
+ pdata->jdata->nports;
+ jackbuf=malloc(framesize*pdata->jdata->buffersize);
+ }
+#endif
pdata->v_encoding_clean=0;
while((pdata->running)){
float **vorbis_buffer;
int count=0,i,j;
- SndBuffer *buff;
+ SndBuffer *buff=NULL;
if(Paused){
pthread_mutex_lock(&pause_mutex);
pthread_cond_wait(&pdata->pause_cond,&pause_mutex);
pthread_mutex_unlock(&pause_mutex);
}
-
- if(pdata->sound_buffer==NULL){
- pdata->v_enc_thread_waiting=1;
- pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
- pthread_cond_wait(&pdata->sound_data_read,
- &pdata->snd_buff_ready_mutex);
- pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
- pdata->v_enc_thread_waiting=0;
+ if(!pdata->args.use_jack){
+ if(pdata->sound_buffer==NULL){
+ pdata->v_enc_thread_waiting=1;
+ pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+ pthread_cond_wait(&pdata->sound_data_read,
+ &pdata->snd_buff_ready_mutex);
+ pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+ pdata->v_enc_thread_waiting=0;
+ }
+ if(pdata->sound_buffer==NULL || !pdata->running)
+ break;
+ pthread_mutex_lock(&pdata->sound_buffer_mutex);
+ buff=pdata->sound_buffer;
+ //advance the list
+ pdata->sound_buffer=pdata->sound_buffer->next;
+ pthread_mutex_unlock(&pdata->sound_buffer_mutex);
+
+ vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,
+ sampread);
+
+ for(i=0;i<sampread;i++){
+ for(j=0;j<pdata->args.channels;j++){
+ vorbis_buffer[j][i]=((buff->data[count+1]<<8)|
+ (0x00ff&(int)buff->data[count]))/
+ 32768.f;
+ count+=2;
+ }
+ }
+ free(buff->data);
+ free(buff);
}
- if(pdata->sound_buffer==NULL || !pdata->running)
- break;
- pthread_mutex_lock(&pdata->sound_buffer_mutex);
- buff=pdata->sound_buffer;
- //advance the list
- pdata->sound_buffer=pdata->sound_buffer->next;
- pthread_mutex_unlock(&pdata->sound_buffer_mutex);
-
- vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,
- sampread);
- for(i=0;i<sampread;i++){
- for(j=0;j<pdata->args.channels;j++){
- vorbis_buffer[j][i]=((buff->data[count+1]<<8)|
- (0x00ff&(int)buff->data[count]))/32768.f;
- count+=2;
+ else{
+#ifdef HAVE_JACK_H
+ if((*jack_ringbuffer_read_space_p)(pdata->jdata->sound_buffer)>=
+ (framesize*pdata->jdata->buffersize)){
+ (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer,
+ jackbuf,
+ (framesize*pdata->jdata->buffersize));
+ vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,
+ sampread);
+ for(j=0;j<pdata->args.channels;j++){
+ for(i=0;i<sampread;i++){
+ vorbis_buffer[j][i]=((float*)jackbuf)[count];
+ count++;
+ }
+ }
+ }
+ else{
+ pdata->v_enc_thread_waiting=1;
+ pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
+ pthread_cond_wait(&pdata->sound_data_read,
+ &pdata->snd_buff_ready_mutex);
+ pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
+ pdata->v_enc_thread_waiting=0;
+ continue;
}
+#endif
}
vorbis_analysis_wrote(&pdata->enc_data->m_vo_dsp,sampread);
@@ -86,8 +127,7 @@ void *EncodeSoundBuffer(ProgData *pdata){
pdata->avd-=pdata->periodtime;
- free(buff->data);
- free(buff);
+
}
pdata->v_encoding_clean=1;
@@ -103,11 +143,23 @@ void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){
int sampread=(buff!=NULL)?pdata->periodsize:0;
vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread);
- for(i=0;i<sampread;i++){
+
+ if(!pdata->args.use_jack){
+ for(i=0;i<sampread;i++){
+ for(j=0;j<pdata->args.channels;j++){
+ vorbis_buffer[j][i]=((buff[count+1]<<8)|
+ (0x00ff&(int)buff[count]))/
+ 32768.f;
+ count+=2;
+ }
+ }
+ }
+ else{
for(j=0;j<pdata->args.channels;j++){
- vorbis_buffer[j][i]=((buff[count+1]<<8)|
- (0x00ff&(int)buff[count]))/32768.f;
- count+=2;
+ for(i=0;i<sampread;i++){
+ vorbis_buffer[j][i]=((float*)buff)[count];
+ count++;
+ }
}
}
diff --git a/recordmydesktop/src/get_frame.c b/recordmydesktop/src/get_frame.c
index 31dba8d..87e71aa 100644
--- a/recordmydesktop/src/get_frame.c
+++ b/recordmydesktop/src/get_frame.c
@@ -58,7 +58,6 @@ void *GetFrame(ProgData *pdata){
}
}
capture_busy=1;
-
//mutexes and lists with changes are useless when full_shots is enabled
if(!pdata->args.full_shots){
tlist_sel=pdata->list_selector;
diff --git a/recordmydesktop/src/initialize_data.c b/recordmydesktop/src/initialize_data.c
index d8f52c0..74d32cf 100644
--- a/recordmydesktop/src/initialize_data.c
+++ b/recordmydesktop/src/initialize_data.c
@@ -27,6 +27,22 @@
#include <recordmydesktop.h>
+#ifdef HAVE_LIBASOUND
+void FixBufferSize(snd_pcm_uframes_t *buffsize){
+ snd_pcm_uframes_t buffsize_t=*buffsize,
+#else
+void FixBufferSize(u_int32_t *buffsize){
+ u_int32_t buffsize_t=*buffsize,
+#endif
+ buffsize_ret=1;
+ while(buffsize_t>1){
+ buffsize_t>>=1;
+ buffsize_ret<<=1;
+ }
+ fprintf(stderr,"Buffer size adjusted to %d from %d frames.\n",
+ (int)buffsize_ret,(int)*buffsize);
+}
+
int InitializeData(ProgData *pdata,
EncData *enc_data,
CacheData *cache_data){
@@ -124,30 +140,56 @@ int InitializeData(ProgData *pdata,
AllPlanes);
}
if(!pdata->args.nosound){
+ if(!pdata->args.use_jack){
+ FixBufferSize(&pdata->args.buffsize);
#ifdef HAVE_LIBASOUND
- pdata->sound_handle=OpenDev( pdata->args.device,
- &pdata->args.channels,
- &pdata->args.frequency,
- &pdata->args.buffsize,
- &pdata->periodsize,
- &pdata->periodtime,
- &pdata->hard_pause);
- if(pdata->sound_handle==NULL){
+ pdata->sound_handle=OpenDev( pdata->args.device,
+ &pdata->args.channels,
+ &pdata->args.frequency,
+ &pdata->args.buffsize,
+ &pdata->periodsize,
+ &pdata->periodtime,
+ &pdata->hard_pause);
+ if(pdata->sound_handle==NULL){
#else
- pdata->sound_handle=OpenDev(pdata->args.device,
- pdata->args.channels,
- pdata->args.frequency);
- pdata->periodtime=(1000000*pdata->args.buffsize)/
- ((pdata->args.channels<<1)*pdata->args.frequency);
- //when using OSS periodsize serves as an alias of buffsize
- pdata->periodsize=pdata->args.buffsize;
- if(pdata->sound_handle<0){
+ pdata->sound_handle=OpenDev(pdata->args.device,
+ pdata->args.channels,
+ pdata->args.frequency);
+ pdata->periodtime=(1000000*pdata->args.buffsize)/
+ ((pdata->args.channels<<1)*pdata->args.frequency);
+ //when using OSS periodsize serves as an alias of buffsize
+ pdata->periodsize=pdata->args.buffsize;
+ if(pdata->sound_handle<0){
+#endif
+ fprintf(stderr,"Error while opening/configuring soundcard %s\n"
+ "Try running with the --no-sound or specify a "
+ "correct device.\n",
+ pdata->args.device);
+ return 3;
+ }
+ }
+ else{
+#ifdef HAVE_JACK_H
+ int jack_error=0;
+ pdata->jdata->port_names=pdata->args.jack_port_names;
+ pdata->jdata->nports=pdata->args.jack_nports;
+ pdata->jdata->snd_buff_ready_mutex=&pdata->snd_buff_ready_mutex;
+ pdata->jdata->sound_data_read=&pdata->sound_data_read;
+ pdata->jdata->capture_started=0;
+
+ if((jack_error=StartJackClient(pdata->jdata))!=0)
+ return jack_error;
+
+ pdata->args.buffsize=pdata->jdata->buffersize;
+ pdata->periodsize=pdata->args.buffsize;
+ pdata->args.frequency=pdata->jdata->frequency;
+ pdata->args.channels=pdata->jdata->nports;
+ pdata->periodtime=(1000000*pdata->args.buffsize)/
+ pdata->args.frequency;
+#else
+ fprintf(stderr,"Should not be here!\n");
+ exit(-1);
#endif
- fprintf(stderr,"Error while opening/configuring soundcard %s\n"
- "Try running with the --no-sound or specify a "
- "correct device.\n",
- pdata->args.device);
- return 3;
}
}
@@ -176,7 +218,6 @@ int InitializeData(ProgData *pdata,
pdata->specs.depth);
pdata->frametime=(1000000)/pdata->args.fps;
-
return 0;
}
diff --git a/recordmydesktop/src/load_cache.c b/recordmydesktop/src/load_cache.c
index f75c375..78c81c5 100644
--- a/recordmydesktop/src/load_cache.c
+++ b/recordmydesktop/src/load_cache.c
@@ -138,6 +138,11 @@ void *LoadCache(ProgData *pdata){
#else
int framesize=pdata->args.channels<<1;//Always signed 16 bit data
#endif
+#ifdef HAVE_JACK_H
+ if(pdata->args.use_jack)
+ framesize=sizeof(jack_default_audio_sample_t)*
+ pdata->jdata->nports;
+#endif
signed char *sound_data=(signed char *)malloc(pdata->periodsize*framesize);
u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES],
diff --git a/recordmydesktop/src/opendev.c b/recordmydesktop/src/opendev.c
index 7810ec6..ea6f436 100644
--- a/recordmydesktop/src/opendev.c
+++ b/recordmydesktop/src/opendev.c
@@ -109,7 +109,6 @@ snd_pcm_t *OpenDev( const char *pcm_dev,
snd_pcm_hw_params_get_period_time(hwparams,periodtime,0);
fprintf(stderr,"Recording on device %s is set to:\n%d channels at %dHz\n",
pcm_dev,*channels,*frequency);
- fprintf(stderr,"Buffer size set to %d frames.\n",(int)(*buffsize));
snd_pcm_prepare(mhandle);
return mhandle;
diff --git a/recordmydesktop/src/parseargs.c b/recordmydesktop/src/parseargs.c
index 9cda42b..4643bf1 100644
--- a/recordmydesktop/src/parseargs.c
+++ b/recordmydesktop/src/parseargs.c
@@ -27,11 +27,26 @@
#include <recordmydesktop.h>
+void PrintConfig(void){
+ fprintf(stderr,"\nrecordMyDesktop was compiled with"
+ " the following options:\n\n");
+#ifdef HAVE_JACK_H
+ fprintf(stdout,"Jack\t\t\t:Enabled\n");
+#else
+ fprintf(stdout,"Jack\t\t\t:Disabled\n");
+#endif
+#ifdef HAVE_LIBASOUND
+ fprintf(stdout,"Default Audio Backend\t:ALSA\n");
+#else
+ fprintf(stdout,"Default Audio Backend\t:OSS\n");
+#endif
+ fprintf(stderr,"\n\n");
+}
int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
int i;
char *usage="\nUsage:\n"
- "\trecordmydesktop [-h| --help| --version|"
+ "\trecordmydesktop [-h| --help| --version| --print-config|"
" -delay n[H|h|M|m]| -windowid id_of_window|\n"
"\t-display DISPLAY| -x X| -y Y|-width N| -height N|"
" -fps N(number>0)| --on-the-fly-encoding|\n"
@@ -39,14 +54,17 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
" -dummy-cursor color|\n"
"\t --no-cursor| -freq N(number>0)| -channels N(number>0)|"
" -buffer-size N(number>0)| -device SOUND_DEVICE|\n"
- "\t --no-sound| --with-shared| --no-cond-shared| -shared-threshold n|"
+ "\t -use-jack port1 port2... portn| --no-sound| --with-shared|"
+ " --no-cond-shared| -shared-threshold n|"
" --full-shots|\n"
"\t --quick-subsampling| -workdir DIR| --zero-compression| --no-wm-check|"
" --overwite| -o filename]^filename\n\n\n"
"General Options:\n"
"\t-h or --help\t\tPrint this help and exit.\n"
- "\t--version\t\tPrint program version and exit.\n\n"
+ "\t--version\t\tPrint program version and exit.\n"
+ "\t--print-config\t\tPrint info about options "
+ "selected during compilation and exit.\n\n"
"Image Options:\n"
"\t-windowid id_of_window\tid of window to be recorded.\n"
@@ -74,17 +92,19 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
"\t-fps N(number>0.0)\tA positive number denoting desired framerate.\n\n"
"Sound Options:\n"
- "\t-channels N\t\tA positive number denoting"
+ "\t-channels N\t\t\tA positive number denoting"
" desired sound channels in recording.\n"
- "\t-freq N\t\t\tA positive number denoting desired sound frequency.\n"
- "\t-buffer-size N\t\tA positive number denoting the desired"
+ "\t-freq N\t\t\t\tA positive number denoting desired sound frequency.\n"
+ "\t-buffer-size N\t\t\tA positive number denoting the desired"
" sound buffer size(in frames)\n"
- "\t-device SOUND_DEVICE\tSound device(default "
+ "\t-device SOUND_DEVICE\t\tSound device(default "
DEFAULT_AUDIO_DEVICE
").\n"
- "\t--no-sound\t\tDo not record sound.\n\n"
+ "\t-use-jack port1 port2... portn\tRecord audio from the specified\n"
+ "\t\t\t\t\tlist of space-separated jack ports.\n"
+ "\t--no-sound\t\t\tDo not record sound.\n\n"
"Encoding Options\n"
"\t--on-the-fly-encoding\tEncode the audio-video data, while recording.\n"
@@ -446,6 +466,44 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
}
i++;
}
+ else if(!strcmp(argv[i],"-use-jack")){
+ if(i+1<argc){
+#ifdef HAVE_JACK_H
+ int k=i+1;
+ arg_return->jack_nports=0;
+ while((k<argc)&&(argv[k][0]!='-')){
+ arg_return->jack_nports++;
+ k++;
+ }
+ if(arg_return->jack_nports>0){
+ arg_return->jack_port_names=malloc(sizeof(char*)*
+ arg_return->jack_nports);
+ for(k=i+1;k<i+1+arg_return->jack_nports;k++){
+ arg_return->jack_port_names[k-i-1]=
+ malloc(strlen(argv[k])+1);
+ strcpy(arg_return->jack_port_names[k-i-1],
+ argv[k]);
+ }
+ i+=arg_return->jack_nports;
+ arg_return->use_jack=1;
+ }
+ else{
+ fprintf(stderr,"Argument Usage: -use-jack port1"
+ " port2... portn\n");
+ return 1;
+ }
+#else
+ fprintf(stderr,"recordMyDesktop is not compiled"
+ " with Jack support!\n");
+ return 1;
+#endif
+ }
+ else{
+ fprintf(stderr,"Argument Usage: -use-jack port1"
+ " port2... portn\n");
+ return 1;
+ }
+ }
else if(!strcmp(argv[i],"--no-sound"))
arg_return->nosound=1;
else if(!strcmp(argv[i],"--drop-frames"))
@@ -475,11 +533,15 @@ int ParseArgs(int argc,char **argv,ProgArgs *arg_return){
}
else if(!strcmp(argv[i],"--help")||!strcmp(argv[i],"-h")){
fprintf(stderr,"%s",usage);
- return 1;
+ exit(0);
}
else if(!strcmp(argv[i],"--version")){
fprintf(stderr,"recordMyDesktop v%s\n\n",VERSION);
- return 1;
+ exit(0);
+ }
+ else if(!strcmp(argv[i],"--print-config")){
+ PrintConfig();
+ exit(0);
}
else{
fprintf(stderr,"\n\tError parsing arguments.\n\t"
diff --git a/recordmydesktop/src/recordmydesktop.c b/recordmydesktop/src/recordmydesktop.c
index c832a3e..f30485c 100644
--- a/recordmydesktop/src/recordmydesktop.c
+++ b/recordmydesktop/src/recordmydesktop.c
@@ -30,6 +30,7 @@
int main(int argc,char **argv){
ProgData pdata;
+
int exit_status=0;
if(XInitThreads ()==0){
fprintf(stderr,"Couldn't initialize thread support!\n");
@@ -52,7 +53,10 @@ int main(int argc,char **argv){
else{
EncData enc_data;
CacheData cache_data;
-
+#ifdef HAVE_JACK_H
+ JackData jdata;
+ pdata.jdata=&jdata;
+#endif
QUERY_DISPLAY_SPECS(pdata.dpy,&pdata.specs);
if((pdata.specs.depth!=32)&&
(pdata.specs.depth!=24)&&
diff --git a/recordmydesktop/src/register_callbacks.c b/recordmydesktop/src/register_callbacks.c
index 7f8d04f..2c5a8a3 100644
--- a/recordmydesktop/src/register_callbacks.c
+++ b/recordmydesktop/src/register_callbacks.c
@@ -32,14 +32,16 @@ void SetExpired(int signum){
if(capture_busy){
frames_lost++;
}
+/*FIXME */
+//This is not safe.
+//cond_var signaling must move away from signal handlers
+//alltogether (JackCapture, SetExpired, SetPaused).
+//Better would be a set of pipes for each of these.
+//The callback should write on the pipe and the main thread
+//should perform a select over the fd's, signaling afterwards the
+//appropriate cond_var.
pthread_mutex_lock(&time_mutex);
- pthread_cond_broadcast(time_cond); //sig handlers should
- //not call this func
- //could be a set_expired
- // and main thread
- //doing a while(running)
- //if set_expired broadcast
- //else usleep(n)
+ pthread_cond_broadcast(time_cond);
pthread_mutex_unlock(&time_mutex);
}
}
@@ -49,6 +51,14 @@ void SetPaused(int signum){
Paused=1;
else{
Paused=0;
+/*FIXME */
+//This is not safe.
+//cond_var signaling must move away from signal handlers
+//alltogether (JackCapture, SetExpired, SetPaused).
+//Better would be a set of pipes for each of these.
+//The callback should write on the pipe and the main thread
+//should perform a select over the fd's, signaling afterwards the
+//appropriate cond_var.
pthread_mutex_lock(&pause_mutex);
pthread_cond_broadcast(pause_cond);
pthread_mutex_unlock(&pause_mutex);
diff --git a/recordmydesktop/src/rmd_jack.c b/recordmydesktop/src/rmd_jack.c
new file mode 100644
index 0000000..6d846a1
--- /dev/null
+++ b/recordmydesktop/src/rmd_jack.c
@@ -0,0 +1,208 @@
+/******************************************************************************
+* recordMyDesktop *
+*******************************************************************************
+* *
+* Copyright (C) 2006,2007 John Varouhakis *
+* *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the Free Software *
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+* *
+* *
+* *
+* For further information contact me at johnvarouhakis@gmail.com *
+******************************************************************************/
+
+
+#include <recordmydesktop.h>
+
+#ifdef HAVE_JACK_H
+int JackCapture(jack_nframes_t nframes,void *jdata_t){
+ int i=0;
+ JackData *jdata=(JackData *)jdata_t;
+
+ if((!*Running)||(Paused) || (!jdata->capture_started))
+ return 0;
+ for(i= 0;i<jdata->nports;i++)
+ jdata->portbuf[i]=jack_port_get_buffer_p(jdata->ports[i],nframes);
+//vorbis analysis buffer wants uninterleaved data
+//so we are simply placing the buffers for every channel
+//sequentially on the ringbuffer
+ for(i=0;i<jdata->nports;i++)
+ (*jack_ringbuffer_write_p)(jdata->sound_buffer,
+ (void *)(jdata->portbuf[i]),
+ nframes*
+ sizeof(jack_default_audio_sample_t));
+/*FIXME */
+//This is not safe.
+//cond_var signaling must move away from signal handlers
+//alltogether (JackCapture, SetExpired, SetPaused).
+//Better would be a set of pipes for each of these.
+//The callback should write on the pipe and the main thread
+//should perform a select over the fd's, signaling afterwards the
+//appropriate cond_var.
+ pthread_mutex_lock(jdata->snd_buff_ready_mutex);
+ pthread_cond_signal(jdata->sound_data_read);
+ pthread_mutex_unlock(jdata->snd_buff_ready_mutex);
+
+ return 0;
+}
+
+int SetupPorts(JackData *jdata){
+ int i=0;
+ jdata->ports=malloc(sizeof(jack_port_t *)*
+ jdata->nports);
+ jdata->portbuf=malloc(sizeof(jack_default_audio_sample_t*)*
+ jdata->nports);
+ memset(jdata->portbuf,0,sizeof(jack_default_audio_sample_t*)*
+ jdata->nports);
+
+ for(i=0;i<jdata->nports;i++){
+ char name[64];//recordMyDesktop:input_n<64 is enough for full name
+ char num[8];
+ strcpy(name,"input_");
+ I16TOA((i+1),num);
+ strcat(name,num);
+ if((jdata->ports[i]=jack_port_register_p(jdata->client,
+ name,
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsInput,
+ 0))==0){
+ fprintf(stderr,"Cannot register input port \"%s\"!\n",name);
+ return 1;
+ }
+ if(jack_connect_p(jdata->client,
+ jdata->port_names[i],
+ jack_port_name_p(jdata->ports[i]))){
+ fprintf(stderr,"Cannot connect input port %s to %s\n",
+ jack_port_name_p(jdata->ports[i]),
+ jdata->port_names[i]);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int LoadJackLib(void *jack_lib_handle){
+ char *error;
+ jack_lib_handle=dlopen("libjack.so",RTLD_LAZY);
+ if(!jack_lib_handle){
+ fprintf(stderr,"%s\n",dlerror());
+ return 1;
+ }
+ if((error=dlerror())!=NULL){
+ fprintf(stderr,"%s\n",dlerror());
+ }
+//this macro will call return with status 1 on failure
+ DLSYM_AND_CHECK(jack_lib_handle,jack_client_new,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_get_sample_rate,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_set_buffer_size,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_get_buffer_size,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_set_process_callback,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_on_shutdown,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_activate,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_client_close,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_port_get_buffer,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_port_register,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_connect,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_port_name,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_port_name_size,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_create,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_free,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_read,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_read_space,error)
+ DLSYM_AND_CHECK(jack_lib_handle,jack_ringbuffer_write,error)
+
+ return 0;
+}
+//in case the jack server shuts down
+//the program should stop recording,
+//encode the result(if not on the fly)
+//an exit cleanly.
+void JackShutdown(void *jdata_t){
+ fprintf (stderr, "JACK shutdown\n");
+ *Running=0;
+}
+
+int StartJackClient(JackData *jdata){
+
+ if(LoadJackLib(jdata->jack_lib_handle)){
+ fprintf (stderr,"Couldn't load the Jack library (libjack.so)!\n");
+ return 14;
+ }
+ if ((jdata->client=(*jack_client_new_p)("recordMyDesktop"))==0){
+ fprintf(stderr,"Could not create new client!\n"
+ "Make sure that Jack server is running!\n");
+ return 15;
+ }
+//in contrast to ALSA and OSS, Jack dictates frequency
+//and buffersize to the values it was launched with.
+//Supposedly jack_set_buffer_size can set the buffersize
+//but that causes some kind of halt and keeps giving me
+//zero buffers.
+//recordMyDesktop cannot handle buffer size changes.
+//FIXME
+//There is a callback for buffer size changes that I should use.
+//It will provide clean exits, instead of ?segfaults? .
+//Continuing though is not possible, with the current layout
+//(it might be in some cases, but it will certainly be the cause
+//of unpredicted problems). A clean exit is preferable
+//and any recording up to that point will be encoded and saved.
+ jdata->frequency=jack_get_sample_rate_p(jdata->client);
+ jdata->buffersize=jack_get_buffer_size_p(jdata->client);
+ jdata->sound_buffer=
+ (*jack_ringbuffer_create_p)(jdata->nports*
+ sizeof(jack_default_audio_sample_t)*
+ jdata->buffersize*
+ BUFFERS_IN_RING);
+ jack_set_process_callback_p(jdata->client,JackCapture,jdata);
+ jack_on_shutdown_p(jdata->client,JackShutdown,jdata);
+
+ if (jack_activate_p(jdata->client)) {
+ fprintf(stderr,"cannot activate client!\n");
+ return 16;
+ }
+ if(SetupPorts(jdata)){
+ jack_client_close_p(jdata->client);
+ return 17;
+ }
+
+ return 0;
+}
+
+int StopJackClient(JackData *jdata){
+ int ret=0;
+
+ (*jack_ringbuffer_free_p)(jdata->sound_buffer);
+ if(jack_client_close_p(jdata->client)){
+ fprintf(stderr,"Cannot close Jack client!\n");
+ ret=1;
+ }
+
+/*TODO*/
+//I need to make some kind of program/thread
+//flow diagram to see where it's safe to dlclose
+//because here it causes a segfault.
+
+// if(dlclose(jdata->jack_lib_handle)){
+// fprintf(stderr,"Cannot unload Jack library!\n");
+// ret=1;
+// }
+// else fprintf(stderr,"Unloaded Jack library.\n");
+
+ return ret;
+}
+
+#endif
+
diff --git a/recordmydesktop/src/rmdthreads.c b/recordmydesktop/src/rmdthreads.c
index 4199472..014a1d6 100644
--- a/recordmydesktop/src/rmdthreads.c
+++ b/recordmydesktop/src/rmdthreads.c
@@ -65,10 +65,11 @@ void rmdThreads(ProgData *pdata){
(void *)pdata);
if(!pdata->args.nosound){
- pthread_create(&sound_capture_t,
- NULL,
- (void *)CaptureSound,
- (void *)pdata);
+ if(!pdata->args.use_jack)
+ pthread_create(&sound_capture_t,
+ NULL,
+ (void *)CaptureSound,
+ (void *)pdata);
if(pdata->args.encOnTheFly)
pthread_create(&sound_encode_t,
NULL,
@@ -88,7 +89,11 @@ void rmdThreads(ProgData *pdata){
RegisterCallbacks(&pdata->args);
fprintf(stderr,"Capturing!\n");
-
+#ifdef HAVE_JACK_H
+ if(pdata->args.use_jack){
+ pdata->jdata->capture_started=1;
+ }
+#endif
//wait all threads to finish
pthread_join(image_capture_t,NULL);
@@ -108,9 +113,14 @@ void rmdThreads(ProgData *pdata){
pthread_join(image_cache_t,NULL);
fprintf(stderr,".");
if(!pdata->args.nosound){
- pthread_join(sound_capture_t,NULL);
+#ifdef HAVE_JACK_H
+ if(pdata->args.use_jack)
+ StopJackClient(pdata->jdata);
+#endif
+ if(!pdata->args.use_jack)
+ pthread_join(sound_capture_t,NULL);
fprintf(stderr,".");
- while(!pdata->v_enc_thread_waiting && !pdata->v_encoding_clean){
+ while(pdata->v_enc_thread_waiting || !pdata->v_encoding_clean){
usleep(10000);
pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
pthread_cond_signal(&pdata->sound_data_read);
© All Rights Reserved