From e5cdc6d4fbec00a52d06414ca243664bb8b40942 Mon Sep 17 00:00:00 2001 From: enselic Date: Sun, 14 Sep 2008 13:06:20 +0000 Subject: src/*.[ch]: Rename files so that the name becomes rmd_some_file.[ch]. The exceptions are recordmydesktop.c which is the main file and skeleton.[ch] which are external files. src/Makefile.am: Adapt. git-svn-id: https://recordmydesktop.svn.sourceforge.net/svnroot/recordmydesktop/trunk@546 f606c939-3180-4ac9-a4b8-4b8779d57d0a --- recordmydesktop/src/Makefile.am | 152 +++--- recordmydesktop/src/block_utils.c | 37 -- recordmydesktop/src/block_utils.h | 170 ------- recordmydesktop/src/cache_audio.c | 108 ----- recordmydesktop/src/cache_audio.h | 42 -- recordmydesktop/src/cache_frame.c | 295 ------------ recordmydesktop/src/cache_frame.h | 43 -- recordmydesktop/src/capture_sound.c | 174 ------- recordmydesktop/src/capture_sound.h | 42 -- recordmydesktop/src/encode_cache.c | 71 --- recordmydesktop/src/encode_cache.h | 41 -- recordmydesktop/src/encode_image_buffer.c | 95 ---- recordmydesktop/src/encode_image_buffer.h | 50 -- recordmydesktop/src/encode_sound_buffer.c | 191 -------- recordmydesktop/src/encode_sound_buffer.h | 51 -- recordmydesktop/src/flush_to_ogg.c | 215 --------- recordmydesktop/src/flush_to_ogg.h | 40 -- recordmydesktop/src/get_frame.c | 669 -------------------------- recordmydesktop/src/get_frame.h | 41 -- recordmydesktop/src/getzpixmap.c | 112 ----- recordmydesktop/src/getzpixmap.h | 98 ---- recordmydesktop/src/init_encoder.c | 370 -------------- recordmydesktop/src/init_encoder.h | 47 -- recordmydesktop/src/initialize_data.c | 256 ---------- recordmydesktop/src/initialize_data.h | 62 --- recordmydesktop/src/load_cache.c | 336 ------------- recordmydesktop/src/load_cache.h | 42 -- recordmydesktop/src/make_dummy_pointer.c | 93 ---- recordmydesktop/src/make_dummy_pointer.h | 58 --- recordmydesktop/src/opendev.c | 176 ------- recordmydesktop/src/opendev.h | 84 ---- recordmydesktop/src/parseargs.c | 586 ---------------------- recordmydesktop/src/parseargs.h | 47 -- recordmydesktop/src/poll_events.c | 208 -------- recordmydesktop/src/poll_events.h | 49 -- recordmydesktop/src/queryextensions.c | 83 ---- recordmydesktop/src/queryextensions.h | 53 -- recordmydesktop/src/recordmydesktop.c | 18 +- recordmydesktop/src/rectinsert.c | 535 -------------------- recordmydesktop/src/rectinsert.h | 55 --- recordmydesktop/src/register_callbacks.c | 87 ---- recordmydesktop/src/register_callbacks.h | 41 -- recordmydesktop/src/rmd_block_utils.c | 37 ++ recordmydesktop/src/rmd_block_utils.h | 170 +++++++ recordmydesktop/src/rmd_cache.c | 6 +- recordmydesktop/src/rmd_cache.h | 2 +- recordmydesktop/src/rmd_cache_audio.c | 108 +++++ recordmydesktop/src/rmd_cache_audio.h | 42 ++ recordmydesktop/src/rmd_cache_frame.c | 295 ++++++++++++ recordmydesktop/src/rmd_cache_frame.h | 43 ++ recordmydesktop/src/rmd_capture_sound.c | 174 +++++++ recordmydesktop/src/rmd_capture_sound.h | 42 ++ recordmydesktop/src/rmd_encode_cache.c | 71 +++ recordmydesktop/src/rmd_encode_cache.h | 41 ++ recordmydesktop/src/rmd_encode_image_buffer.c | 95 ++++ recordmydesktop/src/rmd_encode_image_buffer.h | 50 ++ recordmydesktop/src/rmd_encode_sound_buffer.c | 191 ++++++++ recordmydesktop/src/rmd_encode_sound_buffer.h | 51 ++ recordmydesktop/src/rmd_error.h | 2 +- recordmydesktop/src/rmd_flush_to_ogg.c | 215 +++++++++ recordmydesktop/src/rmd_flush_to_ogg.h | 40 ++ recordmydesktop/src/rmd_frame.h | 2 +- recordmydesktop/src/rmd_get_frame.c | 669 ++++++++++++++++++++++++++ recordmydesktop/src/rmd_get_frame.h | 41 ++ recordmydesktop/src/rmd_getzpixmap.c | 112 +++++ recordmydesktop/src/rmd_getzpixmap.h | 98 ++++ recordmydesktop/src/rmd_init_encoder.c | 372 ++++++++++++++ recordmydesktop/src/rmd_init_encoder.h | 47 ++ recordmydesktop/src/rmd_initialize_data.c | 256 ++++++++++ recordmydesktop/src/rmd_initialize_data.h | 62 +++ recordmydesktop/src/rmd_jack.c | 4 +- recordmydesktop/src/rmd_jack.h | 2 +- recordmydesktop/src/rmd_load_cache.c | 336 +++++++++++++ recordmydesktop/src/rmd_load_cache.h | 42 ++ recordmydesktop/src/rmd_macro.h | 111 +++++ recordmydesktop/src/rmd_make_dummy_pointer.c | 93 ++++ recordmydesktop/src/rmd_make_dummy_pointer.h | 58 +++ recordmydesktop/src/rmd_opendev.c | 176 +++++++ recordmydesktop/src/rmd_opendev.h | 84 ++++ recordmydesktop/src/rmd_parseargs.c | 586 ++++++++++++++++++++++ recordmydesktop/src/rmd_parseargs.h | 47 ++ recordmydesktop/src/rmd_poll_events.c | 208 ++++++++ recordmydesktop/src/rmd_poll_events.h | 49 ++ recordmydesktop/src/rmd_queryextensions.c | 83 ++++ recordmydesktop/src/rmd_queryextensions.h | 53 ++ recordmydesktop/src/rmd_rectinsert.c | 535 ++++++++++++++++++++ recordmydesktop/src/rmd_rectinsert.h | 55 +++ recordmydesktop/src/rmd_register_callbacks.c | 87 ++++ recordmydesktop/src/rmd_register_callbacks.h | 41 ++ recordmydesktop/src/rmd_rescue.c | 12 +- recordmydesktop/src/rmd_setbrwindow.c | 213 ++++++++ recordmydesktop/src/rmd_setbrwindow.h | 53 ++ recordmydesktop/src/rmd_shortcuts.c | 152 ++++++ recordmydesktop/src/rmd_shortcuts.h | 57 +++ recordmydesktop/src/rmd_specsfile.c | 167 +++++++ recordmydesktop/src/rmd_specsfile.h | 59 +++ recordmydesktop/src/rmd_threads.c | 167 +++++++ recordmydesktop/src/rmd_threads.h | 43 ++ recordmydesktop/src/rmd_timer.c | 2 +- recordmydesktop/src/rmd_timer.h | 2 +- recordmydesktop/src/rmd_types.h | 369 ++++++++++++++ recordmydesktop/src/rmd_update_image.c | 86 ++++ recordmydesktop/src/rmd_update_image.h | 70 +++ recordmydesktop/src/rmd_wm_check.c | 79 +++ recordmydesktop/src/rmd_wm_check.h | 45 ++ recordmydesktop/src/rmd_yuv_utils.c | 57 +++ recordmydesktop/src/rmd_yuv_utils.h | 247 ++++++++++ recordmydesktop/src/rmdmacro.h | 111 ----- recordmydesktop/src/rmdthreads.c | 166 ------- recordmydesktop/src/rmdthreads.h | 43 -- recordmydesktop/src/rmdtypes.h | 369 -------------- recordmydesktop/src/setbrwindow.c | 213 -------- recordmydesktop/src/setbrwindow.h | 53 -- recordmydesktop/src/shortcuts.c | 152 ------ recordmydesktop/src/shortcuts.h | 57 --- recordmydesktop/src/specsfile.c | 167 ------- recordmydesktop/src/specsfile.h | 59 --- recordmydesktop/src/test-rectinsert-types.h | 2 +- recordmydesktop/src/test-rectinsert.c | 6 +- recordmydesktop/src/update_image.c | 86 ---- recordmydesktop/src/update_image.h | 70 --- recordmydesktop/src/wm_check.c | 79 --- recordmydesktop/src/wm_check.h | 45 -- recordmydesktop/src/yuv_utils.c | 57 --- recordmydesktop/src/yuv_utils.h | 247 ---------- 125 files changed, 7936 insertions(+), 7933 deletions(-) delete mode 100644 recordmydesktop/src/block_utils.c delete mode 100644 recordmydesktop/src/block_utils.h delete mode 100644 recordmydesktop/src/cache_audio.c delete mode 100644 recordmydesktop/src/cache_audio.h delete mode 100644 recordmydesktop/src/cache_frame.c delete mode 100644 recordmydesktop/src/cache_frame.h delete mode 100644 recordmydesktop/src/capture_sound.c delete mode 100644 recordmydesktop/src/capture_sound.h delete mode 100644 recordmydesktop/src/encode_cache.c delete mode 100644 recordmydesktop/src/encode_cache.h delete mode 100644 recordmydesktop/src/encode_image_buffer.c delete mode 100644 recordmydesktop/src/encode_image_buffer.h delete mode 100644 recordmydesktop/src/encode_sound_buffer.c delete mode 100644 recordmydesktop/src/encode_sound_buffer.h delete mode 100644 recordmydesktop/src/flush_to_ogg.c delete mode 100644 recordmydesktop/src/flush_to_ogg.h delete mode 100644 recordmydesktop/src/get_frame.c delete mode 100644 recordmydesktop/src/get_frame.h delete mode 100644 recordmydesktop/src/getzpixmap.c delete mode 100644 recordmydesktop/src/getzpixmap.h delete mode 100644 recordmydesktop/src/init_encoder.c delete mode 100644 recordmydesktop/src/init_encoder.h delete mode 100644 recordmydesktop/src/initialize_data.c delete mode 100644 recordmydesktop/src/initialize_data.h delete mode 100644 recordmydesktop/src/load_cache.c delete mode 100644 recordmydesktop/src/load_cache.h delete mode 100644 recordmydesktop/src/make_dummy_pointer.c delete mode 100644 recordmydesktop/src/make_dummy_pointer.h delete mode 100644 recordmydesktop/src/opendev.c delete mode 100644 recordmydesktop/src/opendev.h delete mode 100644 recordmydesktop/src/parseargs.c delete mode 100644 recordmydesktop/src/parseargs.h delete mode 100644 recordmydesktop/src/poll_events.c delete mode 100644 recordmydesktop/src/poll_events.h delete mode 100644 recordmydesktop/src/queryextensions.c delete mode 100644 recordmydesktop/src/queryextensions.h delete mode 100644 recordmydesktop/src/rectinsert.c delete mode 100644 recordmydesktop/src/rectinsert.h delete mode 100644 recordmydesktop/src/register_callbacks.c delete mode 100644 recordmydesktop/src/register_callbacks.h create mode 100644 recordmydesktop/src/rmd_block_utils.c create mode 100644 recordmydesktop/src/rmd_block_utils.h create mode 100644 recordmydesktop/src/rmd_cache_audio.c create mode 100644 recordmydesktop/src/rmd_cache_audio.h create mode 100644 recordmydesktop/src/rmd_cache_frame.c create mode 100644 recordmydesktop/src/rmd_cache_frame.h create mode 100644 recordmydesktop/src/rmd_capture_sound.c create mode 100644 recordmydesktop/src/rmd_capture_sound.h create mode 100644 recordmydesktop/src/rmd_encode_cache.c create mode 100644 recordmydesktop/src/rmd_encode_cache.h create mode 100644 recordmydesktop/src/rmd_encode_image_buffer.c create mode 100644 recordmydesktop/src/rmd_encode_image_buffer.h create mode 100644 recordmydesktop/src/rmd_encode_sound_buffer.c create mode 100644 recordmydesktop/src/rmd_encode_sound_buffer.h create mode 100644 recordmydesktop/src/rmd_flush_to_ogg.c create mode 100644 recordmydesktop/src/rmd_flush_to_ogg.h create mode 100644 recordmydesktop/src/rmd_get_frame.c create mode 100644 recordmydesktop/src/rmd_get_frame.h create mode 100644 recordmydesktop/src/rmd_getzpixmap.c create mode 100644 recordmydesktop/src/rmd_getzpixmap.h create mode 100644 recordmydesktop/src/rmd_init_encoder.c create mode 100644 recordmydesktop/src/rmd_init_encoder.h create mode 100644 recordmydesktop/src/rmd_initialize_data.c create mode 100644 recordmydesktop/src/rmd_initialize_data.h create mode 100644 recordmydesktop/src/rmd_load_cache.c create mode 100644 recordmydesktop/src/rmd_load_cache.h create mode 100644 recordmydesktop/src/rmd_macro.h create mode 100644 recordmydesktop/src/rmd_make_dummy_pointer.c create mode 100644 recordmydesktop/src/rmd_make_dummy_pointer.h create mode 100644 recordmydesktop/src/rmd_opendev.c create mode 100644 recordmydesktop/src/rmd_opendev.h create mode 100644 recordmydesktop/src/rmd_parseargs.c create mode 100644 recordmydesktop/src/rmd_parseargs.h create mode 100644 recordmydesktop/src/rmd_poll_events.c create mode 100644 recordmydesktop/src/rmd_poll_events.h create mode 100644 recordmydesktop/src/rmd_queryextensions.c create mode 100644 recordmydesktop/src/rmd_queryextensions.h create mode 100644 recordmydesktop/src/rmd_rectinsert.c create mode 100644 recordmydesktop/src/rmd_rectinsert.h create mode 100644 recordmydesktop/src/rmd_register_callbacks.c create mode 100644 recordmydesktop/src/rmd_register_callbacks.h create mode 100644 recordmydesktop/src/rmd_setbrwindow.c create mode 100644 recordmydesktop/src/rmd_setbrwindow.h create mode 100644 recordmydesktop/src/rmd_shortcuts.c create mode 100644 recordmydesktop/src/rmd_shortcuts.h create mode 100644 recordmydesktop/src/rmd_specsfile.c create mode 100644 recordmydesktop/src/rmd_specsfile.h create mode 100644 recordmydesktop/src/rmd_threads.c create mode 100644 recordmydesktop/src/rmd_threads.h create mode 100644 recordmydesktop/src/rmd_types.h create mode 100644 recordmydesktop/src/rmd_update_image.c create mode 100644 recordmydesktop/src/rmd_update_image.h create mode 100644 recordmydesktop/src/rmd_wm_check.c create mode 100644 recordmydesktop/src/rmd_wm_check.h create mode 100644 recordmydesktop/src/rmd_yuv_utils.c create mode 100644 recordmydesktop/src/rmd_yuv_utils.h delete mode 100644 recordmydesktop/src/rmdmacro.h delete mode 100644 recordmydesktop/src/rmdthreads.c delete mode 100644 recordmydesktop/src/rmdthreads.h delete mode 100644 recordmydesktop/src/rmdtypes.h delete mode 100644 recordmydesktop/src/setbrwindow.c delete mode 100644 recordmydesktop/src/setbrwindow.h delete mode 100644 recordmydesktop/src/shortcuts.c delete mode 100644 recordmydesktop/src/shortcuts.h delete mode 100644 recordmydesktop/src/specsfile.c delete mode 100644 recordmydesktop/src/specsfile.h delete mode 100644 recordmydesktop/src/update_image.c delete mode 100644 recordmydesktop/src/update_image.h delete mode 100644 recordmydesktop/src/wm_check.c delete mode 100644 recordmydesktop/src/wm_check.h delete mode 100644 recordmydesktop/src/yuv_utils.c delete mode 100644 recordmydesktop/src/yuv_utils.h (limited to 'recordmydesktop') diff --git a/recordmydesktop/src/Makefile.am b/recordmydesktop/src/Makefile.am index b334e7b..575b6da 100644 --- a/recordmydesktop/src/Makefile.am +++ b/recordmydesktop/src/Makefile.am @@ -1,77 +1,77 @@ bin_PROGRAMS = recordmydesktop recordmydesktop_SOURCES = \ - block_utils.c \ - block_utils.h \ - cache_audio.c \ - cache_audio.h \ - cache_frame.c \ - cache_frame.h \ - capture_sound.c \ - capture_sound.h \ - encode_cache.c \ - encode_cache.h \ - encode_image_buffer.c \ - encode_image_buffer.h \ - encode_sound_buffer.c \ - encode_sound_buffer.h \ - flush_to_ogg.c \ - flush_to_ogg.h \ - get_frame.c \ - get_frame.h \ - getzpixmap.c \ - getzpixmap.h \ - init_encoder.c \ - init_encoder.h \ - initialize_data.c \ - initialize_data.h \ - load_cache.c \ - load_cache.h \ - make_dummy_pointer.c \ - make_dummy_pointer.h \ - opendev.c \ - opendev.h \ - parseargs.c \ - parseargs.h \ - poll_events.c \ - poll_events.h \ - queryextensions.c \ - queryextensions.h \ - recordmydesktop.c \ - rectinsert.c \ - rectinsert.h \ - register_callbacks.c \ - register_callbacks.h \ - rmd_cache.c \ - rmd_cache.h \ - rmd_error.c \ - rmd_error.h \ - rmd_frame.c \ - rmd_frame.h \ - rmd_jack.c \ - rmd_jack.h \ - rmd_rescue.c \ - rmd_rescue.h \ - rmd_timer.c \ - rmd_timer.h \ - rmdthreads.c \ - rmdthreads.h \ - rmdmacro.h \ - rmdtypes.h \ - setbrwindow.c \ - setbrwindow.h \ - shortcuts.c \ - shortcuts.h \ - skeleton.c \ - skeleton.h \ - specsfile.c \ - specsfile.h \ - update_image.c \ - update_image.h \ - yuv_utils.c \ - yuv_utils.h \ - wm_check.c \ - wm_check.h + recordmydesktop.c \ + rmd_block_utils.c \ + rmd_block_utils.h \ + rmd_cache.c \ + rmd_cache.h \ + rmd_cache_audio.c \ + rmd_cache_audio.h \ + rmd_cache_frame.c \ + rmd_cache_frame.h \ + rmd_capture_sound.c \ + rmd_capture_sound.h \ + rmd_encode_cache.c \ + rmd_encode_cache.h \ + rmd_encode_image_buffer.c \ + rmd_encode_image_buffer.h \ + rmd_encode_sound_buffer.c \ + rmd_encode_sound_buffer.h \ + rmd_error.c \ + rmd_error.h \ + rmd_flush_to_ogg.c \ + rmd_flush_to_ogg.h \ + rmd_frame.c \ + rmd_frame.h \ + rmd_get_frame.c \ + rmd_get_frame.h \ + rmd_getzpixmap.c \ + rmd_getzpixmap.h \ + rmd_init_encoder.c \ + rmd_init_encoder.h \ + rmd_initialize_data.c \ + rmd_initialize_data.h \ + rmd_jack.c \ + rmd_jack.h \ + rmd_load_cache.c \ + rmd_load_cache.h \ + rmd_macro.h \ + rmd_make_dummy_pointer.c \ + rmd_make_dummy_pointer.h \ + rmd_opendev.c \ + rmd_opendev.h \ + rmd_parseargs.c \ + rmd_parseargs.h \ + rmd_poll_events.c \ + rmd_poll_events.h \ + rmd_queryextensions.c \ + rmd_queryextensions.h \ + rmd_rectinsert.c \ + rmd_rectinsert.h \ + rmd_register_callbacks.c \ + rmd_register_callbacks.h \ + rmd_rescue.c \ + rmd_rescue.h \ + rmd_setbrwindow.c \ + rmd_setbrwindow.h \ + rmd_shortcuts.c \ + rmd_shortcuts.h \ + rmd_specsfile.c \ + rmd_specsfile.h \ + rmd_threads.c \ + rmd_threads.h \ + rmd_timer.c \ + rmd_timer.h \ + rmd_types.h \ + rmd_update_image.c \ + rmd_update_image.h \ + rmd_wm_check.c \ + rmd_wm_check.h \ + rmd_yuv_utils.c \ + rmd_yuv_utils.h \ + skeleton.c \ + skeleton.h recordmydesktop_CPPFLAGS = -D_THREAD_SAFE -pthread -Wall recordmydesktop_LDFLAGS = @X_LIBS@ @X_EXTRA_LIBS@ @X_PRE_LIBS@ @@ -83,10 +83,10 @@ EXTRA_PROGRAMS = test-rectinsert CLEANFILES = $(EXTRA_PROGRAMS) test_rectinsert_SOURCES = \ - test-rectinsert.c \ - test-rectinsert-data.c \ - test-rectinsert-data.h \ - test-rectinsert-types.h \ - rectinsert.c + test-rectinsert.c \ + test-rectinsert-data.c \ + test-rectinsert-data.h \ + test-rectinsert-types.h \ + rmd_rectinsert.c test_rectinsert_CFLAGS = -Wall diff --git a/recordmydesktop/src/block_utils.c b/recordmydesktop/src/block_utils.c deleted file mode 100644 index 99b4ce0..0000000 --- a/recordmydesktop/src/block_utils.c +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include "block_utils.h" - - -// FIXME: These globals are modified in other source files! We keep -// thsee here for now. These are the cache blocks. They need to be -// accesible in the dbuf macros -u_int32_t *yblocks, - *ublocks, - *vblocks; diff --git a/recordmydesktop/src/block_utils.h b/recordmydesktop/src/block_utils.h deleted file mode 100644 index 1c2e429..0000000 --- a/recordmydesktop/src/block_utils.h +++ /dev/null @@ -1,170 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef BLOCK_UTILS_H -#define BLOCK_UTILS_H 1 - -#include "rmdtypes.h" -#include "rmdmacro.h" -#include "yuv_utils.h" - - -// We keep these global for now. FIXME: Isolate them. -extern u_int32_t *yblocks, - *ublocks, - *vblocks; - -#define POINT_IN_BLOCK(xv,yv,widthv,blocksize) ((yv/blocksize)*\ - (widthv/blocksize)+\ - (xv/blocksize)) - -#define UPDATE_Y_PLANE_DBUF(data,\ - data_back,\ - x_tm,\ - y_tm,\ - height_tm,\ - width_tm,\ - yuv,\ - __bit_depth__){ \ - int k,i;\ - register u_int##__bit_depth__##_t t_val;\ - register unsigned char *yuv_y=yuv->y+x_tm+y_tm*yuv->y_width,\ - *_yr=Yr,*_yg=Yg,*_yb=Yb;\ - register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\ - *datapi_back=(u_int##__bit_depth__##_t *)data_back;\ - for(k=0;ky_width-width_tm;\ - }\ -} - -#define UPDATE_UV_PLANES_DBUF( data,\ - data_back,\ - x_tm,\ - y_tm,\ - height_tm,\ - width_tm,\ - yuv,\ - __sampling_type,\ - __bit_depth__){ \ - int k,i;\ - register u_int##__bit_depth__##_t t_val;\ - register unsigned char *yuv_u=yuv->u+x_tm/2+(y_tm*yuv->uv_width)/2,\ - *yuv_v=yuv->v+x_tm/2+(y_tm*yuv->uv_width)/2,\ - *_ur=Ur,*_ug=Ug,*_ubvr=UbVr,\ - *_vg=Vg,*_vb=Vb;\ - register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\ - *datapi_next=NULL,\ - *datapi_back=(u_int##__bit_depth__##_t *)data_back,\ - *datapi_back_next=NULL;\ - if(__sampling_type==__PXL_AVERAGE){\ - datapi_next=datapi+width_tm;\ - datapi_back_next=datapi_back+width_tm;\ - for(k=0;ky_width-width_tm)/2;\ - yuv_v+=(yuv->y_width-width_tm)/2;\ - datapi+=width_tm;\ - datapi_back+=width_tm;\ - if(__sampling_type==__PXL_AVERAGE){\ - datapi_next+=width_tm;\ - datapi_back_next+=width_tm;\ - }\ - }\ - }\ - else{\ - for(k=0;ky_width-width_tm)/2;\ - yuv_v+=(yuv->y_width-width_tm)/2;\ - datapi+=width_tm;\ - datapi_back+=width_tm;\ - if(__sampling_type==__PXL_AVERAGE){\ - datapi_next+=width_tm;\ - datapi_back_next+=width_tm;\ - }\ - }\ - }\ -} - - -#endif diff --git a/recordmydesktop/src/cache_audio.c b/recordmydesktop/src/cache_audio.c deleted file mode 100644 index 25f86d3..0000000 --- a/recordmydesktop/src/cache_audio.c +++ /dev/null @@ -1,108 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "cache_audio.h" -#include "rmd_jack.h" - - -void *CacheSoundBuffer(ProgData *pdata){ -//We are simply going to throw sound on the disk. -//It's sound is tiny compared to that of image, so -//compressing would reducethe overall size by only an -//insignificant fraction. -#ifdef HAVE_JACK_H - void *jackbuf=NULL; - if(pdata->args.use_jack){ - jackbuf=malloc(pdata->sound_framesize*pdata->jdata->buffersize); - } -#endif - while((pdata->running)){ - SndBuffer *buff=NULL; - - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - 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*pdata->sound_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)>= - (pdata->sound_framesize*pdata->jdata->buffersize)){ - (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer, - jackbuf, - (pdata->sound_framesize* - pdata->jdata->buffersize)); - fwrite(jackbuf,1,(pdata->sound_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 - } - pdata->avd-=pdata->periodtime; - } - - fclose(pdata->cache_data->afp); - pthread_exit(&errno); -} - - diff --git a/recordmydesktop/src/cache_audio.h b/recordmydesktop/src/cache_audio.h deleted file mode 100644 index 3c2a3ce..0000000 --- a/recordmydesktop/src/cache_audio.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef CACHE_AUDIO_H -#define CACHE_AUDIO_H 1 - -#include "rmdtypes.h" - - -/** -* Sound caching thread. Simply writes the pcm buffers on disk -* -* \param pdata ProgData struct containing all program data -* -*/ -void *CacheSoundBuffer(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/cache_frame.c b/recordmydesktop/src/cache_frame.c deleted file mode 100644 index 4528ae9..0000000 --- a/recordmydesktop/src/cache_frame.c +++ /dev/null @@ -1,295 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include - -#include "rmdtypes.h" - -#include "cache_frame.h" -#include "rmd_cache.h" -#include "block_utils.h" - - -//minimize hard disk access -#define CACHE_OUT_BUFFER_SIZE 4096 -//500 mb file size -#define CACHE_FILE_SIZE_LIMIT (500*1<<20) - - -static int FlushBlock(unsigned char *buf, - int blockno, - int width, - int height, - int blockwidth, - gzFile *fp, - FILE *ucfp, - int flush) { - int j,i, - bytes_written=0, - block_i=(!blockwidth)?0:(blockno/(width/blockwidth)),//place on the grid - block_k=(!blockwidth)?0:(blockno%(width/blockwidth)); - register unsigned char *buf_reg=(&buf[(block_i* - width+ - block_k)*blockwidth]); - static unsigned char out_buffer[CACHE_OUT_BUFFER_SIZE]; - static unsigned int out_buffer_bytes=0; - - if(out_buffer_bytes+pow(blockwidth,2)>=CACHE_OUT_BUFFER_SIZE || - (flush && out_buffer_bytes)){ - if(ucfp==NULL) - gzwrite(fp,(void *)out_buffer,out_buffer_bytes); - else - fwrite((void *)out_buffer,1,out_buffer_bytes,ucfp); - bytes_written=out_buffer_bytes; - out_buffer_bytes=0; - } - if(!flush){ - register unsigned char *out_buf_reg=&out_buffer[out_buffer_bytes]; - for(j=0;jenc_data->yuv.y_width/Y_UNIT_WIDTH, - blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, - firstrun=1, - frameno=0, - nbytes=0, - nth_cache=1; - unsigned int total_bytes=0, - total_received_bytes=0; - u_int32_t ynum,unum,vnum, - y_short_blocks[blocknum_x*blocknum_y], - u_short_blocks[blocknum_x*blocknum_y], - v_short_blocks[blocknum_x*blocknum_y]; - - if(!pdata->args.zerocompression){ - fp=pdata->cache_data->ifp; - if(fp==NULL)exit(13); - } - else{ - ucfp=pdata->cache_data->uncifp; - if(ucfp==NULL)exit(13); - } - - - while(pdata->running){ - int j; - FrameHeader fheader; - ynum=unum=vnum=0; - - pdata->th_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_wait(&pdata->image_buffer_ready, - &pdata->img_buff_ready_mutex); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - pdata->th_enc_thread_waiting=0; - - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - - pthread_mutex_lock(&pdata->yuv_mutex); - - //find and flush different blocks - if(firstrun){ - firstrun=0; - for(j=0;jargs.zerocompression){ - if(ynum*4+unum+vnum>(blocknum_x*blocknum_y*6)/10) - gzsetparams (fp,1,Z_FILTERED); - else - gzsetparams (fp,0,Z_FILTERED); - } - - strncpy(fheader.frame_prefix,"FRAM",4); - fheader.frameno=++frameno; - fheader.current_total = pdata->frames_total; - - fheader.Ynum=ynum; - fheader.Unum=unum; - fheader.Vnum=vnum; - if(!pdata->args.zerocompression){ - nbytes+=gzwrite(fp,(void*)&fheader,sizeof(FrameHeader)); - //flush indexes - if(ynum)nbytes+=gzwrite(fp, - (void*)y_short_blocks, - ynum*index_entry_size); - if(unum)nbytes+=gzwrite(fp, - (void*)u_short_blocks, - unum*index_entry_size); - if(vnum)nbytes+=gzwrite(fp, - (void*)v_short_blocks, - vnum*index_entry_size); - } - else{ - nbytes+=sizeof(FrameHeader)* - fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp); - //flush indexes - if(ynum)nbytes+=index_entry_size* - fwrite(y_short_blocks,index_entry_size,ynum,ucfp); - if(unum)nbytes+=index_entry_size* - fwrite(u_short_blocks,index_entry_size,unum,ucfp); - if(vnum)nbytes+=index_entry_size* - fwrite(v_short_blocks,index_entry_size,vnum,ucfp); - } - //flush the blocks for each buffer - if(ynum){ - for(j=0;jenc_data->yuv.y,y_short_blocks[j], - pdata->enc_data->yuv.y_width, - pdata->enc_data->yuv.y_height, - Y_UNIT_WIDTH, - fp, - ucfp, - 0); - } - if(unum){ - for(j=0;jenc_data->yuv.u,u_short_blocks[j], - pdata->enc_data->yuv.uv_width, - pdata->enc_data->yuv.uv_height, - UV_UNIT_WIDTH, - fp, - ucfp, - 0); - } - if(vnum){ - for(j=0;jenc_data->yuv.v,v_short_blocks[j], - pdata->enc_data->yuv.uv_width, - pdata->enc_data->yuv.uv_height, - UV_UNIT_WIDTH, - fp, - ucfp, - 0); - } - //release main buffer - pthread_mutex_unlock(&pdata->yuv_mutex); - - nbytes+=FlushBlock(NULL,0,0,0,0,fp,ucfp,1); - /**@________________@**/ - pdata->avd+=pdata->frametime; - if(nbytes>CACHE_FILE_SIZE_LIMIT){ - if(SwapCacheFilesWrite(pdata->cache_data->imgdata, - nth_cache,&fp,&ucfp)){ - fprintf(stderr,"New cache file could not be created.\n" - "Ending recording...\n"); - fflush(stderr); - raise(SIGINT); //if for some reason we cannot make a new file - //we have to stop. If we are out of space, - //which means - //that encoding cannot happen either, - //InitEncoder will cause an abrupt end with an - //error code and the cache will remain intact. - //If we've chosen separate two-stages, - //the program will make a - //clean exit. - //In either case data will be preserved so if - //space is freed the recording - //can be proccessed later. - } - total_bytes+=(nbytes>>20); - nth_cache++; - nbytes=0; - } - } - total_bytes+=(nbytes>>20); - total_received_bytes=((frameno*((pdata->specs.depth>=24)?4:2)* - pdata->brwin.rgeom.width*pdata->brwin.rgeom.height)>>20); - if(total_received_bytes){ - fprintf(stderr,"\n*********************************************\n" - "\nCached %u MB, from %u MB that were received.\n" - "Average cache compression ratio: %u %%\n" - "\n*********************************************\n", - total_bytes, - total_received_bytes, - (total_bytes*100)/total_received_bytes); - - } - - fprintf(stderr, - "Saved %d frames in a total of %d requests\n", - frameno, - pdata->frames_total); - fflush(stderr); - - if(!pdata->args.zerocompression){ - gzflush(fp,Z_FINISH); - gzclose(fp); - } - else{ - fflush(ucfp); - fclose(ucfp); - } - pthread_exit(&errno); -} diff --git a/recordmydesktop/src/cache_frame.h b/recordmydesktop/src/cache_frame.h deleted file mode 100644 index adf698c..0000000 --- a/recordmydesktop/src/cache_frame.h +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef CACHE_FRAME_H -#define CACHE_FRAME_H 1 - -#include "rmdtypes.h" - - -/** -* Image caching thread. Copies the yuv buffer, compares with the last one and -* caches the result. -* -* \param pdata ProgData struct containing all program data -* -*/ -void *CacheImageBuffer(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/capture_sound.c b/recordmydesktop/src/capture_sound.c deleted file mode 100644 index 0607aa7..0000000 --- a/recordmydesktop/src/capture_sound.c +++ /dev/null @@ -1,174 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "capture_sound.h" -#include "opendev.h" -#include "rmd_jack.h" - - -void *CaptureSound(ProgData *pdata){ - -#ifdef HAVE_LIBASOUND - int frames=pdata->periodsize; -#endif - //start capturing only after first frame is taken - usleep(pdata->frametime); - - while(pdata->running){ - int sret=0; - SndBuffer *newbuf,*tmp; - if (pdata->paused) { -#ifdef HAVE_LIBASOUND - if(!pdata->hard_pause){ - snd_pcm_pause(pdata->sound_handle,1); - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - snd_pcm_pause(pdata->sound_handle,0); - } - else{//device doesn't support pause(is this the norm?mine doesn't) - snd_pcm_close(pdata->sound_handle); - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - pdata->sound_handle= - OpenDev(pdata->args.device, - &pdata->args.channels, - &pdata->args.frequency, - &pdata->args.buffsize, - NULL, - NULL, - NULL//let's hope that the device capabilities - //didn't magically change - ); - if(pdata->sound_handle==NULL){ - fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); - pdata->running = FALSE; - errno=3; - pthread_exit(&errno); - } - } -#else - close(pdata->sound_handle); - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - pdata->sound_handle= - OpenDev(pdata->args.device, - pdata->args.channels, - pdata->args.frequency); - if(pdata->sound_handle<0){ - fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); - pdata->running = FALSE; - errno=3; - pthread_exit(&errno); - } -#endif - } - - //create new buffer - newbuf=(SndBuffer *)malloc(sizeof(SndBuffer)); -#ifdef HAVE_LIBASOUND - newbuf->data=(signed char *)malloc(frames*pdata->sound_framesize); -#else - newbuf->data=(signed char *)malloc(((pdata->args.buffsize<<1)* - pdata->args.channels)); -#endif - newbuf->next=NULL; - - //read data into new buffer -#ifdef HAVE_LIBASOUND - while(sretsound_handle, - newbuf->data+pdata->sound_framesize*sret, - frames-sret); - if(temp_sret==-EPIPE){ - fprintf(stderr,"%s: Overrun occurred.\n", - snd_strerror(temp_sret)); - snd_pcm_prepare(pdata->sound_handle); - } - else if (temp_sret<0){ - fprintf(stderr,"An error occured while reading sound data:\n" - " %s\n", - snd_strerror(temp_sret)); - snd_pcm_prepare(pdata->sound_handle); - } - else - sret+=temp_sret; - } -#else - sret=0; - //oss recording loop - do{ - int temp_sret=read(pdata->sound_handle, - &newbuf->data[sret], - ((pdata->args.buffsize<<1)* - pdata->args.channels)-sret); - if(temp_sret<0){ - fprintf(stderr,"An error occured while reading from soundcard" - "%s\n" - "Error description:\n" - "%s\n",pdata->args.device,strerror(errno)); - } - else - sret+=temp_sret; - }while(sret<((pdata->args.buffsize<<1)* - pdata->args.channels)); -#endif - //queue the new buffer - pthread_mutex_lock(&pdata->sound_buffer_mutex); - tmp=pdata->sound_buffer; - if(pdata->sound_buffer==NULL) - pdata->sound_buffer=newbuf; - else{ - while(tmp->next!=NULL) - tmp=tmp->next; - tmp->next=newbuf; - } - pthread_mutex_unlock(&pdata->sound_buffer_mutex); - - - //signal that there are data to be proccessed - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_signal(&pdata->sound_data_read); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - } -#ifdef HAVE_LIBASOUND - snd_pcm_close(pdata->sound_handle); -#else - close(pdata->sound_handle); -#endif - pthread_exit(&errno); -} - - - diff --git a/recordmydesktop/src/capture_sound.h b/recordmydesktop/src/capture_sound.h deleted file mode 100644 index c2b6d18..0000000 --- a/recordmydesktop/src/capture_sound.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef CAPTURE_SOUND_H -#define CAPTURE_SOUND_H 1 - -#include "rmdtypes.h" - - -/** -* Sound capturing thread. Data are placed on a -* list to be picked up by other threads. -* -* \param pdata ProgData struct containing all program data -*/ -void *CaptureSound(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/encode_cache.c b/recordmydesktop/src/encode_cache.c deleted file mode 100644 index a1d23a3..0000000 --- a/recordmydesktop/src/encode_cache.c +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "encode_cache.h" -#include "flush_to_ogg.h" -#include "init_encoder.h" -#include "load_cache.h" - - -void EncodeCache(ProgData *pdata){ - pthread_t flush_to_ogg_t, - load_cache_t; - fprintf(stderr,"STATE:ENCODING\n");fflush(stderr); - fprintf(stderr,"Encoding started!\nThis may take several minutes.\n" - "Pressing Ctrl-C will cancel the procedure" - " (resuming will not be possible, but\n" - "any portion of the video, which is already encoded won't be deleted).\n" - "Please wait...\n"); - pdata->running = TRUE; - InitEncoder(pdata,pdata->enc_data,1); - //load encoding and flushing threads - if(!pdata->args.nosound){ - //before we start loading again - //we need to free any left-overs - while(pdata->sound_buffer!=NULL){ - free(pdata->sound_buffer->data); - pdata->sound_buffer=pdata->sound_buffer->next; - } - } - pthread_create(&flush_to_ogg_t,NULL,(void *)FlushToOgg,(void *)pdata); - - //start loading image and audio - pthread_create(&load_cache_t,NULL,(void *)LoadCache,(void *)pdata); - - //join and finish - pthread_join(load_cache_t,NULL); - fprintf(stderr,"Encoding finished!\nWait a moment please...\n"); - pthread_join(flush_to_ogg_t,NULL); - -} - - diff --git a/recordmydesktop/src/encode_cache.h b/recordmydesktop/src/encode_cache.h deleted file mode 100644 index 661b00b..0000000 --- a/recordmydesktop/src/encode_cache.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef ENCODE_CACHE_H -#define ENCODE_CACHE_H 1 - -#include "rmdtypes.h" - - -/** -* Encode cache into an -* ogg stream. -* \param pdata ProgData struct containing all program data -*/ -void EncodeCache(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/encode_image_buffer.c b/recordmydesktop/src/encode_image_buffer.c deleted file mode 100644 index aee3673..0000000 --- a/recordmydesktop/src/encode_image_buffer.c +++ /dev/null @@ -1,95 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include "rmdtypes.h" - -#include "encode_image_buffer.h" - - -void *EncodeImageBuffer(ProgData *pdata){ - pdata->th_encoding_clean=0; - while(pdata->running){ - pdata->th_enc_thread_waiting=1; - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_wait(&pdata->image_buffer_ready, - &pdata->img_buff_ready_mutex); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - pdata->th_enc_thread_waiting=0; - pdata->encoder_busy = TRUE; - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - pthread_mutex_lock(&pdata->yuv_mutex); - - if(theora_encode_YUVin(&pdata->enc_data->m_th_st, - &pdata->enc_data->yuv)){ - fprintf(stderr,"Encoder not ready!\n"); - pthread_mutex_unlock(&pdata->yuv_mutex); - } - else{ - pthread_mutex_unlock(&pdata->yuv_mutex); - if(theora_encode_packetout(&pdata->enc_data->m_th_st,0, - &pdata->enc_data->m_ogg_pckt1)==1){ - pthread_mutex_lock(&pdata->libogg_mutex); - ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, - &pdata->enc_data->m_ogg_pckt1); - pthread_mutex_unlock(&pdata->libogg_mutex); - pdata->avd+=pdata->frametime; - } - } - pdata->encoder_busy = FALSE; - } - //last packet - pdata->th_encoding_clean=1; - pthread_mutex_lock(&pdata->theora_lib_mutex); - pthread_cond_signal(&pdata->theora_lib_clean); - pthread_mutex_unlock(&pdata->theora_lib_mutex); - pthread_exit(&errno); -} - -//this function is meant to be called normally -//not through a thread of it's own -void SyncEncodeImageBuffer(ProgData *pdata){ - if(theora_encode_YUVin(&pdata->enc_data->m_th_st, - &pdata->enc_data->yuv)){ - fprintf(stderr,"Encoder not ready!\n"); - } - else{ - if(theora_encode_packetout(&pdata->enc_data->m_th_st,!pdata->running, - &pdata->enc_data->m_ogg_pckt1)==1){ - pthread_mutex_lock(&pdata->libogg_mutex); - ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, - &pdata->enc_data->m_ogg_pckt1); - if(!pdata->running)pdata->enc_data->m_ogg_ts.e_o_s=1; - pthread_mutex_unlock(&pdata->libogg_mutex); - pdata->avd+=pdata->frametime; - } - } -} diff --git a/recordmydesktop/src/encode_image_buffer.h b/recordmydesktop/src/encode_image_buffer.h deleted file mode 100644 index e5bb51f..0000000 --- a/recordmydesktop/src/encode_image_buffer.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef ENCODE_IMAGE_BUFFER_H -#define ENCODE_IMAGE_BUFFER_H 1 - -#include "rmdtypes.h" - - -/** -* feed a yuv buffer to the theora encoder and submit outcome to -* the ogg stream. -* \param pdata ProgData struct containing all program data -*/ -void *EncodeImageBuffer(ProgData *pdata); - -/** -* As EncodeImageBuffer, only with the assumption that -* this is not a thread on it's own -* -* \param pdata ProgData struct containing all program data -* -*/ -void SyncEncodeImageBuffer(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/encode_sound_buffer.c b/recordmydesktop/src/encode_sound_buffer.c deleted file mode 100644 index 5b7c880..0000000 --- a/recordmydesktop/src/encode_sound_buffer.c +++ /dev/null @@ -1,191 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "encode_sound_buffer.h" -#include "rmd_jack.h" - - -void *EncodeSoundBuffer(ProgData *pdata){ - int sampread=pdata->periodsize; -#ifdef HAVE_JACK_H - void *jackbuf=NULL; - if(pdata->args.use_jack){ - jackbuf=malloc(pdata->sound_framesize*pdata->jdata->buffersize); - } -#endif - pdata->v_encoding_clean=0; - while((pdata->running)){ - float **vorbis_buffer; - int count=0,i,j; - SndBuffer *buff=NULL; - - if (pdata->paused) { - pthread_mutex_lock(&pdata->pause_mutex); - pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); - pthread_mutex_unlock(&pdata->pause_mutex); - } - 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;iargs.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); - } - else{ -#ifdef HAVE_JACK_H - if((*jack_ringbuffer_read_space_p)(pdata->jdata->sound_buffer)>= - (pdata->sound_framesize*pdata->jdata->buffersize)){ - (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer, - jackbuf, - (pdata->sound_framesize* - pdata->jdata->buffersize)); - vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp, - sampread); - for(j=0;jargs.channels;j++){ - for(i=0;iv_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); - - pthread_mutex_lock(&pdata->libogg_mutex); - while(vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_vo_block)==1){ - - vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); - vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); - - while(vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_ogg_pckt2)){ - ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, - &pdata->enc_data->m_ogg_pckt2); - } - } - pthread_mutex_unlock(&pdata->libogg_mutex); - - pdata->avd-=pdata->periodtime; - - - } - - pdata->v_encoding_clean=1; - pthread_mutex_lock(&pdata->vorbis_lib_mutex); - pthread_cond_signal(&pdata->vorbis_lib_clean); - pthread_mutex_unlock(&pdata->vorbis_lib_mutex); - pthread_exit(&errno); -} - -void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ - float **vorbis_buffer; - int count=0,i,j; - int sampread=(buff!=NULL)?pdata->periodsize:0; - - vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); - - if(!pdata->args.use_jack){ - for(i=0;iargs.channels;j++){ - vorbis_buffer[j][i]=((buff[count+1]<<8)| - (0x00ff&(int)buff[count]))/ - 32768.f; - count+=2; - } - } - } - else{ - for(j=0;jargs.channels;j++){ - for(i=0;ienc_data->m_vo_dsp,sampread); - - pthread_mutex_lock(&pdata->libogg_mutex); - while(vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_vo_block)==1){ - - vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); - vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); - - while(vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, - &pdata->enc_data->m_ogg_pckt2)){ - ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, - &pdata->enc_data->m_ogg_pckt2); - } - } - pthread_mutex_unlock(&pdata->libogg_mutex); - - if(!pdata->running)pdata->enc_data->m_ogg_vs.e_o_s=1; - - pdata->avd-=pdata->periodtime; -} - diff --git a/recordmydesktop/src/encode_sound_buffer.h b/recordmydesktop/src/encode_sound_buffer.h deleted file mode 100644 index 1757240..0000000 --- a/recordmydesktop/src/encode_sound_buffer.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef ENCODE_SOUND_BUFFER_H -#define ENCODE_SOUND_BUFFER_H 1 - -#include "rmdtypes.h" - - -/** -* Sound encoding thread. Picks up data from the buffer queue , -* encodes and places them on the vorbis stream. -* -* \param pdata ProgData struct containing all program data -*/ -void *EncodeSoundBuffer(ProgData *pdata); - -/** -* As EncodeSoundBuffer, only with the assumption that -* this is not a thread on it's own -* -* \param pdata ProgData struct containing all program data -* -*/ -void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff); - - -#endif diff --git a/recordmydesktop/src/flush_to_ogg.c b/recordmydesktop/src/flush_to_ogg.c deleted file mode 100644 index 05007af..0000000 --- a/recordmydesktop/src/flush_to_ogg.c +++ /dev/null @@ -1,215 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "encode_image_buffer.h" -#include "encode_sound_buffer.h" -#include "flush_to_ogg.h" - - -//we copy the page because the next call to ogg_stream_pageout -//will invalidate it. But we must have pages from -//both streams at every time in -//order to do correct multiplexing -static void ogg_page_cp(ogg_page *new, ogg_page *old) { - int i=0; - register unsigned char *newp,*oldp; - - new->header_len=old->header_len; - new->header=malloc(new->header_len); - new->body_len=old->body_len; - new->body=malloc(new->body_len); - - newp=new->header; - oldp=old->header; - for(i=0;iheader_len;i++) - *(newp++)=*(oldp++); - newp=new->body; - oldp=old->body; - for(i=0;ibody_len;i++) - *(newp++)=*(oldp++); - -} -//free our copy -static void ogg_page_cp_free(ogg_page *pg) { - pg->header_len=pg->body_len=0; - free(pg->header); - free(pg->body); -} - -void *FlushToOgg(ProgData *pdata){ - int videoflag=0,audioflag=0; - double video_bytesout=0,audio_bytesout=0; - ogg_page videopage,//owned by libogg - videopage_copy,//owned by the application - audiopage,//owned by libogg - audiopage_copy;//owned by the application - - double audiotime=0; - double videotime=0; - int working=1, - th_st_fin=0, - v_st_fin=(pdata->args.nosound); - while(working){ - int audio_or_video=0; - if(pdata->running){ - pthread_mutex_lock(&pdata->libogg_mutex); - if(!videoflag){ - videoflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_ts, - &videopage); - videotime=(videoflag)? - theora_granule_time(&pdata->enc_data->m_th_st, - ogg_page_granulepos(&videopage)):-1; - if(videoflag)ogg_page_cp(&videopage_copy,&videopage); - } - if(!pdata->args.nosound) - if(!audioflag){ - audioflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_vs, - &audiopage); - audiotime=(audioflag)? - vorbis_granule_time(&pdata->enc_data->m_vo_dsp, - ogg_page_granulepos(&audiopage)):-1; - if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); - } - pthread_mutex_unlock(&pdata->libogg_mutex); - } - else{ - if(!th_st_fin && !videoflag){ - pthread_mutex_lock(&pdata->libogg_mutex); - videoflag=ogg_stream_flush(&pdata->enc_data->m_ogg_ts, - &videopage); - videotime=(videoflag)? - theora_granule_time(&pdata->enc_data->m_th_st, - ogg_page_granulepos(&videopage)):-1; - if(videoflag)ogg_page_cp(&videopage_copy,&videopage); - pthread_mutex_unlock(&pdata->libogg_mutex); - //we need the last page to properly close the stream - if(!videoflag){ - if(!pdata->th_encoding_clean){ - pthread_mutex_lock(&pdata->theora_lib_mutex); - pthread_cond_wait(&pdata->theora_lib_clean, - &pdata->theora_lib_mutex); - pthread_mutex_unlock(&pdata->theora_lib_mutex); - } - SyncEncodeImageBuffer(pdata); - } - } - if(!pdata->args.nosound && !v_st_fin &&!audioflag){ - pthread_mutex_lock(&pdata->libogg_mutex); - audioflag=ogg_stream_flush(&pdata->enc_data->m_ogg_vs, - &audiopage); - audiotime=(audioflag)? - vorbis_granule_time(&pdata->enc_data->m_vo_dsp, - ogg_page_granulepos(&audiopage)):-1; - if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); - pthread_mutex_unlock(&pdata->libogg_mutex); - //we need the last page to properly close the stream - if(!audioflag){ - if(!pdata->v_encoding_clean){ - pthread_mutex_lock(&pdata->vorbis_lib_mutex); - pthread_cond_wait(&pdata->vorbis_lib_clean, - &pdata->vorbis_lib_mutex); - pthread_mutex_unlock(&pdata->vorbis_lib_mutex); - } - SyncEncodeSoundBuffer(pdata,NULL); - } - } - } - if(th_st_fin)videoflag=0; - if(v_st_fin)audioflag=0; - if((!audioflag && !v_st_fin && !pdata->args.nosound)|| - (!videoflag && !th_st_fin)){ - usleep(10000); - continue; - } - if(!audioflag){ - audio_or_video=1; - } - else if(!videoflag) { - audio_or_video=0; - } - else{ - if(audiotimeenc_data->fp); - video_bytesout+=fwrite(videopage_copy.body,1, - videopage_copy.body_len, - pdata->enc_data->fp); - videoflag=0; - if(!pdata->running){ - pthread_mutex_lock(&pdata->libogg_mutex); - if(ogg_page_eos(&videopage_copy)) - th_st_fin=1; - pthread_mutex_unlock(&pdata->libogg_mutex); - } - ogg_page_cp_free(&videopage_copy); - } - else{ - audio_bytesout+=fwrite(audiopage_copy.header,1, - audiopage_copy.header_len, - pdata->enc_data->fp); - audio_bytesout+=fwrite(audiopage_copy.body,1, - audiopage_copy.body_len, - pdata->enc_data->fp); - audioflag=0; - if(!pdata->running){ - pthread_mutex_lock(&pdata->libogg_mutex); - if(ogg_page_eos(&audiopage_copy)) - v_st_fin=1; - pthread_mutex_unlock(&pdata->libogg_mutex); - } - ogg_page_cp_free(&audiopage_copy); - } - working=(!th_st_fin || !v_st_fin); - - } - pthread_mutex_lock(&pdata->libogg_mutex); - ogg_stream_clear(&pdata->enc_data->m_ogg_ts); - if(!pdata->args.nosound) - ogg_stream_clear(&pdata->enc_data->m_ogg_vs); - pthread_mutex_unlock(&pdata->libogg_mutex); -//this always gives me a segfault :( -// theora_clear(&pdata->enc_data->m_th_st); - - if(pdata->enc_data->fp)fclose(pdata->enc_data->fp); - fprintf(stderr,"\r \nDone.\nWritten %.0f bytes\n" - "(%.0f of which were video data " - "and %.0f audio data)\n\n", - video_bytesout+audio_bytesout, - video_bytesout,audio_bytesout); - pthread_exit(&errno); -} diff --git a/recordmydesktop/src/flush_to_ogg.h b/recordmydesktop/src/flush_to_ogg.h deleted file mode 100644 index d7a2fcd..0000000 --- a/recordmydesktop/src/flush_to_ogg.h +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef FLUSH_TO_OGG_H -#define FLUSH_TO_OGG_H 1 - -#include "rmdtypes.h" - - -/** -* Query theora and vorbis streams for ready packages and -* flush them on the disk -* \param pdata ProgData struct containing all program data -*/ -void *FlushToOgg(ProgData *pdata); - -#endif diff --git a/recordmydesktop/src/get_frame.c b/recordmydesktop/src/get_frame.c deleted file mode 100644 index bc221db..0000000 --- a/recordmydesktop/src/get_frame.c +++ /dev/null @@ -1,669 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include -#include - -#include -#include - -#include "rmdtypes.h" - -#include "get_frame.h" -#include "getzpixmap.h" -#include "poll_events.h" -#include "rectinsert.h" -#include "rmd_cache.h" -#include "rmd_frame.h" -#include "update_image.h" -#include "yuv_utils.h" - - -#define AVG_4_PIXELS(data_array,width_img,k_tm,i_tm,offset)\ - ((data_array[(k_tm*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+\ - data_array[((k_tm-1)*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+\ - data_array[(k_tm*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset]+\ - data_array[((k_tm-1)*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset])/4) - -#define CLIP_DUMMY_POINTER_AREA(dummy_p_area,brwin,wgeom){\ - (wgeom)->x=((((dummy_p_area).x+\ - (dummy_p_area).width>=(brwin)->rgeom.x)&&\ - ((dummy_p_area).x<=(brwin)->rgeom.x+\ - (brwin)->rgeom.width))?\ - (((dummy_p_area).x<=(brwin)->rgeom.x)?\ - (brwin)->rgeom.x:(dummy_p_area).x):-1);\ - (wgeom)->y=((((dummy_p_area).y+\ - (dummy_p_area).height>=(brwin)->rgeom.y)&&\ - ((dummy_p_area).y<=(brwin)->rgeom.y+\ - (brwin)->rgeom.height))?\ - (((dummy_p_area).y<=(brwin)->rgeom.y)?\ - (brwin)->rgeom.y:(dummy_p_area).y):-1);\ - (wgeom)->width=((dummy_p_area).x<=(brwin)->rgeom.x)?\ - (dummy_p_area).width-\ - ((brwin)->rgeom.x-(dummy_p_area).x):\ - ((dummy_p_area).x<=(brwin)->rgeom.x+\ - (brwin)->rgeom.width)?\ - ((brwin)->rgeom.width-(dummy_p_area).x+\ - (brwin)->rgeom.x<(dummy_p_area).width)?\ - (brwin)->rgeom.width-(dummy_p_area).x+\ - (brwin)->rgeom.x:(dummy_p_area).width:-1;\ - (wgeom)->height=((dummy_p_area).y<=(brwin)->rgeom.y)?\ - (dummy_p_area).height-\ - ((brwin)->rgeom.y-(dummy_p_area).y):\ - ((dummy_p_area).y<=(brwin)->rgeom.y+\ - (brwin)->rgeom.height)?\ - ((brwin)->rgeom.height-(dummy_p_area).y+\ - (brwin)->rgeom.y<(dummy_p_area).height)?\ - (brwin)->rgeom.height-(dummy_p_area).y+\ - (brwin)->rgeom.y:(dummy_p_area).height:-1;\ - if((wgeom)->width>(brwin)->rgeom.width)\ - (wgeom)->width=(brwin)->rgeom.width;\ - if((wgeom)->height>(brwin)->rgeom.height)\ - (wgeom)->height=(brwin)->rgeom.height;\ -} - -#define XFIXES_POINTER_TO_YUV(yuv,\ - data,\ - x_tm,\ - y_tm,\ - width_tm,\ - height_tm,\ - x_offset,\ - y_offset,\ - column_discard_stride){\ - int i,k,j=0;\ - unsigned char avg0,avg1,avg2,avg3;\ - int x_2=x_tm/2,y_2=y_tm/2;\ - for(k=y_offset;ky[x_tm+(i-x_offset)+(k+y_tm-y_offset)*yuv->y_width]=\ - (yuv->y[x_tm+(i-x_offset)+(k-y_offset+y_tm)*yuv->y_width]*\ - (UCHAR_MAX-data[(j*RMD_ULONG_SIZE_T)+__ABYTE])+\ - (Yr[data[(j*RMD_ULONG_SIZE_T)+__RBYTE]]+\ - Yg[data[(j*RMD_ULONG_SIZE_T)+__GBYTE]] +\ - Yb[data[(j*RMD_ULONG_SIZE_T)+__BBYTE]])*\ - data[(j*RMD_ULONG_SIZE_T)+__ABYTE])/UCHAR_MAX ;\ - if((k%2)&&(i%2)){\ - avg3=AVG_4_PIXELS(data,\ - (width_tm+column_discard_stride),\ - k,i,__ABYTE);\ - avg2=AVG_4_PIXELS(data,\ - (width_tm+column_discard_stride),\ - k,i,__RBYTE);\ - avg1=AVG_4_PIXELS(data,\ - (width_tm+column_discard_stride),\ - k,i,__GBYTE);\ - avg0=AVG_4_PIXELS(data,\ - (width_tm+column_discard_stride),\ - k,i,__BBYTE);\ - yuv->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ - yuv->uv_width]=\ - (yuv->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ - yuv->uv_width]*\ - (UCHAR_MAX-avg3)+\ - (Ur[avg2] + Ug[avg1] +UbVr[avg0])*avg3)/UCHAR_MAX;\ - yuv->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ - yuv->uv_width]=\ - (yuv->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ - yuv->uv_width]*\ - (UCHAR_MAX-avg3)+\ - (UbVr[avg2] + Vg[avg1] +Vb[avg0])*avg3)/UCHAR_MAX;\ - }\ - }\ - }\ -} - -#define MARK_BACK_BUFFER_C( data,\ - x_tm,\ - y_tm,\ - width_tm,\ - height_tm,\ - buffer_width,\ - __bit_depth__){\ - int k,i;\ - register u_int##__bit_depth__##_t\ - *datapi=\ - ((u_int##__bit_depth__##_t *)data)+y_tm*buffer_width+x_tm;\ - for(k=0;kargs.noshared)){ - - *pxl_data=(char *)malloc(pdata->brwin.nbytes); - - (*image)=XCreateImage(pdata->dpy, - pdata->specs.visual, - pdata->specs.depth, - ZPixmap, - 0, - *pxl_data, - pdata->brwin.rgeom.width, - pdata->brwin.rgeom.height, - 8, - 0); - XInitImage((*image)); - GetZPixmap(pdata->dpy,pdata->specs.root, - (*image)->data, - pdata->brwin.rgeom.x, - pdata->brwin.rgeom.y, - pdata->brwin.rgeom.width, - pdata->brwin.rgeom.height); - } - else{ - (*image)=XShmCreateImage(pdata->dpy, - pdata->specs.visual, - pdata->specs.depth, - ZPixmap, - *pxl_data, - shminfo, - pdata->brwin.rgeom.width, - pdata->brwin.rgeom.height); - (*shminfo).shmid=shmget(IPC_PRIVATE, - (*image)->bytes_per_line* - (*image)->height, - IPC_CREAT|0777); - if((*shminfo).shmid==-1){ - fprintf(stderr,"Failed to obtain Shared Memory segment!\n"); - return 12; - } - (*shminfo).shmaddr=(*image)->data=shmat((*shminfo).shmid, - NULL,0); - (*shminfo).readOnly = False; - if(!XShmAttach(pdata->dpy,shminfo)){ - fprintf(stderr,"Failed to attach shared memory to proccess.\n"); - return 12; - } - XShmGetImage(pdata->dpy, - pdata->specs.root, - (*image), - pdata->brwin.rgeom.x, - pdata->brwin.rgeom.y, - AllPlanes); - } - - UPDATE_YUV_BUFFER((&pdata->enc_data->yuv), - ((unsigned char*)((*image))->data),NULL, - (pdata->enc_data->x_offset),(pdata->enc_data->y_offset), - (pdata->brwin.rgeom.width),(pdata->brwin.rgeom.height), - (pdata->args.no_quick_subsample), - pdata->specs.depth); - - return 0; -} - -//make a deep copy -static void BRWinCpy(BRWindow *target, BRWindow *source) { - - target->geom.x=source->geom.x; - target->geom.y=source->geom.y; - target->geom.width=source->geom.width; - target->geom.height=source->geom.height; - target->rgeom.x=source->rgeom.x; - target->rgeom.y=source->rgeom.y; - target->rgeom.width=source->rgeom.width; - target->rgeom.height=source->rgeom.height; - target->nbytes=source->nbytes; - target->windowid=source->windowid; - -} - -//recenters the capture area to the mouse -//without exiting the display bounding box -static void MoveCaptureArea(BRWindow *brwin, - int cursor_x, - int cursor_y, - int width, - int height) { - int t_x=0,t_y=0; - - t_x=cursor_x-brwin->rgeom.width/2; - t_x=(t_x>>1)<<1; - brwin->rgeom.x=(t_x<0)?0:((t_x+brwin->rgeom.width>width)? - width-brwin->rgeom.width:t_x); - t_y=cursor_y-brwin->rgeom.height/2; - t_y=(t_y>>1)<<1; - brwin->rgeom.y=(t_y<0)?0:((t_y+brwin->rgeom.height>height)? - height-brwin->rgeom.height:t_y); -} - -/** -* Extract cache blocks from damage list -* -* \param root Root entry of the list with damaged areas -* -* \param x_offset left x of the recording area -* -* \param x_offset upper y of the recording area -* -* \param blocknum_x Width of image in blocks -* -* \param blocknum_y Height of image in blocks -*/ -static void BlocksFromList (RectArea **root, - unsigned int x_offset, - unsigned int y_offset, - unsigned int blocknum_x, - unsigned int blocknum_y) { - - RectArea *temp; - unsigned int i, - j, - blockno, - row_start, - row_end, - column_start, - column_end; - - temp = *root; - - for (i = 0; i < blocknum_x * blocknum_y; i++) { - yblocks[i] = ublocks[i] = vblocks[i] = 0; - } - - while (temp != NULL) { - - column_start = (temp->geom.x - x_offset) / Y_UNIT_WIDTH; - column_end = (temp->geom.x + (temp->geom.width - 1) - x_offset) / Y_UNIT_WIDTH; - row_start = (temp->geom.y - y_offset) / Y_UNIT_WIDTH; - row_end = (temp->geom.y + (temp->geom.height - 1) - y_offset) / Y_UNIT_WIDTH; - - for (i = row_start; i < row_end + 1; i++) { - for (j = column_start; j < column_end + 1; j++) { - blockno = i * blocknum_x + j; - yblocks[blockno] = 1; - ublocks[blockno] = 1; - vblocks[blockno] = 1; - } - } - - temp = temp->next; - } -} - -void *GetFrame(ProgData *pdata){ - int i=0, - blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, - blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH; - unsigned int msk_ret; - WGeometry mouse_pos_abs,mouse_pos_rel,mouse_pos_temp; - BRWindow temp_brwin; - Window root_ret, - child_ret; //Frame - XFixesCursorImage *xcim=NULL; - XImage *image=NULL,*image_back=NULL; //the image that holds - //the current full screenshot - XShmSegmentInfo shminfo,shminfo_back;//info structure for the image above. - int init_img1=0,init_img2=0, - img_sel,d_buff; - char *pxl_data=NULL,*pxl_data_back=NULL; - - - - - img_sel=d_buff=pdata->args.full_shots; - - if((init_img1=FirstFrame(pdata,&image,&shminfo,&pxl_data)!=0)){ - if(pdata->args.encOnTheFly){ - if(remove(pdata->args.filename)){ - perror("Error while removing file:\n"); - } - else{ - fprintf(stderr,"SIGABRT received,file %s removed\n", - pdata->args.filename); - } - } - else{ - PurgeCache(pdata->cache_data,!pdata->args.nosound); - } - exit(init_img1); - } - if(d_buff){ - if((init_img2=FirstFrame(pdata,&image_back,&shminfo_back, - &pxl_data_back)!=0)){ - if(pdata->args.encOnTheFly){ - if(remove(pdata->args.filename)){ - perror("Error while removing file:\n"); - } - else{ - fprintf(stderr,"SIGABRT received,file %s removed\n", - pdata->args.filename); - } - } - else{ - PurgeCache(pdata->cache_data,!pdata->args.nosound); - } - exit(init_img2); - } - - } - - if(!pdata->args.noframe){ - pdata->shaped_w=rmdFrameInit(pdata->dpy, - pdata->specs.screen, - pdata->specs.root, - pdata->brwin.rgeom.x, - pdata->brwin.rgeom.y, - pdata->brwin.rgeom.width, - pdata->brwin.rgeom.height); - XSelectInput(pdata->dpy,pdata->shaped_w,ExposureMask); - } - - mouse_pos_abs.x=mouse_pos_temp.x=0; - mouse_pos_abs.y=mouse_pos_temp.y=0; - mouse_pos_abs.width=mouse_pos_temp.width=pdata->dummy_p_size; - mouse_pos_abs.height=mouse_pos_temp.height=pdata->dummy_p_size; - - //This is the the place where we call XSelectInput - //and arrange so that we listen for damage on all - //windows - InitEventsPolling(pdata); - - while(pdata->running){ - - //if we are left behind we must not wait. - //also before actually pausing we must make sure the streams - //are synced. sound stops so this should only happen quickly. - if(pdata->avd>0 || pdata->args.nosound){ - pthread_mutex_lock(&pdata->time_mutex); - pthread_cond_wait(&pdata->time_cond, &pdata->time_mutex); - pthread_mutex_unlock(&pdata->time_mutex); - if (pdata->paused) { - //this is necessary since event loop processes - //the shortcuts which will unpause the program - EventLoop(pdata); - continue; - } - } - //read all events and construct list with damage - //events (if not full_shots) - EventLoop(pdata); - - //switch back and front buffers (full_shots only) - if(d_buff) - img_sel=(img_sel)?0:1; - pdata->capture_busy = TRUE; - - BRWinCpy(&temp_brwin,&pdata->brwin); - - - if(pdata->args.xfixes_cursor || - pdata->args.have_dummy_cursor|| - pdata->args.follow_mouse){ - //pointer sequence - //update previous_position - //(if full_shots is enabled the new cursor is - //entered on the list for update. - //When taking full shots we keep it for further - //bellow, to mark the area as dirty when dbuffering. - CLIP_DUMMY_POINTER_AREA(mouse_pos_abs,&temp_brwin, - &mouse_pos_temp); - if(!pdata->args.full_shots){ - if((mouse_pos_temp.x>=0)&& - (mouse_pos_temp.y>=0)&& - (mouse_pos_temp.width>0)&& - (mouse_pos_temp.height>0)) - RectInsert(&pdata->rect_root,&mouse_pos_temp); - } - //find new one - if(pdata->args.xfixes_cursor){ - xcim=XFixesGetCursorImage(pdata->dpy); - mouse_pos_abs.x=xcim->x-xcim->xhot; - mouse_pos_abs.y=xcim->y-xcim->yhot; - mouse_pos_abs.width=xcim->width; - mouse_pos_abs.height=xcim->height; - } - else{ - XQueryPointer(pdata->dpy, - pdata->specs.root, - &root_ret,&child_ret, - &mouse_pos_abs.x,&mouse_pos_abs.y, - &mouse_pos_rel.x,&mouse_pos_rel.y,&msk_ret); - } - } - if(pdata->args.follow_mouse){ - MoveCaptureArea(&pdata->brwin, - mouse_pos_abs.x+ - ((pdata->args.xfixes_cursor)?xcim->xhot:0), - mouse_pos_abs.y+ - ((pdata->args.xfixes_cursor)?xcim->yhot:0), - pdata->specs.width, - pdata->specs.height); - if(!pdata->args.noframe){ - rmdMoveFrame(pdata->dpy, - pdata->shaped_w, - temp_brwin.rgeom.x, - temp_brwin.rgeom.y); - - } - } - - if(!pdata->args.full_shots){ - pthread_mutex_lock(&pdata->yuv_mutex); - UpdateImage(pdata->dpy, - &pdata->enc_data->yuv, - &pdata->specs, - &pdata->rect_root, - &temp_brwin, - pdata->enc_data, - image->data, - pdata->args.noshared, - &shminfo, - pdata->shm_opcode, - pdata->args.no_quick_subsample); - BlocksFromList(&pdata->rect_root, - temp_brwin.rgeom.x, - temp_brwin.rgeom.y, - pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, - pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH); - pthread_mutex_unlock(&pdata->yuv_mutex); - } - else{ - unsigned char *front_buff=(!img_sel)?((unsigned char*)image->data): - ((unsigned char*)image_back->data); - unsigned char *back_buff=(!d_buff)?NULL:((img_sel)? - ((unsigned char*)image->data): - ((unsigned char*)image_back->data)); - - if(!pdata->args.noshared){ - XShmGetImage(pdata->dpy,pdata->specs.root, - ((!img_sel)?image:image_back), - (temp_brwin.rgeom.x), - (temp_brwin.rgeom.y),AllPlanes); - } - if(pdata->args.noshared){ - GetZPixmap( pdata->dpy, - pdata->specs.root, - image->data, - temp_brwin.rgeom.x, - temp_brwin.rgeom.y, - temp_brwin.rgeom.width, - temp_brwin.rgeom.height); - } - pthread_mutex_lock(&pdata->yuv_mutex); - for(i=0;ienc_data->yuv), - front_buff,back_buff, - (pdata->enc_data->x_offset), - (pdata->enc_data->y_offset), - (temp_brwin.rgeom.width), - (temp_brwin.rgeom.height), - pdata->args.no_quick_subsample, - pdata->specs.depth); - pthread_mutex_unlock(&pdata->yuv_mutex); - } - if(pdata->args.xfixes_cursor || - pdata->args.have_dummy_cursor){ - int mouse_xoffset, - mouse_yoffset; - //avoid segfaults - CLIP_DUMMY_POINTER_AREA(mouse_pos_abs,&temp_brwin, - &mouse_pos_temp); - mouse_xoffset=mouse_pos_temp.x-mouse_pos_abs.x; - mouse_yoffset=mouse_pos_temp.y-mouse_pos_abs.y; - if((mouse_xoffset<0) || (mouse_xoffset>mouse_pos_abs.width)) - mouse_xoffset=0; - if((mouse_yoffset<0) || (mouse_yoffset>mouse_pos_abs.height)) - mouse_yoffset=0; - //draw the cursor - if((mouse_pos_temp.x>=0)&& - (mouse_pos_temp.y>=0)&& - (mouse_pos_temp.width>0)&& - (mouse_pos_temp.height>0)){ - if(pdata->args.xfixes_cursor){ - XFIXES_POINTER_TO_YUV((&pdata->enc_data->yuv), - ((unsigned char*)xcim->pixels), - (mouse_pos_temp.x- - temp_brwin.rgeom.x+ - pdata->enc_data->x_offset), - (mouse_pos_temp.y- - temp_brwin.rgeom.y+ - pdata->enc_data->y_offset), - mouse_pos_temp.width, - mouse_pos_temp.height, - mouse_xoffset, - mouse_yoffset, - (xcim->width-mouse_pos_temp.width)); - } - else{ - DUMMY_POINTER_TO_YUV((&pdata->enc_data->yuv), - pdata->dummy_pointer, - (mouse_pos_temp.x- - temp_brwin.rgeom.x+ - pdata->enc_data->x_offset), - (mouse_pos_temp.y- - temp_brwin.rgeom.y+ - pdata->enc_data->y_offset), - mouse_pos_temp.width, - mouse_pos_temp.height, - mouse_xoffset, - mouse_yoffset, - pdata->npxl); - } - if(d_buff){ - //make previous cursor position dirty - unsigned char *front_buff= - (!img_sel)?((unsigned char*)image->data): - ((unsigned char*)image_back->data); - - MARK_BACK_BUFFER( front_buff, - (mouse_pos_temp.x- - temp_brwin.rgeom.x+ - pdata->enc_data->x_offset), - (mouse_pos_temp.y- - temp_brwin.rgeom.y+ - pdata->enc_data->y_offset), - mouse_pos_temp.width, - mouse_pos_temp.height, - (temp_brwin.rgeom.width), - pdata->specs.depth) - } - - } - if(pdata->args.xfixes_cursor){ - XFree(xcim); - xcim=NULL; - } - } - if(!pdata->args.full_shots){ - ClearList(&pdata->rect_root); - } - if (pdata->encoder_busy) { - pdata->frames_lost++; - } - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_broadcast(&pdata->image_buffer_ready); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - pdata->capture_busy = FALSE; - } - - if(!pdata->args.noframe){ - XDestroyWindow(pdata->dpy,pdata->shaped_w); - } - - - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_broadcast(&pdata->image_buffer_ready); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - if(!pdata->args.noshared){ - XShmDetach (pdata->dpy, &shminfo); - shmdt (shminfo.shmaddr); - shmctl (shminfo.shmid, IPC_RMID, 0); - if(d_buff){ - XShmDetach (pdata->dpy, &shminfo_back); - shmdt (shminfo_back.shmaddr); - shmctl (shminfo_back.shmid, IPC_RMID, 0); - } - } - pthread_exit(&errno); -} - diff --git a/recordmydesktop/src/get_frame.h b/recordmydesktop/src/get_frame.h deleted file mode 100644 index 9c4c6d0..0000000 --- a/recordmydesktop/src/get_frame.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef GET_FRAME_H -#define GET_FRAME_H 1 - -#include "rmdtypes.h" - - -/** -* Retrieve frame form xserver, and transform to a yuv buffer, -* either directly(full shots) or by calling UpdateImage. -* \param pdata ProgData struct containing all program data -*/ -void *GetFrame(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/getzpixmap.c b/recordmydesktop/src/getzpixmap.c deleted file mode 100644 index b73bd01..0000000 --- a/recordmydesktop/src/getzpixmap.c +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include -#include -#include - -#include "rmdtypes.h" - -#include "getzpixmap.h" - - -int GetZPixmap(Display *dpy, - Window root, - char *data, - int x, - int y, - int width, - int height){ - xGetImageReply reply; - xGetImageReq *request; - long nbytes; - - LockDisplay(dpy); - GetReq(GetImage,request); - request->drawable=root; - request->x=x; - request->y=y; - request->width=width; - request->height=height; - request->planeMask=AllPlanes; - request->format=ZPixmap; - if((!_XReply(dpy,(xReply *)&reply,0,xFalse))||(!reply.length)){ - UnlockDisplay(dpy); - SyncHandle(); - return 1; - } - nbytes=(long)reply.length<<2; - _XReadPad(dpy,data,nbytes); - UnlockDisplay(dpy); - SyncHandle(); - return 0; -} - -int GetZPixmapSHM(Display *dpy, - Window root, - XShmSegmentInfo *shminfo, - int shm_opcode, - char *data, - int x, - int y, - int width, - int height){ - xShmGetImageReply reply; - xShmGetImageReq *request=NULL; - long nbytes; - - LockDisplay(dpy); - GetReq(ShmGetImage,request); - - request->reqType=shm_opcode; - request->shmReqType=X_ShmGetImage; - request->shmseg=shminfo->shmseg; - - request->drawable=root; - request->x=x; - request->y=y; - request->width=width; - request->height=height; - request->planeMask=AllPlanes; - request->format=ZPixmap; - request->offset=data-shminfo->shmaddr; - - if((!_XReply(dpy,(xReply *)&reply,0,xFalse))||(!reply.length)){ - UnlockDisplay(dpy); - SyncHandle(); - return 1; - } - - nbytes=(long)reply.length << 2; - _XReadPad(dpy,data,nbytes); - UnlockDisplay(dpy); - SyncHandle(); - - return 0; -} diff --git a/recordmydesktop/src/getzpixmap.h b/recordmydesktop/src/getzpixmap.h deleted file mode 100644 index 68242b0..0000000 --- a/recordmydesktop/src/getzpixmap.h +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef GETZPIXMAP_H -#define GETZPIXMAP_H 1 - -#include "rmdtypes.h" - - -/** -* Rerieve pixmap data from xserver -* -* \param dpy Connection to the server -* -* \param root root window of the display -* -* \param data (preallocated)buffer to place the data -* -* \param x x position of the screenshot -* -* \param y y position of the screenshot -* -* \param x x position of the screenshot -* -* \param width width of the screenshot -* -* \param height height position of the screenshot -* -* \returns 0 on Success 1 on Failure -*/ -int GetZPixmap(Display *dpy, - Window root, - char *data, - int x, - int y, - int width, - int height); - -/** -* Rerieve pixmap data from xserver through the MIT-Shm extension -* -* \param dpy Connection to the server -* -* \param root root window of the display -* -* \param shminfo Info for the shared memory segment -* -* \param shm_opcode Opcode of Shm extension -* -* \param data (preallocated)buffer to place the data -* -* \param x x position of the screenshot -* -* \param y y position of the screenshot -* -* \param x x position of the screenshot -* -* \param width width of the screenshot -* -* \param height height position of the screenshot -* -* \returns 0 on Success 1 on Failure -*/ -int GetZPixmapSHM(Display *dpy, - Window root, - XShmSegmentInfo *shminfo, - int shm_opcode, - char *data, - int x, - int y, - int width, - int height); - - -#endif diff --git a/recordmydesktop/src/init_encoder.c b/recordmydesktop/src/init_encoder.c deleted file mode 100644 index b093292..0000000 --- a/recordmydesktop/src/init_encoder.c +++ /dev/null @@ -1,370 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include - -#include "rmdtypes.h" - -#include "init_encoder.h" -#include "rmdmacro.h" -#include "skeleton.h" - - -static void m_add_fishead_packet(ogg_stream_state *m_ogg_state) { - - fishead_packet skel_fp; - - skel_fp.ptime_n=skel_fp.btime_n=0; - skel_fp.ptime_d=skel_fp.btime_d=1000; - - add_fishead_to_stream(m_ogg_state,&skel_fp); - - -} - - -static int IncrementalNaming(char **name) { - struct stat buff; - char *base_name__; - int i=0, - fname_length=strlen(*name)-4; - - base_name__=malloc(fname_length+1); - strncpy(base_name__,*name,fname_length); - base_name__[fname_length]='\0'; - - - //this will go on an endless loop if you have 65536? - //files with the same name - //or it will crash and die.anyone interested in trying ? - while (stat(*name,&buff)==0){ - //create new name - char *tname=malloc(strlen(*name)+10); - char numbuf[8]; - - strcpy(tname,base_name__); - strcat(tname,"-"); - i++; - I16TOA((i),numbuf) - strcat(tname,numbuf); - strcat(tname,".ogv"); - //save new name - - free(*name); - *name=malloc(strlen(tname)+1); - strcpy(*name,tname); - free(tname); - } - - free(base_name__); - return 0; -} - -void InitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready){ - - int y0, - y1, - y2, - fname_length; - ogg_stream_state m_ogg_skel; - ogg_page skel_og_pg; - fisbone_packet skel_fbv, //video fisbone packet - skel_fba ; //audio fisbone packet - - (pdata)->enc_data=enc_data_t; - - fname_length=strlen(pdata->args.filename); - if(!(fname_length>4 && - pdata->args.filename[fname_length-4] == '.' && - (pdata->args.filename[fname_length-3] == 'o' || - pdata->args.filename[fname_length-3] == 'O') && - (pdata->args.filename[fname_length-2] == 'g' || - pdata->args.filename[fname_length-2] == 'G') && - (pdata->args.filename[fname_length-1] == 'v' || - pdata->args.filename[fname_length-1] == 'V'))){ - - char *new_name=malloc(fname_length+5); - strcpy(new_name,pdata->args.filename); - strcat(new_name,".ogv"); - - free(pdata->args.filename); - pdata->args.filename=new_name; - - - } - - if(!pdata->args.overwrite) - IncrementalNaming(&(pdata)->args.filename); - enc_data_t->fp=fopen((pdata)->args.filename,"w"); - if(enc_data_t->fp==NULL){ - fprintf(stderr,"Cannot open file %s for writting!\n", - (pdata)->args.filename); - exit(13); - } - - //each stream must have a unique - srand(time(NULL)); - y0=rand()+1; - y1=rand()+1; - y2=rand()+1; - y2+=(y1==y2); - y0=(((y0==y1)||(y0==y2))?(y1+y2):y0); - - //init ogg streams - //skeleton first - ogg_stream_init(&m_ogg_skel,y0); - m_add_fishead_packet(&m_ogg_skel); - if(ogg_stream_pageout(&m_ogg_skel,&skel_og_pg)!= 1){ - fprintf (stderr, "Internal Ogg library error.\n"); - exit (2); - } - fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); - fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); - - - - ogg_stream_init(&enc_data_t->m_ogg_ts,y1); - if(!pdata->args.nosound) - ogg_stream_init(&enc_data_t->m_ogg_vs,y2); - - - - theora_info_init(&enc_data_t->m_th_inf); - enc_data_t->m_th_inf.frame_width=(pdata)->brwin.rgeom.width; - enc_data_t->m_th_inf.frame_height=(pdata)->brwin.rgeom.height; - enc_data_t->m_th_inf.width=((enc_data_t->m_th_inf.frame_width+15)>>4)<<4; - enc_data_t->m_th_inf.height=((enc_data_t->m_th_inf.frame_height+15)>>4)<<4; - enc_data_t->m_th_inf.offset_x=((enc_data_t->m_th_inf.width- - enc_data_t->m_th_inf.frame_width)/2)&~1; - enc_data_t->m_th_inf.offset_y=((enc_data_t->m_th_inf.height- - enc_data_t->m_th_inf.frame_height)/2)&~1; - enc_data_t->m_th_inf.fps_numerator=((pdata)->args.fps*100.0); - enc_data_t->m_th_inf.fps_denominator=100; - enc_data_t->m_th_inf.aspect_numerator=1;//(pdata)->brwin.rgeom.width; - enc_data_t->m_th_inf.aspect_denominator=1;//(pdata)->brwin.rgeom.height; - enc_data_t->m_th_inf.colorspace=OC_CS_UNSPECIFIED; - enc_data_t->m_th_inf.pixelformat=OC_PF_420; - enc_data_t->m_th_inf.target_bitrate=(pdata)->args.v_bitrate; - enc_data_t->m_th_inf.quality=(pdata)->args.v_quality; - enc_data_t->m_th_inf.dropframes_p=0; - enc_data_t->m_th_inf.quick_p=1; - enc_data_t->m_th_inf.keyframe_auto_p=1; - enc_data_t->m_th_inf.keyframe_frequency=64; - enc_data_t->m_th_inf.keyframe_frequency_force=64; - enc_data_t->m_th_inf.keyframe_data_target_bitrate= - enc_data_t->m_th_inf.quality*1.5; - - enc_data_t->m_th_inf.keyframe_auto_threshold=80; - enc_data_t->m_th_inf.keyframe_mindistance=8; - enc_data_t->m_th_inf.noise_sensitivity=1; - enc_data_t->m_th_inf.sharpness=2; - - theora_encode_init(&enc_data_t->m_th_st,&enc_data_t->m_th_inf); - - - - if(!pdata->args.nosound){ - int ret; - vorbis_info_init(&enc_data_t->m_vo_inf); - ret = vorbis_encode_init_vbr(&enc_data_t->m_vo_inf, - pdata->args.channels, - pdata->args.frequency, - (float)pdata->args.s_quality*0.1); - if(ret){ - fprintf(stderr,"Error while setting up vorbis stream quality!\n"); - exit(2); - } - vorbis_comment_init(&enc_data_t->m_vo_cmmnt); - vorbis_analysis_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_inf); - vorbis_block_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_block); - } - - - theora_encode_header(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); - ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); - if(ogg_stream_pageout(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pg)!=1){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - - theora_comment_init(&enc_data_t->m_th_cmmnt); - theora_comment_add_tag(&enc_data_t->m_th_cmmnt,"recordMyDesktop",VERSION); - theora_encode_comment(&enc_data_t->m_th_cmmnt,&enc_data_t->m_ogg_pckt1); - ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); - theora_encode_tables(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); - ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); - - - if(!pdata->args.nosound){ - ogg_packet header; - ogg_packet header_comm; - ogg_packet header_code; - - vorbis_analysis_headerout(&enc_data_t->m_vo_dsp, - &enc_data_t->m_vo_cmmnt, - &header,&header_comm, - &header_code); - ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header); - if(ogg_stream_pageout(&enc_data_t->m_ogg_vs,&enc_data_t->m_ogg_pg)!=1){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - - ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_comm); - ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_code); - } - - //fishbone packets go here - memset(&skel_fbv,0,sizeof(skel_fbv)); - skel_fbv.serial_no=enc_data_t->m_ogg_ts.serialno; - skel_fbv.nr_header_packet=3; - skel_fbv.granule_rate_n=enc_data_t->m_th_inf.fps_numerator; - skel_fbv.granule_rate_d=enc_data_t->m_th_inf.fps_denominator; - skel_fbv.start_granule=0; - skel_fbv.preroll=0; - skel_fbv.granule_shift=theora_granule_shift(&enc_data_t->m_th_inf); - add_message_header_field(&skel_fbv, - "Content-Type", - "video/theora"); - - add_fisbone_to_stream(&m_ogg_skel,&skel_fbv); - - if(!pdata->args.nosound){ - - memset(&skel_fba,0,sizeof(skel_fba)); - skel_fba.serial_no=enc_data_t->m_ogg_vs.serialno; - skel_fba.nr_header_packet=3; - skel_fba.granule_rate_n=pdata->args.frequency; - skel_fba.granule_rate_d=(ogg_int64_t)1; - skel_fba.start_granule=0; - skel_fba.preroll=2; - skel_fba.granule_shift=0; - add_message_header_field(&skel_fba, - "Content-Type", - "audio/vorbis"); - - add_fisbone_to_stream(&m_ogg_skel,&skel_fba); - - } - - while(1){ - int result = ogg_stream_flush(&m_ogg_skel, &skel_og_pg); - if(result<0){ - fprintf (stderr, "Internal Ogg library error.\n"); - exit(2); - } - if(result==0) - break; - fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); - fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); - } - - - - while(1){ - int result = ogg_stream_flush(&enc_data_t->m_ogg_ts, - &enc_data_t->m_ogg_pg); - if(result<0){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - if(result==0)break; - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - } - - if(!pdata->args.nosound){ - while(1){ - int result=ogg_stream_flush(&enc_data_t->m_ogg_vs, - &enc_data_t->m_ogg_pg); - if(result<0){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - if(result==0)break; - fwrite(enc_data_t->m_ogg_pg.header,1, - enc_data_t->m_ogg_pg.header_len, - enc_data_t->fp); - fwrite(enc_data_t->m_ogg_pg.body,1, - enc_data_t->m_ogg_pg.body_len, - enc_data_t->fp); - } - } - - //skeleton eos - add_eos_packet_to_stream(&m_ogg_skel); - if(ogg_stream_flush(&m_ogg_skel,&skel_og_pg)<0){ - fprintf(stderr,"Internal Ogg library error.\n"); - exit(2); - } - fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); - fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); - - - //theora buffer allocation, if any - if(!buffer_ready){ - enc_data_t->yuv.y=(unsigned char *)malloc(enc_data_t->m_th_inf.height* - enc_data_t->m_th_inf.width); - enc_data_t->yuv.u=(unsigned char *)malloc(enc_data_t->m_th_inf.height* - enc_data_t->m_th_inf.width/4); - enc_data_t->yuv.v=(unsigned char *)malloc(enc_data_t->m_th_inf.height* - enc_data_t->m_th_inf.width/4); - enc_data_t->yuv.y_width=enc_data_t->m_th_inf.width; - enc_data_t->yuv.y_height=enc_data_t->m_th_inf.height; - enc_data_t->yuv.y_stride=enc_data_t->m_th_inf.width; - - enc_data_t->yuv.uv_width=enc_data_t->m_th_inf.width/2; - enc_data_t->yuv.uv_height=enc_data_t->m_th_inf.height/2; - enc_data_t->yuv.uv_stride=enc_data_t->m_th_inf.width/2; - enc_data_t->x_offset=enc_data_t->m_th_inf.offset_x; - enc_data_t->y_offset=enc_data_t->m_th_inf.offset_y; - } - theora_info_clear(&enc_data_t->m_th_inf); - -} - - - - diff --git a/recordmydesktop/src/init_encoder.h b/recordmydesktop/src/init_encoder.h deleted file mode 100644 index 42ebaa8..0000000 --- a/recordmydesktop/src/init_encoder.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef INIT_ENCODER_H -#define INIT_ENCODER_H 1 - -#include "rmdtypes.h" - - -/** -* Initialize theora,vorbis encoders, and their respective ogg streams. -* -* \param pdata ProgData struct containing all program data -* -* \param enc_data_t Encoding options -* -* \param buffer_ready when 1, the yuv buffer must be preallocated -* when 0 InitEncoder will alocate a new one -* -*/ -void InitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready); - - -#endif diff --git a/recordmydesktop/src/initialize_data.c b/recordmydesktop/src/initialize_data.c deleted file mode 100644 index 72d38cb..0000000 --- a/recordmydesktop/src/initialize_data.c +++ /dev/null @@ -1,256 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "block_utils.h" -#include "init_encoder.h" -#include "make_dummy_pointer.h" -#include "opendev.h" -#include "rmd_cache.h" -#include "rmd_jack.h" -#include "yuv_utils.h" - - -#ifdef HAVE_LIBASOUND -static void FixBufferSize(snd_pcm_uframes_t *buffsize) { - snd_pcm_uframes_t buffsize_t=*buffsize, -#else -static 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){ - int i; - - fprintf(stderr,"Initializing...\n"); - MakeMatrices(); - if(pdata->args.have_dummy_cursor){ - pdata->dummy_pointer=MakeDummyPointer(&pdata->specs,16, - pdata->args.cursor_color,0, - &pdata->npxl); - pdata->dummy_p_size=16; - } - else - pdata->dummy_p_size=0; - - - pdata->rect_root=NULL; - pthread_mutex_init(&pdata->sound_buffer_mutex,NULL); - pthread_mutex_init(&pdata->snd_buff_ready_mutex,NULL); - pthread_mutex_init(&pdata->img_buff_ready_mutex,NULL); - pthread_mutex_init(&pdata->theora_lib_mutex,NULL); - pthread_mutex_init(&pdata->vorbis_lib_mutex,NULL); - pthread_mutex_init(&pdata->libogg_mutex,NULL); - pthread_mutex_init(&pdata->yuv_mutex,NULL); - pthread_mutex_init(&pdata->pause_mutex, NULL); - pthread_mutex_init(&pdata->time_mutex, NULL); - pthread_cond_init(&pdata->time_cond,NULL); - pthread_cond_init(&pdata->pause_cond,NULL); - pthread_cond_init(&pdata->image_buffer_ready,NULL); - pthread_cond_init(&pdata->sound_buffer_ready,NULL); - pthread_cond_init(&pdata->sound_data_read,NULL); - pthread_cond_init(&pdata->theora_lib_clean,NULL); - pthread_cond_init(&pdata->vorbis_lib_clean,NULL); - pdata->th_encoding_clean=pdata->v_encoding_clean=1; - pdata->avd=0; - pdata->sound_buffer=NULL; - pdata->running = TRUE; - pdata->paused = FALSE; - pdata->aborted = FALSE; - pdata->pause_state_changed = FALSE; - pdata->frames_total = 0; - pdata->frames_lost = 0; - pdata->encoder_busy = FALSE; - pdata->capture_busy = FALSE; - - 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); - pdata->sound_framesize=((snd_pcm_format_width( - SND_PCM_FORMAT_S16_LE))/8)* - pdata->args.channels; - - 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; - pdata->sound_framesize=pdata->args.channels<<1; - 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->ringbuffer_secs=pdata->args.jack_ringbuffer_secs; - 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; - pdata->sound_framesize=sizeof(jack_default_audio_sample_t)* - pdata->jdata->nports; - -#else - fprintf(stderr,"Should not be here!\n"); - exit(-1); -#endif - } - } - - if(pdata->args.encOnTheFly) - InitEncoder(pdata,enc_data,0); - else - InitCacheData(pdata,enc_data,cache_data); - - for(i=0;i<(pdata->enc_data->yuv.y_width*pdata->enc_data->yuv.y_height);i++) - pdata->enc_data->yuv.y[i]=0; - for(i=0; - i<(pdata->enc_data->yuv.uv_width*pdata->enc_data->yuv.uv_height); - i++){ - pdata->enc_data->yuv.v[i]=pdata->enc_data->yuv.u[i]=127; - } - - yblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* - (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); - ublocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* - (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); - vblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* - (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); - - pdata->frametime=(1000000)/pdata->args.fps; - return 0; - -} - -void SetupDefaultArgs(ProgArgs *args) { - - args->delay = 0; - args->windowid = 0; - args->x = 0; - args->y = 0; - args->width = 0; - args->height = 0; - args->nosound = 0; - args->full_shots = 0; - args->follow_mouse = 0; - args->encOnTheFly = 0; - args->nowmcheck = 0; - args->overwrite = 0; - args->use_jack = 0; - args->noshared = 0; - args->no_encode = 0; - args->noframe = 0; - args->jack_nports = 0; - args->jack_ringbuffer_secs = 3.0; - args->jack_port_names = NULL; - args->zerocompression = 1; - args->no_quick_subsample = 1; - args->cursor_color = 1; - args->have_dummy_cursor = 0; - args->xfixes_cursor = 1; - args->fps = 15; - args->channels = 1; - args->frequency = 22050; - args->buffsize = 4096; - args->v_bitrate = 45000; - args->v_quality = 63; - args->s_quality = 10; - - if (getenv("DISPLAY") != NULL) { - args->display = (char *) malloc(strlen(getenv("DISPLAY")) + 1); - strcpy(args->display, getenv("DISPLAY")); - } - else { - args->display = NULL; - } - - args->device = (char *) malloc(strlen(DEFAULT_AUDIO_DEVICE) + 1); - strcpy(args->device, DEFAULT_AUDIO_DEVICE); - - args->workdir = (char *) malloc(5); - strcpy(args->workdir, "/tmp"); - - args->pause_shortcut = (char *) malloc(15); - strcpy(args->pause_shortcut, "Control+Mod1+p"); - - args->stop_shortcut = (char *) malloc(15); - strcpy(args->stop_shortcut, "Control+Mod1+s"); - - args->filename = (char *) malloc(8); - strcpy(args->filename, "out.ogv"); -} - -void CleanUp(void){ - - free(yblocks); - free(ublocks); - free(vblocks); - -} diff --git a/recordmydesktop/src/initialize_data.h b/recordmydesktop/src/initialize_data.h deleted file mode 100644 index 3ffc244..0000000 --- a/recordmydesktop/src/initialize_data.h +++ /dev/null @@ -1,62 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef INITIALIZE_DATA_H -#define INITIALIZE_DATA_H 1 - -#include "rmdtypes.h" - - -/** -* initialize lists,mutexes,image buffers, take first screenshot, -* and anything else needed before launching the capture threads. -* -* \param pdata ProgData struct containing all program data -* -* \param enc_data reference to enc_data structure -* -* \param cache_data reference to cache_data structure -* -* \returns 0 on success, other values must cause the program to exit -*/ -int InitializeData(ProgData *pdata, - EncData *enc_data, - CacheData *cache_data); - -/** -* Sets up the ProgArgs structure to default values. -*/ -void SetupDefaultArgs(ProgArgs *args); - -/** -* Currently only frees some memory -* (y,u,v blocks) -* -*/ -void CleanUp(void); - - -#endif diff --git a/recordmydesktop/src/load_cache.c b/recordmydesktop/src/load_cache.c deleted file mode 100644 index 4a86ada..0000000 --- a/recordmydesktop/src/load_cache.c +++ /dev/null @@ -1,336 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include - -#include "rmdtypes.h" - -#include "encode_image_buffer.h" -#include "encode_sound_buffer.h" -#include "load_cache.h" -#include "rmd_cache.h" -#include "rmdmacro.h" - - -//The number of bytes for every -//sub-block of the y,u and v planes. -//Since the blocks are square -//these are obviously the squares -//of the widths(specified above), -//but the definitions bellow are only -//for convenience anyway. -#define Y_UNIT_BYTES 0x0100 -#define UV_UNIT_BYTES 0x0040 - - -//The frame after retrieval. -//Based on the Header information -//we can read the correct amount of bytes. -typedef struct _CachedFrame{ - FrameHeader *header; - u_int32_t *YBlocks, //identifying number on the grid, - *UBlocks, //starting at top left - *VBlocks; // >> >> - unsigned char *YData, //pointer to data for the blocks that have changed, - *UData, //which have to be remapped - *VData; //on the buffer when reading -}CachedFrame; - - -static void LoadBlock(unsigned char *dest, - unsigned char *source, - int blockno, - int width, - int height, - int blockwidth) { - int j, - block_i=blockno/(width/blockwidth),//place on the grid - block_k=blockno%(width/blockwidth); - for(j=0;jheader->Ynum>0){ - if(ReadZF(frame->YBlocks, - index_entry_size, - frame->header->Ynum, - ucfp, - ifp)!=index_entry_size*frame->header->Ynum){ - return -1; - } - } - if(frame->header->Unum>0){ - if(ReadZF(frame->UBlocks, - index_entry_size, - frame->header->Unum, - ucfp, - ifp)!=index_entry_size*frame->header->Unum){ - return -1; - } - } - if(frame->header->Vnum>0){ - if(ReadZF(frame->VBlocks, - index_entry_size, - frame->header->Vnum, - ucfp, - ifp)!=index_entry_size*frame->header->Vnum){ - return -1; - } - } - if(frame->header->Ynum>0){ - if(ReadZF(frame->YData, - Y_UNIT_BYTES, - frame->header->Ynum, - ucfp, - ifp)!=Y_UNIT_BYTES*frame->header->Ynum){ - return -2; - } - } - if(frame->header->Unum>0){ - if(ReadZF(frame->UData, - UV_UNIT_BYTES, - frame->header->Unum, - ucfp, - ifp)!=UV_UNIT_BYTES*frame->header->Unum){ - return -2; - } - } - if(frame->header->Vnum>0){ - if(ReadZF(frame->VData, - UV_UNIT_BYTES, - frame->header->Vnum, - ucfp, - ifp)!=UV_UNIT_BYTES*frame->header->Vnum){ - return -2; - } - } - return 0; -} - -void *LoadCache(ProgData *pdata){ - - yuv_buffer *yuv=&pdata->enc_data->yuv; - gzFile *ifp=NULL; - FILE *ucfp=NULL; - FILE *afp=pdata->cache_data->afp; - FrameHeader fheader; - CachedFrame frame; - int j=0, - nth_cache=1, - audio_end=0, - extra_frames=0,//total number of duplicated frames - missing_frames=0,//if this is found >0 current run will not load - //a frame but it will proccess the previous - thread_exit=0,//0 success, -1 couldn't find files,1 couldn't remove - blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, - blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, - blockszy=Y_UNIT_BYTES,//size of y plane block in bytes - blockszuv=UV_UNIT_BYTES;//size of u,v plane blocks in bytes - signed char *sound_data=(signed char *)malloc(pdata->periodsize* - pdata->sound_framesize); - - u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES], - UBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES], - VBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES]; - - // We allocate the frame that we will use - frame.header = &fheader; - frame.YBlocks = YBlocks; - frame.UBlocks = UBlocks; - frame.VBlocks = VBlocks; - frame.YData = malloc(yuv->y_width * yuv->y_height); - frame.UData = malloc(yuv->uv_width * yuv->uv_height); - frame.VData = malloc(yuv->uv_width * yuv->uv_height); - - //and the we open our files - if(!pdata->args.zerocompression){ - ifp=gzopen(pdata->cache_data->imgdata,"rb"); - if(ifp==NULL){ - thread_exit=-1; - pthread_exit(&thread_exit); - } - } - else{ - ucfp=fopen(pdata->cache_data->imgdata,"rb"); - if(ucfp==NULL){ - thread_exit=-1; - pthread_exit(&thread_exit); - } - } - - - if(!pdata->args.nosound){ - afp=fopen(pdata->cache_data->audiodata,"rb"); - if(afp==NULL){ - thread_exit=-1; - pthread_exit(&thread_exit); - } - } - - //this will be used now to define if we proccess audio or video - //on any given loop. - pdata->avd=0; - //If sound finishes first,we go on with the video. - //If video ends we will do one more run to flush audio in the ogg file - while(pdata->running){ - //video load and encoding - if(pdata->avd<=0 || pdata->args.nosound || audio_end){ - if(missing_frames>0){ - extra_frames++; - missing_frames--; - SyncEncodeImageBuffer(pdata); - } - else if(((!pdata->args.zerocompression)&& - (gzread(ifp,frame.header,sizeof(FrameHeader))== - sizeof(FrameHeader) ))|| - ((pdata->args.zerocompression)&& - (fread(frame.header,sizeof(FrameHeader),1,ucfp)==1))){ - //sync - missing_frames+=frame.header->current_total- - (extra_frames+frame.header->frameno); - if (pdata->frames_total) { - fprintf(stdout, - "\r[%d%%] ", - ((frame.header->frameno + extra_frames) * 100) / pdata->frames_total); - } - else - fprintf(stdout,"\r[%d frames rendered] ", - (frame.header->frameno+extra_frames)); - fflush(stdout); - if( (frame.header->Ynum<=blocknum_x*blocknum_y) && - (frame.header->Unum<=blocknum_x*blocknum_y) && - (frame.header->Vnum<=blocknum_x*blocknum_y) && - (!ReadFrame(&frame, - ((pdata->args.zerocompression)?ucfp:NULL), - ((pdata->args.zerocompression)?NULL:ifp))) - ){ - //load the blocks for each buffer - if(frame.header->Ynum) - for(j=0;jYnum;j++) - LoadBlock( yuv->y, - &frame.YData[j*blockszy], - frame.YBlocks[j], - yuv->y_width, - yuv->y_height, - Y_UNIT_WIDTH); - if(frame.header->Unum) - for(j=0;jUnum;j++) - LoadBlock( yuv->u, - &frame.UData[j*blockszuv], - frame.UBlocks[j], - yuv->uv_width, - yuv->uv_height, - UV_UNIT_WIDTH); - if(frame.header->Vnum) - for(j=0;jVnum;j++) - LoadBlock( yuv->v, - &frame.VData[j*blockszuv], - frame.VBlocks[j], - yuv->uv_width, - yuv->uv_height, - UV_UNIT_WIDTH); - //encode. This is not made in a thread since - //now blocking is not a problem - //and this way sync problems - //can be avoided more easily. - SyncEncodeImageBuffer(pdata); - } - else{ - raise(SIGINT); - continue; - } - } - else{ - if(SwapCacheFilesRead(pdata->cache_data->imgdata, - nth_cache, - &ifp, - &ucfp)){ - raise(SIGINT); - } - else{ - fprintf(stderr,"\t[Cache File %d]",nth_cache); - nth_cache++; - } - continue; - } - } - //audio load and encoding - else{ - if(!audio_end){ - int nbytes=fread(sound_data,1,pdata->periodsize* - pdata->sound_framesize,afp); - if(nbytes<=0) - audio_end=1; - else - SyncEncodeSoundBuffer(pdata,sound_data); - } - } - } - - pdata->v_encoding_clean=pdata->th_encoding_clean=1; - pthread_mutex_lock(&pdata->theora_lib_mutex); - pthread_cond_signal(&pdata->theora_lib_clean); - pthread_mutex_unlock(&pdata->theora_lib_mutex); - pthread_mutex_lock(&pdata->vorbis_lib_mutex); - pthread_cond_signal(&pdata->vorbis_lib_clean); - pthread_mutex_unlock(&pdata->vorbis_lib_mutex); - fprintf(stdout,"\n"); - - // Clear frame - free(frame.YData); - free(frame.UData); - free(frame.VData); - - free(sound_data); - - if(!pdata->args.nosound){ - fclose(afp); - } - - pthread_exit(&thread_exit); - - -} - diff --git a/recordmydesktop/src/load_cache.h b/recordmydesktop/src/load_cache.h deleted file mode 100644 index fca0cbb..0000000 --- a/recordmydesktop/src/load_cache.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef LOAD_CACHE -#define LOAD_CACHE 1 - -#include "rmdtypes.h" - - -/** -* Cache loading and processing thread -* -* \param pdata ProgData struct containing all program data -* -*/ -void *LoadCache(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/make_dummy_pointer.c b/recordmydesktop/src/make_dummy_pointer.c deleted file mode 100644 index 77363e5..0000000 --- a/recordmydesktop/src/make_dummy_pointer.c +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include "rmdtypes.h" - -#include "make_dummy_pointer.h" -#include "rmdmacro.h" - - -unsigned char *MakeDummyPointer(DisplaySpecs *specs, - int size, - int color, - int type, - unsigned char *npxl){ - int i,k,o='.'; - unsigned long b=(color)?'w':'b', - w=(color)?'b':'w'; - char pmask[1][16][16]={{ - {w,w,o,o,o,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,w,o,o,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,w,o,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,w,o,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,w,o,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,b,w,o,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,b,b,w,o,o,o,o,o,o,o}, - {w,b,b,b,b,b,b,b,b,w,o,o,o,o,o,o}, - {w,b,b,b,b,b,w,w,w,w,o,o,o,o,o,o}, - {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, - {w,b,b,w,w,b,b,w,o,o,o,o,o,o,o,o}, - {w,b,w,o,w,b,b,w,o,o,o,o,o,o,o,o}, - {w,w,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, - {o,o,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, - {o,o,o,o,o,o,w,w,o,o,o,o,o,o,o,o}} - }; - unsigned char *ret=malloc(size*sizeof(char[size*4])); - unsigned char wp[4]={ - ((specs->wpixel^0xff000000)>>24), - ((specs->wpixel^0x00ff0000)>>16), - ((specs->wpixel^0x0000ff00)>>8), - ((specs->wpixel^0x000000ff)) - }; - unsigned char bp[4]={ - ((specs->bpixel^0xff000000)>>24), - ((specs->bpixel^0x00ff0000)>>16), - ((specs->bpixel^0x0000ff00)>>8), - ((specs->bpixel^0x000000ff)) - }; - *npxl=((wp[0]-1)!=bp[0])?wp[0]-100:wp[0]-102; - for(i=0;i -#include -#include -#include - -#ifdef HAVE_LIBASOUND - #include -#else - #include - #include -#endif - -#include "opendev.h" - -#ifdef HAVE_LIBASOUND - -snd_pcm_t *OpenDev( const char *pcm_dev, - unsigned int *channels, - unsigned int *frequency, - snd_pcm_uframes_t *buffsize, - snd_pcm_uframes_t *periodsize, - unsigned int *periodtime, - int *hard_pause){ - - snd_pcm_t *mhandle; - snd_pcm_hw_params_t *hwparams; - unsigned int periods=2; - unsigned int exactrate = *frequency; - - // The compiler might warn us because the expansion starts with - // assert(&hwparams) - snd_pcm_hw_params_alloca(&hwparams); - - if (snd_pcm_open(&mhandle,pcm_dev,SND_PCM_STREAM_CAPTURE,SND_PCM_ASYNC)<0){ - fprintf(stderr, "Couldn't open PCM device %s\n", pcm_dev); - return NULL; - } - else - fprintf(stderr, "Opened PCM device %s\n", pcm_dev); - if (snd_pcm_hw_params_any(mhandle, hwparams)<0){ - fprintf(stderr, "Couldn't configure PCM device.\n"); - return NULL; - } - if (snd_pcm_hw_params_set_access(mhandle, - hwparams, - SND_PCM_ACCESS_RW_INTERLEAVED)<0){ - fprintf(stderr, "Couldn't set access.\n"); - return NULL; - } - if (snd_pcm_hw_params_set_format(mhandle, - hwparams, - SND_PCM_FORMAT_S16_LE)<0){ - fprintf(stderr, "Couldn't set format.\n"); - return NULL; - } - if (snd_pcm_hw_params_set_rate_near(mhandle, hwparams, &exactrate, 0)<0){ - fprintf(stderr, "Couldn't set frequency.\n"); - return NULL; - } - if (*frequency != exactrate){ - fprintf(stderr, "Playback frequency %dHz is not available...\n" - "Using %dHz instead.\n",*frequency,exactrate); - *frequency=exactrate; - } - if (snd_pcm_hw_params_set_channels_near(mhandle, hwparams, channels)<0){ - fprintf(stderr, "Couldn't set channels number.\n"); - return NULL; - } - if(*channels>2){ - fprintf(stderr,"Channels number should be 1(mono) or 2(stereo).\n"); - return NULL; - } - if (snd_pcm_hw_params_set_periods_near(mhandle,hwparams,&periods,0)<0){ - fprintf(stderr, "Couldn't set periods.\n"); - return NULL; - } - - if (snd_pcm_hw_params_set_buffer_size_near(mhandle,hwparams,buffsize)<0){ - fprintf(stderr, "Couldn't set buffer size.\n"); - return NULL; - } - if (snd_pcm_hw_params(mhandle,hwparams)<0){ - fprintf(stderr, "Couldn't set hardware parameters.\n"); - return NULL; - } - if(hard_pause!=NULL) - if(!snd_pcm_hw_params_can_pause(hwparams)){ - *hard_pause=1; - } - if(periodsize!=NULL) - snd_pcm_hw_params_get_period_size(hwparams,periodsize,0); - - if(periodtime!=NULL) - 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); - snd_pcm_prepare(mhandle); - - return mhandle; -} - -#else - -int OpenDev( const char *pcm_dev, - unsigned int channels, - unsigned int frequency){ - int fd ; - fd=open(pcm_dev,O_RDONLY); - - if(fd!=-1){ - unsigned int value; - - if(ioctl(fd,SNDCTL_DSP_GETFMTS,&value)<0){ - fprintf(stderr,"Couldn't get audio format list\n"); - return -1; - } - if(value & AFMT_S16_LE){ - value=AFMT_S16_LE; - } - else if(value & AFMT_S16_BE){ - value=AFMT_S16_BE; - } - else{ - fprintf(stderr,"Soundcard doesn't support signed 16-bit-data\n"); - return -1; - } - if(ioctl(fd,SNDCTL_DSP_SETFMT,&value)<0){ - fprintf(stderr,"Couldn't set audio format\n" ); - return -1; - } - value = channels; - if(ioctl(fd,SNDCTL_DSP_CHANNELS,&value)<0){ - fprintf(stderr,"Cannot set the number of channels\n" ); - return -1; - } - value = frequency; - if(ioctl(fd,SNDCTL_DSP_SPEED,&value)<0){ - fprintf(stderr,"Couldn't set audio frequency\n" ); - return -1; - } - if(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NONBLOCK)<0){ - fprintf(stderr,"Couldn't set audio blocking mode\n" ); - return -1; - } - } - return fd; -} -#endif diff --git a/recordmydesktop/src/opendev.h b/recordmydesktop/src/opendev.h deleted file mode 100644 index c6ac144..0000000 --- a/recordmydesktop/src/opendev.h +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef OPENDEV_H -#define OPENDEV_H 1 - -#include "rmdtypes.h" - - -#ifdef HAVE_LIBASOUND -/** -* Try to open (alsa) sound device, with the desired parameters, -* and place the obtained ones on their place -* -* \param pcm_dev name of the device -* -* \param channels desired number of channels -* (gets modified with the acieved value) -* -* \param frequency desired frequency(gets modified with the acieved value) -* -* \param buffsize Size of buffer -* -* \param periodsize Size of a period(can be NULL) -* -* \param periodtime Duration of a period(can be NULL) -* -* \param hardpause Set to 1 when the device has to be stopped during pause -* and to 0 when it supports pausing -* (can be NULL) -* -* \returns snd_pcm_t handle on success, NULL on failure -*/ -snd_pcm_t *OpenDev( const char *pcm_dev, - unsigned int *channels, - unsigned int *frequency, - snd_pcm_uframes_t *buffsize, - snd_pcm_uframes_t *periodsize, - unsigned int *periodtime, - int *hardpause); -#else -/** -* Try to open (OSS) sound device, with the desired parameters. -* -* -* \param pcm_dev name of the device -* -* \param channels desired number of channels -* -* \param frequency desired frequency -* -* -* \returns file descriptor of open device,-1 on failure -*/ -int OpenDev( const char *pcm_dev, - unsigned int channels, - unsigned int frequency); -#endif - - -#endif diff --git a/recordmydesktop/src/parseargs.c b/recordmydesktop/src/parseargs.c deleted file mode 100644 index 863f34f..0000000 --- a/recordmydesktop/src/parseargs.c +++ /dev/null @@ -1,586 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include "rmdtypes.h" - -#include "rmd_rescue.h" -#include "rmdmacro.h" - - -static 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"); -} - -boolean ParseArgs(int argc, char **argv, ProgArgs *arg_return) { - int i; - char *usage="\nUsage:\n" - "\trecordmydesktop [OPTIONS]^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" - "\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" - "\t-display DISPLAY\tDisplay to connect to.\n" - "\t-x X\t\t\tOffset in x direction.\n" - "\t-y Y\t\t\tOffset in y direction.\n" - "\t-width N\t\tWidth of recorded window.\n" - "\t-height N\t\tHeight of recorded window.\n\n" - - "\t-dummy-cursor color\tColor of the dummy cursor [black|white]\n" - "\t--no-cursor\t\tDisable drawing of the cursor.\n" - "\t--no-shared\t\tDisable usage of" - " MIT-shared memory extension(Not Recommended!).\n" - - "\t--full-shots\t\tTake full screenshot at every frame(Not recomended!).\n" - "\t--quick-subsampling\tDo subsampling" - " of the chroma planes by discarding,not averaging.\n" - - "\t-fps N(number>0.0)\tA positive number denoting desired framerate.\n\n" - - "Sound Options:\n" - "\t-channels N\t\t\tA positive number denoting" - " desired sound channels in recording.\n" - - "\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,when using ALSA or OSS)\n" - "\t-ring-buffer-size N\t\tA float number denoting the desired" - " ring buffer size (in seconds,when using JACK only).\n" - - "\t-device SOUND_DEVICE\t\tSound device(default " - DEFAULT_AUDIO_DEVICE - ").\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" - "\t-v_quality n\t\tA number from 0 to 63 for" - " desired encoded video quality(default 63).\n" - - "\t-v_bitrate n\t\tA number from 45000 to 2000000" - " for desired encoded video bitrate(default 45000).\n" - - "\t-s_quality n\t\tDesired audio quality(-1 to 10).\n\n" - - "Misc Options:\n" - "\t-rescue path_to_data\tEncode data from a previous, crashed, session.\n" - "\t--no-wm-check\t\tDo not try to detect" - " the window manager(and set options according to it)\n" - - "\t-pause-shortcut MOD+KEY\tShortcut that will be used for (un)pausing" - "(default Control+Mod1+p).\n" - "\t-stop-shortcut MOD+KEY\tShortcut that will be used to stop the " - "recording (default Control+Mod1+s).\n" - - "\t--compress-cache\tImage data are cached with light compression.\n" - "\t-workdir DIR\t\tLocation where a temporary directory" - " will be created to hold project files(default $HOME).\n" - - "\t-delay n[H|h|M|m]\tNumber of secs(default),minutes or hours" - " before capture starts(number can be float)\n" - - "\t--overwrite\t\tIf there is already a file with the same name," - " delete it\n" - - "\t\t\t\t(default is to add a number postfix to the new one).\n" - "\t-o filename\t\tName of recorded video(default out.ogv).\n" - "\n\tIf no other options are specified, filename can be given " - "without the -o switch.\n\n\n"; - - if(argc==2){ - if(argv[1][0]!='-'){ - free(arg_return->filename); - arg_return->filename=malloc(strlen(argv[1])+1); - strcpy(arg_return->filename,argv[1]); - return TRUE; - } - } - for(i=1;i0.0){ - int k; - for(k=0;kdelay=(int)num; - } - else{ - fprintf(stderr,"Argument Usage: -delay n[H|h|M|m]\n" - "where n is a float number\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -delay n[H|h|M|m]\n" - "where n is a float number\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-windowid")){ - if(i+10) - arg_return->windowid=num; - else{ - fprintf(stderr,"Argument Usage:" - " -windowid id_of_window(number)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage:" - " -windowid id_of_window(number)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-display")){ - if(i+1display!=NULL) - free(arg_return->display); - arg_return->display=malloc(strlen(argv[i+1])+1); - strcpy(arg_return->display,argv[i+1]); - } - else{ - fprintf(stderr,"Argument Usage: -display DISPLAY\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-x")){ - if(i+10) - arg_return->x=num; - else{ - fprintf(stderr,"Argument Usage: -x X(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -x X(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-y")){ - if(i+10) - arg_return->y=num; - else{ - fprintf(stderr,"Argument Usage: -y Y(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -y Y(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-width")){ - if(i+10) - arg_return->width=num; - else{ - fprintf(stderr,"Argument Usage: -width N(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -width N(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-height")){ - if(i+10) - arg_return->height=num; - else{ - fprintf(stderr,"Argument Usage: -height N(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -height N(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-o")){ - if(i+1filename); - arg_return->filename=malloc(strlen(argv[i+1])+1); - strcpy(arg_return->filename,argv[i+1]); - } - else{ - fprintf(stderr,"Argument Usage: -o filename\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-fps")){ - if(i+10.0) - arg_return->fps=num; - else{ - fprintf(stderr,"Argument Usage: -fps N(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -fps N(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-v_quality")){ - if(i+1=0)&&(num<64)) - arg_return->v_quality=num; - else{ - fprintf(stderr,"Argument Usage:" - " -v_quality n(number 0-63)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage:" - " -v_quality n(number 0-63)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-v_bitrate")){ - if(i+1=45000)&&(num<=2000000)) - arg_return->v_bitrate=num; - else{ - fprintf(stderr,"Argument Usage:" - " -v_bitrate n(number 45000-2000000)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage:" - " -v_bitrate n(number 45000-2000000)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-dummy-cursor")){ - if(i+1cursor_color=0; - else if(!strcmp(argv[i+1],"black")) - arg_return->cursor_color=1; - else{ - fprintf(stderr,"Argument Usage:" - " -dummy-cursor [black|white]\n"); - return FALSE; - } - arg_return->have_dummy_cursor=1; - arg_return->xfixes_cursor=0; - } - else{ - fprintf(stderr,"Argument Usage:" - " -dummy-cursor [black|white]\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"--no-cursor")) - arg_return->xfixes_cursor=0; - else if(!strcmp(argv[i],"-freq")){ - if(i+10) - arg_return->frequency=num; - else{ - fprintf(stderr,"Argument Usage: -freq N(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -freq N(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-channels")){ - if(i+10) - arg_return->channels=num; - else{ - fprintf(stderr,"Argument Usage: -channels N(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -channels N(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-s_quality")){ - if(i+1=-1)&&(num<=10)) - arg_return->s_quality=num; - else{ - fprintf(stderr,"Argument Usage:" - " -s_quality n(number -1 to 10)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage:" - " -s_quality n(number -1 to 10)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-device")){ - if(i+1device); - arg_return->device=malloc(strlen(argv[i+1])+1); - strcpy(arg_return->device,argv[i+1]); - } - else{ - fprintf(stderr,"Argument Usage: -device SOUND_DEVICE\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-workdir")){ - if(i+1workdir); - arg_return->workdir=malloc(strlen(argv[i+1])+1); - strcpy(arg_return->workdir,argv[i+1]); - } - else{ - fprintf(stderr,"Argument Usage: -workdir DIR\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-pause-shortcut")){ - if(i+1pause_shortcut); - arg_return->pause_shortcut=malloc(strlen(argv[i+1])+1); - strcpy(arg_return->pause_shortcut,argv[i+1]); - } - else{ - fprintf(stderr,"Argument Usage: -pause-shortcut MOD+KEY\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-stop-shortcut")){ - if(i+1stop_shortcut); - arg_return->stop_shortcut=malloc(strlen(argv[i+1])+1); - strcpy(arg_return->stop_shortcut,argv[i+1]); - } - else{ - fprintf(stderr,"Argument Usage: -stop-shortcut MOD+KEY\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-buffer-size")){ - if(i+10) - arg_return->buffsize=num; - else{ - fprintf(stderr,"Argument Usage:" - " -buffer-size N(number>0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: -buffer-size N(number>0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-use-jack")){ - if(i+1jack_nports=0; - while((kjack_nports++; - k++; - } - if(arg_return->jack_nports>0){ - arg_return->jack_port_names=malloc(sizeof(char*)* - arg_return->jack_nports); - for(k=i+1;kjack_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 FALSE; - } -#else - fprintf(stderr,"recordMyDesktop is not compiled" - " with Jack support!\n"); - return FALSE; -#endif - } - else{ - fprintf(stderr,"Argument Usage: -use-jack port1" - " port2... portn\n"); - return FALSE; - } - } - else if(!strcmp(argv[i],"-ring-buffer-size")){ - if(i+10.0) - arg_return->jack_ringbuffer_secs=num; - else{ - fprintf(stderr,"Argument Usage: --ring-buffer-size" - " N(floating point number>0.0)\n"); - return FALSE; - } - } - else{ - fprintf(stderr,"Argument Usage: --ring-buffer-size" - " N(floating point number>0.0)\n"); - return FALSE; - } - i++; - } - else if(!strcmp(argv[i],"-rescue")){ - if(i+1nosound=1; - else if(!strcmp(argv[i],"--no-shared")){ - arg_return->noshared=1; - } - else if(!strcmp(argv[i],"--full-shots")){ - arg_return->full_shots=1; - } - else if(!strcmp(argv[i],"--no-frame")){ - arg_return->noframe=1; - } - else if(!strcmp(argv[i],"--follow-mouse")){ - arg_return->full_shots=1; - arg_return->follow_mouse=1; - } - else if(!strcmp(argv[i],"--no-encode")) - arg_return->no_encode=1; - else if(!strcmp(argv[i],"--quick-subsampling")){ - arg_return->no_quick_subsample=0; - } - else if(!strcmp(argv[i],"--on-the-fly-encoding")){ - arg_return->encOnTheFly=1; - } - else if(!strcmp(argv[i],"--overwrite")) - arg_return->overwrite=1; - else if(!strcmp(argv[i],"--no-wm-check")) - arg_return->nowmcheck=1; - else if(!strcmp(argv[i],"--compress-cache")){ - arg_return->zerocompression=0; - } - else if(!strcmp(argv[i],"--help")||!strcmp(argv[i],"-h")){ - fprintf(stderr,"%s",usage); - exit(0); - } - else if(!strcmp(argv[i],"--version")){ - fprintf(stderr,"recordMyDesktop v%s\n\n",VERSION); - exit(0); - } - else if(!strcmp(argv[i],"--print-config")){ - PrintConfig(); - exit(0); - } - else{ - fprintf(stderr,"\n\tError parsing arguments.\n\t" - "Type --help or -h for usage.\n\n"); - return FALSE; - } - } - - return TRUE; -} diff --git a/recordmydesktop/src/parseargs.h b/recordmydesktop/src/parseargs.h deleted file mode 100644 index cec12d9..0000000 --- a/recordmydesktop/src/parseargs.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef PARSEARGS_H -#define PARSEARGS_H 1 - -#include "rmdtypes.h" - - -/** -* Fill ProgArgs struct with arguments entered at execution -* -* \param argc argc as entered from main -* -* \param argv argv as entered from main -* -* \param arg_return ProgArgs struct to be filled with the options -* -* \returns 0 on Success 1 on Failure -*/ -boolean ParseArgs(int argc, char **argv, ProgArgs *arg_return); - - -#endif diff --git a/recordmydesktop/src/poll_events.c b/recordmydesktop/src/poll_events.c deleted file mode 100644 index 35e1320..0000000 --- a/recordmydesktop/src/poll_events.c +++ /dev/null @@ -1,208 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "poll_events.h" -#include "rectinsert.h" -#include "rmd_frame.h" -#include "rmdmacro.h" -#include "rmdtypes.h" - - -#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)&&\ - ((e)->area.height<(brwin)->rgeom.height)){\ - (wgeom)->x=(brwin)->rgeom.x;\ - (wgeom)->y=(brwin)->rgeom.y;\ - (wgeom)->width=(brwin)->rgeom.width;\ - (wgeom)->height=(brwin)->rgeom.height;\ - }\ - else{\ - (wgeom)->x=((((e)->area.x+(e)->area.width>=(brwin)->rgeom.x)&&\ - ((e)->area.x<=(brwin)->rgeom.x+(brwin)->rgeom.width))?\ - (((e)->area.x<=(brwin)->rgeom.x)?(brwin)->rgeom.x:(e)->area.x):-1);\ - \ - (wgeom)->y=((((e)->area.y+(e)->area.height>=(brwin)->rgeom.y)&&\ - ((e)->area.y<=(brwin)->rgeom.y+(brwin)->rgeom.height))?\ - (((e)->area.y<=(brwin)->rgeom.y)?(brwin)->rgeom.y:(e)->area.y):-1);\ - \ - (wgeom)->width=((e)->area.x<=(brwin)->rgeom.x)?\ - (e)->area.width-((brwin)->rgeom.x-(e)->area.x):\ - ((e)->area.x<=(brwin)->rgeom.x+(brwin)->rgeom.width)?\ - (((brwin)->rgeom.width-(e)->area.x+(brwin)->rgeom.x<(e)->area.width)?\ - (brwin)->rgeom.width-(e)->area.x+(brwin)->rgeom.x:e->area.width):-1;\ - \ - (wgeom)->height=((e)->area.y<=(brwin)->rgeom.y)?\ - (e)->area.height-((brwin)->rgeom.y-(e)->area.y):\ - ((e)->area.y<=(brwin)->rgeom.y+(brwin)->rgeom.height)?\ - (((brwin)->rgeom.height-(e)->area.y+\ - (brwin)->rgeom.y<(e)->area.height)?\ - (brwin)->rgeom.height-(e)->area.y+\ - (brwin)->rgeom.y:(e)->area.height):-1;\ - \ - if((wgeom)->width>(brwin)->rgeom.width)\ - (wgeom)->width=(brwin)->rgeom.width;\ - if((wgeom)->height>(brwin)->rgeom.height)\ - (wgeom)->height=(brwin)->rgeom.height;\ - }\ -} - - -void InitEventsPolling(ProgData *pdata){ - Window root_return, - parent_return, - *children; - unsigned int i, - nchildren; - - - XSelectInput (pdata->dpy,pdata->specs.root, SubstructureNotifyMask); - - - if(!pdata->args.full_shots){ - XQueryTree (pdata->dpy, - pdata->specs.root, - &root_return, - &parent_return, - &children, - &nchildren); - - for (i = 0; i < nchildren; i++){ - XWindowAttributes attribs; - if (XGetWindowAttributes (pdata->dpy,children[i],&attribs)){ - if(!attribs.override_redirect && - attribs.depth==pdata->specs.depth) - XDamageCreate(pdata->dpy, - children[i], - XDamageReportRawRectangles); - } - } - XFree(children); - XDamageCreate(pdata->dpy, - pdata->specs.root, - XDamageReportRawRectangles); - } - - - -} - - -void EventLoop(ProgData *pdata){ - int inserts=0; - - XEvent event; - - while(XPending(pdata->dpy)){ - XNextEvent(pdata->dpy,&event); - if(event.type == KeyPress){ - XKeyEvent *e=(XKeyEvent *)(&event); - if(e->keycode == pdata->pause_key.key){ - int i=0; - int found=0; - for(i=0;ipause_key.modnum;i++){ - if(pdata->pause_key.mask[i]==e->state){ - found=1; - break; - } - } - if(found){ - raise(SIGUSR1); - continue; - } - } - if(e->keycode == pdata->stop_key.key){ - int i=0; - int found=0; - for(i=0;istop_key.modnum;i++){ - if(pdata->stop_key.mask[i]==e->state){ - found=1; - break; - } - } - if(found){ - raise(SIGINT); - continue; - } - } - } - else if(event.type == Expose){ - - if(event.xexpose.count!=0) - continue; - else if(!pdata->args.noframe){ - rmdDrawFrame(pdata->dpy, - pdata->specs.screen, - pdata->shaped_w, - pdata->brwin.rgeom.width, - pdata->brwin.rgeom.height); - - } - - } - else if(!pdata->args.full_shots){ - if(event.type == MapNotify ){ - XWindowAttributes attribs; - if (!((XMapEvent *)(&event))->override_redirect&& - XGetWindowAttributes(pdata->dpy, - event.xcreatewindow.window, - &attribs)){ - if(!attribs.override_redirect&& - attribs.depth==pdata->specs.depth) - XDamageCreate(pdata->dpy, - event.xcreatewindow.window, - XDamageReportRawRectangles); - } - } - else if(event.type == pdata->damage_event + XDamageNotify ){ - XDamageNotifyEvent *e =(XDamageNotifyEvent *)( &event ); - WGeometry wgeom; - CLIP_EVENT_AREA(e,&(pdata->brwin),&wgeom); - if((wgeom.x>=0)&&(wgeom.y>=0)&& - (wgeom.width>0)&&(wgeom.height>0)){ - - inserts+=RectInsert(&pdata->rect_root,&wgeom); - - } - } - } - - } - - -} - - diff --git a/recordmydesktop/src/poll_events.h b/recordmydesktop/src/poll_events.h deleted file mode 100644 index 6195237..0000000 --- a/recordmydesktop/src/poll_events.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef POLL_EVENTS_H -#define POLL_EVENTS_H 1 - -#include "rmdtypes.h" - - -/** -* Start listening to damage and substructure notify events -* (needed before EventLoop call) -* \param pdata ProgData struct containing all program data -*/ -void InitEventsPolling(ProgData *pdata); - -/** -* Loop calling XNextEvent.Retrieve and place on -* list damage events that arive, create damage for new windows -* and pickup key events for shortcuts. -* \param pdata ProgData struct containing all program data -*/ -void EventLoop(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/queryextensions.c b/recordmydesktop/src/queryextensions.c deleted file mode 100644 index 3164932..0000000 --- a/recordmydesktop/src/queryextensions.c +++ /dev/null @@ -1,83 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include -#include - -#include "rmdtypes.h" - -#include "queryextensions.h" - - -void QueryExtensions(Display *dpy, - ProgArgs *args, - int *damage_event, - int *damage_error, - int *shm_opcode){ - int xf_event_basep, - xf_error_basep, - shm_event_base, - shm_error_base, - shape_event_base, - shape_error_base; - - if((!(args->full_shots))&&(!XDamageQueryExtension( dpy, damage_event, damage_error))){ - fprintf(stderr,"XDamage extension not found!!!\n" - "Try again using the --full-shots option, though\n" - "enabling XDamage is highly recommended,\n" - "for performance reasons.\n"); - exit(4); - } - if((!args->noshared)&&(!XQueryExtension(dpy, - "MIT-SHM", - shm_opcode, - &shm_event_base, - &shm_error_base))){ - args->noshared=1; - fprintf(stderr,"Shared Memory extension not present!\n" - "Try again using the --no-shared option\n"); - exit(5); - } - if((args->xfixes_cursor)&& - (XFixesQueryExtension(dpy,&xf_event_basep,&xf_error_basep)==False)){ - args->xfixes_cursor=0; - fprintf(stderr,"Xfixes extension not present!\n" - "Please run with the -dummy-cursor or" - " --no-cursor option.\n"); - exit(6); - } - if((!args->noframe)&& - (!XShapeQueryExtension(dpy,&shape_event_base,&shape_error_base))){ - fprintf(stderr,"XShape Not Found!!!\n" - "Frame won't be available.\n"); - - args->noframe=1; - } - -} diff --git a/recordmydesktop/src/queryextensions.h b/recordmydesktop/src/queryextensions.h deleted file mode 100644 index bde9abd..0000000 --- a/recordmydesktop/src/queryextensions.h +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef QUERYEXTENSIONS_H -#define QUERYEXTENSIONS_H 1 - -#include "rmdtypes.h" - - -/** -* Check if needed extensions are present -* -* \param dpy Connection to the server -* -* \param args ProgArgs struct containing the user-set options -* -* \param damage_event gets filled with damage event number -* -* \param damage_error gets filled with damage error number -* -* \note Can be an exit point if extensions are not found -*/ -void QueryExtensions(Display *dpy, - ProgArgs *args, - int *damage_event, - int *damage_error, - int *shm_opcode); - - -#endif diff --git a/recordmydesktop/src/recordmydesktop.c b/recordmydesktop/src/recordmydesktop.c index eeb04a5..5eb4bf2 100644 --- a/recordmydesktop/src/recordmydesktop.c +++ b/recordmydesktop/src/recordmydesktop.c @@ -26,18 +26,18 @@ #include "config.h" -#include "rmdtypes.h" +#include "rmd_types.h" -#include "encode_cache.h" -#include "initialize_data.h" -#include "parseargs.h" -#include "queryextensions.h" +#include "rmd_encode_cache.h" +#include "rmd_initialize_data.h" +#include "rmd_parseargs.h" +#include "rmd_queryextensions.h" #include "rmd_cache.h" #include "rmd_error.h" -#include "rmdthreads.h" -#include "setbrwindow.h" -#include "shortcuts.h" -#include "wm_check.h" +#include "rmd_threads.h" +#include "rmd_setbrwindow.h" +#include "rmd_shortcuts.h" +#include "rmd_wm_check.h" int main(int argc,char **argv){ diff --git a/recordmydesktop/src/rectinsert.c b/recordmydesktop/src/rectinsert.c deleted file mode 100644 index 258ff6e..0000000 --- a/recordmydesktop/src/rectinsert.c +++ /dev/null @@ -1,535 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include "rmdtypes.h" -#include "rectinsert.h" - - -/** -* Collide two rectangles and dictate most sane action for insertion, -* as well as provide the updated rectangle(s) -* \param wgeom1 resident rectangle -* -* \param wgeom2 New rectangle -* -* \param wgeom_return Pointer to rectangles to be inserted -* -* \param ngeoms number of entries in wgeom_return -* -* \retval 0 No collision -* -* \retval 1 wgeom1 is covered by wgeom2 -* -* \retval 2 wgeom2 is covered by wgeom1 -* -* \retval -1 wgeom1 was broken (new is picked up in wgeom_return) -* -* \retval -2 wgeom2 was broken (new is picked up in wgeom_return) -* -* \retval -10 Grouping the two geoms is possible -* -*/ -static int CollideRects(WGeometry *wgeom1, - WGeometry *wgeom2, - WGeometry **wgeom_return, - int *ngeoms) { - //1 fits in 2 - if((wgeom1->x>=wgeom2->x)&& - (wgeom1->x+wgeom1->width<=wgeom2->x+wgeom2->width)&& - (wgeom1->y>=wgeom2->y)&& - (wgeom1->y+wgeom1->height<=wgeom2->y+wgeom2->height)){ - *ngeoms=0; - return 1; - } - //2 fits in 1 - else if((wgeom2->x>=wgeom1->x)&& - (wgeom2->x+wgeom2->width<=wgeom1->x+wgeom1->width)&& - (wgeom2->y>=wgeom1->y)&& - (wgeom2->y+wgeom2->height<=wgeom1->y+wgeom1->height)){ - *ngeoms=0; - return 2; - } - //no collision - else if((wgeom1->x+wgeom1->widthx)|| - (wgeom2->x+wgeom2->widthx)|| - (wgeom1->y+wgeom1->heighty)|| - (wgeom2->y+wgeom2->heighty)){ - *ngeoms=0; - return 0; - } - else{ -//overlapping points are considered enclosed -//this happens because libxdamage may generate many events for one change -//and some of them may be in the the exact same region -//so identical rects would be considered not colliding -//in order though to avoid endless recursion on the RectInsert -//function should always start at the next element(which is logical since -//if any rect makes it to a points none of it's part collides with previous -//nodes on the list, too) - int x1[2]={wgeom1->x,wgeom1->x+wgeom1->width}; - int y1[2]={wgeom1->y,wgeom1->y+wgeom1->height}; - int x2[2]={wgeom2->x,wgeom2->x+wgeom2->width}; - int y2[2]={wgeom2->y,wgeom2->y+wgeom2->height}; - int enclosed[2][4],tot1,tot2; - enclosed[0][0]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& - (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); - enclosed[0][1]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& - (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); - enclosed[0][2]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& - (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); - enclosed[0][3]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& - (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); - enclosed[1][0]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& - (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); - enclosed[1][1]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& - (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); - enclosed[1][2]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& - (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); - enclosed[1][3]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& - (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); - tot1=enclosed[0][0]+enclosed[0][1]+enclosed[0][2]+enclosed[0][3]; - tot2=enclosed[1][0]+enclosed[1][1]+enclosed[1][2]+enclosed[1][3]; - if((tot1==2)&&(tot2==2)){//same width or height, which is the best case - //group - if((enclosed[1][0]&&enclosed[1][1])&& - (wgeom1->width==wgeom2->width)){ - wgeom_return[0]=(WGeometry *)malloc(sizeof(WGeometry)); - *ngeoms=1; - wgeom_return[0]->x=wgeom1->x; - wgeom_return[0]->y=wgeom1->y; - wgeom_return[0]->width=wgeom1->width; - wgeom_return[0]->height=wgeom2->height+wgeom2->y-wgeom1->y; - return -10; - } - else if((enclosed[1][0]&&enclosed[1][2])&& - (wgeom1->height==wgeom2->height)){ - *ngeoms=1; - wgeom_return[0]->x=wgeom1->x; - wgeom_return[0]->y=wgeom1->y; - wgeom_return[0]->width=wgeom2->width+wgeom2->x-wgeom1->x; - wgeom_return[0]->height=wgeom1->height; - return -10; - } - else if((enclosed[1][3]&&enclosed[1][1])&& - (wgeom1->height==wgeom2->height)){ - *ngeoms=1; - wgeom_return[0]->x=wgeom2->x; - wgeom_return[0]->y=wgeom2->y; - wgeom_return[0]->width=wgeom1->width+wgeom1->x-wgeom2->x; - wgeom_return[0]->height=wgeom2->height; - return -10; - } - else if((enclosed[1][3]&&enclosed[1][2])&& - (wgeom1->width==wgeom2->width)){ - *ngeoms=1; - wgeom_return[0]->x=wgeom2->x; - wgeom_return[0]->y=wgeom2->y; - wgeom_return[0]->width=wgeom2->width; - wgeom_return[0]->height=wgeom1->height+wgeom1->y-wgeom2->y; - return -10; - } - //if control reaches here therewasn't a group and we go on - } - if(tot2==2){ - //break geom2 - wgeom_return[0]->x=wgeom2->x; - wgeom_return[0]->y=wgeom2->y; - wgeom_return[0]->width=wgeom2->width; - wgeom_return[0]->height=wgeom2->height; - *ngeoms=1; - if(enclosed[1][0]&&enclosed[1][1]){ - wgeom_return[0]->y=y1[1]; - wgeom_return[0]->height-=y1[1]-y2[0]; - } - else if(enclosed[1][0]&&enclosed[1][2]){ - wgeom_return[0]->x=x1[1]; - wgeom_return[0]->width-=x1[1]-x2[0]; - } - else if(enclosed[1][3]&&enclosed[1][1]) - wgeom_return[0]->width-=x2[1]-x1[0]; - else if(enclosed[1][3]&&enclosed[1][2]) - wgeom_return[0]->height-=y2[1]-y1[0]; - return -2; - } - else if(tot1==2){ - //if the first one breaks(which is already inserted) - //then we reenter the part that was left and the one - //that was to be inserted - wgeom_return[1]->x=wgeom2->x; - wgeom_return[1]->y=wgeom2->y; - wgeom_return[1]->width=wgeom2->width; - wgeom_return[1]->height=wgeom2->height; - wgeom_return[0]->x=wgeom1->x; - wgeom_return[0]->y=wgeom1->y; - wgeom_return[0]->width=wgeom1->width; - wgeom_return[0]->height=wgeom1->height; - *ngeoms=1; - if(enclosed[0][0]&&enclosed[0][1]){ - wgeom_return[0]->y=y2[1]; - wgeom_return[0]->height-=y2[1]-y1[0]; - } - else if(enclosed[0][0]&&enclosed[0][2]){ - wgeom_return[0]->x=x2[1]; - wgeom_return[0]->width-=x2[1]-x1[0]; - } - else if(enclosed[0][3]&&enclosed[0][1]) - wgeom_return[0]->width-=x1[1]-x2[0]; - else if(enclosed[0][3]&&enclosed[0][2]) - wgeom_return[0]->height-=y1[1]-y2[0]; - return -1; - - } - else if(tot2==1){ //in which case there is also tot1==1 - //but we rather not break that - //break geom2 in two - *ngeoms=2; - if(enclosed[1][0]){ -//first - wgeom_return[0]->x=x1[1]; - wgeom_return[0]->y=y2[0]; - wgeom_return[0]->width=wgeom2->width-x1[1]+x2[0]; - wgeom_return[0]->height=wgeom2->height; -//second - wgeom_return[1]->x=x2[0]; - wgeom_return[1]->y=y1[1]; - wgeom_return[1]->width=x1[1]-x2[0]; - wgeom_return[1]->height=wgeom2->height-y1[1]+y2[0]; - } - else if(enclosed[1][1]){ -//first - wgeom_return[0]->x=x2[0]; - wgeom_return[0]->y=y2[0]; - wgeom_return[0]->width=wgeom2->width-x2[1]+x1[0]; - wgeom_return[0]->height=wgeom2->height; -//second - wgeom_return[1]->x=x1[0]; - wgeom_return[1]->y=y1[1]; - wgeom_return[1]->width=x2[1]-x1[0]; - wgeom_return[1]->height=wgeom2->height-y1[1]+y2[0]; - } - else if(enclosed[1][2]){ -//first(same as [1][0]) - wgeom_return[0]->x=x1[1]; - wgeom_return[0]->y=y2[0]; - wgeom_return[0]->width=wgeom2->width-x1[1]+x2[0]; - wgeom_return[0]->height=wgeom2->height; -//second - wgeom_return[1]->x=x2[0]; - wgeom_return[1]->y=y2[0]; - wgeom_return[1]->width=x1[1]-x2[0]; - wgeom_return[1]->height=wgeom2->height-y2[1]+y1[0]; - } - else if(enclosed[1][3]){ -//first(same as [1][1]) - wgeom_return[0]->x=x2[0]; - wgeom_return[0]->y=y2[0]; - wgeom_return[0]->width=wgeom2->width-x2[1]+x1[0]; - wgeom_return[0]->height=wgeom2->height; -//second - wgeom_return[1]->x=x1[0]; - wgeom_return[1]->y=y2[0]; - wgeom_return[1]->width=x2[1]-x1[0]; - wgeom_return[1]->height=wgeom2->height-y2[1]+y1[0]; - } - return -2; - } - else{//polygons collide but no point of one is in the other - //so we just keep the two parts of geom2 that are outside geom1 - - //break geom2 in two - //two cases: - //geom2 crossing vertically geom1 - //and geom2 crossing horizontally geom1 - //The proper one can be found by simply checking x,y positions - *ngeoms=2; - if(wgeom2->yy){ - //common - wgeom_return[0]->x=wgeom_return[1]->x=x2[0]; - wgeom_return[0]->width=wgeom_return[1]->width=wgeom2->width; - - wgeom_return[0]->y=y2[0]; - wgeom_return[0]->height=wgeom2->height-y2[1]+y1[0]; - wgeom_return[1]->y=y1[1]; - wgeom_return[1]->height=y2[1]-y1[1]; - } - else{ - //common - wgeom_return[0]->y=wgeom_return[1]->y=y2[0]; - wgeom_return[0]->height=wgeom_return[1]->height=wgeom2->height; - - wgeom_return[0]->x=x2[0]; - wgeom_return[0]->width=wgeom2->width-x2[1]+x1[0]; - wgeom_return[1]->x=x1[1]; - wgeom_return[1]->width=x2[1]-x1[1]; - } - return -2; - } - } -} - -int RectInsert(RectArea **root,WGeometry *wgeom){ - - int total_insertions=0; - RectArea *temp=NULL,*newnode=(RectArea *)malloc(sizeof(RectArea)); - //align - //we do need to know boundaries - wgeom->width+=(wgeom->width%2)|(wgeom->x%2); - wgeom->height+=(wgeom->height%2)|(wgeom->y%2); - wgeom->width+=(wgeom->width%2); - wgeom->height+=(wgeom->height%2); - wgeom->x-=wgeom->x%2; - wgeom->y-=wgeom->y%2; -// fprintf(stderr," %d %d %d %d\n",wgeom->x, - - newnode->geom.x=wgeom->x; - newnode->geom.y=wgeom->y; - newnode->geom.width=wgeom->width; - newnode->geom.height=wgeom->height; - newnode->prev=newnode->next=NULL; - if(*root==NULL){ - *root=newnode; - total_insertions=1; - } - else{ - WGeometry *wgeom_return[2]; - wgeom_return[0]=(WGeometry *)malloc(sizeof(WGeometry)); - wgeom_return[1]=(WGeometry *)malloc(sizeof(WGeometry)); - - int ngeoms=0,insert_ok=1,i=0; - temp=*root; - while(insert_ok){ //if something is broken list does not procceed - //(except on -1 collres case) - int collres=CollideRects(&(temp->geom),wgeom,wgeom_return,&ngeoms); - if((!collres)) - insert_ok=1; - else{ - for(i=0;iwidth+=(wgeom_return[i]->width%2)| - (wgeom_return[i]->x%2); - wgeom_return[i]->height+=(wgeom_return[i]->height%2)| - (wgeom_return[i]->y%2); - wgeom_return[i]->width+=(wgeom_return[i]->width%2); - wgeom_return[i]->height+=(wgeom_return[i]->height%2); - wgeom_return[i]->x-=wgeom_return[i]->x%2; - wgeom_return[i]->y-=wgeom_return[i]->y%2; - } - insert_ok=0; - switch(collres){ - case 1://remove current node,reinsert new one - total_insertions--; - if(temp->prev!=NULL){//no root - if(temp->next!=NULL){// - RectArea *temp1=temp->next; - temp->prev->next=temp->next; - temp->next->prev=temp->prev; - free(temp); - if((wgeom->width>0)&&(wgeom->height>0)) - total_insertions+=RectInsert(&temp1,wgeom); - } - else{ - temp->prev->next=newnode; - newnode->prev=temp->prev; - total_insertions++; - free(temp); - } - } - else{//root - if((*root)->next!=NULL){ - (*root)=(*root)->next; - (*root)->prev=NULL; - if((wgeom->width>0)&&(wgeom->height>0)) - total_insertions+=RectInsert(root,wgeom); - } - else if((wgeom->width>0)&&(wgeom->height>0)){ - *root=newnode; - total_insertions++; - } - else{ - *root=NULL; - total_insertions++; - } - free(temp); - } - break; - case 2://done,area is already covered - free(newnode); - break; - case -1://current node is broken and reinserted - //(in same pos) - //newnode is also reinserted - if((wgeom_return[0]->width>0)&& - (wgeom_return[0]->height>0)){ - temp->geom.x=wgeom_return[0]->x; - temp->geom.y=wgeom_return[0]->y; - temp->geom.width=wgeom_return[0]->width; - temp->geom.height=wgeom_return[0]->height; - if(temp->next==NULL){ - temp->next=newnode; - newnode->prev=temp; - total_insertions++; - } - else{ - insert_ok=1; - } - } - else{//it might happen that the old and now broken node - //is of zero width or height - //(so it isn't reinserted) - if((temp->prev==NULL)&&(temp->next!=NULL)){ - *root=(*root)->next; - (*root)->prev=NULL; - } - else if((temp->next==NULL)&&(temp->prev!=NULL)){ - temp->prev->next=newnode; - newnode->prev=temp->prev; - } - else if((temp->next==NULL)&&(temp->prev==NULL)) - (*root)=newnode; - else{ - total_insertions--; - temp->next->prev=temp->prev; - temp->prev->next=temp->next; - total_insertions+=RectInsert(&temp->next, - wgeom); - } - free(temp); - } - break; - case -2://new is broken and reinserted - if(temp->next==NULL){ - total_insertions+=ngeoms; - newnode->geom.x=wgeom_return[0]->x; - newnode->geom.y=wgeom_return[0]->y; - newnode->geom.width=wgeom_return[0]->width; - newnode->geom.height=wgeom_return[0]->height; - temp->next=newnode; - newnode->prev=temp; - if(ngeoms>1){ - RectArea *newnode1= - (RectArea *)malloc(sizeof(RectArea)); - - newnode1->geom.x=wgeom_return[1]->x; - newnode1->geom.y=wgeom_return[1]->y; - newnode1->geom.width=wgeom_return[1]->width; - newnode1->geom.height=wgeom_return[1]->height; - newnode->next=newnode1; - newnode1->prev=newnode; - newnode1->next=NULL; - } - } - else{ - for(i=0;iwidth>0)&& - (wgeom_return[i]->height>0)) - total_insertions+= - RectInsert(&temp->next,wgeom_return[i]); - } - } - break; - case -10://grouped - if(temp->prev==NULL){ - if(temp->next==NULL){//empty list - newnode->geom.x=wgeom_return[0]->x; - newnode->geom.y=wgeom_return[0]->y; - newnode->geom.width=wgeom_return[0]->width; - newnode->geom.height= - wgeom_return[0]->height; - - *root=newnode; - free(temp); - } - else{ - total_insertions--; - *root=temp->next; - (*root)->prev=NULL; - free(temp); - if((wgeom_return[0]->width>0)&& - (wgeom_return[0]->height>0)) - total_insertions+= - RectInsert(root,wgeom_return[0]); - } - } - else if(temp->next==NULL){//last, enter anyway - newnode->geom.x=wgeom_return[0]->x; - newnode->geom.y=wgeom_return[0]->y; - newnode->geom.width=wgeom_return[0]->width; - newnode->geom.height=wgeom_return[0]->height; - temp->prev->next=newnode; - newnode->prev=temp->prev; - free(temp); - } - else{//remove node and reinsert, starting where we were - total_insertions--; - RectArea *temp1=temp->next; - temp->prev->next=temp->next; - temp->next->prev=temp->prev; - free(temp); - if((wgeom_return[0]->width>0)&& - (wgeom_return[0]->height>0)) - total_insertions+= - RectInsert(&temp1,wgeom_return[0]); - } - break; - } - } - if(insert_ok){ - if(temp->next==NULL){ - temp->next=newnode; - newnode->prev=temp; - total_insertions++; - break; - } - else{ - temp=temp->next; - } - } - else{ - break; - } - }; - - free(wgeom_return[0]); - free(wgeom_return[1]); - } - return total_insertions; -} - -void ClearList(RectArea **root){ - - RectArea *temp; - temp=*root; - if(temp!=NULL){ - while(temp->next!=NULL){ - temp=temp->next; - free(temp->prev); - - } - free(temp); - *root=NULL; - } -} diff --git a/recordmydesktop/src/rectinsert.h b/recordmydesktop/src/rectinsert.h deleted file mode 100644 index 414f01f..0000000 --- a/recordmydesktop/src/rectinsert.h +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef RECTINSERT_H -#define RECTINSERT_H 1 - - -#include "rmdtypes.h" - - -/** -* Insert a new rectangle on the list, making sure it doesn't overlap -* with the existing ones -* \param root Root entry of the list -* -* \param wgeom New area to be inserted -* -* \returns Number of insertions during operation -* -* \note This function is reentrant and recursive. The number -* of insertions takes this into account. -*/ -int RectInsert(RectArea **root, WGeometry *wgeom); - -/** -* Clean up a list of areas marked for update. -* \param root Root entry of the list -*/ -void ClearList(RectArea **root); - - -#endif diff --git a/recordmydesktop/src/register_callbacks.c b/recordmydesktop/src/register_callbacks.c deleted file mode 100644 index de6d93e..0000000 --- a/recordmydesktop/src/register_callbacks.c +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "register_callbacks.h" - - -// There seem to be no way of passing user data to the signal handler, -// so hack around not being able to pass ProgData to them -static int *pdata_running = NULL; -static int *pdata_paused = NULL; -static int *pdata_aborted = NULL; -static int *pdata_pause_state_changed = NULL; - - -static void SetPaused(int signum) { - - *pdata_pause_state_changed = TRUE; -} - -static void SetRunning(int signum) { - - if (!*pdata_paused) { - - *pdata_running = FALSE; - - if (signum == SIGABRT) { - *pdata_aborted = TRUE; - } - } -} - -void RegisterCallbacks(ProgData *pdata) { - - struct sigaction pause_act; - struct sigaction end_act; - - // Is there some way to pass pdata to the signal handlers? - pdata_running = &pdata->running; - pdata_paused = &pdata->paused; - pdata_aborted = &pdata->aborted; - pdata_pause_state_changed = &pdata->pause_state_changed; - - // Setup pause_act - sigfillset(&pause_act.sa_mask); - pause_act.sa_flags = SA_RESTART; - pause_act.sa_handler = SetPaused; - - sigaction(SIGUSR1, &pause_act, NULL); - - // Setup end_act - sigfillset(&end_act.sa_mask); - end_act.sa_flags = SA_RESTART; - end_act.sa_handler = SetRunning; - - sigaction(SIGINT, &end_act, NULL); - sigaction(SIGTERM, &end_act, NULL); - sigaction(SIGABRT, &end_act, NULL); -} diff --git a/recordmydesktop/src/register_callbacks.h b/recordmydesktop/src/register_callbacks.h deleted file mode 100644 index 1fb3b76..0000000 --- a/recordmydesktop/src/register_callbacks.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef REGISTER_CALLBACKS_H -#define REGISTER_CALLBACKS_H 1 - - -#include "rmdtypes.h" - - -/** -* Set up all callbacks and signal handlers -* \param pdata ProgData struct containing all program data -*/ -void RegisterCallbacks(ProgData *prog_data); - - -#endif diff --git a/recordmydesktop/src/rmd_block_utils.c b/recordmydesktop/src/rmd_block_utils.c new file mode 100644 index 0000000..20b5aac --- /dev/null +++ b/recordmydesktop/src/rmd_block_utils.c @@ -0,0 +1,37 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include "rmd_block_utils.h" + + +// FIXME: These globals are modified in other source files! We keep +// thsee here for now. These are the cache blocks. They need to be +// accesible in the dbuf macros +u_int32_t *yblocks, + *ublocks, + *vblocks; diff --git a/recordmydesktop/src/rmd_block_utils.h b/recordmydesktop/src/rmd_block_utils.h new file mode 100644 index 0000000..02aa77f --- /dev/null +++ b/recordmydesktop/src/rmd_block_utils.h @@ -0,0 +1,170 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef BLOCK_UTILS_H +#define BLOCK_UTILS_H 1 + +#include "rmd_macro.h" +#include "rmd_types.h" +#include "rmd_yuv_utils.h" + + +// We keep these global for now. FIXME: Isolate them. +extern u_int32_t *yblocks, + *ublocks, + *vblocks; + +#define POINT_IN_BLOCK(xv,yv,widthv,blocksize) ((yv/blocksize)*\ + (widthv/blocksize)+\ + (xv/blocksize)) + +#define UPDATE_Y_PLANE_DBUF(data,\ + data_back,\ + x_tm,\ + y_tm,\ + height_tm,\ + width_tm,\ + yuv,\ + __bit_depth__){ \ + int k,i;\ + register u_int##__bit_depth__##_t t_val;\ + register unsigned char *yuv_y=yuv->y+x_tm+y_tm*yuv->y_width,\ + *_yr=Yr,*_yg=Yg,*_yb=Yb;\ + register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\ + *datapi_back=(u_int##__bit_depth__##_t *)data_back;\ + for(k=0;ky_width-width_tm;\ + }\ +} + +#define UPDATE_UV_PLANES_DBUF( data,\ + data_back,\ + x_tm,\ + y_tm,\ + height_tm,\ + width_tm,\ + yuv,\ + __sampling_type,\ + __bit_depth__){ \ + int k,i;\ + register u_int##__bit_depth__##_t t_val;\ + register unsigned char *yuv_u=yuv->u+x_tm/2+(y_tm*yuv->uv_width)/2,\ + *yuv_v=yuv->v+x_tm/2+(y_tm*yuv->uv_width)/2,\ + *_ur=Ur,*_ug=Ug,*_ubvr=UbVr,\ + *_vg=Vg,*_vb=Vb;\ + register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\ + *datapi_next=NULL,\ + *datapi_back=(u_int##__bit_depth__##_t *)data_back,\ + *datapi_back_next=NULL;\ + if(__sampling_type==__PXL_AVERAGE){\ + datapi_next=datapi+width_tm;\ + datapi_back_next=datapi_back+width_tm;\ + for(k=0;ky_width-width_tm)/2;\ + yuv_v+=(yuv->y_width-width_tm)/2;\ + datapi+=width_tm;\ + datapi_back+=width_tm;\ + if(__sampling_type==__PXL_AVERAGE){\ + datapi_next+=width_tm;\ + datapi_back_next+=width_tm;\ + }\ + }\ + }\ + else{\ + for(k=0;ky_width-width_tm)/2;\ + yuv_v+=(yuv->y_width-width_tm)/2;\ + datapi+=width_tm;\ + datapi_back+=width_tm;\ + if(__sampling_type==__PXL_AVERAGE){\ + datapi_next+=width_tm;\ + datapi_back_next+=width_tm;\ + }\ + }\ + }\ +} + + +#endif diff --git a/recordmydesktop/src/rmd_cache.c b/recordmydesktop/src/rmd_cache.c index 6fa23eb..18e7bf3 100644 --- a/recordmydesktop/src/rmd_cache.c +++ b/recordmydesktop/src/rmd_cache.c @@ -28,11 +28,11 @@ #include -#include "rmdtypes.h" +#include "rmd_types.h" #include "rmd_cache.h" -#include "specsfile.h" -#include "rmdmacro.h" +#include "rmd_macro.h" +#include "rmd_specsfile.h" /** diff --git a/recordmydesktop/src/rmd_cache.h b/recordmydesktop/src/rmd_cache.h index 4ddb5e9..01efa21 100644 --- a/recordmydesktop/src/rmd_cache.h +++ b/recordmydesktop/src/rmd_cache.h @@ -27,7 +27,7 @@ #ifndef RMD_CACHE_H #define RMD_CACHE_H 1 -#include "rmdtypes.h" +#include "rmd_types.h" /** diff --git a/recordmydesktop/src/rmd_cache_audio.c b/recordmydesktop/src/rmd_cache_audio.c new file mode 100644 index 0000000..dc2edf3 --- /dev/null +++ b/recordmydesktop/src/rmd_cache_audio.c @@ -0,0 +1,108 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_cache_audio.h" +#include "rmd_jack.h" + + +void *CacheSoundBuffer(ProgData *pdata){ +//We are simply going to throw sound on the disk. +//It's sound is tiny compared to that of image, so +//compressing would reducethe overall size by only an +//insignificant fraction. +#ifdef HAVE_JACK_H + void *jackbuf=NULL; + if(pdata->args.use_jack){ + jackbuf=malloc(pdata->sound_framesize*pdata->jdata->buffersize); + } +#endif + while((pdata->running)){ + SndBuffer *buff=NULL; + + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + 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*pdata->sound_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)>= + (pdata->sound_framesize*pdata->jdata->buffersize)){ + (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer, + jackbuf, + (pdata->sound_framesize* + pdata->jdata->buffersize)); + fwrite(jackbuf,1,(pdata->sound_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 + } + pdata->avd-=pdata->periodtime; + } + + fclose(pdata->cache_data->afp); + pthread_exit(&errno); +} + + diff --git a/recordmydesktop/src/rmd_cache_audio.h b/recordmydesktop/src/rmd_cache_audio.h new file mode 100644 index 0000000..2820c42 --- /dev/null +++ b/recordmydesktop/src/rmd_cache_audio.h @@ -0,0 +1,42 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef CACHE_AUDIO_H +#define CACHE_AUDIO_H 1 + +#include "rmd_types.h" + + +/** +* Sound caching thread. Simply writes the pcm buffers on disk +* +* \param pdata ProgData struct containing all program data +* +*/ +void *CacheSoundBuffer(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_cache_frame.c b/recordmydesktop/src/rmd_cache_frame.c new file mode 100644 index 0000000..1c98ec9 --- /dev/null +++ b/recordmydesktop/src/rmd_cache_frame.c @@ -0,0 +1,295 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include + +#include "rmd_types.h" + +#include "rmd_block_utils.h" +#include "rmd_cache.h" +#include "rmd_cache_frame.h" + + +//minimize hard disk access +#define CACHE_OUT_BUFFER_SIZE 4096 +//500 mb file size +#define CACHE_FILE_SIZE_LIMIT (500*1<<20) + + +static int FlushBlock(unsigned char *buf, + int blockno, + int width, + int height, + int blockwidth, + gzFile *fp, + FILE *ucfp, + int flush) { + int j,i, + bytes_written=0, + block_i=(!blockwidth)?0:(blockno/(width/blockwidth)),//place on the grid + block_k=(!blockwidth)?0:(blockno%(width/blockwidth)); + register unsigned char *buf_reg=(&buf[(block_i* + width+ + block_k)*blockwidth]); + static unsigned char out_buffer[CACHE_OUT_BUFFER_SIZE]; + static unsigned int out_buffer_bytes=0; + + if(out_buffer_bytes+pow(blockwidth,2)>=CACHE_OUT_BUFFER_SIZE || + (flush && out_buffer_bytes)){ + if(ucfp==NULL) + gzwrite(fp,(void *)out_buffer,out_buffer_bytes); + else + fwrite((void *)out_buffer,1,out_buffer_bytes,ucfp); + bytes_written=out_buffer_bytes; + out_buffer_bytes=0; + } + if(!flush){ + register unsigned char *out_buf_reg=&out_buffer[out_buffer_bytes]; + for(j=0;jenc_data->yuv.y_width/Y_UNIT_WIDTH, + blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, + firstrun=1, + frameno=0, + nbytes=0, + nth_cache=1; + unsigned int total_bytes=0, + total_received_bytes=0; + u_int32_t ynum,unum,vnum, + y_short_blocks[blocknum_x*blocknum_y], + u_short_blocks[blocknum_x*blocknum_y], + v_short_blocks[blocknum_x*blocknum_y]; + + if(!pdata->args.zerocompression){ + fp=pdata->cache_data->ifp; + if(fp==NULL)exit(13); + } + else{ + ucfp=pdata->cache_data->uncifp; + if(ucfp==NULL)exit(13); + } + + + while(pdata->running){ + int j; + FrameHeader fheader; + ynum=unum=vnum=0; + + pdata->th_enc_thread_waiting=1; + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_wait(&pdata->image_buffer_ready, + &pdata->img_buff_ready_mutex); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + pdata->th_enc_thread_waiting=0; + + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + + pthread_mutex_lock(&pdata->yuv_mutex); + + //find and flush different blocks + if(firstrun){ + firstrun=0; + for(j=0;jargs.zerocompression){ + if(ynum*4+unum+vnum>(blocknum_x*blocknum_y*6)/10) + gzsetparams (fp,1,Z_FILTERED); + else + gzsetparams (fp,0,Z_FILTERED); + } + + strncpy(fheader.frame_prefix,"FRAM",4); + fheader.frameno=++frameno; + fheader.current_total = pdata->frames_total; + + fheader.Ynum=ynum; + fheader.Unum=unum; + fheader.Vnum=vnum; + if(!pdata->args.zerocompression){ + nbytes+=gzwrite(fp,(void*)&fheader,sizeof(FrameHeader)); + //flush indexes + if(ynum)nbytes+=gzwrite(fp, + (void*)y_short_blocks, + ynum*index_entry_size); + if(unum)nbytes+=gzwrite(fp, + (void*)u_short_blocks, + unum*index_entry_size); + if(vnum)nbytes+=gzwrite(fp, + (void*)v_short_blocks, + vnum*index_entry_size); + } + else{ + nbytes+=sizeof(FrameHeader)* + fwrite((void*)&fheader,sizeof(FrameHeader),1,ucfp); + //flush indexes + if(ynum)nbytes+=index_entry_size* + fwrite(y_short_blocks,index_entry_size,ynum,ucfp); + if(unum)nbytes+=index_entry_size* + fwrite(u_short_blocks,index_entry_size,unum,ucfp); + if(vnum)nbytes+=index_entry_size* + fwrite(v_short_blocks,index_entry_size,vnum,ucfp); + } + //flush the blocks for each buffer + if(ynum){ + for(j=0;jenc_data->yuv.y,y_short_blocks[j], + pdata->enc_data->yuv.y_width, + pdata->enc_data->yuv.y_height, + Y_UNIT_WIDTH, + fp, + ucfp, + 0); + } + if(unum){ + for(j=0;jenc_data->yuv.u,u_short_blocks[j], + pdata->enc_data->yuv.uv_width, + pdata->enc_data->yuv.uv_height, + UV_UNIT_WIDTH, + fp, + ucfp, + 0); + } + if(vnum){ + for(j=0;jenc_data->yuv.v,v_short_blocks[j], + pdata->enc_data->yuv.uv_width, + pdata->enc_data->yuv.uv_height, + UV_UNIT_WIDTH, + fp, + ucfp, + 0); + } + //release main buffer + pthread_mutex_unlock(&pdata->yuv_mutex); + + nbytes+=FlushBlock(NULL,0,0,0,0,fp,ucfp,1); + /**@________________@**/ + pdata->avd+=pdata->frametime; + if(nbytes>CACHE_FILE_SIZE_LIMIT){ + if(SwapCacheFilesWrite(pdata->cache_data->imgdata, + nth_cache,&fp,&ucfp)){ + fprintf(stderr,"New cache file could not be created.\n" + "Ending recording...\n"); + fflush(stderr); + raise(SIGINT); //if for some reason we cannot make a new file + //we have to stop. If we are out of space, + //which means + //that encoding cannot happen either, + //InitEncoder will cause an abrupt end with an + //error code and the cache will remain intact. + //If we've chosen separate two-stages, + //the program will make a + //clean exit. + //In either case data will be preserved so if + //space is freed the recording + //can be proccessed later. + } + total_bytes+=(nbytes>>20); + nth_cache++; + nbytes=0; + } + } + total_bytes+=(nbytes>>20); + total_received_bytes=((frameno*((pdata->specs.depth>=24)?4:2)* + pdata->brwin.rgeom.width*pdata->brwin.rgeom.height)>>20); + if(total_received_bytes){ + fprintf(stderr,"\n*********************************************\n" + "\nCached %u MB, from %u MB that were received.\n" + "Average cache compression ratio: %u %%\n" + "\n*********************************************\n", + total_bytes, + total_received_bytes, + (total_bytes*100)/total_received_bytes); + + } + + fprintf(stderr, + "Saved %d frames in a total of %d requests\n", + frameno, + pdata->frames_total); + fflush(stderr); + + if(!pdata->args.zerocompression){ + gzflush(fp,Z_FINISH); + gzclose(fp); + } + else{ + fflush(ucfp); + fclose(ucfp); + } + pthread_exit(&errno); +} diff --git a/recordmydesktop/src/rmd_cache_frame.h b/recordmydesktop/src/rmd_cache_frame.h new file mode 100644 index 0000000..347c50d --- /dev/null +++ b/recordmydesktop/src/rmd_cache_frame.h @@ -0,0 +1,43 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef CACHE_FRAME_H +#define CACHE_FRAME_H 1 + +#include "rmd_types.h" + + +/** +* Image caching thread. Copies the yuv buffer, compares with the last one and +* caches the result. +* +* \param pdata ProgData struct containing all program data +* +*/ +void *CacheImageBuffer(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_capture_sound.c b/recordmydesktop/src/rmd_capture_sound.c new file mode 100644 index 0000000..b9be47b --- /dev/null +++ b/recordmydesktop/src/rmd_capture_sound.c @@ -0,0 +1,174 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_capture_sound.h" +#include "rmd_jack.h" +#include "rmd_opendev.h" + + +void *CaptureSound(ProgData *pdata){ + +#ifdef HAVE_LIBASOUND + int frames=pdata->periodsize; +#endif + //start capturing only after first frame is taken + usleep(pdata->frametime); + + while(pdata->running){ + int sret=0; + SndBuffer *newbuf,*tmp; + if (pdata->paused) { +#ifdef HAVE_LIBASOUND + if(!pdata->hard_pause){ + snd_pcm_pause(pdata->sound_handle,1); + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + snd_pcm_pause(pdata->sound_handle,0); + } + else{//device doesn't support pause(is this the norm?mine doesn't) + snd_pcm_close(pdata->sound_handle); + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + pdata->sound_handle= + OpenDev(pdata->args.device, + &pdata->args.channels, + &pdata->args.frequency, + &pdata->args.buffsize, + NULL, + NULL, + NULL//let's hope that the device capabilities + //didn't magically change + ); + if(pdata->sound_handle==NULL){ + fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); + pdata->running = FALSE; + errno=3; + pthread_exit(&errno); + } + } +#else + close(pdata->sound_handle); + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + pdata->sound_handle= + OpenDev(pdata->args.device, + pdata->args.channels, + pdata->args.frequency); + if(pdata->sound_handle<0){ + fprintf(stderr,"Couldn't reopen sound device.Exiting\n"); + pdata->running = FALSE; + errno=3; + pthread_exit(&errno); + } +#endif + } + + //create new buffer + newbuf=(SndBuffer *)malloc(sizeof(SndBuffer)); +#ifdef HAVE_LIBASOUND + newbuf->data=(signed char *)malloc(frames*pdata->sound_framesize); +#else + newbuf->data=(signed char *)malloc(((pdata->args.buffsize<<1)* + pdata->args.channels)); +#endif + newbuf->next=NULL; + + //read data into new buffer +#ifdef HAVE_LIBASOUND + while(sretsound_handle, + newbuf->data+pdata->sound_framesize*sret, + frames-sret); + if(temp_sret==-EPIPE){ + fprintf(stderr,"%s: Overrun occurred.\n", + snd_strerror(temp_sret)); + snd_pcm_prepare(pdata->sound_handle); + } + else if (temp_sret<0){ + fprintf(stderr,"An error occured while reading sound data:\n" + " %s\n", + snd_strerror(temp_sret)); + snd_pcm_prepare(pdata->sound_handle); + } + else + sret+=temp_sret; + } +#else + sret=0; + //oss recording loop + do{ + int temp_sret=read(pdata->sound_handle, + &newbuf->data[sret], + ((pdata->args.buffsize<<1)* + pdata->args.channels)-sret); + if(temp_sret<0){ + fprintf(stderr,"An error occured while reading from soundcard" + "%s\n" + "Error description:\n" + "%s\n",pdata->args.device,strerror(errno)); + } + else + sret+=temp_sret; + }while(sret<((pdata->args.buffsize<<1)* + pdata->args.channels)); +#endif + //queue the new buffer + pthread_mutex_lock(&pdata->sound_buffer_mutex); + tmp=pdata->sound_buffer; + if(pdata->sound_buffer==NULL) + pdata->sound_buffer=newbuf; + else{ + while(tmp->next!=NULL) + tmp=tmp->next; + tmp->next=newbuf; + } + pthread_mutex_unlock(&pdata->sound_buffer_mutex); + + + //signal that there are data to be proccessed + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_signal(&pdata->sound_data_read); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + } +#ifdef HAVE_LIBASOUND + snd_pcm_close(pdata->sound_handle); +#else + close(pdata->sound_handle); +#endif + pthread_exit(&errno); +} + + + diff --git a/recordmydesktop/src/rmd_capture_sound.h b/recordmydesktop/src/rmd_capture_sound.h new file mode 100644 index 0000000..b4e6531 --- /dev/null +++ b/recordmydesktop/src/rmd_capture_sound.h @@ -0,0 +1,42 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef CAPTURE_SOUND_H +#define CAPTURE_SOUND_H 1 + +#include "rmd_types.h" + + +/** +* Sound capturing thread. Data are placed on a +* list to be picked up by other threads. +* +* \param pdata ProgData struct containing all program data +*/ +void *CaptureSound(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_encode_cache.c b/recordmydesktop/src/rmd_encode_cache.c new file mode 100644 index 0000000..40b0a8d --- /dev/null +++ b/recordmydesktop/src/rmd_encode_cache.c @@ -0,0 +1,71 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_encode_cache.h" +#include "rmd_flush_to_ogg.h" +#include "rmd_init_encoder.h" +#include "rmd_load_cache.h" + + +void EncodeCache(ProgData *pdata){ + pthread_t flush_to_ogg_t, + load_cache_t; + fprintf(stderr,"STATE:ENCODING\n");fflush(stderr); + fprintf(stderr,"Encoding started!\nThis may take several minutes.\n" + "Pressing Ctrl-C will cancel the procedure" + " (resuming will not be possible, but\n" + "any portion of the video, which is already encoded won't be deleted).\n" + "Please wait...\n"); + pdata->running = TRUE; + InitEncoder(pdata,pdata->enc_data,1); + //load encoding and flushing threads + if(!pdata->args.nosound){ + //before we start loading again + //we need to free any left-overs + while(pdata->sound_buffer!=NULL){ + free(pdata->sound_buffer->data); + pdata->sound_buffer=pdata->sound_buffer->next; + } + } + pthread_create(&flush_to_ogg_t,NULL,(void *)FlushToOgg,(void *)pdata); + + //start loading image and audio + pthread_create(&load_cache_t,NULL,(void *)LoadCache,(void *)pdata); + + //join and finish + pthread_join(load_cache_t,NULL); + fprintf(stderr,"Encoding finished!\nWait a moment please...\n"); + pthread_join(flush_to_ogg_t,NULL); + +} + + diff --git a/recordmydesktop/src/rmd_encode_cache.h b/recordmydesktop/src/rmd_encode_cache.h new file mode 100644 index 0000000..2c021c3 --- /dev/null +++ b/recordmydesktop/src/rmd_encode_cache.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef ENCODE_CACHE_H +#define ENCODE_CACHE_H 1 + +#include "rmd_types.h" + + +/** +* Encode cache into an +* ogg stream. +* \param pdata ProgData struct containing all program data +*/ +void EncodeCache(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_encode_image_buffer.c b/recordmydesktop/src/rmd_encode_image_buffer.c new file mode 100644 index 0000000..4b91239 --- /dev/null +++ b/recordmydesktop/src/rmd_encode_image_buffer.c @@ -0,0 +1,95 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include "rmd_types.h" + +#include "rmd_encode_image_buffer.h" + + +void *EncodeImageBuffer(ProgData *pdata){ + pdata->th_encoding_clean=0; + while(pdata->running){ + pdata->th_enc_thread_waiting=1; + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_wait(&pdata->image_buffer_ready, + &pdata->img_buff_ready_mutex); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + pdata->th_enc_thread_waiting=0; + pdata->encoder_busy = TRUE; + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + pthread_mutex_lock(&pdata->yuv_mutex); + + if(theora_encode_YUVin(&pdata->enc_data->m_th_st, + &pdata->enc_data->yuv)){ + fprintf(stderr,"Encoder not ready!\n"); + pthread_mutex_unlock(&pdata->yuv_mutex); + } + else{ + pthread_mutex_unlock(&pdata->yuv_mutex); + if(theora_encode_packetout(&pdata->enc_data->m_th_st,0, + &pdata->enc_data->m_ogg_pckt1)==1){ + pthread_mutex_lock(&pdata->libogg_mutex); + ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, + &pdata->enc_data->m_ogg_pckt1); + pthread_mutex_unlock(&pdata->libogg_mutex); + pdata->avd+=pdata->frametime; + } + } + pdata->encoder_busy = FALSE; + } + //last packet + pdata->th_encoding_clean=1; + pthread_mutex_lock(&pdata->theora_lib_mutex); + pthread_cond_signal(&pdata->theora_lib_clean); + pthread_mutex_unlock(&pdata->theora_lib_mutex); + pthread_exit(&errno); +} + +//this function is meant to be called normally +//not through a thread of it's own +void SyncEncodeImageBuffer(ProgData *pdata){ + if(theora_encode_YUVin(&pdata->enc_data->m_th_st, + &pdata->enc_data->yuv)){ + fprintf(stderr,"Encoder not ready!\n"); + } + else{ + if(theora_encode_packetout(&pdata->enc_data->m_th_st,!pdata->running, + &pdata->enc_data->m_ogg_pckt1)==1){ + pthread_mutex_lock(&pdata->libogg_mutex); + ogg_stream_packetin(&pdata->enc_data->m_ogg_ts, + &pdata->enc_data->m_ogg_pckt1); + if(!pdata->running)pdata->enc_data->m_ogg_ts.e_o_s=1; + pthread_mutex_unlock(&pdata->libogg_mutex); + pdata->avd+=pdata->frametime; + } + } +} diff --git a/recordmydesktop/src/rmd_encode_image_buffer.h b/recordmydesktop/src/rmd_encode_image_buffer.h new file mode 100644 index 0000000..dcb2435 --- /dev/null +++ b/recordmydesktop/src/rmd_encode_image_buffer.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef ENCODE_IMAGE_BUFFER_H +#define ENCODE_IMAGE_BUFFER_H 1 + +#include "rmd_types.h" + + +/** +* feed a yuv buffer to the theora encoder and submit outcome to +* the ogg stream. +* \param pdata ProgData struct containing all program data +*/ +void *EncodeImageBuffer(ProgData *pdata); + +/** +* As EncodeImageBuffer, only with the assumption that +* this is not a thread on it's own +* +* \param pdata ProgData struct containing all program data +* +*/ +void SyncEncodeImageBuffer(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_encode_sound_buffer.c b/recordmydesktop/src/rmd_encode_sound_buffer.c new file mode 100644 index 0000000..3f67d40 --- /dev/null +++ b/recordmydesktop/src/rmd_encode_sound_buffer.c @@ -0,0 +1,191 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_encode_sound_buffer.h" +#include "rmd_jack.h" + + +void *EncodeSoundBuffer(ProgData *pdata){ + int sampread=pdata->periodsize; +#ifdef HAVE_JACK_H + void *jackbuf=NULL; + if(pdata->args.use_jack){ + jackbuf=malloc(pdata->sound_framesize*pdata->jdata->buffersize); + } +#endif + pdata->v_encoding_clean=0; + while((pdata->running)){ + float **vorbis_buffer; + int count=0,i,j; + SndBuffer *buff=NULL; + + if (pdata->paused) { + pthread_mutex_lock(&pdata->pause_mutex); + pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex); + pthread_mutex_unlock(&pdata->pause_mutex); + } + 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;iargs.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); + } + else{ +#ifdef HAVE_JACK_H + if((*jack_ringbuffer_read_space_p)(pdata->jdata->sound_buffer)>= + (pdata->sound_framesize*pdata->jdata->buffersize)){ + (*jack_ringbuffer_read_p)(pdata->jdata->sound_buffer, + jackbuf, + (pdata->sound_framesize* + pdata->jdata->buffersize)); + vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp, + sampread); + for(j=0;jargs.channels;j++){ + for(i=0;iv_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); + + pthread_mutex_lock(&pdata->libogg_mutex); + while(vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, + &pdata->enc_data->m_vo_block)==1){ + + vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); + vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); + + while(vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, + &pdata->enc_data->m_ogg_pckt2)){ + ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, + &pdata->enc_data->m_ogg_pckt2); + } + } + pthread_mutex_unlock(&pdata->libogg_mutex); + + pdata->avd-=pdata->periodtime; + + + } + + pdata->v_encoding_clean=1; + pthread_mutex_lock(&pdata->vorbis_lib_mutex); + pthread_cond_signal(&pdata->vorbis_lib_clean); + pthread_mutex_unlock(&pdata->vorbis_lib_mutex); + pthread_exit(&errno); +} + +void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff){ + float **vorbis_buffer; + int count=0,i,j; + int sampread=(buff!=NULL)?pdata->periodsize:0; + + vorbis_buffer=vorbis_analysis_buffer(&pdata->enc_data->m_vo_dsp,sampread); + + if(!pdata->args.use_jack){ + for(i=0;iargs.channels;j++){ + vorbis_buffer[j][i]=((buff[count+1]<<8)| + (0x00ff&(int)buff[count]))/ + 32768.f; + count+=2; + } + } + } + else{ + for(j=0;jargs.channels;j++){ + for(i=0;ienc_data->m_vo_dsp,sampread); + + pthread_mutex_lock(&pdata->libogg_mutex); + while(vorbis_analysis_blockout(&pdata->enc_data->m_vo_dsp, + &pdata->enc_data->m_vo_block)==1){ + + vorbis_analysis(&pdata->enc_data->m_vo_block,NULL); + vorbis_bitrate_addblock(&pdata->enc_data->m_vo_block); + + while(vorbis_bitrate_flushpacket(&pdata->enc_data->m_vo_dsp, + &pdata->enc_data->m_ogg_pckt2)){ + ogg_stream_packetin(&pdata->enc_data->m_ogg_vs, + &pdata->enc_data->m_ogg_pckt2); + } + } + pthread_mutex_unlock(&pdata->libogg_mutex); + + if(!pdata->running)pdata->enc_data->m_ogg_vs.e_o_s=1; + + pdata->avd-=pdata->periodtime; +} + diff --git a/recordmydesktop/src/rmd_encode_sound_buffer.h b/recordmydesktop/src/rmd_encode_sound_buffer.h new file mode 100644 index 0000000..b773e12 --- /dev/null +++ b/recordmydesktop/src/rmd_encode_sound_buffer.h @@ -0,0 +1,51 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef ENCODE_SOUND_BUFFER_H +#define ENCODE_SOUND_BUFFER_H 1 + +#include "rmd_types.h" + + +/** +* Sound encoding thread. Picks up data from the buffer queue , +* encodes and places them on the vorbis stream. +* +* \param pdata ProgData struct containing all program data +*/ +void *EncodeSoundBuffer(ProgData *pdata); + +/** +* As EncodeSoundBuffer, only with the assumption that +* this is not a thread on it's own +* +* \param pdata ProgData struct containing all program data +* +*/ +void SyncEncodeSoundBuffer(ProgData *pdata,signed char *buff); + + +#endif diff --git a/recordmydesktop/src/rmd_error.h b/recordmydesktop/src/rmd_error.h index 82529c7..4d27264 100644 --- a/recordmydesktop/src/rmd_error.h +++ b/recordmydesktop/src/rmd_error.h @@ -27,7 +27,7 @@ #ifndef RMD_ERROR_H #define RMD_ERROR_H 1 -#include "rmdtypes.h" +#include "rmd_types.h" /* diff --git a/recordmydesktop/src/rmd_flush_to_ogg.c b/recordmydesktop/src/rmd_flush_to_ogg.c new file mode 100644 index 0000000..1f78115 --- /dev/null +++ b/recordmydesktop/src/rmd_flush_to_ogg.c @@ -0,0 +1,215 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_encode_image_buffer.h" +#include "rmd_encode_sound_buffer.h" +#include "rmd_flush_to_ogg.h" + + +//we copy the page because the next call to ogg_stream_pageout +//will invalidate it. But we must have pages from +//both streams at every time in +//order to do correct multiplexing +static void ogg_page_cp(ogg_page *new, ogg_page *old) { + int i=0; + register unsigned char *newp,*oldp; + + new->header_len=old->header_len; + new->header=malloc(new->header_len); + new->body_len=old->body_len; + new->body=malloc(new->body_len); + + newp=new->header; + oldp=old->header; + for(i=0;iheader_len;i++) + *(newp++)=*(oldp++); + newp=new->body; + oldp=old->body; + for(i=0;ibody_len;i++) + *(newp++)=*(oldp++); + +} +//free our copy +static void ogg_page_cp_free(ogg_page *pg) { + pg->header_len=pg->body_len=0; + free(pg->header); + free(pg->body); +} + +void *FlushToOgg(ProgData *pdata){ + int videoflag=0,audioflag=0; + double video_bytesout=0,audio_bytesout=0; + ogg_page videopage,//owned by libogg + videopage_copy,//owned by the application + audiopage,//owned by libogg + audiopage_copy;//owned by the application + + double audiotime=0; + double videotime=0; + int working=1, + th_st_fin=0, + v_st_fin=(pdata->args.nosound); + while(working){ + int audio_or_video=0; + if(pdata->running){ + pthread_mutex_lock(&pdata->libogg_mutex); + if(!videoflag){ + videoflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_ts, + &videopage); + videotime=(videoflag)? + theora_granule_time(&pdata->enc_data->m_th_st, + ogg_page_granulepos(&videopage)):-1; + if(videoflag)ogg_page_cp(&videopage_copy,&videopage); + } + if(!pdata->args.nosound) + if(!audioflag){ + audioflag=ogg_stream_pageout(&pdata->enc_data->m_ogg_vs, + &audiopage); + audiotime=(audioflag)? + vorbis_granule_time(&pdata->enc_data->m_vo_dsp, + ogg_page_granulepos(&audiopage)):-1; + if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); + } + pthread_mutex_unlock(&pdata->libogg_mutex); + } + else{ + if(!th_st_fin && !videoflag){ + pthread_mutex_lock(&pdata->libogg_mutex); + videoflag=ogg_stream_flush(&pdata->enc_data->m_ogg_ts, + &videopage); + videotime=(videoflag)? + theora_granule_time(&pdata->enc_data->m_th_st, + ogg_page_granulepos(&videopage)):-1; + if(videoflag)ogg_page_cp(&videopage_copy,&videopage); + pthread_mutex_unlock(&pdata->libogg_mutex); + //we need the last page to properly close the stream + if(!videoflag){ + if(!pdata->th_encoding_clean){ + pthread_mutex_lock(&pdata->theora_lib_mutex); + pthread_cond_wait(&pdata->theora_lib_clean, + &pdata->theora_lib_mutex); + pthread_mutex_unlock(&pdata->theora_lib_mutex); + } + SyncEncodeImageBuffer(pdata); + } + } + if(!pdata->args.nosound && !v_st_fin &&!audioflag){ + pthread_mutex_lock(&pdata->libogg_mutex); + audioflag=ogg_stream_flush(&pdata->enc_data->m_ogg_vs, + &audiopage); + audiotime=(audioflag)? + vorbis_granule_time(&pdata->enc_data->m_vo_dsp, + ogg_page_granulepos(&audiopage)):-1; + if(audioflag)ogg_page_cp(&audiopage_copy,&audiopage); + pthread_mutex_unlock(&pdata->libogg_mutex); + //we need the last page to properly close the stream + if(!audioflag){ + if(!pdata->v_encoding_clean){ + pthread_mutex_lock(&pdata->vorbis_lib_mutex); + pthread_cond_wait(&pdata->vorbis_lib_clean, + &pdata->vorbis_lib_mutex); + pthread_mutex_unlock(&pdata->vorbis_lib_mutex); + } + SyncEncodeSoundBuffer(pdata,NULL); + } + } + } + if(th_st_fin)videoflag=0; + if(v_st_fin)audioflag=0; + if((!audioflag && !v_st_fin && !pdata->args.nosound)|| + (!videoflag && !th_st_fin)){ + usleep(10000); + continue; + } + if(!audioflag){ + audio_or_video=1; + } + else if(!videoflag) { + audio_or_video=0; + } + else{ + if(audiotimeenc_data->fp); + video_bytesout+=fwrite(videopage_copy.body,1, + videopage_copy.body_len, + pdata->enc_data->fp); + videoflag=0; + if(!pdata->running){ + pthread_mutex_lock(&pdata->libogg_mutex); + if(ogg_page_eos(&videopage_copy)) + th_st_fin=1; + pthread_mutex_unlock(&pdata->libogg_mutex); + } + ogg_page_cp_free(&videopage_copy); + } + else{ + audio_bytesout+=fwrite(audiopage_copy.header,1, + audiopage_copy.header_len, + pdata->enc_data->fp); + audio_bytesout+=fwrite(audiopage_copy.body,1, + audiopage_copy.body_len, + pdata->enc_data->fp); + audioflag=0; + if(!pdata->running){ + pthread_mutex_lock(&pdata->libogg_mutex); + if(ogg_page_eos(&audiopage_copy)) + v_st_fin=1; + pthread_mutex_unlock(&pdata->libogg_mutex); + } + ogg_page_cp_free(&audiopage_copy); + } + working=(!th_st_fin || !v_st_fin); + + } + pthread_mutex_lock(&pdata->libogg_mutex); + ogg_stream_clear(&pdata->enc_data->m_ogg_ts); + if(!pdata->args.nosound) + ogg_stream_clear(&pdata->enc_data->m_ogg_vs); + pthread_mutex_unlock(&pdata->libogg_mutex); +//this always gives me a segfault :( +// theora_clear(&pdata->enc_data->m_th_st); + + if(pdata->enc_data->fp)fclose(pdata->enc_data->fp); + fprintf(stderr,"\r \nDone.\nWritten %.0f bytes\n" + "(%.0f of which were video data " + "and %.0f audio data)\n\n", + video_bytesout+audio_bytesout, + video_bytesout,audio_bytesout); + pthread_exit(&errno); +} diff --git a/recordmydesktop/src/rmd_flush_to_ogg.h b/recordmydesktop/src/rmd_flush_to_ogg.h new file mode 100644 index 0000000..a97a3b3 --- /dev/null +++ b/recordmydesktop/src/rmd_flush_to_ogg.h @@ -0,0 +1,40 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef FLUSH_TO_OGG_H +#define FLUSH_TO_OGG_H 1 + +#include "rmd_types.h" + + +/** +* Query theora and vorbis streams for ready packages and +* flush them on the disk +* \param pdata ProgData struct containing all program data +*/ +void *FlushToOgg(ProgData *pdata); + +#endif diff --git a/recordmydesktop/src/rmd_frame.h b/recordmydesktop/src/rmd_frame.h index 9d46662..c3969f8 100644 --- a/recordmydesktop/src/rmd_frame.h +++ b/recordmydesktop/src/rmd_frame.h @@ -27,7 +27,7 @@ #ifndef RMD_FRAME_H #define RMD_FRAME_H 1 -#include "rmdtypes.h" +#include "rmd_types.h" /* diff --git a/recordmydesktop/src/rmd_get_frame.c b/recordmydesktop/src/rmd_get_frame.c new file mode 100644 index 0000000..045368c --- /dev/null +++ b/recordmydesktop/src/rmd_get_frame.c @@ -0,0 +1,669 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include + +#include +#include + +#include "rmd_types.h" + +#include "rmd_cache.h" +#include "rmd_frame.h" +#include "rmd_get_frame.h" +#include "rmd_getzpixmap.h" +#include "rmd_poll_events.h" +#include "rmd_rectinsert.h" +#include "rmd_update_image.h" +#include "rmd_yuv_utils.h" + + +#define AVG_4_PIXELS(data_array,width_img,k_tm,i_tm,offset)\ + ((data_array[(k_tm*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+\ + data_array[((k_tm-1)*width_img+i_tm)*RMD_ULONG_SIZE_T+offset]+\ + data_array[(k_tm*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset]+\ + data_array[((k_tm-1)*width_img+i_tm-1)*RMD_ULONG_SIZE_T+offset])/4) + +#define CLIP_DUMMY_POINTER_AREA(dummy_p_area,brwin,wgeom){\ + (wgeom)->x=((((dummy_p_area).x+\ + (dummy_p_area).width>=(brwin)->rgeom.x)&&\ + ((dummy_p_area).x<=(brwin)->rgeom.x+\ + (brwin)->rgeom.width))?\ + (((dummy_p_area).x<=(brwin)->rgeom.x)?\ + (brwin)->rgeom.x:(dummy_p_area).x):-1);\ + (wgeom)->y=((((dummy_p_area).y+\ + (dummy_p_area).height>=(brwin)->rgeom.y)&&\ + ((dummy_p_area).y<=(brwin)->rgeom.y+\ + (brwin)->rgeom.height))?\ + (((dummy_p_area).y<=(brwin)->rgeom.y)?\ + (brwin)->rgeom.y:(dummy_p_area).y):-1);\ + (wgeom)->width=((dummy_p_area).x<=(brwin)->rgeom.x)?\ + (dummy_p_area).width-\ + ((brwin)->rgeom.x-(dummy_p_area).x):\ + ((dummy_p_area).x<=(brwin)->rgeom.x+\ + (brwin)->rgeom.width)?\ + ((brwin)->rgeom.width-(dummy_p_area).x+\ + (brwin)->rgeom.x<(dummy_p_area).width)?\ + (brwin)->rgeom.width-(dummy_p_area).x+\ + (brwin)->rgeom.x:(dummy_p_area).width:-1;\ + (wgeom)->height=((dummy_p_area).y<=(brwin)->rgeom.y)?\ + (dummy_p_area).height-\ + ((brwin)->rgeom.y-(dummy_p_area).y):\ + ((dummy_p_area).y<=(brwin)->rgeom.y+\ + (brwin)->rgeom.height)?\ + ((brwin)->rgeom.height-(dummy_p_area).y+\ + (brwin)->rgeom.y<(dummy_p_area).height)?\ + (brwin)->rgeom.height-(dummy_p_area).y+\ + (brwin)->rgeom.y:(dummy_p_area).height:-1;\ + if((wgeom)->width>(brwin)->rgeom.width)\ + (wgeom)->width=(brwin)->rgeom.width;\ + if((wgeom)->height>(brwin)->rgeom.height)\ + (wgeom)->height=(brwin)->rgeom.height;\ +} + +#define XFIXES_POINTER_TO_YUV(yuv,\ + data,\ + x_tm,\ + y_tm,\ + width_tm,\ + height_tm,\ + x_offset,\ + y_offset,\ + column_discard_stride){\ + int i,k,j=0;\ + unsigned char avg0,avg1,avg2,avg3;\ + int x_2=x_tm/2,y_2=y_tm/2;\ + for(k=y_offset;ky[x_tm+(i-x_offset)+(k+y_tm-y_offset)*yuv->y_width]=\ + (yuv->y[x_tm+(i-x_offset)+(k-y_offset+y_tm)*yuv->y_width]*\ + (UCHAR_MAX-data[(j*RMD_ULONG_SIZE_T)+__ABYTE])+\ + (Yr[data[(j*RMD_ULONG_SIZE_T)+__RBYTE]]+\ + Yg[data[(j*RMD_ULONG_SIZE_T)+__GBYTE]] +\ + Yb[data[(j*RMD_ULONG_SIZE_T)+__BBYTE]])*\ + data[(j*RMD_ULONG_SIZE_T)+__ABYTE])/UCHAR_MAX ;\ + if((k%2)&&(i%2)){\ + avg3=AVG_4_PIXELS(data,\ + (width_tm+column_discard_stride),\ + k,i,__ABYTE);\ + avg2=AVG_4_PIXELS(data,\ + (width_tm+column_discard_stride),\ + k,i,__RBYTE);\ + avg1=AVG_4_PIXELS(data,\ + (width_tm+column_discard_stride),\ + k,i,__GBYTE);\ + avg0=AVG_4_PIXELS(data,\ + (width_tm+column_discard_stride),\ + k,i,__BBYTE);\ + yuv->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ + yuv->uv_width]=\ + (yuv->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ + yuv->uv_width]*\ + (UCHAR_MAX-avg3)+\ + (Ur[avg2] + Ug[avg1] +UbVr[avg0])*avg3)/UCHAR_MAX;\ + yuv->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ + yuv->uv_width]=\ + (yuv->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*\ + yuv->uv_width]*\ + (UCHAR_MAX-avg3)+\ + (UbVr[avg2] + Vg[avg1] +Vb[avg0])*avg3)/UCHAR_MAX;\ + }\ + }\ + }\ +} + +#define MARK_BACK_BUFFER_C( data,\ + x_tm,\ + y_tm,\ + width_tm,\ + height_tm,\ + buffer_width,\ + __bit_depth__){\ + int k,i;\ + register u_int##__bit_depth__##_t\ + *datapi=\ + ((u_int##__bit_depth__##_t *)data)+y_tm*buffer_width+x_tm;\ + for(k=0;kargs.noshared)){ + + *pxl_data=(char *)malloc(pdata->brwin.nbytes); + + (*image)=XCreateImage(pdata->dpy, + pdata->specs.visual, + pdata->specs.depth, + ZPixmap, + 0, + *pxl_data, + pdata->brwin.rgeom.width, + pdata->brwin.rgeom.height, + 8, + 0); + XInitImage((*image)); + GetZPixmap(pdata->dpy,pdata->specs.root, + (*image)->data, + pdata->brwin.rgeom.x, + pdata->brwin.rgeom.y, + pdata->brwin.rgeom.width, + pdata->brwin.rgeom.height); + } + else{ + (*image)=XShmCreateImage(pdata->dpy, + pdata->specs.visual, + pdata->specs.depth, + ZPixmap, + *pxl_data, + shminfo, + pdata->brwin.rgeom.width, + pdata->brwin.rgeom.height); + (*shminfo).shmid=shmget(IPC_PRIVATE, + (*image)->bytes_per_line* + (*image)->height, + IPC_CREAT|0777); + if((*shminfo).shmid==-1){ + fprintf(stderr,"Failed to obtain Shared Memory segment!\n"); + return 12; + } + (*shminfo).shmaddr=(*image)->data=shmat((*shminfo).shmid, + NULL,0); + (*shminfo).readOnly = False; + if(!XShmAttach(pdata->dpy,shminfo)){ + fprintf(stderr,"Failed to attach shared memory to proccess.\n"); + return 12; + } + XShmGetImage(pdata->dpy, + pdata->specs.root, + (*image), + pdata->brwin.rgeom.x, + pdata->brwin.rgeom.y, + AllPlanes); + } + + UPDATE_YUV_BUFFER((&pdata->enc_data->yuv), + ((unsigned char*)((*image))->data),NULL, + (pdata->enc_data->x_offset),(pdata->enc_data->y_offset), + (pdata->brwin.rgeom.width),(pdata->brwin.rgeom.height), + (pdata->args.no_quick_subsample), + pdata->specs.depth); + + return 0; +} + +//make a deep copy +static void BRWinCpy(BRWindow *target, BRWindow *source) { + + target->geom.x=source->geom.x; + target->geom.y=source->geom.y; + target->geom.width=source->geom.width; + target->geom.height=source->geom.height; + target->rgeom.x=source->rgeom.x; + target->rgeom.y=source->rgeom.y; + target->rgeom.width=source->rgeom.width; + target->rgeom.height=source->rgeom.height; + target->nbytes=source->nbytes; + target->windowid=source->windowid; + +} + +//recenters the capture area to the mouse +//without exiting the display bounding box +static void MoveCaptureArea(BRWindow *brwin, + int cursor_x, + int cursor_y, + int width, + int height) { + int t_x=0,t_y=0; + + t_x=cursor_x-brwin->rgeom.width/2; + t_x=(t_x>>1)<<1; + brwin->rgeom.x=(t_x<0)?0:((t_x+brwin->rgeom.width>width)? + width-brwin->rgeom.width:t_x); + t_y=cursor_y-brwin->rgeom.height/2; + t_y=(t_y>>1)<<1; + brwin->rgeom.y=(t_y<0)?0:((t_y+brwin->rgeom.height>height)? + height-brwin->rgeom.height:t_y); +} + +/** +* Extract cache blocks from damage list +* +* \param root Root entry of the list with damaged areas +* +* \param x_offset left x of the recording area +* +* \param x_offset upper y of the recording area +* +* \param blocknum_x Width of image in blocks +* +* \param blocknum_y Height of image in blocks +*/ +static void BlocksFromList (RectArea **root, + unsigned int x_offset, + unsigned int y_offset, + unsigned int blocknum_x, + unsigned int blocknum_y) { + + RectArea *temp; + unsigned int i, + j, + blockno, + row_start, + row_end, + column_start, + column_end; + + temp = *root; + + for (i = 0; i < blocknum_x * blocknum_y; i++) { + yblocks[i] = ublocks[i] = vblocks[i] = 0; + } + + while (temp != NULL) { + + column_start = (temp->geom.x - x_offset) / Y_UNIT_WIDTH; + column_end = (temp->geom.x + (temp->geom.width - 1) - x_offset) / Y_UNIT_WIDTH; + row_start = (temp->geom.y - y_offset) / Y_UNIT_WIDTH; + row_end = (temp->geom.y + (temp->geom.height - 1) - y_offset) / Y_UNIT_WIDTH; + + for (i = row_start; i < row_end + 1; i++) { + for (j = column_start; j < column_end + 1; j++) { + blockno = i * blocknum_x + j; + yblocks[blockno] = 1; + ublocks[blockno] = 1; + vblocks[blockno] = 1; + } + } + + temp = temp->next; + } +} + +void *GetFrame(ProgData *pdata){ + int i=0, + blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, + blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH; + unsigned int msk_ret; + WGeometry mouse_pos_abs,mouse_pos_rel,mouse_pos_temp; + BRWindow temp_brwin; + Window root_ret, + child_ret; //Frame + XFixesCursorImage *xcim=NULL; + XImage *image=NULL,*image_back=NULL; //the image that holds + //the current full screenshot + XShmSegmentInfo shminfo,shminfo_back;//info structure for the image above. + int init_img1=0,init_img2=0, + img_sel,d_buff; + char *pxl_data=NULL,*pxl_data_back=NULL; + + + + + img_sel=d_buff=pdata->args.full_shots; + + if((init_img1=FirstFrame(pdata,&image,&shminfo,&pxl_data)!=0)){ + if(pdata->args.encOnTheFly){ + if(remove(pdata->args.filename)){ + perror("Error while removing file:\n"); + } + else{ + fprintf(stderr,"SIGABRT received,file %s removed\n", + pdata->args.filename); + } + } + else{ + PurgeCache(pdata->cache_data,!pdata->args.nosound); + } + exit(init_img1); + } + if(d_buff){ + if((init_img2=FirstFrame(pdata,&image_back,&shminfo_back, + &pxl_data_back)!=0)){ + if(pdata->args.encOnTheFly){ + if(remove(pdata->args.filename)){ + perror("Error while removing file:\n"); + } + else{ + fprintf(stderr,"SIGABRT received,file %s removed\n", + pdata->args.filename); + } + } + else{ + PurgeCache(pdata->cache_data,!pdata->args.nosound); + } + exit(init_img2); + } + + } + + if(!pdata->args.noframe){ + pdata->shaped_w=rmdFrameInit(pdata->dpy, + pdata->specs.screen, + pdata->specs.root, + pdata->brwin.rgeom.x, + pdata->brwin.rgeom.y, + pdata->brwin.rgeom.width, + pdata->brwin.rgeom.height); + XSelectInput(pdata->dpy,pdata->shaped_w,ExposureMask); + } + + mouse_pos_abs.x=mouse_pos_temp.x=0; + mouse_pos_abs.y=mouse_pos_temp.y=0; + mouse_pos_abs.width=mouse_pos_temp.width=pdata->dummy_p_size; + mouse_pos_abs.height=mouse_pos_temp.height=pdata->dummy_p_size; + + //This is the the place where we call XSelectInput + //and arrange so that we listen for damage on all + //windows + InitEventsPolling(pdata); + + while(pdata->running){ + + //if we are left behind we must not wait. + //also before actually pausing we must make sure the streams + //are synced. sound stops so this should only happen quickly. + if(pdata->avd>0 || pdata->args.nosound){ + pthread_mutex_lock(&pdata->time_mutex); + pthread_cond_wait(&pdata->time_cond, &pdata->time_mutex); + pthread_mutex_unlock(&pdata->time_mutex); + if (pdata->paused) { + //this is necessary since event loop processes + //the shortcuts which will unpause the program + EventLoop(pdata); + continue; + } + } + //read all events and construct list with damage + //events (if not full_shots) + EventLoop(pdata); + + //switch back and front buffers (full_shots only) + if(d_buff) + img_sel=(img_sel)?0:1; + pdata->capture_busy = TRUE; + + BRWinCpy(&temp_brwin,&pdata->brwin); + + + if(pdata->args.xfixes_cursor || + pdata->args.have_dummy_cursor|| + pdata->args.follow_mouse){ + //pointer sequence + //update previous_position + //(if full_shots is enabled the new cursor is + //entered on the list for update. + //When taking full shots we keep it for further + //bellow, to mark the area as dirty when dbuffering. + CLIP_DUMMY_POINTER_AREA(mouse_pos_abs,&temp_brwin, + &mouse_pos_temp); + if(!pdata->args.full_shots){ + if((mouse_pos_temp.x>=0)&& + (mouse_pos_temp.y>=0)&& + (mouse_pos_temp.width>0)&& + (mouse_pos_temp.height>0)) + RectInsert(&pdata->rect_root,&mouse_pos_temp); + } + //find new one + if(pdata->args.xfixes_cursor){ + xcim=XFixesGetCursorImage(pdata->dpy); + mouse_pos_abs.x=xcim->x-xcim->xhot; + mouse_pos_abs.y=xcim->y-xcim->yhot; + mouse_pos_abs.width=xcim->width; + mouse_pos_abs.height=xcim->height; + } + else{ + XQueryPointer(pdata->dpy, + pdata->specs.root, + &root_ret,&child_ret, + &mouse_pos_abs.x,&mouse_pos_abs.y, + &mouse_pos_rel.x,&mouse_pos_rel.y,&msk_ret); + } + } + if(pdata->args.follow_mouse){ + MoveCaptureArea(&pdata->brwin, + mouse_pos_abs.x+ + ((pdata->args.xfixes_cursor)?xcim->xhot:0), + mouse_pos_abs.y+ + ((pdata->args.xfixes_cursor)?xcim->yhot:0), + pdata->specs.width, + pdata->specs.height); + if(!pdata->args.noframe){ + rmdMoveFrame(pdata->dpy, + pdata->shaped_w, + temp_brwin.rgeom.x, + temp_brwin.rgeom.y); + + } + } + + if(!pdata->args.full_shots){ + pthread_mutex_lock(&pdata->yuv_mutex); + UpdateImage(pdata->dpy, + &pdata->enc_data->yuv, + &pdata->specs, + &pdata->rect_root, + &temp_brwin, + pdata->enc_data, + image->data, + pdata->args.noshared, + &shminfo, + pdata->shm_opcode, + pdata->args.no_quick_subsample); + BlocksFromList(&pdata->rect_root, + temp_brwin.rgeom.x, + temp_brwin.rgeom.y, + pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, + pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH); + pthread_mutex_unlock(&pdata->yuv_mutex); + } + else{ + unsigned char *front_buff=(!img_sel)?((unsigned char*)image->data): + ((unsigned char*)image_back->data); + unsigned char *back_buff=(!d_buff)?NULL:((img_sel)? + ((unsigned char*)image->data): + ((unsigned char*)image_back->data)); + + if(!pdata->args.noshared){ + XShmGetImage(pdata->dpy,pdata->specs.root, + ((!img_sel)?image:image_back), + (temp_brwin.rgeom.x), + (temp_brwin.rgeom.y),AllPlanes); + } + if(pdata->args.noshared){ + GetZPixmap( pdata->dpy, + pdata->specs.root, + image->data, + temp_brwin.rgeom.x, + temp_brwin.rgeom.y, + temp_brwin.rgeom.width, + temp_brwin.rgeom.height); + } + pthread_mutex_lock(&pdata->yuv_mutex); + for(i=0;ienc_data->yuv), + front_buff,back_buff, + (pdata->enc_data->x_offset), + (pdata->enc_data->y_offset), + (temp_brwin.rgeom.width), + (temp_brwin.rgeom.height), + pdata->args.no_quick_subsample, + pdata->specs.depth); + pthread_mutex_unlock(&pdata->yuv_mutex); + } + if(pdata->args.xfixes_cursor || + pdata->args.have_dummy_cursor){ + int mouse_xoffset, + mouse_yoffset; + //avoid segfaults + CLIP_DUMMY_POINTER_AREA(mouse_pos_abs,&temp_brwin, + &mouse_pos_temp); + mouse_xoffset=mouse_pos_temp.x-mouse_pos_abs.x; + mouse_yoffset=mouse_pos_temp.y-mouse_pos_abs.y; + if((mouse_xoffset<0) || (mouse_xoffset>mouse_pos_abs.width)) + mouse_xoffset=0; + if((mouse_yoffset<0) || (mouse_yoffset>mouse_pos_abs.height)) + mouse_yoffset=0; + //draw the cursor + if((mouse_pos_temp.x>=0)&& + (mouse_pos_temp.y>=0)&& + (mouse_pos_temp.width>0)&& + (mouse_pos_temp.height>0)){ + if(pdata->args.xfixes_cursor){ + XFIXES_POINTER_TO_YUV((&pdata->enc_data->yuv), + ((unsigned char*)xcim->pixels), + (mouse_pos_temp.x- + temp_brwin.rgeom.x+ + pdata->enc_data->x_offset), + (mouse_pos_temp.y- + temp_brwin.rgeom.y+ + pdata->enc_data->y_offset), + mouse_pos_temp.width, + mouse_pos_temp.height, + mouse_xoffset, + mouse_yoffset, + (xcim->width-mouse_pos_temp.width)); + } + else{ + DUMMY_POINTER_TO_YUV((&pdata->enc_data->yuv), + pdata->dummy_pointer, + (mouse_pos_temp.x- + temp_brwin.rgeom.x+ + pdata->enc_data->x_offset), + (mouse_pos_temp.y- + temp_brwin.rgeom.y+ + pdata->enc_data->y_offset), + mouse_pos_temp.width, + mouse_pos_temp.height, + mouse_xoffset, + mouse_yoffset, + pdata->npxl); + } + if(d_buff){ + //make previous cursor position dirty + unsigned char *front_buff= + (!img_sel)?((unsigned char*)image->data): + ((unsigned char*)image_back->data); + + MARK_BACK_BUFFER( front_buff, + (mouse_pos_temp.x- + temp_brwin.rgeom.x+ + pdata->enc_data->x_offset), + (mouse_pos_temp.y- + temp_brwin.rgeom.y+ + pdata->enc_data->y_offset), + mouse_pos_temp.width, + mouse_pos_temp.height, + (temp_brwin.rgeom.width), + pdata->specs.depth) + } + + } + if(pdata->args.xfixes_cursor){ + XFree(xcim); + xcim=NULL; + } + } + if(!pdata->args.full_shots){ + ClearList(&pdata->rect_root); + } + if (pdata->encoder_busy) { + pdata->frames_lost++; + } + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_broadcast(&pdata->image_buffer_ready); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + pdata->capture_busy = FALSE; + } + + if(!pdata->args.noframe){ + XDestroyWindow(pdata->dpy,pdata->shaped_w); + } + + + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_broadcast(&pdata->image_buffer_ready); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + if(!pdata->args.noshared){ + XShmDetach (pdata->dpy, &shminfo); + shmdt (shminfo.shmaddr); + shmctl (shminfo.shmid, IPC_RMID, 0); + if(d_buff){ + XShmDetach (pdata->dpy, &shminfo_back); + shmdt (shminfo_back.shmaddr); + shmctl (shminfo_back.shmid, IPC_RMID, 0); + } + } + pthread_exit(&errno); +} + diff --git a/recordmydesktop/src/rmd_get_frame.h b/recordmydesktop/src/rmd_get_frame.h new file mode 100644 index 0000000..36c378d --- /dev/null +++ b/recordmydesktop/src/rmd_get_frame.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef GET_FRAME_H +#define GET_FRAME_H 1 + +#include "rmd_types.h" + + +/** +* Retrieve frame form xserver, and transform to a yuv buffer, +* either directly(full shots) or by calling UpdateImage. +* \param pdata ProgData struct containing all program data +*/ +void *GetFrame(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_getzpixmap.c b/recordmydesktop/src/rmd_getzpixmap.c new file mode 100644 index 0000000..f001844 --- /dev/null +++ b/recordmydesktop/src/rmd_getzpixmap.c @@ -0,0 +1,112 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include +#include + +#include "rmd_types.h" + +#include "rmd_getzpixmap.h" + + +int GetZPixmap(Display *dpy, + Window root, + char *data, + int x, + int y, + int width, + int height){ + xGetImageReply reply; + xGetImageReq *request; + long nbytes; + + LockDisplay(dpy); + GetReq(GetImage,request); + request->drawable=root; + request->x=x; + request->y=y; + request->width=width; + request->height=height; + request->planeMask=AllPlanes; + request->format=ZPixmap; + if((!_XReply(dpy,(xReply *)&reply,0,xFalse))||(!reply.length)){ + UnlockDisplay(dpy); + SyncHandle(); + return 1; + } + nbytes=(long)reply.length<<2; + _XReadPad(dpy,data,nbytes); + UnlockDisplay(dpy); + SyncHandle(); + return 0; +} + +int GetZPixmapSHM(Display *dpy, + Window root, + XShmSegmentInfo *shminfo, + int shm_opcode, + char *data, + int x, + int y, + int width, + int height){ + xShmGetImageReply reply; + xShmGetImageReq *request=NULL; + long nbytes; + + LockDisplay(dpy); + GetReq(ShmGetImage,request); + + request->reqType=shm_opcode; + request->shmReqType=X_ShmGetImage; + request->shmseg=shminfo->shmseg; + + request->drawable=root; + request->x=x; + request->y=y; + request->width=width; + request->height=height; + request->planeMask=AllPlanes; + request->format=ZPixmap; + request->offset=data-shminfo->shmaddr; + + if((!_XReply(dpy,(xReply *)&reply,0,xFalse))||(!reply.length)){ + UnlockDisplay(dpy); + SyncHandle(); + return 1; + } + + nbytes=(long)reply.length << 2; + _XReadPad(dpy,data,nbytes); + UnlockDisplay(dpy); + SyncHandle(); + + return 0; +} diff --git a/recordmydesktop/src/rmd_getzpixmap.h b/recordmydesktop/src/rmd_getzpixmap.h new file mode 100644 index 0000000..b154e5a --- /dev/null +++ b/recordmydesktop/src/rmd_getzpixmap.h @@ -0,0 +1,98 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef GETZPIXMAP_H +#define GETZPIXMAP_H 1 + +#include "rmd_types.h" + + +/** +* Rerieve pixmap data from xserver +* +* \param dpy Connection to the server +* +* \param root root window of the display +* +* \param data (preallocated)buffer to place the data +* +* \param x x position of the screenshot +* +* \param y y position of the screenshot +* +* \param x x position of the screenshot +* +* \param width width of the screenshot +* +* \param height height position of the screenshot +* +* \returns 0 on Success 1 on Failure +*/ +int GetZPixmap(Display *dpy, + Window root, + char *data, + int x, + int y, + int width, + int height); + +/** +* Rerieve pixmap data from xserver through the MIT-Shm extension +* +* \param dpy Connection to the server +* +* \param root root window of the display +* +* \param shminfo Info for the shared memory segment +* +* \param shm_opcode Opcode of Shm extension +* +* \param data (preallocated)buffer to place the data +* +* \param x x position of the screenshot +* +* \param y y position of the screenshot +* +* \param x x position of the screenshot +* +* \param width width of the screenshot +* +* \param height height position of the screenshot +* +* \returns 0 on Success 1 on Failure +*/ +int GetZPixmapSHM(Display *dpy, + Window root, + XShmSegmentInfo *shminfo, + int shm_opcode, + char *data, + int x, + int y, + int width, + int height); + + +#endif diff --git a/recordmydesktop/src/rmd_init_encoder.c b/recordmydesktop/src/rmd_init_encoder.c new file mode 100644 index 0000000..4fb2538 --- /dev/null +++ b/recordmydesktop/src/rmd_init_encoder.c @@ -0,0 +1,372 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include + +#include "skeleton.h" + +#include "rmd_types.h" + +#include "rmd_init_encoder.h" +#include "rmd_macro.h" + + +static void m_add_fishead_packet(ogg_stream_state *m_ogg_state) { + + fishead_packet skel_fp; + + skel_fp.ptime_n=skel_fp.btime_n=0; + skel_fp.ptime_d=skel_fp.btime_d=1000; + + add_fishead_to_stream(m_ogg_state,&skel_fp); + + +} + + +static int IncrementalNaming(char **name) { + struct stat buff; + char *base_name__; + int i=0, + fname_length=strlen(*name)-4; + + base_name__=malloc(fname_length+1); + strncpy(base_name__,*name,fname_length); + base_name__[fname_length]='\0'; + + + //this will go on an endless loop if you have 65536? + //files with the same name + //or it will crash and die.anyone interested in trying ? + while (stat(*name,&buff)==0){ + //create new name + char *tname=malloc(strlen(*name)+10); + char numbuf[8]; + + strcpy(tname,base_name__); + strcat(tname,"-"); + i++; + I16TOA((i),numbuf) + strcat(tname,numbuf); + strcat(tname,".ogv"); + //save new name + + free(*name); + *name=malloc(strlen(tname)+1); + strcpy(*name,tname); + free(tname); + } + + free(base_name__); + return 0; +} + +void InitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready){ + + int y0, + y1, + y2, + fname_length; + ogg_stream_state m_ogg_skel; + ogg_page skel_og_pg; + fisbone_packet skel_fbv, //video fisbone packet + skel_fba ; //audio fisbone packet + + (pdata)->enc_data=enc_data_t; + + fname_length=strlen(pdata->args.filename); + if(!(fname_length>4 && + pdata->args.filename[fname_length-4] == '.' && + (pdata->args.filename[fname_length-3] == 'o' || + pdata->args.filename[fname_length-3] == 'O') && + (pdata->args.filename[fname_length-2] == 'g' || + pdata->args.filename[fname_length-2] == 'G') && + (pdata->args.filename[fname_length-1] == 'v' || + pdata->args.filename[fname_length-1] == 'V'))){ + + char *new_name=malloc(fname_length+5); + strcpy(new_name,pdata->args.filename); + strcat(new_name,".ogv"); + + free(pdata->args.filename); + pdata->args.filename=new_name; + + + } + + if(!pdata->args.overwrite) + IncrementalNaming(&(pdata)->args.filename); + enc_data_t->fp=fopen((pdata)->args.filename,"w"); + if(enc_data_t->fp==NULL){ + fprintf(stderr,"Cannot open file %s for writting!\n", + (pdata)->args.filename); + exit(13); + } + + //each stream must have a unique + srand(time(NULL)); + y0=rand()+1; + y1=rand()+1; + y2=rand()+1; + y2+=(y1==y2); + y0=(((y0==y1)||(y0==y2))?(y1+y2):y0); + + //init ogg streams + //skeleton first + ogg_stream_init(&m_ogg_skel,y0); + m_add_fishead_packet(&m_ogg_skel); + if(ogg_stream_pageout(&m_ogg_skel,&skel_og_pg)!= 1){ + fprintf (stderr, "Internal Ogg library error.\n"); + exit (2); + } + fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); + fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); + + + + ogg_stream_init(&enc_data_t->m_ogg_ts,y1); + if(!pdata->args.nosound) + ogg_stream_init(&enc_data_t->m_ogg_vs,y2); + + + + theora_info_init(&enc_data_t->m_th_inf); + enc_data_t->m_th_inf.frame_width=(pdata)->brwin.rgeom.width; + enc_data_t->m_th_inf.frame_height=(pdata)->brwin.rgeom.height; + enc_data_t->m_th_inf.width=((enc_data_t->m_th_inf.frame_width+15)>>4)<<4; + enc_data_t->m_th_inf.height=((enc_data_t->m_th_inf.frame_height+15)>>4)<<4; + enc_data_t->m_th_inf.offset_x=((enc_data_t->m_th_inf.width- + enc_data_t->m_th_inf.frame_width)/2)&~1; + enc_data_t->m_th_inf.offset_y=((enc_data_t->m_th_inf.height- + enc_data_t->m_th_inf.frame_height)/2)&~1; + enc_data_t->m_th_inf.fps_numerator=((pdata)->args.fps*100.0); + enc_data_t->m_th_inf.fps_denominator=100; + enc_data_t->m_th_inf.aspect_numerator=1;//(pdata)->brwin.rgeom.width; + enc_data_t->m_th_inf.aspect_denominator=1;//(pdata)->brwin.rgeom.height; + enc_data_t->m_th_inf.colorspace=OC_CS_UNSPECIFIED; + enc_data_t->m_th_inf.pixelformat=OC_PF_420; + enc_data_t->m_th_inf.target_bitrate=(pdata)->args.v_bitrate; + enc_data_t->m_th_inf.quality=(pdata)->args.v_quality; + enc_data_t->m_th_inf.dropframes_p=0; + enc_data_t->m_th_inf.quick_p=1; + enc_data_t->m_th_inf.keyframe_auto_p=1; + enc_data_t->m_th_inf.keyframe_frequency=64; + enc_data_t->m_th_inf.keyframe_frequency_force=64; + enc_data_t->m_th_inf.keyframe_data_target_bitrate= + enc_data_t->m_th_inf.quality*1.5; + + enc_data_t->m_th_inf.keyframe_auto_threshold=80; + enc_data_t->m_th_inf.keyframe_mindistance=8; + enc_data_t->m_th_inf.noise_sensitivity=1; + enc_data_t->m_th_inf.sharpness=2; + + theora_encode_init(&enc_data_t->m_th_st,&enc_data_t->m_th_inf); + + + + if(!pdata->args.nosound){ + int ret; + vorbis_info_init(&enc_data_t->m_vo_inf); + ret = vorbis_encode_init_vbr(&enc_data_t->m_vo_inf, + pdata->args.channels, + pdata->args.frequency, + (float)pdata->args.s_quality*0.1); + if(ret){ + fprintf(stderr,"Error while setting up vorbis stream quality!\n"); + exit(2); + } + vorbis_comment_init(&enc_data_t->m_vo_cmmnt); + vorbis_analysis_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_inf); + vorbis_block_init(&enc_data_t->m_vo_dsp,&enc_data_t->m_vo_block); + } + + + theora_encode_header(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); + ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); + if(ogg_stream_pageout(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pg)!=1){ + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + fwrite(enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + fwrite(enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + + theora_comment_init(&enc_data_t->m_th_cmmnt); + theora_comment_add_tag(&enc_data_t->m_th_cmmnt,"recordMyDesktop",VERSION); + theora_encode_comment(&enc_data_t->m_th_cmmnt,&enc_data_t->m_ogg_pckt1); + ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); + theora_encode_tables(&enc_data_t->m_th_st,&enc_data_t->m_ogg_pckt1); + ogg_stream_packetin(&enc_data_t->m_ogg_ts,&enc_data_t->m_ogg_pckt1); + + + if(!pdata->args.nosound){ + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout(&enc_data_t->m_vo_dsp, + &enc_data_t->m_vo_cmmnt, + &header,&header_comm, + &header_code); + ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header); + if(ogg_stream_pageout(&enc_data_t->m_ogg_vs,&enc_data_t->m_ogg_pg)!=1){ + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + fwrite(enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + fwrite(enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + + ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_comm); + ogg_stream_packetin(&enc_data_t->m_ogg_vs,&header_code); + } + + //fishbone packets go here + memset(&skel_fbv,0,sizeof(skel_fbv)); + skel_fbv.serial_no=enc_data_t->m_ogg_ts.serialno; + skel_fbv.nr_header_packet=3; + skel_fbv.granule_rate_n=enc_data_t->m_th_inf.fps_numerator; + skel_fbv.granule_rate_d=enc_data_t->m_th_inf.fps_denominator; + skel_fbv.start_granule=0; + skel_fbv.preroll=0; + skel_fbv.granule_shift=theora_granule_shift(&enc_data_t->m_th_inf); + add_message_header_field(&skel_fbv, + "Content-Type", + "video/theora"); + + add_fisbone_to_stream(&m_ogg_skel,&skel_fbv); + + if(!pdata->args.nosound){ + + memset(&skel_fba,0,sizeof(skel_fba)); + skel_fba.serial_no=enc_data_t->m_ogg_vs.serialno; + skel_fba.nr_header_packet=3; + skel_fba.granule_rate_n=pdata->args.frequency; + skel_fba.granule_rate_d=(ogg_int64_t)1; + skel_fba.start_granule=0; + skel_fba.preroll=2; + skel_fba.granule_shift=0; + add_message_header_field(&skel_fba, + "Content-Type", + "audio/vorbis"); + + add_fisbone_to_stream(&m_ogg_skel,&skel_fba); + + } + + while(1){ + int result = ogg_stream_flush(&m_ogg_skel, &skel_og_pg); + if(result<0){ + fprintf (stderr, "Internal Ogg library error.\n"); + exit(2); + } + if(result==0) + break; + fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); + fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); + } + + + + while(1){ + int result = ogg_stream_flush(&enc_data_t->m_ogg_ts, + &enc_data_t->m_ogg_pg); + if(result<0){ + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + if(result==0)break; + fwrite(enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + fwrite(enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + } + + if(!pdata->args.nosound){ + while(1){ + int result=ogg_stream_flush(&enc_data_t->m_ogg_vs, + &enc_data_t->m_ogg_pg); + if(result<0){ + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + if(result==0)break; + fwrite(enc_data_t->m_ogg_pg.header,1, + enc_data_t->m_ogg_pg.header_len, + enc_data_t->fp); + fwrite(enc_data_t->m_ogg_pg.body,1, + enc_data_t->m_ogg_pg.body_len, + enc_data_t->fp); + } + } + + //skeleton eos + add_eos_packet_to_stream(&m_ogg_skel); + if(ogg_stream_flush(&m_ogg_skel,&skel_og_pg)<0){ + fprintf(stderr,"Internal Ogg library error.\n"); + exit(2); + } + fwrite(skel_og_pg.header,1,skel_og_pg.header_len,enc_data_t->fp); + fwrite(skel_og_pg.body,1,skel_og_pg.body_len,enc_data_t->fp); + + + //theora buffer allocation, if any + if(!buffer_ready){ + enc_data_t->yuv.y=(unsigned char *)malloc(enc_data_t->m_th_inf.height* + enc_data_t->m_th_inf.width); + enc_data_t->yuv.u=(unsigned char *)malloc(enc_data_t->m_th_inf.height* + enc_data_t->m_th_inf.width/4); + enc_data_t->yuv.v=(unsigned char *)malloc(enc_data_t->m_th_inf.height* + enc_data_t->m_th_inf.width/4); + enc_data_t->yuv.y_width=enc_data_t->m_th_inf.width; + enc_data_t->yuv.y_height=enc_data_t->m_th_inf.height; + enc_data_t->yuv.y_stride=enc_data_t->m_th_inf.width; + + enc_data_t->yuv.uv_width=enc_data_t->m_th_inf.width/2; + enc_data_t->yuv.uv_height=enc_data_t->m_th_inf.height/2; + enc_data_t->yuv.uv_stride=enc_data_t->m_th_inf.width/2; + enc_data_t->x_offset=enc_data_t->m_th_inf.offset_x; + enc_data_t->y_offset=enc_data_t->m_th_inf.offset_y; + } + theora_info_clear(&enc_data_t->m_th_inf); + +} + + + + diff --git a/recordmydesktop/src/rmd_init_encoder.h b/recordmydesktop/src/rmd_init_encoder.h new file mode 100644 index 0000000..fd871bb --- /dev/null +++ b/recordmydesktop/src/rmd_init_encoder.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef INIT_ENCODER_H +#define INIT_ENCODER_H 1 + +#include "rmd_types.h" + + +/** +* Initialize theora,vorbis encoders, and their respective ogg streams. +* +* \param pdata ProgData struct containing all program data +* +* \param enc_data_t Encoding options +* +* \param buffer_ready when 1, the yuv buffer must be preallocated +* when 0 InitEncoder will alocate a new one +* +*/ +void InitEncoder(ProgData *pdata,EncData *enc_data_t,int buffer_ready); + + +#endif diff --git a/recordmydesktop/src/rmd_initialize_data.c b/recordmydesktop/src/rmd_initialize_data.c new file mode 100644 index 0000000..c71dc9b --- /dev/null +++ b/recordmydesktop/src/rmd_initialize_data.c @@ -0,0 +1,256 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_block_utils.h" +#include "rmd_cache.h" +#include "rmd_init_encoder.h" +#include "rmd_jack.h" +#include "rmd_make_dummy_pointer.h" +#include "rmd_opendev.h" +#include "rmd_yuv_utils.h" + + +#ifdef HAVE_LIBASOUND +static void FixBufferSize(snd_pcm_uframes_t *buffsize) { + snd_pcm_uframes_t buffsize_t=*buffsize, +#else +static 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){ + int i; + + fprintf(stderr,"Initializing...\n"); + MakeMatrices(); + if(pdata->args.have_dummy_cursor){ + pdata->dummy_pointer=MakeDummyPointer(&pdata->specs,16, + pdata->args.cursor_color,0, + &pdata->npxl); + pdata->dummy_p_size=16; + } + else + pdata->dummy_p_size=0; + + + pdata->rect_root=NULL; + pthread_mutex_init(&pdata->sound_buffer_mutex,NULL); + pthread_mutex_init(&pdata->snd_buff_ready_mutex,NULL); + pthread_mutex_init(&pdata->img_buff_ready_mutex,NULL); + pthread_mutex_init(&pdata->theora_lib_mutex,NULL); + pthread_mutex_init(&pdata->vorbis_lib_mutex,NULL); + pthread_mutex_init(&pdata->libogg_mutex,NULL); + pthread_mutex_init(&pdata->yuv_mutex,NULL); + pthread_mutex_init(&pdata->pause_mutex, NULL); + pthread_mutex_init(&pdata->time_mutex, NULL); + pthread_cond_init(&pdata->time_cond,NULL); + pthread_cond_init(&pdata->pause_cond,NULL); + pthread_cond_init(&pdata->image_buffer_ready,NULL); + pthread_cond_init(&pdata->sound_buffer_ready,NULL); + pthread_cond_init(&pdata->sound_data_read,NULL); + pthread_cond_init(&pdata->theora_lib_clean,NULL); + pthread_cond_init(&pdata->vorbis_lib_clean,NULL); + pdata->th_encoding_clean=pdata->v_encoding_clean=1; + pdata->avd=0; + pdata->sound_buffer=NULL; + pdata->running = TRUE; + pdata->paused = FALSE; + pdata->aborted = FALSE; + pdata->pause_state_changed = FALSE; + pdata->frames_total = 0; + pdata->frames_lost = 0; + pdata->encoder_busy = FALSE; + pdata->capture_busy = FALSE; + + 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); + pdata->sound_framesize=((snd_pcm_format_width( + SND_PCM_FORMAT_S16_LE))/8)* + pdata->args.channels; + + 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; + pdata->sound_framesize=pdata->args.channels<<1; + 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->ringbuffer_secs=pdata->args.jack_ringbuffer_secs; + 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; + pdata->sound_framesize=sizeof(jack_default_audio_sample_t)* + pdata->jdata->nports; + +#else + fprintf(stderr,"Should not be here!\n"); + exit(-1); +#endif + } + } + + if(pdata->args.encOnTheFly) + InitEncoder(pdata,enc_data,0); + else + InitCacheData(pdata,enc_data,cache_data); + + for(i=0;i<(pdata->enc_data->yuv.y_width*pdata->enc_data->yuv.y_height);i++) + pdata->enc_data->yuv.y[i]=0; + for(i=0; + i<(pdata->enc_data->yuv.uv_width*pdata->enc_data->yuv.uv_height); + i++){ + pdata->enc_data->yuv.v[i]=pdata->enc_data->yuv.u[i]=127; + } + + yblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* + (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); + ublocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* + (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); + vblocks=malloc(sizeof(u_int32_t)*(pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH)* + (pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH)); + + pdata->frametime=(1000000)/pdata->args.fps; + return 0; + +} + +void SetupDefaultArgs(ProgArgs *args) { + + args->delay = 0; + args->windowid = 0; + args->x = 0; + args->y = 0; + args->width = 0; + args->height = 0; + args->nosound = 0; + args->full_shots = 0; + args->follow_mouse = 0; + args->encOnTheFly = 0; + args->nowmcheck = 0; + args->overwrite = 0; + args->use_jack = 0; + args->noshared = 0; + args->no_encode = 0; + args->noframe = 0; + args->jack_nports = 0; + args->jack_ringbuffer_secs = 3.0; + args->jack_port_names = NULL; + args->zerocompression = 1; + args->no_quick_subsample = 1; + args->cursor_color = 1; + args->have_dummy_cursor = 0; + args->xfixes_cursor = 1; + args->fps = 15; + args->channels = 1; + args->frequency = 22050; + args->buffsize = 4096; + args->v_bitrate = 45000; + args->v_quality = 63; + args->s_quality = 10; + + if (getenv("DISPLAY") != NULL) { + args->display = (char *) malloc(strlen(getenv("DISPLAY")) + 1); + strcpy(args->display, getenv("DISPLAY")); + } + else { + args->display = NULL; + } + + args->device = (char *) malloc(strlen(DEFAULT_AUDIO_DEVICE) + 1); + strcpy(args->device, DEFAULT_AUDIO_DEVICE); + + args->workdir = (char *) malloc(5); + strcpy(args->workdir, "/tmp"); + + args->pause_shortcut = (char *) malloc(15); + strcpy(args->pause_shortcut, "Control+Mod1+p"); + + args->stop_shortcut = (char *) malloc(15); + strcpy(args->stop_shortcut, "Control+Mod1+s"); + + args->filename = (char *) malloc(8); + strcpy(args->filename, "out.ogv"); +} + +void CleanUp(void){ + + free(yblocks); + free(ublocks); + free(vblocks); + +} diff --git a/recordmydesktop/src/rmd_initialize_data.h b/recordmydesktop/src/rmd_initialize_data.h new file mode 100644 index 0000000..29bd2fc --- /dev/null +++ b/recordmydesktop/src/rmd_initialize_data.h @@ -0,0 +1,62 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef INITIALIZE_DATA_H +#define INITIALIZE_DATA_H 1 + +#include "rmd_types.h" + + +/** +* initialize lists,mutexes,image buffers, take first screenshot, +* and anything else needed before launching the capture threads. +* +* \param pdata ProgData struct containing all program data +* +* \param enc_data reference to enc_data structure +* +* \param cache_data reference to cache_data structure +* +* \returns 0 on success, other values must cause the program to exit +*/ +int InitializeData(ProgData *pdata, + EncData *enc_data, + CacheData *cache_data); + +/** +* Sets up the ProgArgs structure to default values. +*/ +void SetupDefaultArgs(ProgArgs *args); + +/** +* Currently only frees some memory +* (y,u,v blocks) +* +*/ +void CleanUp(void); + + +#endif diff --git a/recordmydesktop/src/rmd_jack.c b/recordmydesktop/src/rmd_jack.c index 9038781..25ae297 100644 --- a/recordmydesktop/src/rmd_jack.c +++ b/recordmydesktop/src/rmd_jack.c @@ -28,10 +28,10 @@ #include -#include "rmdtypes.h" +#include "rmd_types.h" #include "rmd_jack.h" -#include "rmdmacro.h" +#include "rmd_macro.h" #ifdef HAVE_JACK_H diff --git a/recordmydesktop/src/rmd_jack.h b/recordmydesktop/src/rmd_jack.h index 96492b0..55d8991 100644 --- a/recordmydesktop/src/rmd_jack.h +++ b/recordmydesktop/src/rmd_jack.h @@ -27,7 +27,7 @@ #ifndef RMD_JACK_H #define RMD_JACK_H 1 -#include "rmdtypes.h" +#include "rmd_types.h" #ifdef HAVE_JACK_H diff --git a/recordmydesktop/src/rmd_load_cache.c b/recordmydesktop/src/rmd_load_cache.c new file mode 100644 index 0000000..c402473 --- /dev/null +++ b/recordmydesktop/src/rmd_load_cache.c @@ -0,0 +1,336 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include + +#include "rmd_types.h" + +#include "rmd_cache.h" +#include "rmd_encode_image_buffer.h" +#include "rmd_encode_sound_buffer.h" +#include "rmd_load_cache.h" +#include "rmd_macro.h" + + +//The number of bytes for every +//sub-block of the y,u and v planes. +//Since the blocks are square +//these are obviously the squares +//of the widths(specified above), +//but the definitions bellow are only +//for convenience anyway. +#define Y_UNIT_BYTES 0x0100 +#define UV_UNIT_BYTES 0x0040 + + +//The frame after retrieval. +//Based on the Header information +//we can read the correct amount of bytes. +typedef struct _CachedFrame{ + FrameHeader *header; + u_int32_t *YBlocks, //identifying number on the grid, + *UBlocks, //starting at top left + *VBlocks; // >> >> + unsigned char *YData, //pointer to data for the blocks that have changed, + *UData, //which have to be remapped + *VData; //on the buffer when reading +}CachedFrame; + + +static void LoadBlock(unsigned char *dest, + unsigned char *source, + int blockno, + int width, + int height, + int blockwidth) { + int j, + block_i=blockno/(width/blockwidth),//place on the grid + block_k=blockno%(width/blockwidth); + for(j=0;jheader->Ynum>0){ + if(ReadZF(frame->YBlocks, + index_entry_size, + frame->header->Ynum, + ucfp, + ifp)!=index_entry_size*frame->header->Ynum){ + return -1; + } + } + if(frame->header->Unum>0){ + if(ReadZF(frame->UBlocks, + index_entry_size, + frame->header->Unum, + ucfp, + ifp)!=index_entry_size*frame->header->Unum){ + return -1; + } + } + if(frame->header->Vnum>0){ + if(ReadZF(frame->VBlocks, + index_entry_size, + frame->header->Vnum, + ucfp, + ifp)!=index_entry_size*frame->header->Vnum){ + return -1; + } + } + if(frame->header->Ynum>0){ + if(ReadZF(frame->YData, + Y_UNIT_BYTES, + frame->header->Ynum, + ucfp, + ifp)!=Y_UNIT_BYTES*frame->header->Ynum){ + return -2; + } + } + if(frame->header->Unum>0){ + if(ReadZF(frame->UData, + UV_UNIT_BYTES, + frame->header->Unum, + ucfp, + ifp)!=UV_UNIT_BYTES*frame->header->Unum){ + return -2; + } + } + if(frame->header->Vnum>0){ + if(ReadZF(frame->VData, + UV_UNIT_BYTES, + frame->header->Vnum, + ucfp, + ifp)!=UV_UNIT_BYTES*frame->header->Vnum){ + return -2; + } + } + return 0; +} + +void *LoadCache(ProgData *pdata){ + + yuv_buffer *yuv=&pdata->enc_data->yuv; + gzFile *ifp=NULL; + FILE *ucfp=NULL; + FILE *afp=pdata->cache_data->afp; + FrameHeader fheader; + CachedFrame frame; + int j=0, + nth_cache=1, + audio_end=0, + extra_frames=0,//total number of duplicated frames + missing_frames=0,//if this is found >0 current run will not load + //a frame but it will proccess the previous + thread_exit=0,//0 success, -1 couldn't find files,1 couldn't remove + blocknum_x=pdata->enc_data->yuv.y_width/Y_UNIT_WIDTH, + blocknum_y=pdata->enc_data->yuv.y_height/Y_UNIT_WIDTH, + blockszy=Y_UNIT_BYTES,//size of y plane block in bytes + blockszuv=UV_UNIT_BYTES;//size of u,v plane blocks in bytes + signed char *sound_data=(signed char *)malloc(pdata->periodsize* + pdata->sound_framesize); + + u_int32_t YBlocks[(yuv->y_width*yuv->y_height)/Y_UNIT_BYTES], + UBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES], + VBlocks[(yuv->uv_width*yuv->uv_height)/UV_UNIT_BYTES]; + + // We allocate the frame that we will use + frame.header = &fheader; + frame.YBlocks = YBlocks; + frame.UBlocks = UBlocks; + frame.VBlocks = VBlocks; + frame.YData = malloc(yuv->y_width * yuv->y_height); + frame.UData = malloc(yuv->uv_width * yuv->uv_height); + frame.VData = malloc(yuv->uv_width * yuv->uv_height); + + //and the we open our files + if(!pdata->args.zerocompression){ + ifp=gzopen(pdata->cache_data->imgdata,"rb"); + if(ifp==NULL){ + thread_exit=-1; + pthread_exit(&thread_exit); + } + } + else{ + ucfp=fopen(pdata->cache_data->imgdata,"rb"); + if(ucfp==NULL){ + thread_exit=-1; + pthread_exit(&thread_exit); + } + } + + + if(!pdata->args.nosound){ + afp=fopen(pdata->cache_data->audiodata,"rb"); + if(afp==NULL){ + thread_exit=-1; + pthread_exit(&thread_exit); + } + } + + //this will be used now to define if we proccess audio or video + //on any given loop. + pdata->avd=0; + //If sound finishes first,we go on with the video. + //If video ends we will do one more run to flush audio in the ogg file + while(pdata->running){ + //video load and encoding + if(pdata->avd<=0 || pdata->args.nosound || audio_end){ + if(missing_frames>0){ + extra_frames++; + missing_frames--; + SyncEncodeImageBuffer(pdata); + } + else if(((!pdata->args.zerocompression)&& + (gzread(ifp,frame.header,sizeof(FrameHeader))== + sizeof(FrameHeader) ))|| + ((pdata->args.zerocompression)&& + (fread(frame.header,sizeof(FrameHeader),1,ucfp)==1))){ + //sync + missing_frames+=frame.header->current_total- + (extra_frames+frame.header->frameno); + if (pdata->frames_total) { + fprintf(stdout, + "\r[%d%%] ", + ((frame.header->frameno + extra_frames) * 100) / pdata->frames_total); + } + else + fprintf(stdout,"\r[%d frames rendered] ", + (frame.header->frameno+extra_frames)); + fflush(stdout); + if( (frame.header->Ynum<=blocknum_x*blocknum_y) && + (frame.header->Unum<=blocknum_x*blocknum_y) && + (frame.header->Vnum<=blocknum_x*blocknum_y) && + (!ReadFrame(&frame, + ((pdata->args.zerocompression)?ucfp:NULL), + ((pdata->args.zerocompression)?NULL:ifp))) + ){ + //load the blocks for each buffer + if(frame.header->Ynum) + for(j=0;jYnum;j++) + LoadBlock( yuv->y, + &frame.YData[j*blockszy], + frame.YBlocks[j], + yuv->y_width, + yuv->y_height, + Y_UNIT_WIDTH); + if(frame.header->Unum) + for(j=0;jUnum;j++) + LoadBlock( yuv->u, + &frame.UData[j*blockszuv], + frame.UBlocks[j], + yuv->uv_width, + yuv->uv_height, + UV_UNIT_WIDTH); + if(frame.header->Vnum) + for(j=0;jVnum;j++) + LoadBlock( yuv->v, + &frame.VData[j*blockszuv], + frame.VBlocks[j], + yuv->uv_width, + yuv->uv_height, + UV_UNIT_WIDTH); + //encode. This is not made in a thread since + //now blocking is not a problem + //and this way sync problems + //can be avoided more easily. + SyncEncodeImageBuffer(pdata); + } + else{ + raise(SIGINT); + continue; + } + } + else{ + if(SwapCacheFilesRead(pdata->cache_data->imgdata, + nth_cache, + &ifp, + &ucfp)){ + raise(SIGINT); + } + else{ + fprintf(stderr,"\t[Cache File %d]",nth_cache); + nth_cache++; + } + continue; + } + } + //audio load and encoding + else{ + if(!audio_end){ + int nbytes=fread(sound_data,1,pdata->periodsize* + pdata->sound_framesize,afp); + if(nbytes<=0) + audio_end=1; + else + SyncEncodeSoundBuffer(pdata,sound_data); + } + } + } + + pdata->v_encoding_clean=pdata->th_encoding_clean=1; + pthread_mutex_lock(&pdata->theora_lib_mutex); + pthread_cond_signal(&pdata->theora_lib_clean); + pthread_mutex_unlock(&pdata->theora_lib_mutex); + pthread_mutex_lock(&pdata->vorbis_lib_mutex); + pthread_cond_signal(&pdata->vorbis_lib_clean); + pthread_mutex_unlock(&pdata->vorbis_lib_mutex); + fprintf(stdout,"\n"); + + // Clear frame + free(frame.YData); + free(frame.UData); + free(frame.VData); + + free(sound_data); + + if(!pdata->args.nosound){ + fclose(afp); + } + + pthread_exit(&thread_exit); + + +} + diff --git a/recordmydesktop/src/rmd_load_cache.h b/recordmydesktop/src/rmd_load_cache.h new file mode 100644 index 0000000..055c720 --- /dev/null +++ b/recordmydesktop/src/rmd_load_cache.h @@ -0,0 +1,42 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef LOAD_CACHE +#define LOAD_CACHE 1 + +#include "rmd_types.h" + + +/** +* Cache loading and processing thread +* +* \param pdata ProgData struct containing all program data +* +*/ +void *LoadCache(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_macro.h b/recordmydesktop/src/rmd_macro.h new file mode 100644 index 0000000..78e6102 --- /dev/null +++ b/recordmydesktop/src/rmd_macro.h @@ -0,0 +1,111 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef RMDMACRO_H +#define RMDMACRO_H 1 + +#include "config.h" + +#include + +#include "rmd_types.h" + + +//define which way we are reading a pixmap +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define __ABYTE 3 +#define __RBYTE 2 +#define __GBYTE 1 +#define __BBYTE 0 + +#elif __BYTE_ORDER == __BIG_ENDIAN + +#define __ABYTE 0 +#define __RBYTE 1 +#define __GBYTE 2 +#define __BBYTE 3 + +#else +#error Only little-endian and big-endian systems are supported +#endif + +#define __RVALUE_32(tmp_val) (((tmp_val)&0x00ff0000)>>16) +#define __GVALUE_32(tmp_val) (((tmp_val)&0x0000ff00)>>8) +#define __BVALUE_32(tmp_val) (((tmp_val)&0x000000ff)) + +#define __R16_MASK 0xf800 +#define __G16_MASK 0x7e0 +#define __B16_MASK 0x1f + +#define __RVALUE_16(tmp_val) ((((tmp_val)&__R16_MASK)>>11)*8) +#define __GVALUE_16(tmp_val) ((((tmp_val)&__G16_MASK)>>5)*4) +#define __BVALUE_16(tmp_val) ((((tmp_val)&__B16_MASK))*8) + +//xfixes pointer data are written as unsigned long +//(even though the server returns CARD32) +//so we need to set the step accordingly to +//avoid problems (amd64 has 8byte ulong) +#define RMD_ULONG_SIZE_T (sizeof(unsigned long)) + +//size of stride when comparing planes(depending on type) +//this is just to avoid thousands of sizeof's +#ifdef HAVE_U_INT64_T + #define COMPARE_STRIDE 8 +#else + #define COMPARE_STRIDE 4 +#endif + +//The width, in bytes, of the blocks +//on which the y,u and v planes are broken. +//These blocks are square. +#define Y_UNIT_WIDTH 0x0010 +#define UV_UNIT_WIDTH 0x0008 + +#ifdef HAVE_LIBASOUND + #define DEFAULT_AUDIO_DEVICE "hw:0,0" +#else + #define DEFAULT_AUDIO_DEVICE "/dev/dsp" +#endif + +#define I16TOA(number,buffer){\ + int t_num=(number),__k=0,__i=0;\ + char *t_buf=malloc(8);\ + t_num=t_num&((2<<15)-1);\ + while(t_num>0){\ + int digit=t_num%10;\ + t_buf[__k]=digit+48;\ + t_num-=digit;\ + t_num/=10;\ + __k++;\ + }\ + while(__k>0)\ + (buffer)[__i++]=t_buf[--__k];\ + (buffer)[__i]='\0';\ + free(t_buf);\ +};\ + + +#endif diff --git a/recordmydesktop/src/rmd_make_dummy_pointer.c b/recordmydesktop/src/rmd_make_dummy_pointer.c new file mode 100644 index 0000000..e49178e --- /dev/null +++ b/recordmydesktop/src/rmd_make_dummy_pointer.c @@ -0,0 +1,93 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include "rmd_types.h" + +#include "rmd_macro.h" +#include "rmd_make_dummy_pointer.h" + + +unsigned char *MakeDummyPointer(DisplaySpecs *specs, + int size, + int color, + int type, + unsigned char *npxl){ + int i,k,o='.'; + unsigned long b=(color)?'w':'b', + w=(color)?'b':'w'; + char pmask[1][16][16]={{ + {w,w,o,o,o,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,w,o,o,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,w,o,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,w,o,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,w,o,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,b,w,o,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,b,b,w,o,o,o,o,o,o,o}, + {w,b,b,b,b,b,b,b,b,w,o,o,o,o,o,o}, + {w,b,b,b,b,b,w,w,w,w,o,o,o,o,o,o}, + {w,b,b,b,b,b,w,o,o,o,o,o,o,o,o,o}, + {w,b,b,w,w,b,b,w,o,o,o,o,o,o,o,o}, + {w,b,w,o,w,b,b,w,o,o,o,o,o,o,o,o}, + {w,w,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, + {o,o,o,o,o,w,b,b,w,o,o,o,o,o,o,o}, + {o,o,o,o,o,o,w,w,o,o,o,o,o,o,o,o}} + }; + unsigned char *ret=malloc(size*sizeof(char[size*4])); + unsigned char wp[4]={ + ((specs->wpixel^0xff000000)>>24), + ((specs->wpixel^0x00ff0000)>>16), + ((specs->wpixel^0x0000ff00)>>8), + ((specs->wpixel^0x000000ff)) + }; + unsigned char bp[4]={ + ((specs->bpixel^0xff000000)>>24), + ((specs->bpixel^0x00ff0000)>>16), + ((specs->bpixel^0x0000ff00)>>8), + ((specs->bpixel^0x000000ff)) + }; + *npxl=((wp[0]-1)!=bp[0])?wp[0]-100:wp[0]-102; + for(i=0;i +#include +#include +#include + +#ifdef HAVE_LIBASOUND + #include +#else + #include + #include +#endif + +#include "rmd_opendev.h" + +#ifdef HAVE_LIBASOUND + +snd_pcm_t *OpenDev( const char *pcm_dev, + unsigned int *channels, + unsigned int *frequency, + snd_pcm_uframes_t *buffsize, + snd_pcm_uframes_t *periodsize, + unsigned int *periodtime, + int *hard_pause){ + + snd_pcm_t *mhandle; + snd_pcm_hw_params_t *hwparams; + unsigned int periods=2; + unsigned int exactrate = *frequency; + + // The compiler might warn us because the expansion starts with + // assert(&hwparams) + snd_pcm_hw_params_alloca(&hwparams); + + if (snd_pcm_open(&mhandle,pcm_dev,SND_PCM_STREAM_CAPTURE,SND_PCM_ASYNC)<0){ + fprintf(stderr, "Couldn't open PCM device %s\n", pcm_dev); + return NULL; + } + else + fprintf(stderr, "Opened PCM device %s\n", pcm_dev); + if (snd_pcm_hw_params_any(mhandle, hwparams)<0){ + fprintf(stderr, "Couldn't configure PCM device.\n"); + return NULL; + } + if (snd_pcm_hw_params_set_access(mhandle, + hwparams, + SND_PCM_ACCESS_RW_INTERLEAVED)<0){ + fprintf(stderr, "Couldn't set access.\n"); + return NULL; + } + if (snd_pcm_hw_params_set_format(mhandle, + hwparams, + SND_PCM_FORMAT_S16_LE)<0){ + fprintf(stderr, "Couldn't set format.\n"); + return NULL; + } + if (snd_pcm_hw_params_set_rate_near(mhandle, hwparams, &exactrate, 0)<0){ + fprintf(stderr, "Couldn't set frequency.\n"); + return NULL; + } + if (*frequency != exactrate){ + fprintf(stderr, "Playback frequency %dHz is not available...\n" + "Using %dHz instead.\n",*frequency,exactrate); + *frequency=exactrate; + } + if (snd_pcm_hw_params_set_channels_near(mhandle, hwparams, channels)<0){ + fprintf(stderr, "Couldn't set channels number.\n"); + return NULL; + } + if(*channels>2){ + fprintf(stderr,"Channels number should be 1(mono) or 2(stereo).\n"); + return NULL; + } + if (snd_pcm_hw_params_set_periods_near(mhandle,hwparams,&periods,0)<0){ + fprintf(stderr, "Couldn't set periods.\n"); + return NULL; + } + + if (snd_pcm_hw_params_set_buffer_size_near(mhandle,hwparams,buffsize)<0){ + fprintf(stderr, "Couldn't set buffer size.\n"); + return NULL; + } + if (snd_pcm_hw_params(mhandle,hwparams)<0){ + fprintf(stderr, "Couldn't set hardware parameters.\n"); + return NULL; + } + if(hard_pause!=NULL) + if(!snd_pcm_hw_params_can_pause(hwparams)){ + *hard_pause=1; + } + if(periodsize!=NULL) + snd_pcm_hw_params_get_period_size(hwparams,periodsize,0); + + if(periodtime!=NULL) + 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); + snd_pcm_prepare(mhandle); + + return mhandle; +} + +#else + +int OpenDev( const char *pcm_dev, + unsigned int channels, + unsigned int frequency){ + int fd ; + fd=open(pcm_dev,O_RDONLY); + + if(fd!=-1){ + unsigned int value; + + if(ioctl(fd,SNDCTL_DSP_GETFMTS,&value)<0){ + fprintf(stderr,"Couldn't get audio format list\n"); + return -1; + } + if(value & AFMT_S16_LE){ + value=AFMT_S16_LE; + } + else if(value & AFMT_S16_BE){ + value=AFMT_S16_BE; + } + else{ + fprintf(stderr,"Soundcard doesn't support signed 16-bit-data\n"); + return -1; + } + if(ioctl(fd,SNDCTL_DSP_SETFMT,&value)<0){ + fprintf(stderr,"Couldn't set audio format\n" ); + return -1; + } + value = channels; + if(ioctl(fd,SNDCTL_DSP_CHANNELS,&value)<0){ + fprintf(stderr,"Cannot set the number of channels\n" ); + return -1; + } + value = frequency; + if(ioctl(fd,SNDCTL_DSP_SPEED,&value)<0){ + fprintf(stderr,"Couldn't set audio frequency\n" ); + return -1; + } + if(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NONBLOCK)<0){ + fprintf(stderr,"Couldn't set audio blocking mode\n" ); + return -1; + } + } + return fd; +} +#endif diff --git a/recordmydesktop/src/rmd_opendev.h b/recordmydesktop/src/rmd_opendev.h new file mode 100644 index 0000000..c782a02 --- /dev/null +++ b/recordmydesktop/src/rmd_opendev.h @@ -0,0 +1,84 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef OPENDEV_H +#define OPENDEV_H 1 + +#include "rmd_types.h" + + +#ifdef HAVE_LIBASOUND +/** +* Try to open (alsa) sound device, with the desired parameters, +* and place the obtained ones on their place +* +* \param pcm_dev name of the device +* +* \param channels desired number of channels +* (gets modified with the acieved value) +* +* \param frequency desired frequency(gets modified with the acieved value) +* +* \param buffsize Size of buffer +* +* \param periodsize Size of a period(can be NULL) +* +* \param periodtime Duration of a period(can be NULL) +* +* \param hardpause Set to 1 when the device has to be stopped during pause +* and to 0 when it supports pausing +* (can be NULL) +* +* \returns snd_pcm_t handle on success, NULL on failure +*/ +snd_pcm_t *OpenDev( const char *pcm_dev, + unsigned int *channels, + unsigned int *frequency, + snd_pcm_uframes_t *buffsize, + snd_pcm_uframes_t *periodsize, + unsigned int *periodtime, + int *hardpause); +#else +/** +* Try to open (OSS) sound device, with the desired parameters. +* +* +* \param pcm_dev name of the device +* +* \param channels desired number of channels +* +* \param frequency desired frequency +* +* +* \returns file descriptor of open device,-1 on failure +*/ +int OpenDev( const char *pcm_dev, + unsigned int channels, + unsigned int frequency); +#endif + + +#endif diff --git a/recordmydesktop/src/rmd_parseargs.c b/recordmydesktop/src/rmd_parseargs.c new file mode 100644 index 0000000..4fa1eac --- /dev/null +++ b/recordmydesktop/src/rmd_parseargs.c @@ -0,0 +1,586 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include "rmd_types.h" + +#include "rmd_macro.h" +#include "rmd_rescue.h" + + +static 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"); +} + +boolean ParseArgs(int argc, char **argv, ProgArgs *arg_return) { + int i; + char *usage="\nUsage:\n" + "\trecordmydesktop [OPTIONS]^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" + "\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" + "\t-display DISPLAY\tDisplay to connect to.\n" + "\t-x X\t\t\tOffset in x direction.\n" + "\t-y Y\t\t\tOffset in y direction.\n" + "\t-width N\t\tWidth of recorded window.\n" + "\t-height N\t\tHeight of recorded window.\n\n" + + "\t-dummy-cursor color\tColor of the dummy cursor [black|white]\n" + "\t--no-cursor\t\tDisable drawing of the cursor.\n" + "\t--no-shared\t\tDisable usage of" + " MIT-shared memory extension(Not Recommended!).\n" + + "\t--full-shots\t\tTake full screenshot at every frame(Not recomended!).\n" + "\t--quick-subsampling\tDo subsampling" + " of the chroma planes by discarding,not averaging.\n" + + "\t-fps N(number>0.0)\tA positive number denoting desired framerate.\n\n" + + "Sound Options:\n" + "\t-channels N\t\t\tA positive number denoting" + " desired sound channels in recording.\n" + + "\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,when using ALSA or OSS)\n" + "\t-ring-buffer-size N\t\tA float number denoting the desired" + " ring buffer size (in seconds,when using JACK only).\n" + + "\t-device SOUND_DEVICE\t\tSound device(default " + DEFAULT_AUDIO_DEVICE + ").\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" + "\t-v_quality n\t\tA number from 0 to 63 for" + " desired encoded video quality(default 63).\n" + + "\t-v_bitrate n\t\tA number from 45000 to 2000000" + " for desired encoded video bitrate(default 45000).\n" + + "\t-s_quality n\t\tDesired audio quality(-1 to 10).\n\n" + + "Misc Options:\n" + "\t-rescue path_to_data\tEncode data from a previous, crashed, session.\n" + "\t--no-wm-check\t\tDo not try to detect" + " the window manager(and set options according to it)\n" + + "\t-pause-shortcut MOD+KEY\tShortcut that will be used for (un)pausing" + "(default Control+Mod1+p).\n" + "\t-stop-shortcut MOD+KEY\tShortcut that will be used to stop the " + "recording (default Control+Mod1+s).\n" + + "\t--compress-cache\tImage data are cached with light compression.\n" + "\t-workdir DIR\t\tLocation where a temporary directory" + " will be created to hold project files(default $HOME).\n" + + "\t-delay n[H|h|M|m]\tNumber of secs(default),minutes or hours" + " before capture starts(number can be float)\n" + + "\t--overwrite\t\tIf there is already a file with the same name," + " delete it\n" + + "\t\t\t\t(default is to add a number postfix to the new one).\n" + "\t-o filename\t\tName of recorded video(default out.ogv).\n" + "\n\tIf no other options are specified, filename can be given " + "without the -o switch.\n\n\n"; + + if(argc==2){ + if(argv[1][0]!='-'){ + free(arg_return->filename); + arg_return->filename=malloc(strlen(argv[1])+1); + strcpy(arg_return->filename,argv[1]); + return TRUE; + } + } + for(i=1;i0.0){ + int k; + for(k=0;kdelay=(int)num; + } + else{ + fprintf(stderr,"Argument Usage: -delay n[H|h|M|m]\n" + "where n is a float number\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -delay n[H|h|M|m]\n" + "where n is a float number\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-windowid")){ + if(i+10) + arg_return->windowid=num; + else{ + fprintf(stderr,"Argument Usage:" + " -windowid id_of_window(number)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage:" + " -windowid id_of_window(number)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-display")){ + if(i+1display!=NULL) + free(arg_return->display); + arg_return->display=malloc(strlen(argv[i+1])+1); + strcpy(arg_return->display,argv[i+1]); + } + else{ + fprintf(stderr,"Argument Usage: -display DISPLAY\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-x")){ + if(i+10) + arg_return->x=num; + else{ + fprintf(stderr,"Argument Usage: -x X(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -x X(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-y")){ + if(i+10) + arg_return->y=num; + else{ + fprintf(stderr,"Argument Usage: -y Y(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -y Y(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-width")){ + if(i+10) + arg_return->width=num; + else{ + fprintf(stderr,"Argument Usage: -width N(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -width N(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-height")){ + if(i+10) + arg_return->height=num; + else{ + fprintf(stderr,"Argument Usage: -height N(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -height N(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-o")){ + if(i+1filename); + arg_return->filename=malloc(strlen(argv[i+1])+1); + strcpy(arg_return->filename,argv[i+1]); + } + else{ + fprintf(stderr,"Argument Usage: -o filename\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-fps")){ + if(i+10.0) + arg_return->fps=num; + else{ + fprintf(stderr,"Argument Usage: -fps N(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -fps N(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-v_quality")){ + if(i+1=0)&&(num<64)) + arg_return->v_quality=num; + else{ + fprintf(stderr,"Argument Usage:" + " -v_quality n(number 0-63)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage:" + " -v_quality n(number 0-63)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-v_bitrate")){ + if(i+1=45000)&&(num<=2000000)) + arg_return->v_bitrate=num; + else{ + fprintf(stderr,"Argument Usage:" + " -v_bitrate n(number 45000-2000000)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage:" + " -v_bitrate n(number 45000-2000000)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-dummy-cursor")){ + if(i+1cursor_color=0; + else if(!strcmp(argv[i+1],"black")) + arg_return->cursor_color=1; + else{ + fprintf(stderr,"Argument Usage:" + " -dummy-cursor [black|white]\n"); + return FALSE; + } + arg_return->have_dummy_cursor=1; + arg_return->xfixes_cursor=0; + } + else{ + fprintf(stderr,"Argument Usage:" + " -dummy-cursor [black|white]\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"--no-cursor")) + arg_return->xfixes_cursor=0; + else if(!strcmp(argv[i],"-freq")){ + if(i+10) + arg_return->frequency=num; + else{ + fprintf(stderr,"Argument Usage: -freq N(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -freq N(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-channels")){ + if(i+10) + arg_return->channels=num; + else{ + fprintf(stderr,"Argument Usage: -channels N(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -channels N(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-s_quality")){ + if(i+1=-1)&&(num<=10)) + arg_return->s_quality=num; + else{ + fprintf(stderr,"Argument Usage:" + " -s_quality n(number -1 to 10)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage:" + " -s_quality n(number -1 to 10)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-device")){ + if(i+1device); + arg_return->device=malloc(strlen(argv[i+1])+1); + strcpy(arg_return->device,argv[i+1]); + } + else{ + fprintf(stderr,"Argument Usage: -device SOUND_DEVICE\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-workdir")){ + if(i+1workdir); + arg_return->workdir=malloc(strlen(argv[i+1])+1); + strcpy(arg_return->workdir,argv[i+1]); + } + else{ + fprintf(stderr,"Argument Usage: -workdir DIR\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-pause-shortcut")){ + if(i+1pause_shortcut); + arg_return->pause_shortcut=malloc(strlen(argv[i+1])+1); + strcpy(arg_return->pause_shortcut,argv[i+1]); + } + else{ + fprintf(stderr,"Argument Usage: -pause-shortcut MOD+KEY\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-stop-shortcut")){ + if(i+1stop_shortcut); + arg_return->stop_shortcut=malloc(strlen(argv[i+1])+1); + strcpy(arg_return->stop_shortcut,argv[i+1]); + } + else{ + fprintf(stderr,"Argument Usage: -stop-shortcut MOD+KEY\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-buffer-size")){ + if(i+10) + arg_return->buffsize=num; + else{ + fprintf(stderr,"Argument Usage:" + " -buffer-size N(number>0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: -buffer-size N(number>0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-use-jack")){ + if(i+1jack_nports=0; + while((kjack_nports++; + k++; + } + if(arg_return->jack_nports>0){ + arg_return->jack_port_names=malloc(sizeof(char*)* + arg_return->jack_nports); + for(k=i+1;kjack_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 FALSE; + } +#else + fprintf(stderr,"recordMyDesktop is not compiled" + " with Jack support!\n"); + return FALSE; +#endif + } + else{ + fprintf(stderr,"Argument Usage: -use-jack port1" + " port2... portn\n"); + return FALSE; + } + } + else if(!strcmp(argv[i],"-ring-buffer-size")){ + if(i+10.0) + arg_return->jack_ringbuffer_secs=num; + else{ + fprintf(stderr,"Argument Usage: --ring-buffer-size" + " N(floating point number>0.0)\n"); + return FALSE; + } + } + else{ + fprintf(stderr,"Argument Usage: --ring-buffer-size" + " N(floating point number>0.0)\n"); + return FALSE; + } + i++; + } + else if(!strcmp(argv[i],"-rescue")){ + if(i+1nosound=1; + else if(!strcmp(argv[i],"--no-shared")){ + arg_return->noshared=1; + } + else if(!strcmp(argv[i],"--full-shots")){ + arg_return->full_shots=1; + } + else if(!strcmp(argv[i],"--no-frame")){ + arg_return->noframe=1; + } + else if(!strcmp(argv[i],"--follow-mouse")){ + arg_return->full_shots=1; + arg_return->follow_mouse=1; + } + else if(!strcmp(argv[i],"--no-encode")) + arg_return->no_encode=1; + else if(!strcmp(argv[i],"--quick-subsampling")){ + arg_return->no_quick_subsample=0; + } + else if(!strcmp(argv[i],"--on-the-fly-encoding")){ + arg_return->encOnTheFly=1; + } + else if(!strcmp(argv[i],"--overwrite")) + arg_return->overwrite=1; + else if(!strcmp(argv[i],"--no-wm-check")) + arg_return->nowmcheck=1; + else if(!strcmp(argv[i],"--compress-cache")){ + arg_return->zerocompression=0; + } + else if(!strcmp(argv[i],"--help")||!strcmp(argv[i],"-h")){ + fprintf(stderr,"%s",usage); + exit(0); + } + else if(!strcmp(argv[i],"--version")){ + fprintf(stderr,"recordMyDesktop v%s\n\n",VERSION); + exit(0); + } + else if(!strcmp(argv[i],"--print-config")){ + PrintConfig(); + exit(0); + } + else{ + fprintf(stderr,"\n\tError parsing arguments.\n\t" + "Type --help or -h for usage.\n\n"); + return FALSE; + } + } + + return TRUE; +} diff --git a/recordmydesktop/src/rmd_parseargs.h b/recordmydesktop/src/rmd_parseargs.h new file mode 100644 index 0000000..02c3966 --- /dev/null +++ b/recordmydesktop/src/rmd_parseargs.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef PARSEARGS_H +#define PARSEARGS_H 1 + +#include "rmd_types.h" + + +/** +* Fill ProgArgs struct with arguments entered at execution +* +* \param argc argc as entered from main +* +* \param argv argv as entered from main +* +* \param arg_return ProgArgs struct to be filled with the options +* +* \returns 0 on Success 1 on Failure +*/ +boolean ParseArgs(int argc, char **argv, ProgArgs *arg_return); + + +#endif diff --git a/recordmydesktop/src/rmd_poll_events.c b/recordmydesktop/src/rmd_poll_events.c new file mode 100644 index 0000000..bfe96c9 --- /dev/null +++ b/recordmydesktop/src/rmd_poll_events.c @@ -0,0 +1,208 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "rmd_frame.h" +#include "rmd_macro.h" +#include "rmd_poll_events.h" +#include "rmd_rectinsert.h" +#include "rmd_types.h" + + +#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)&&\ + ((e)->area.height<(brwin)->rgeom.height)){\ + (wgeom)->x=(brwin)->rgeom.x;\ + (wgeom)->y=(brwin)->rgeom.y;\ + (wgeom)->width=(brwin)->rgeom.width;\ + (wgeom)->height=(brwin)->rgeom.height;\ + }\ + else{\ + (wgeom)->x=((((e)->area.x+(e)->area.width>=(brwin)->rgeom.x)&&\ + ((e)->area.x<=(brwin)->rgeom.x+(brwin)->rgeom.width))?\ + (((e)->area.x<=(brwin)->rgeom.x)?(brwin)->rgeom.x:(e)->area.x):-1);\ + \ + (wgeom)->y=((((e)->area.y+(e)->area.height>=(brwin)->rgeom.y)&&\ + ((e)->area.y<=(brwin)->rgeom.y+(brwin)->rgeom.height))?\ + (((e)->area.y<=(brwin)->rgeom.y)?(brwin)->rgeom.y:(e)->area.y):-1);\ + \ + (wgeom)->width=((e)->area.x<=(brwin)->rgeom.x)?\ + (e)->area.width-((brwin)->rgeom.x-(e)->area.x):\ + ((e)->area.x<=(brwin)->rgeom.x+(brwin)->rgeom.width)?\ + (((brwin)->rgeom.width-(e)->area.x+(brwin)->rgeom.x<(e)->area.width)?\ + (brwin)->rgeom.width-(e)->area.x+(brwin)->rgeom.x:e->area.width):-1;\ + \ + (wgeom)->height=((e)->area.y<=(brwin)->rgeom.y)?\ + (e)->area.height-((brwin)->rgeom.y-(e)->area.y):\ + ((e)->area.y<=(brwin)->rgeom.y+(brwin)->rgeom.height)?\ + (((brwin)->rgeom.height-(e)->area.y+\ + (brwin)->rgeom.y<(e)->area.height)?\ + (brwin)->rgeom.height-(e)->area.y+\ + (brwin)->rgeom.y:(e)->area.height):-1;\ + \ + if((wgeom)->width>(brwin)->rgeom.width)\ + (wgeom)->width=(brwin)->rgeom.width;\ + if((wgeom)->height>(brwin)->rgeom.height)\ + (wgeom)->height=(brwin)->rgeom.height;\ + }\ +} + + +void InitEventsPolling(ProgData *pdata){ + Window root_return, + parent_return, + *children; + unsigned int i, + nchildren; + + + XSelectInput (pdata->dpy,pdata->specs.root, SubstructureNotifyMask); + + + if(!pdata->args.full_shots){ + XQueryTree (pdata->dpy, + pdata->specs.root, + &root_return, + &parent_return, + &children, + &nchildren); + + for (i = 0; i < nchildren; i++){ + XWindowAttributes attribs; + if (XGetWindowAttributes (pdata->dpy,children[i],&attribs)){ + if(!attribs.override_redirect && + attribs.depth==pdata->specs.depth) + XDamageCreate(pdata->dpy, + children[i], + XDamageReportRawRectangles); + } + } + XFree(children); + XDamageCreate(pdata->dpy, + pdata->specs.root, + XDamageReportRawRectangles); + } + + + +} + + +void EventLoop(ProgData *pdata){ + int inserts=0; + + XEvent event; + + while(XPending(pdata->dpy)){ + XNextEvent(pdata->dpy,&event); + if(event.type == KeyPress){ + XKeyEvent *e=(XKeyEvent *)(&event); + if(e->keycode == pdata->pause_key.key){ + int i=0; + int found=0; + for(i=0;ipause_key.modnum;i++){ + if(pdata->pause_key.mask[i]==e->state){ + found=1; + break; + } + } + if(found){ + raise(SIGUSR1); + continue; + } + } + if(e->keycode == pdata->stop_key.key){ + int i=0; + int found=0; + for(i=0;istop_key.modnum;i++){ + if(pdata->stop_key.mask[i]==e->state){ + found=1; + break; + } + } + if(found){ + raise(SIGINT); + continue; + } + } + } + else if(event.type == Expose){ + + if(event.xexpose.count!=0) + continue; + else if(!pdata->args.noframe){ + rmdDrawFrame(pdata->dpy, + pdata->specs.screen, + pdata->shaped_w, + pdata->brwin.rgeom.width, + pdata->brwin.rgeom.height); + + } + + } + else if(!pdata->args.full_shots){ + if(event.type == MapNotify ){ + XWindowAttributes attribs; + if (!((XMapEvent *)(&event))->override_redirect&& + XGetWindowAttributes(pdata->dpy, + event.xcreatewindow.window, + &attribs)){ + if(!attribs.override_redirect&& + attribs.depth==pdata->specs.depth) + XDamageCreate(pdata->dpy, + event.xcreatewindow.window, + XDamageReportRawRectangles); + } + } + else if(event.type == pdata->damage_event + XDamageNotify ){ + XDamageNotifyEvent *e =(XDamageNotifyEvent *)( &event ); + WGeometry wgeom; + CLIP_EVENT_AREA(e,&(pdata->brwin),&wgeom); + if((wgeom.x>=0)&&(wgeom.y>=0)&& + (wgeom.width>0)&&(wgeom.height>0)){ + + inserts+=RectInsert(&pdata->rect_root,&wgeom); + + } + } + } + + } + + +} + + diff --git a/recordmydesktop/src/rmd_poll_events.h b/recordmydesktop/src/rmd_poll_events.h new file mode 100644 index 0000000..b0418b9 --- /dev/null +++ b/recordmydesktop/src/rmd_poll_events.h @@ -0,0 +1,49 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef POLL_EVENTS_H +#define POLL_EVENTS_H 1 + +#include "rmd_types.h" + + +/** +* Start listening to damage and substructure notify events +* (needed before EventLoop call) +* \param pdata ProgData struct containing all program data +*/ +void InitEventsPolling(ProgData *pdata); + +/** +* Loop calling XNextEvent.Retrieve and place on +* list damage events that arive, create damage for new windows +* and pickup key events for shortcuts. +* \param pdata ProgData struct containing all program data +*/ +void EventLoop(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_queryextensions.c b/recordmydesktop/src/rmd_queryextensions.c new file mode 100644 index 0000000..cc9c69c --- /dev/null +++ b/recordmydesktop/src/rmd_queryextensions.c @@ -0,0 +1,83 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include + +#include "rmd_types.h" + +#include "rmd_queryextensions.h" + + +void QueryExtensions(Display *dpy, + ProgArgs *args, + int *damage_event, + int *damage_error, + int *shm_opcode){ + int xf_event_basep, + xf_error_basep, + shm_event_base, + shm_error_base, + shape_event_base, + shape_error_base; + + if((!(args->full_shots))&&(!XDamageQueryExtension( dpy, damage_event, damage_error))){ + fprintf(stderr,"XDamage extension not found!!!\n" + "Try again using the --full-shots option, though\n" + "enabling XDamage is highly recommended,\n" + "for performance reasons.\n"); + exit(4); + } + if((!args->noshared)&&(!XQueryExtension(dpy, + "MIT-SHM", + shm_opcode, + &shm_event_base, + &shm_error_base))){ + args->noshared=1; + fprintf(stderr,"Shared Memory extension not present!\n" + "Try again using the --no-shared option\n"); + exit(5); + } + if((args->xfixes_cursor)&& + (XFixesQueryExtension(dpy,&xf_event_basep,&xf_error_basep)==False)){ + args->xfixes_cursor=0; + fprintf(stderr,"Xfixes extension not present!\n" + "Please run with the -dummy-cursor or" + " --no-cursor option.\n"); + exit(6); + } + if((!args->noframe)&& + (!XShapeQueryExtension(dpy,&shape_event_base,&shape_error_base))){ + fprintf(stderr,"XShape Not Found!!!\n" + "Frame won't be available.\n"); + + args->noframe=1; + } + +} diff --git a/recordmydesktop/src/rmd_queryextensions.h b/recordmydesktop/src/rmd_queryextensions.h new file mode 100644 index 0000000..578bd73 --- /dev/null +++ b/recordmydesktop/src/rmd_queryextensions.h @@ -0,0 +1,53 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef QUERYEXTENSIONS_H +#define QUERYEXTENSIONS_H 1 + +#include "rmd_types.h" + + +/** +* Check if needed extensions are present +* +* \param dpy Connection to the server +* +* \param args ProgArgs struct containing the user-set options +* +* \param damage_event gets filled with damage event number +* +* \param damage_error gets filled with damage error number +* +* \note Can be an exit point if extensions are not found +*/ +void QueryExtensions(Display *dpy, + ProgArgs *args, + int *damage_event, + int *damage_error, + int *shm_opcode); + + +#endif diff --git a/recordmydesktop/src/rmd_rectinsert.c b/recordmydesktop/src/rmd_rectinsert.c new file mode 100644 index 0000000..df43e15 --- /dev/null +++ b/recordmydesktop/src/rmd_rectinsert.c @@ -0,0 +1,535 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include "rmd_rectinsert.h" +#include "rmd_types.h" + + +/** +* Collide two rectangles and dictate most sane action for insertion, +* as well as provide the updated rectangle(s) +* \param wgeom1 resident rectangle +* +* \param wgeom2 New rectangle +* +* \param wgeom_return Pointer to rectangles to be inserted +* +* \param ngeoms number of entries in wgeom_return +* +* \retval 0 No collision +* +* \retval 1 wgeom1 is covered by wgeom2 +* +* \retval 2 wgeom2 is covered by wgeom1 +* +* \retval -1 wgeom1 was broken (new is picked up in wgeom_return) +* +* \retval -2 wgeom2 was broken (new is picked up in wgeom_return) +* +* \retval -10 Grouping the two geoms is possible +* +*/ +static int CollideRects(WGeometry *wgeom1, + WGeometry *wgeom2, + WGeometry **wgeom_return, + int *ngeoms) { + //1 fits in 2 + if((wgeom1->x>=wgeom2->x)&& + (wgeom1->x+wgeom1->width<=wgeom2->x+wgeom2->width)&& + (wgeom1->y>=wgeom2->y)&& + (wgeom1->y+wgeom1->height<=wgeom2->y+wgeom2->height)){ + *ngeoms=0; + return 1; + } + //2 fits in 1 + else if((wgeom2->x>=wgeom1->x)&& + (wgeom2->x+wgeom2->width<=wgeom1->x+wgeom1->width)&& + (wgeom2->y>=wgeom1->y)&& + (wgeom2->y+wgeom2->height<=wgeom1->y+wgeom1->height)){ + *ngeoms=0; + return 2; + } + //no collision + else if((wgeom1->x+wgeom1->widthx)|| + (wgeom2->x+wgeom2->widthx)|| + (wgeom1->y+wgeom1->heighty)|| + (wgeom2->y+wgeom2->heighty)){ + *ngeoms=0; + return 0; + } + else{ +//overlapping points are considered enclosed +//this happens because libxdamage may generate many events for one change +//and some of them may be in the the exact same region +//so identical rects would be considered not colliding +//in order though to avoid endless recursion on the RectInsert +//function should always start at the next element(which is logical since +//if any rect makes it to a points none of it's part collides with previous +//nodes on the list, too) + int x1[2]={wgeom1->x,wgeom1->x+wgeom1->width}; + int y1[2]={wgeom1->y,wgeom1->y+wgeom1->height}; + int x2[2]={wgeom2->x,wgeom2->x+wgeom2->width}; + int y2[2]={wgeom2->y,wgeom2->y+wgeom2->height}; + int enclosed[2][4],tot1,tot2; + enclosed[0][0]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& + (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); + enclosed[0][1]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& + (y1[0]>=y2[0])&&(y1[0]<=y2[1]))?1:0); + enclosed[0][2]=(((x1[0]>=x2[0])&&(x1[0]<=x2[1])&& + (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); + enclosed[0][3]=(((x1[1]>=x2[0])&&(x1[1]<=x2[1])&& + (y1[1]>=y2[0])&&(y1[1]<=y2[1]))?1:0); + enclosed[1][0]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& + (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); + enclosed[1][1]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& + (y2[0]>=y1[0])&&(y2[0]<=y1[1]))?1:0); + enclosed[1][2]=(((x2[0]>=x1[0])&&(x2[0]<=x1[1])&& + (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); + enclosed[1][3]=(((x2[1]>=x1[0])&&(x2[1]<=x1[1])&& + (y2[1]>=y1[0])&&(y2[1]<=y1[1]))?1:0); + tot1=enclosed[0][0]+enclosed[0][1]+enclosed[0][2]+enclosed[0][3]; + tot2=enclosed[1][0]+enclosed[1][1]+enclosed[1][2]+enclosed[1][3]; + if((tot1==2)&&(tot2==2)){//same width or height, which is the best case + //group + if((enclosed[1][0]&&enclosed[1][1])&& + (wgeom1->width==wgeom2->width)){ + wgeom_return[0]=(WGeometry *)malloc(sizeof(WGeometry)); + *ngeoms=1; + wgeom_return[0]->x=wgeom1->x; + wgeom_return[0]->y=wgeom1->y; + wgeom_return[0]->width=wgeom1->width; + wgeom_return[0]->height=wgeom2->height+wgeom2->y-wgeom1->y; + return -10; + } + else if((enclosed[1][0]&&enclosed[1][2])&& + (wgeom1->height==wgeom2->height)){ + *ngeoms=1; + wgeom_return[0]->x=wgeom1->x; + wgeom_return[0]->y=wgeom1->y; + wgeom_return[0]->width=wgeom2->width+wgeom2->x-wgeom1->x; + wgeom_return[0]->height=wgeom1->height; + return -10; + } + else if((enclosed[1][3]&&enclosed[1][1])&& + (wgeom1->height==wgeom2->height)){ + *ngeoms=1; + wgeom_return[0]->x=wgeom2->x; + wgeom_return[0]->y=wgeom2->y; + wgeom_return[0]->width=wgeom1->width+wgeom1->x-wgeom2->x; + wgeom_return[0]->height=wgeom2->height; + return -10; + } + else if((enclosed[1][3]&&enclosed[1][2])&& + (wgeom1->width==wgeom2->width)){ + *ngeoms=1; + wgeom_return[0]->x=wgeom2->x; + wgeom_return[0]->y=wgeom2->y; + wgeom_return[0]->width=wgeom2->width; + wgeom_return[0]->height=wgeom1->height+wgeom1->y-wgeom2->y; + return -10; + } + //if control reaches here therewasn't a group and we go on + } + if(tot2==2){ + //break geom2 + wgeom_return[0]->x=wgeom2->x; + wgeom_return[0]->y=wgeom2->y; + wgeom_return[0]->width=wgeom2->width; + wgeom_return[0]->height=wgeom2->height; + *ngeoms=1; + if(enclosed[1][0]&&enclosed[1][1]){ + wgeom_return[0]->y=y1[1]; + wgeom_return[0]->height-=y1[1]-y2[0]; + } + else if(enclosed[1][0]&&enclosed[1][2]){ + wgeom_return[0]->x=x1[1]; + wgeom_return[0]->width-=x1[1]-x2[0]; + } + else if(enclosed[1][3]&&enclosed[1][1]) + wgeom_return[0]->width-=x2[1]-x1[0]; + else if(enclosed[1][3]&&enclosed[1][2]) + wgeom_return[0]->height-=y2[1]-y1[0]; + return -2; + } + else if(tot1==2){ + //if the first one breaks(which is already inserted) + //then we reenter the part that was left and the one + //that was to be inserted + wgeom_return[1]->x=wgeom2->x; + wgeom_return[1]->y=wgeom2->y; + wgeom_return[1]->width=wgeom2->width; + wgeom_return[1]->height=wgeom2->height; + wgeom_return[0]->x=wgeom1->x; + wgeom_return[0]->y=wgeom1->y; + wgeom_return[0]->width=wgeom1->width; + wgeom_return[0]->height=wgeom1->height; + *ngeoms=1; + if(enclosed[0][0]&&enclosed[0][1]){ + wgeom_return[0]->y=y2[1]; + wgeom_return[0]->height-=y2[1]-y1[0]; + } + else if(enclosed[0][0]&&enclosed[0][2]){ + wgeom_return[0]->x=x2[1]; + wgeom_return[0]->width-=x2[1]-x1[0]; + } + else if(enclosed[0][3]&&enclosed[0][1]) + wgeom_return[0]->width-=x1[1]-x2[0]; + else if(enclosed[0][3]&&enclosed[0][2]) + wgeom_return[0]->height-=y1[1]-y2[0]; + return -1; + + } + else if(tot2==1){ //in which case there is also tot1==1 + //but we rather not break that + //break geom2 in two + *ngeoms=2; + if(enclosed[1][0]){ +//first + wgeom_return[0]->x=x1[1]; + wgeom_return[0]->y=y2[0]; + wgeom_return[0]->width=wgeom2->width-x1[1]+x2[0]; + wgeom_return[0]->height=wgeom2->height; +//second + wgeom_return[1]->x=x2[0]; + wgeom_return[1]->y=y1[1]; + wgeom_return[1]->width=x1[1]-x2[0]; + wgeom_return[1]->height=wgeom2->height-y1[1]+y2[0]; + } + else if(enclosed[1][1]){ +//first + wgeom_return[0]->x=x2[0]; + wgeom_return[0]->y=y2[0]; + wgeom_return[0]->width=wgeom2->width-x2[1]+x1[0]; + wgeom_return[0]->height=wgeom2->height; +//second + wgeom_return[1]->x=x1[0]; + wgeom_return[1]->y=y1[1]; + wgeom_return[1]->width=x2[1]-x1[0]; + wgeom_return[1]->height=wgeom2->height-y1[1]+y2[0]; + } + else if(enclosed[1][2]){ +//first(same as [1][0]) + wgeom_return[0]->x=x1[1]; + wgeom_return[0]->y=y2[0]; + wgeom_return[0]->width=wgeom2->width-x1[1]+x2[0]; + wgeom_return[0]->height=wgeom2->height; +//second + wgeom_return[1]->x=x2[0]; + wgeom_return[1]->y=y2[0]; + wgeom_return[1]->width=x1[1]-x2[0]; + wgeom_return[1]->height=wgeom2->height-y2[1]+y1[0]; + } + else if(enclosed[1][3]){ +//first(same as [1][1]) + wgeom_return[0]->x=x2[0]; + wgeom_return[0]->y=y2[0]; + wgeom_return[0]->width=wgeom2->width-x2[1]+x1[0]; + wgeom_return[0]->height=wgeom2->height; +//second + wgeom_return[1]->x=x1[0]; + wgeom_return[1]->y=y2[0]; + wgeom_return[1]->width=x2[1]-x1[0]; + wgeom_return[1]->height=wgeom2->height-y2[1]+y1[0]; + } + return -2; + } + else{//polygons collide but no point of one is in the other + //so we just keep the two parts of geom2 that are outside geom1 + + //break geom2 in two + //two cases: + //geom2 crossing vertically geom1 + //and geom2 crossing horizontally geom1 + //The proper one can be found by simply checking x,y positions + *ngeoms=2; + if(wgeom2->yy){ + //common + wgeom_return[0]->x=wgeom_return[1]->x=x2[0]; + wgeom_return[0]->width=wgeom_return[1]->width=wgeom2->width; + + wgeom_return[0]->y=y2[0]; + wgeom_return[0]->height=wgeom2->height-y2[1]+y1[0]; + wgeom_return[1]->y=y1[1]; + wgeom_return[1]->height=y2[1]-y1[1]; + } + else{ + //common + wgeom_return[0]->y=wgeom_return[1]->y=y2[0]; + wgeom_return[0]->height=wgeom_return[1]->height=wgeom2->height; + + wgeom_return[0]->x=x2[0]; + wgeom_return[0]->width=wgeom2->width-x2[1]+x1[0]; + wgeom_return[1]->x=x1[1]; + wgeom_return[1]->width=x2[1]-x1[1]; + } + return -2; + } + } +} + +int RectInsert(RectArea **root,WGeometry *wgeom){ + + int total_insertions=0; + RectArea *temp=NULL,*newnode=(RectArea *)malloc(sizeof(RectArea)); + //align + //we do need to know boundaries + wgeom->width+=(wgeom->width%2)|(wgeom->x%2); + wgeom->height+=(wgeom->height%2)|(wgeom->y%2); + wgeom->width+=(wgeom->width%2); + wgeom->height+=(wgeom->height%2); + wgeom->x-=wgeom->x%2; + wgeom->y-=wgeom->y%2; +// fprintf(stderr," %d %d %d %d\n",wgeom->x, + + newnode->geom.x=wgeom->x; + newnode->geom.y=wgeom->y; + newnode->geom.width=wgeom->width; + newnode->geom.height=wgeom->height; + newnode->prev=newnode->next=NULL; + if(*root==NULL){ + *root=newnode; + total_insertions=1; + } + else{ + WGeometry *wgeom_return[2]; + wgeom_return[0]=(WGeometry *)malloc(sizeof(WGeometry)); + wgeom_return[1]=(WGeometry *)malloc(sizeof(WGeometry)); + + int ngeoms=0,insert_ok=1,i=0; + temp=*root; + while(insert_ok){ //if something is broken list does not procceed + //(except on -1 collres case) + int collres=CollideRects(&(temp->geom),wgeom,wgeom_return,&ngeoms); + if((!collres)) + insert_ok=1; + else{ + for(i=0;iwidth+=(wgeom_return[i]->width%2)| + (wgeom_return[i]->x%2); + wgeom_return[i]->height+=(wgeom_return[i]->height%2)| + (wgeom_return[i]->y%2); + wgeom_return[i]->width+=(wgeom_return[i]->width%2); + wgeom_return[i]->height+=(wgeom_return[i]->height%2); + wgeom_return[i]->x-=wgeom_return[i]->x%2; + wgeom_return[i]->y-=wgeom_return[i]->y%2; + } + insert_ok=0; + switch(collres){ + case 1://remove current node,reinsert new one + total_insertions--; + if(temp->prev!=NULL){//no root + if(temp->next!=NULL){// + RectArea *temp1=temp->next; + temp->prev->next=temp->next; + temp->next->prev=temp->prev; + free(temp); + if((wgeom->width>0)&&(wgeom->height>0)) + total_insertions+=RectInsert(&temp1,wgeom); + } + else{ + temp->prev->next=newnode; + newnode->prev=temp->prev; + total_insertions++; + free(temp); + } + } + else{//root + if((*root)->next!=NULL){ + (*root)=(*root)->next; + (*root)->prev=NULL; + if((wgeom->width>0)&&(wgeom->height>0)) + total_insertions+=RectInsert(root,wgeom); + } + else if((wgeom->width>0)&&(wgeom->height>0)){ + *root=newnode; + total_insertions++; + } + else{ + *root=NULL; + total_insertions++; + } + free(temp); + } + break; + case 2://done,area is already covered + free(newnode); + break; + case -1://current node is broken and reinserted + //(in same pos) + //newnode is also reinserted + if((wgeom_return[0]->width>0)&& + (wgeom_return[0]->height>0)){ + temp->geom.x=wgeom_return[0]->x; + temp->geom.y=wgeom_return[0]->y; + temp->geom.width=wgeom_return[0]->width; + temp->geom.height=wgeom_return[0]->height; + if(temp->next==NULL){ + temp->next=newnode; + newnode->prev=temp; + total_insertions++; + } + else{ + insert_ok=1; + } + } + else{//it might happen that the old and now broken node + //is of zero width or height + //(so it isn't reinserted) + if((temp->prev==NULL)&&(temp->next!=NULL)){ + *root=(*root)->next; + (*root)->prev=NULL; + } + else if((temp->next==NULL)&&(temp->prev!=NULL)){ + temp->prev->next=newnode; + newnode->prev=temp->prev; + } + else if((temp->next==NULL)&&(temp->prev==NULL)) + (*root)=newnode; + else{ + total_insertions--; + temp->next->prev=temp->prev; + temp->prev->next=temp->next; + total_insertions+=RectInsert(&temp->next, + wgeom); + } + free(temp); + } + break; + case -2://new is broken and reinserted + if(temp->next==NULL){ + total_insertions+=ngeoms; + newnode->geom.x=wgeom_return[0]->x; + newnode->geom.y=wgeom_return[0]->y; + newnode->geom.width=wgeom_return[0]->width; + newnode->geom.height=wgeom_return[0]->height; + temp->next=newnode; + newnode->prev=temp; + if(ngeoms>1){ + RectArea *newnode1= + (RectArea *)malloc(sizeof(RectArea)); + + newnode1->geom.x=wgeom_return[1]->x; + newnode1->geom.y=wgeom_return[1]->y; + newnode1->geom.width=wgeom_return[1]->width; + newnode1->geom.height=wgeom_return[1]->height; + newnode->next=newnode1; + newnode1->prev=newnode; + newnode1->next=NULL; + } + } + else{ + for(i=0;iwidth>0)&& + (wgeom_return[i]->height>0)) + total_insertions+= + RectInsert(&temp->next,wgeom_return[i]); + } + } + break; + case -10://grouped + if(temp->prev==NULL){ + if(temp->next==NULL){//empty list + newnode->geom.x=wgeom_return[0]->x; + newnode->geom.y=wgeom_return[0]->y; + newnode->geom.width=wgeom_return[0]->width; + newnode->geom.height= + wgeom_return[0]->height; + + *root=newnode; + free(temp); + } + else{ + total_insertions--; + *root=temp->next; + (*root)->prev=NULL; + free(temp); + if((wgeom_return[0]->width>0)&& + (wgeom_return[0]->height>0)) + total_insertions+= + RectInsert(root,wgeom_return[0]); + } + } + else if(temp->next==NULL){//last, enter anyway + newnode->geom.x=wgeom_return[0]->x; + newnode->geom.y=wgeom_return[0]->y; + newnode->geom.width=wgeom_return[0]->width; + newnode->geom.height=wgeom_return[0]->height; + temp->prev->next=newnode; + newnode->prev=temp->prev; + free(temp); + } + else{//remove node and reinsert, starting where we were + total_insertions--; + RectArea *temp1=temp->next; + temp->prev->next=temp->next; + temp->next->prev=temp->prev; + free(temp); + if((wgeom_return[0]->width>0)&& + (wgeom_return[0]->height>0)) + total_insertions+= + RectInsert(&temp1,wgeom_return[0]); + } + break; + } + } + if(insert_ok){ + if(temp->next==NULL){ + temp->next=newnode; + newnode->prev=temp; + total_insertions++; + break; + } + else{ + temp=temp->next; + } + } + else{ + break; + } + }; + + free(wgeom_return[0]); + free(wgeom_return[1]); + } + return total_insertions; +} + +void ClearList(RectArea **root){ + + RectArea *temp; + temp=*root; + if(temp!=NULL){ + while(temp->next!=NULL){ + temp=temp->next; + free(temp->prev); + + } + free(temp); + *root=NULL; + } +} diff --git a/recordmydesktop/src/rmd_rectinsert.h b/recordmydesktop/src/rmd_rectinsert.h new file mode 100644 index 0000000..6f93cb6 --- /dev/null +++ b/recordmydesktop/src/rmd_rectinsert.h @@ -0,0 +1,55 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef RECTINSERT_H +#define RECTINSERT_H 1 + + +#include "rmd_types.h" + + +/** +* Insert a new rectangle on the list, making sure it doesn't overlap +* with the existing ones +* \param root Root entry of the list +* +* \param wgeom New area to be inserted +* +* \returns Number of insertions during operation +* +* \note This function is reentrant and recursive. The number +* of insertions takes this into account. +*/ +int RectInsert(RectArea **root, WGeometry *wgeom); + +/** +* Clean up a list of areas marked for update. +* \param root Root entry of the list +*/ +void ClearList(RectArea **root); + + +#endif diff --git a/recordmydesktop/src/rmd_register_callbacks.c b/recordmydesktop/src/rmd_register_callbacks.c new file mode 100644 index 0000000..6291825 --- /dev/null +++ b/recordmydesktop/src/rmd_register_callbacks.c @@ -0,0 +1,87 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_register_callbacks.h" + + +// There seem to be no way of passing user data to the signal handler, +// so hack around not being able to pass ProgData to them +static int *pdata_running = NULL; +static int *pdata_paused = NULL; +static int *pdata_aborted = NULL; +static int *pdata_pause_state_changed = NULL; + + +static void SetPaused(int signum) { + + *pdata_pause_state_changed = TRUE; +} + +static void SetRunning(int signum) { + + if (!*pdata_paused) { + + *pdata_running = FALSE; + + if (signum == SIGABRT) { + *pdata_aborted = TRUE; + } + } +} + +void RegisterCallbacks(ProgData *pdata) { + + struct sigaction pause_act; + struct sigaction end_act; + + // Is there some way to pass pdata to the signal handlers? + pdata_running = &pdata->running; + pdata_paused = &pdata->paused; + pdata_aborted = &pdata->aborted; + pdata_pause_state_changed = &pdata->pause_state_changed; + + // Setup pause_act + sigfillset(&pause_act.sa_mask); + pause_act.sa_flags = SA_RESTART; + pause_act.sa_handler = SetPaused; + + sigaction(SIGUSR1, &pause_act, NULL); + + // Setup end_act + sigfillset(&end_act.sa_mask); + end_act.sa_flags = SA_RESTART; + end_act.sa_handler = SetRunning; + + sigaction(SIGINT, &end_act, NULL); + sigaction(SIGTERM, &end_act, NULL); + sigaction(SIGABRT, &end_act, NULL); +} diff --git a/recordmydesktop/src/rmd_register_callbacks.h b/recordmydesktop/src/rmd_register_callbacks.h new file mode 100644 index 0000000..b1e41e2 --- /dev/null +++ b/recordmydesktop/src/rmd_register_callbacks.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef REGISTER_CALLBACKS_H +#define REGISTER_CALLBACKS_H 1 + + +#include "rmd_types.h" + + +/** +* Set up all callbacks and signal handlers +* \param pdata ProgData struct containing all program data +*/ +void RegisterCallbacks(ProgData *prog_data); + + +#endif diff --git a/recordmydesktop/src/rmd_rescue.c b/recordmydesktop/src/rmd_rescue.c index 783636f..b017e92 100644 --- a/recordmydesktop/src/rmd_rescue.c +++ b/recordmydesktop/src/rmd_rescue.c @@ -28,14 +28,14 @@ #include -#include "rmdtypes.h" +#include "rmd_types.h" -#include "block_utils.h" -#include "encode_cache.h" -#include "initialize_data.h" -#include "register_callbacks.h" +#include "rmd_block_utils.h" +#include "rmd_encode_cache.h" +#include "rmd_initialize_data.h" +#include "rmd_register_callbacks.h" #include "rmd_rescue.h" -#include "specsfile.h" +#include "rmd_specsfile.h" int rmdRescue(const char *path){ diff --git a/recordmydesktop/src/rmd_setbrwindow.c b/recordmydesktop/src/rmd_setbrwindow.c new file mode 100644 index 0000000..17b77bb --- /dev/null +++ b/recordmydesktop/src/rmd_setbrwindow.c @@ -0,0 +1,213 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include "rmd_types.h" + +#include "rmd_setbrwindow.h" + + +/** +*Align the recording window to a divisible by 2 pixel start and +*and a size divisible by 16. +* +* \param start x or y of the recording window +* +* \param size width or height of the recording window +* +* \param limit width or height of the Display +* +* \note This is called separately for width and height. +*/ +static void SizePack2_8_16(int *start, int *size, int limit) { + int octoffset,hexoffset; + + //align in two + //an odd x can always go down and still be in recording area. + //Resolutions come in even numbers + //so if x is an odd numer, width max is an odd number, too + //thus since x will go down one then width can go up one too and still + //be inbounds + (*size)+=((*size)%2)|((*start)%2); + //but if x goes down 1 and width is already even,it becomes odd so: + (*size)+=((*size)%2); + (*start)-=(*start)%2; + + + //32 bit pack align + //we already have disible by two width,so + //it's 2, 4 or 6 + octoffset=((*size)%8); + if(octoffset==2){ + (*size)-=2; + + } + else if(octoffset==6){ + if((*size)+(*start)+2<=limit) + (*size)+=2; + else if((*start)>=2){ + (*start)-=2; + (*size)+=2; + } + else{ + (*start)+=2; + (*size)-=4; + } + } + + else if(octoffset==4){ + if(((*size)+(*start)+2<=limit)&&((*start)>=2)){ + (*start)-=2; + (*size)+=4; + } + else if((*size)+(*start)+4<=limit){ + (*size)+=4; + } + else if((*start)>=4){ + (*start)-=4; + (*size)+=4; + } + else{ + (*start)+=2; + (*size)-=4; + } + } + + //16 divisble width(needed for shared memory only, + //but applied anyway since theora wants it, too) + //we already have divisibility by 8 so module + //by 16 is euther 8 or 0 + hexoffset=((*size)%16); + if(hexoffset){ + if(((*size)+(*start)+4<=limit)&&((*start)>=4)){ + (*start)-=4; + (*size)+=8; + } + else if((*size)+(*start)+8<=limit){ + (*size)+=8; + } + else if((*start)>=8){ + (*start)-=8; + (*size)+=8; + } + else{ + (*start)+=4; + (*size)-=8; + } + } + +} + + + +int SetBRWindow(Display *dpy, + BRWindow *brwin, + DisplaySpecs *specs, + ProgArgs *args){ + //before we start recording we have to make sure the ranges are valid + if(args->windowid==0){//root window + //first set it up + brwin->windowid=specs->root; + brwin->geom.x=brwin->geom.y=0; + brwin->geom.width=specs->width; + brwin->geom.height=specs->height; + brwin->rgeom.x=args->x; + brwin->rgeom.y=args->y; + brwin->rgeom.width=((args->width)? + args->width:specs->width-brwin->rgeom.x); + brwin->rgeom.height=((args->height)? + args->height:specs->height-brwin->rgeom.y); + //and then check validity + if((brwin->rgeom.x+brwin->rgeom.width>specs->width)|| + (brwin->rgeom.y+brwin->rgeom.height>specs->height)){ + fprintf(stderr,"Window size specification out of bounds!" + "(current resolution:%dx%d)\n", + specs->width,specs->height); + return 1; + } + } + else{ + Window wchid; + int transl_x,transl_y; + + XWindowAttributes attribs; + XGetWindowAttributes(dpy,args->windowid,&attribs); + if((attribs.map_state==IsUnviewable)||(attribs.map_state==IsUnmapped)){ + fprintf(stderr,"Window must be mapped and visible!\n"); + return 1; + } + XTranslateCoordinates(dpy, + specs->root, + args->windowid, + attribs.x, + attribs.y, + &transl_x, + &transl_y, + &wchid); + + brwin->geom.x=attribs.x-transl_x; + brwin->geom.y=attribs.y-transl_y; + brwin->geom.width=attribs.width; + brwin->geom.height=attribs.height; + if((brwin->geom.x+brwin->geom.width>specs->width)|| + (brwin->geom.y+brwin->geom.height>specs->height)){ + fprintf(stderr,"Window must be on visible screen area!\n"); + return 1; + } + + brwin->rgeom.x=brwin->geom.x+args->x; + brwin->rgeom.y=brwin->geom.y+args->y; + brwin->rgeom.width=((args->width)? + args->width:brwin->geom.width-args->x); + brwin->rgeom.height=((args->height)? + args->height:brwin->geom.height-args->y); + if((args->x+brwin->rgeom.width>brwin->geom.width)|| + (args->y+brwin->rgeom.height>brwin->geom.height)){ + fprintf(stderr,"Specified Area is larger than window!\n"); + return 1; + } + } + fprintf(stderr, "Initial recording window is set to:\n" + "X:%d Y:%d Width:%d Height:%d\n", + brwin->rgeom.x,brwin->rgeom.y, + brwin->rgeom.width,brwin->rgeom.height); + SizePack2_8_16(&brwin->rgeom.x,&brwin->rgeom.width,specs->width); + SizePack2_8_16(&brwin->rgeom.y,&brwin->rgeom.height,specs->height); + + fprintf(stderr, "Adjusted recording window is set to:\n" + "X:%d Y:%d Width:%d Height:%d\n", + brwin->rgeom.x,brwin->rgeom.y, + brwin->rgeom.width,brwin->rgeom.height); + + + + brwin->nbytes=(((brwin->rgeom.width+15)>>4)<<4)* + (((brwin->rgeom.height+15)>>4)<<4)* + ((specs->depth==16)?2:4); + + return 0; +} diff --git a/recordmydesktop/src/rmd_setbrwindow.h b/recordmydesktop/src/rmd_setbrwindow.h new file mode 100644 index 0000000..91894fd --- /dev/null +++ b/recordmydesktop/src/rmd_setbrwindow.h @@ -0,0 +1,53 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef SETBRWINDOW_H +#define SETBRWINDOW_H 1 + +#include "rmd_types.h" + + +/** +* Check and align window size +* +* \param dpy Connection to the server +* +* \param brwin BRWindow struct contaning the initial and final window +* +* \param specs DisplaySpecs struct with +* information about the display to be recorded +* +* \param args ProgArgs struct containing the user-set options +* +* \returns 0 on Success 1 on Failure +*/ +int SetBRWindow(Display *dpy, + BRWindow *brwin, + DisplaySpecs *specs, + ProgArgs *args); + + +#endif diff --git a/recordmydesktop/src/rmd_shortcuts.c b/recordmydesktop/src/rmd_shortcuts.c new file mode 100644 index 0000000..a4031bc --- /dev/null +++ b/recordmydesktop/src/rmd_shortcuts.c @@ -0,0 +1,152 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include +#include +#include +#include + +#include "rmd_shortcuts.h" +#include "rmd_types.h" + +int RegisterShortcut(Display *dpy, + Window root, + const char *shortcut, + HotKey *hotkey){ + + int keycode=0, + i, j ; + KeySym key=0; + unsigned int modifier_mask=0, + numlock_mask=0; + char *keystr=NULL; + XModifierKeymap *modmap; + + if(strstr(shortcut,"Shift")) + modifier_mask = modifier_mask|ShiftMask; + if(strstr(shortcut,"Control")) + modifier_mask = modifier_mask|ControlMask; + if(strstr(shortcut,"Mod1")) + modifier_mask = modifier_mask|Mod1Mask; + if(strstr(shortcut,"Mod2")) + modifier_mask = modifier_mask|Mod2Mask; + if(strstr(shortcut,"Mod3")) + modifier_mask = modifier_mask|Mod3Mask; + if(strstr(shortcut,"Mod4")) + modifier_mask = modifier_mask|Mod4Mask; + if(strstr(shortcut,"Mod5")) + modifier_mask = modifier_mask|Mod5Mask; + + //we register the shortcut on the root + //window, which means on every keypress event, + //so I think it's neccessary to have at least one + //modifier. + if(modifier_mask == 0) + return 1; + if((keystr=rindex(shortcut,'+'))!=NULL){ + keystr++; + if((key=XStringToKeysym(keystr))==NoSymbol) + return 1; + else + keycode=XKeysymToKeycode(dpy,key); + } + else + return 1; + + + /* Key grabbing stuff taken from tilda who took it from yeahconsole + * who took it from evilwm */ + + modmap = XGetModifierMapping(dpy); + for(i=0;i<8;i++){ + for(j=0;jmax_keypermod;j++){ + if(modmap->modifiermap[i*modmap->max_keypermod+j]== + XKeysymToKeycode(dpy,XK_Num_Lock)) + numlock_mask=(1<modnum=0; + hotkey->key=keycode; + + XGrabKey(dpy, + keycode, + modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[0]=modifier_mask; + hotkey->modnum++; + + XGrabKey(dpy, + keycode, + LockMask | modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[1]=LockMask | modifier_mask; + hotkey->modnum++; + + if(numlock_mask){ + + XGrabKey(dpy, + keycode, + numlock_mask | modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[2]=numlock_mask | modifier_mask; + hotkey->modnum++; + + XGrabKey(dpy, + keycode, + numlock_mask | LockMask | modifier_mask, + root, + True, + GrabModeAsync, + GrabModeAsync); + hotkey->mask[3]=numlock_mask | LockMask | modifier_mask; + hotkey->modnum++; + + } + + return 0; + +} + + + + + + diff --git a/recordmydesktop/src/rmd_shortcuts.h b/recordmydesktop/src/rmd_shortcuts.h new file mode 100644 index 0000000..6b36854 --- /dev/null +++ b/recordmydesktop/src/rmd_shortcuts.h @@ -0,0 +1,57 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef SHORTCUTS_H +#define CHORTCUTS_H 1 + +#include "rmd_types.h" + + +/* + * Check a shortcut combination and if valid, + * register it, on the root window. + * + * \param dpy Connection to the X Server + * + * \param root Root window id + * + * \param shortcut String represantation of the shortcut + * + * \param HotKey Pre-allocated struct that is filled with the + * modifiers and the keycode, for checks on incoming + * keypress events. Left untouched if the call fails. + * + * + * \returns 0 on Success, 1 on Failure. + * + */ +int RegisterShortcut(Display *dpy, + Window root, + const char *shortcut, + HotKey *hotkey); + + +#endif diff --git a/recordmydesktop/src/rmd_specsfile.c b/recordmydesktop/src/rmd_specsfile.c new file mode 100644 index 0000000..13ec249 --- /dev/null +++ b/recordmydesktop/src/rmd_specsfile.c @@ -0,0 +1,167 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include + +#include "rmd_specsfile.h" +#include "rmd_types.h" + + +int WriteSpecsFile(ProgData *pdata){ + + FILE *fp; + + + fp=fopen(pdata->cache_data->specsfile,"wb"); + if(fp==NULL) + return 1; + else{ + + fprintf(fp,"recordMyDesktop = %s\n",VERSION); + fprintf(fp,"Width = %d\n",pdata->brwin.rgeom.width); + fprintf(fp,"Height = %d\n",pdata->brwin.rgeom.height); + fprintf(fp,"Filename = %s\n",pdata->args.filename); + fprintf(fp,"FPS = %f\n",pdata->args.fps); + fprintf(fp,"NoSound = %d\n",pdata->args.nosound); + fprintf(fp,"Frequency = %d\n",pdata->args.frequency); + fprintf(fp,"Channels = %d\n",pdata->args.channels); + fprintf(fp,"BufferSize = %lu\n",pdata->args.buffsize); + fprintf(fp,"SoundFrameSize = %d\n",pdata->sound_framesize); + fprintf(fp,"PeriodSize = %lu\n",pdata->periodsize); + fprintf(fp,"UsedJack = %d\n",pdata->args.use_jack); + fprintf(fp,"v_bitrate = %d\n",pdata->args.v_bitrate); + fprintf(fp,"v_quality = %d\n",pdata->args.v_quality); + fprintf(fp,"s_quality = %d\n",pdata->args.s_quality); + fprintf(fp,"ZeroCompression = %d\n",pdata->args.zerocompression); + + + } + + fclose(fp); + return 0; + +} + +int ReadSpecsFile(ProgData *pdata){ + + + FILE *fp; + + + fp=fopen(pdata->cache_data->specsfile,"rb"); + if(fp==NULL) + return 1; + else{ + + char Cached_Version[256]; + free(pdata->args.filename); + pdata->args.filename=malloc(512); + + //Take that single-point-of-exit advocates !!! + //15 points of exit, just for your pleasure. + //Also, Vi(m) rules, emacs sucks. + + if(fscanf(fp,"recordMyDesktop = %s\n",Cached_Version)!=1){ + fprintf(stderr,"Error reading VERSION attribute!!!\n"); + return 1; + } + if(fscanf(fp,"Width = %d\n",&pdata->brwin.rgeom.width)!=1){ + fprintf(stderr,"Error reading Width attribute!!!\n"); + return 1; + } + if(fscanf(fp,"Height = %d\n",&pdata->brwin.rgeom.height)!=1){ + fprintf(stderr,"Error reading Height attribute!!!\n"); + return 1; + } + if(fscanf(fp,"Filename = %s\n",pdata->args.filename)!=1){ + fprintf(stderr,"Error reading Filename attribute!!!\n"); + return 1; + } + if(fscanf(fp,"FPS = %f\n",&pdata->args.fps)!=1){ + fprintf(stderr,"Error reading FPS attribute!!!\n"); + return 1; + } + if(fscanf(fp,"NoSound = %d\n",&pdata->args.nosound)!=1){ + fprintf(stderr,"Error reading NoSound attribute!!!\n"); + return 1; + } + if(fscanf(fp,"Frequency = %d\n",&pdata->args.frequency)!=1){ + fprintf(stderr,"Error reading Frequency attribute!!!\n"); + return 1; + } + if(fscanf(fp,"Channels = %d\n",&pdata->args.channels)!=1){ + fprintf(stderr,"Error reading Channels attribute!!!\n"); + return 1; + } + if(fscanf(fp,"BufferSize = %lu\n",&pdata->args.buffsize)!=1){ + fprintf(stderr,"Error reading BufferSize attribute!!!\n"); + return 1; + } + if(fscanf(fp,"SoundFrameSize = %d\n",&pdata->sound_framesize)!=1){ + fprintf(stderr,"Error reading SoundFrameSize attribute!!!\n"); + return 1; + } + if(fscanf(fp,"PeriodSize = %lu\n",&pdata->periodsize)!=1){ + fprintf(stderr,"Error reading PeriodSize attribute!!!\n"); + return 1; + } + if(fscanf(fp,"UsedJack = %u\n",&pdata->args.use_jack)!=1){ + fprintf(stderr,"Error reading UsedJack attribute!!!\n"); + return 1; + } + if(fscanf(fp,"v_bitrate = %d\n",&pdata->args.v_bitrate)!=1){ + fprintf(stderr,"Error reading v_bitrate attribute!!!\n"); + return 1; + } + if(fscanf(fp,"v_quality = %d\n",&pdata->args.v_quality)!=1){ + fprintf(stderr,"Error reading v_quality attribute!!!\n"); + return 1; + } + if(fscanf(fp,"s_quality = %d\n",&pdata->args.s_quality)!=1){ + fprintf(stderr,"Error reading s_quality attribute!!!\n"); + return 1; + } + if(fscanf(fp,"ZeroCompression = %d\n",&pdata->args.zerocompression)!=1){ + fprintf(stderr,"Error reading ZeroCompression attribute!!!\n"); + return 1; + } + + + } + + fclose(fp); + return 0; + +} + + + + + + diff --git a/recordmydesktop/src/rmd_specsfile.h b/recordmydesktop/src/rmd_specsfile.h new file mode 100644 index 0000000..f381eaa --- /dev/null +++ b/recordmydesktop/src/rmd_specsfile.h @@ -0,0 +1,59 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef SPECSFILE_H +#define SPECSFILE_H 1 + +#include "rmd_types.h" + + +/* + * Create a text file that holds the required + * capture attributes, in the cache directory. + * + * \param pdata ProgData struct containing all program data + * + * \returns 0 on Success, 1 on failure + * + */ +int WriteSpecsFile(ProgData *pdata); + + + +/* + * Read the text file that holds the required + * capture attributes, in the cache directory. + * + * \param pdata ProgData struct that will be fille + * with all program data + * + * \returns 0 on Success, 1 on failure + * + */ +int ReadSpecsFile(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_threads.c b/recordmydesktop/src/rmd_threads.c new file mode 100644 index 0000000..f500384 --- /dev/null +++ b/recordmydesktop/src/rmd_threads.c @@ -0,0 +1,167 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include +#include + +#include "rmd_types.h" + +#include "rmd_cache_audio.h" +#include "rmd_cache_frame.h" +#include "rmd_capture_sound.h" +#include "rmd_encode_image_buffer.h" +#include "rmd_encode_sound_buffer.h" +#include "rmd_flush_to_ogg.h" +#include "rmd_get_frame.h" +#include "rmd_jack.h" +#include "rmd_register_callbacks.h" +#include "rmd_threads.h" +#include "rmd_timer.h" + + +void rmdThreads(ProgData *pdata){ + pthread_t image_capture_t, + image_encode_t, + image_cache_t, + sound_capture_t, + sound_encode_t, + sound_cache_t, + flush_to_ogg_t, + timer_t; + + if(pdata->args.delay>0){ + fprintf(stderr,"Will sleep for %d seconds now.\n",pdata->args.delay); + sleep(pdata->args.delay); + } + + /*start threads*/ + pthread_create(&image_capture_t, + NULL, + (void *)GetFrame, + (void *)pdata); + if(pdata->args.encOnTheFly) + pthread_create(&image_encode_t, + NULL, + (void *)EncodeImageBuffer, + (void *)pdata); + else + pthread_create(&image_cache_t, + NULL, + (void *)CacheImageBuffer, + (void *)pdata); + + if(!pdata->args.nosound){ + 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, + (void *)EncodeSoundBuffer, + (void *)pdata); + else + pthread_create(&sound_cache_t, + NULL, + (void *)CacheSoundBuffer, + (void *)pdata); + } + if(pdata->args.encOnTheFly) + pthread_create(&flush_to_ogg_t, + NULL, + (void *)FlushToOgg, + (void *)pdata); + + RegisterCallbacks(pdata); + pdata->timer_alive=1; + pthread_create(&timer_t, + NULL, + (void *)rmdTimer, + (void *)pdata); + 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); + fprintf(stderr,"Shutting down."); + //if no damage events have been received the thread will get stuck + while(!pdata->th_enc_thread_waiting && !pdata->th_encoding_clean){ + usleep(10000); + pthread_mutex_lock(&pdata->img_buff_ready_mutex); + pthread_cond_signal(&pdata->image_buffer_ready); + pthread_mutex_unlock(&pdata->img_buff_ready_mutex); + } + + if(pdata->args.encOnTheFly){ + pthread_join(image_encode_t,NULL); + } + else + pthread_join(image_cache_t,NULL); + fprintf(stderr,"."); + + if(!pdata->args.nosound){ +#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){ + usleep(10000); + pthread_mutex_lock(&pdata->snd_buff_ready_mutex); + pthread_cond_signal(&pdata->sound_data_read); + pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); + } + if(pdata->args.encOnTheFly){ + pthread_join(sound_encode_t,NULL); + } + else{ + pthread_join(sound_cache_t,NULL); + } + } + else + fprintf(stderr,".."); + + if(pdata->args.encOnTheFly) + pthread_join(flush_to_ogg_t,NULL); + fprintf(stderr,"."); + + //Now that we are done with recording we cancel the timer + pdata->timer_alive=0; + pthread_join(timer_t,NULL); + + +} diff --git a/recordmydesktop/src/rmd_threads.h b/recordmydesktop/src/rmd_threads.h new file mode 100644 index 0000000..e2c103a --- /dev/null +++ b/recordmydesktop/src/rmd_threads.h @@ -0,0 +1,43 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef RMDTHREADS_H +#define RMDTHREADS_H 1 + +#include "rmd_types.h" + + +/** +* Launch and wait capture threads. +* Also creates and waits the encoding threads when +* encode-on-the-fly is enabled. +* +* \param pdata ProgData struct containing all program data +*/ +void rmdThreads(ProgData *pdata); + + +#endif diff --git a/recordmydesktop/src/rmd_timer.c b/recordmydesktop/src/rmd_timer.c index ed3dbc2..78de72b 100644 --- a/recordmydesktop/src/rmd_timer.c +++ b/recordmydesktop/src/rmd_timer.c @@ -30,7 +30,7 @@ #include #include -#include "rmdtypes.h" +#include "rmd_types.h" #include "rmd_timer.h" diff --git a/recordmydesktop/src/rmd_timer.h b/recordmydesktop/src/rmd_timer.h index 28b9898..d9292d9 100644 --- a/recordmydesktop/src/rmd_timer.h +++ b/recordmydesktop/src/rmd_timer.h @@ -27,7 +27,7 @@ #ifndef RMD_TIMER_H #define RMD_TIMER_H 1 -#include "rmdtypes.h" +#include "rmd_types.h" /** diff --git a/recordmydesktop/src/rmd_types.h b/recordmydesktop/src/rmd_types.h new file mode 100644 index 0000000..e520c84 --- /dev/null +++ b/recordmydesktop/src/rmd_types.h @@ -0,0 +1,369 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef RMDTYPES_H +#define RMDTYPES_H 1 + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBASOUND + #include +#else + #include + #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. +//The performance gain comes from casting the unsigned char +//buffers to this type before comparing the two blocks. +//This is made possible by the fact that blocks +//for the Y plane are 16 bytes in width and blocks +//for the U,V planes are 8 bytes in width +#ifdef HAVE_U_INT64_T +typedef u_int64_t cmp_int_t; +#else +typedef u_int32_t cmp_int_t; +#endif + +//type of pixel proccessing for the Cb,Cr planes +//when converting from full rgb to 4:2:2 Ycbcr +enum{ + __PXL_DISCARD, //only select 1 pixel in every block of four + __PXL_AVERAGE //calculate the average of all four pixels +}; + +// Boolean type +typedef int boolean; +#define FALSE (0) +#define TRUE (!FALSE) + +// Forward declarations +typedef struct _ProgData ProgData; + +typedef struct _DisplaySpecs{ //this struct holds some basic information + int screen; //about the display,needed mostly for + unsigned int width; //validity checks at startup + unsigned int height; + Window root; + Visual *visual; + GC gc; + int depth; + unsigned long bpixel; + unsigned long wpixel; +}DisplaySpecs; + +typedef struct _WGeometry{ //basic geometry of a window or area + int x; + int y; + int width; + int height; +}WGeometry; + +typedef struct _RectArea{ //an area that has been damaged gets stored + WGeometry geom; //in a list comprised of structs of this type + struct _RectArea *prev,*next; +}RectArea; + +typedef struct _BRWindow{ //'basic recorded window' specs + WGeometry geom; //window attributes + WGeometry rgeom; //part of window that is recorded + int nbytes; //size of zpixmap when screenshoting + Window windowid; //id +}BRWindow; + +//defaults in the following comment lines may be out of sync with reality +//check DEFAULT_ARGS macro further bellow +typedef struct _ProgArgs{ + int delay; //start up delay + Window windowid; //window to record(default root) + char *display; //display to connect(default :0) + int x,y; //x,y offset(default 0,0) + int width,height; //defaults to window width and height + char *filename; //output file(default out.[ogg|*]) + int cursor_color; //black or white=>1 or 0 + int have_dummy_cursor; //disable/enable drawing of the dummy cursor + int xfixes_cursor; //disable/enable drawing of a cursor obtained + //through the xfixes extension + float fps; //desired framerate(default 15) + unsigned int frequency; //desired frequency (default 22050) + unsigned int channels; //no of channels(default 2) + char *device; //default sound device +#ifdef HAVE_LIBASOUND + snd_pcm_uframes_t buffsize; //buffer size(in frames) for sound capturing +#else + u_int32_t buffsize; +#endif + int nosound; //do not record sound(default 0) + int noshared; //do not use shared memory extension(default 0) + int nowmcheck; //do not check if there's a 3d comp window manager + //(which changes full-shots and with-shared to 1) + int full_shots; //do not poll damage, take full screenshots + int follow_mouse; //capture area follows the mouse(fullshots auto enabled) + int no_encode; //do not encode or delete the temporary files(debug opt) + int no_quick_subsample; //average pixels in chroma planes + int v_bitrate,v_quality,s_quality; //video bitrate,video-sound quality + int encOnTheFly; //encode while recording, no caching(default 0) + char *workdir; //directory to be used for cache files(default $HOME) + char *pause_shortcut; //pause/unpause shortcut sequence(Control+Alt+p) + char *stop_shortcut; //stop shortcut sequence(Control+Alt+s) + int noframe; //don't draw a frame around the recording area + 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; + float jack_ringbuffer_secs; +}ProgArgs; + +//this struct holds anything related to encoding AND +//writting out to file. +typedef struct _EncData{ + ogg_stream_state m_ogg_ts; //theora + ogg_stream_state m_ogg_vs; //vorbis + ogg_page m_ogg_pg; //this could be avoided since + // it is used only while initializing + ogg_packet m_ogg_pckt1; //theora stream + ogg_packet m_ogg_pckt2; //vorbis stream +//theora data + theora_state m_th_st; + theora_info m_th_inf; + theora_comment m_th_cmmnt; + yuv_buffer yuv; +//vorbis data + vorbis_info m_vo_inf; + vorbis_comment m_vo_cmmnt; + vorbis_dsp_state m_vo_dsp; + vorbis_block m_vo_block; +//these should be 0, since area is quantized +//before input + int x_offset, + y_offset; +//our file + FILE *fp; +}EncData; + +//this struct will hold a few basic +//information, needed for caching the frames. +typedef struct _CacheData{ + char *workdir, //The directory were the project + //will be stored, while recording. + //Since this will take a lot of space, the user must be + //able to change the location. + *projname, //This is the name of the folder that + //will hold the project. + //It is rMD-session-%d where %d is the pid + //of the current proccess. + //This way, running two instances + //will not create problems + //and also, a frontend can identify + //leftovers from a possible crash + //and delete them + *specsfile, //workdir+projname+specs.txt + *imgdata, //workdir+projname+img.out.gz + *audiodata; //workdir+projname+audio.pcm + + gzFile *ifp; //image data file pointer + FILE *uncifp; //uncompressed image data file pointer + + FILE *afp; //audio data file pointer + +}CacheData; + +//sound buffer +//sound keeps coming so we que it in this list +//which we then traverse +typedef struct _SndBuffer{ + signed char *data; + struct _SndBuffer *next; +}SndBuffer; + +#ifdef HAVE_JACK_H +typedef struct _JackData{ + ProgData *pdata; //pointer to prog data + 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. + float ringbuffer_secs; + 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 + +typedef struct _HotKey{ //Hold info about the shortcuts + int modnum; //modnum is the number of modifier masks + unsigned int mask[4]; //that should be checked (the initial + int key; //user requested modifier plus it's +}HotKey; //combinations with LockMask and NumLockMask). + +//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 +//at the same time usage of any globals. +struct _ProgData { +/**recordMyDesktop specific structs*/ + ProgArgs args; //the program arguments + DisplaySpecs specs; //Display specific information + BRWindow brwin; //recording window + RectArea *rect_root; //the interchanging list roots for storing + //the changed regions + SndBuffer *sound_buffer; + EncData *enc_data; + CacheData *cache_data; + HotKey pause_key, //Shortcuts + stop_key; +#ifdef HAVE_JACK_H + JackData *jdata; +#endif +/**X related info*/ + Display *dpy; //curtrent display +/** Mutexes*/ + pthread_mutex_t sound_buffer_mutex, + snd_buff_ready_mutex, + img_buff_ready_mutex, + theora_lib_mutex, + vorbis_lib_mutex, + libogg_mutex, //libogg is not thread safe, + yuv_mutex; //this might not be needed since we only have + //one read-only and one write-only thread + //also on previous versions, + //y component was looped separately + //and then u and v so this was needed + //to avoid wrong coloring to render + //Currently this mutex only prevents + //the cursor from flickering +/**Condition Variables*/ + pthread_cond_t time_cond, //this gets a broadcast by the handler + //whenever it's time to get a screenshot + pause_cond, //this is blocks execution, + //when program is paused + sound_buffer_ready, //sound encoding finished + sound_data_read, //a buffer is ready for proccessing + image_buffer_ready, //image encoding finished + theora_lib_clean, //the flush_ogg thread cannot + //procceed to creating last + vorbis_lib_clean; //packages until these two libs + //are no longer used, by other threads +/**Buffers,Flags and other vars*/ + unsigned char *dummy_pointer, //a dummy pointer to be drawn + //in every frame + //data is casted to unsigned for + //later use in YUV buffer + npxl; //this is the no pixel convention + //when drawing the dummy pointer + unsigned int periodtime,//time that a sound buffer lasts (microsecs) + frametime; //time that a frame lasts (microsecs) + char *window_manager; //name of the window manager at program launch + Window shaped_w; //frame + int damage_event, //damage event base code + damage_error, //damage error base code + shm_opcode, //MIT-Shm opcode + dummy_p_size, //dummy pointer size,initially 16x16,always square + th_encoding_clean, //thread exit inidcator + v_encoding_clean, // >> >> + v_enc_thread_waiting, //these indicate a wait + th_enc_thread_waiting, //condition on the cond vars. + timer_alive, //determines loop of timer thread + hard_pause, //if sound device doesn't support pause + //we have to close and reopen + avd, //syncronization among audio and video + sound_framesize; //size of each sound frame + + /** Progam state vars */ + boolean running; //1 while the program is capturing/paused/encoding + boolean paused; //1 while the program is paused + boolean aborted; //1 if we should abort + boolean pause_state_changed; //1 if pause state changed + + //the following values are of no effect + //but they might be usefull later for profiling + unsigned int frames_total, //frames calculated by total time expirations + frames_lost; //the value of shame + + //used to determine frame drop which can + //happen on failure to receive a signal over a condition variable + boolean capture_busy, + encoder_busy; + + pthread_mutex_t pause_mutex; + pthread_mutex_t time_mutex; + +#ifdef HAVE_LIBASOUND + snd_pcm_t *sound_handle; + snd_pcm_uframes_t periodsize; +#else + int sound_handle; + u_int32_t periodsize; +#endif +}; + + +//This is the header of every frame. +//Reconstruction will be correct only if made on +//the same platform. + +//We need the total number of blocks +//for each plane. + +//The number of the frame compared to the +//number of time expirations at the time of +//caching, will enable us to make up for lost frames. + + +typedef struct _FrameHeader{ + char frame_prefix[4]; //always FRAM + u_int32_t frameno, //number of frame(cached frames) + current_total; //number of frames that should have been + //taken at time of caching this one + u_int32_t Ynum, //number of changed blocks in the Y plane + Unum, //number of changed blocks in the U plane + Vnum; //number of changed blocks in the V plane +}FrameHeader; + +#endif + diff --git a/recordmydesktop/src/rmd_update_image.c b/recordmydesktop/src/rmd_update_image.c new file mode 100644 index 0000000..0051e69 --- /dev/null +++ b/recordmydesktop/src/rmd_update_image.c @@ -0,0 +1,86 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include +#include +#include + +#include "rmd_types.h" + +#include "rmd_getzpixmap.h" +#include "rmd_update_image.h" +#include "rmd_yuv_utils.h" + + +void UpdateImage(Display * dpy, + yuv_buffer *yuv, + DisplaySpecs *specs, + RectArea **root, + BRWindow *brwin, + EncData *enc, + char *datatemp, + int noshmem, + XShmSegmentInfo *shminfo, + int shm_opcode, + int no_quick_subsample){ + RectArea *temp; + unsigned char *dtap=(unsigned char*)datatemp; + temp=*root; + + if(temp!=NULL){ + do{ + if(noshmem){ + GetZPixmap( dpy, + specs->root, + datatemp, + temp->geom.x, + temp->geom.y, + temp->geom.width, + temp->geom.height); + } + else{ + GetZPixmapSHM(dpy, + specs->root, + shminfo, + shm_opcode, + datatemp,temp->geom.x, + temp->geom.y, + temp->geom.width, + temp->geom.height); + } + UPDATE_YUV_BUFFER(yuv,dtap,NULL, + (temp->geom.x-brwin->rgeom.x+enc->x_offset), + (temp->geom.y-brwin->rgeom.y+enc->y_offset), + (temp->geom.width),(temp->geom.height), + no_quick_subsample, + specs->depth); + temp=temp->next; + }while(temp!=NULL); + } +} + diff --git a/recordmydesktop/src/rmd_update_image.h b/recordmydesktop/src/rmd_update_image.h new file mode 100644 index 0000000..f31e735 --- /dev/null +++ b/recordmydesktop/src/rmd_update_image.h @@ -0,0 +1,70 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef UPDATE_IMAGE_H +#define UPDATE_IMAGE_H 1 + +#include "rmd_types.h" + + +/** +* Retrieve and apply all changes, if xdamage is used. +* +* \param dpy Connection to the server +* +* \param yuv yuv_buffer that is to be modified +* +* \param specs DisplaySpecs struct with +* information about the display to be recorded +* +* \param root Root entry of the list with damaged areas +* +* \param brwin BRWindow struct contaning the recording window specs +* +* \param enc Encoding options +* +* \param datatemp Buffer for pixel data to be +* retrieved before placed on the yuv buffer +* +* \param noshmem don't use MIT_Shm extension +* +* \param no_quick_subsample Don't do quick subsampling +* +*/ +void UpdateImage(Display * dpy, + yuv_buffer *yuv, + DisplaySpecs *specs, + RectArea **root, + BRWindow *brwin, + EncData *enc, + char *datatemp, + int noshmem, + XShmSegmentInfo *shminfo, + int shm_opcode, + int no_quick_subsample); + + +#endif diff --git a/recordmydesktop/src/rmd_wm_check.c b/recordmydesktop/src/rmd_wm_check.c new file mode 100644 index 0000000..b0692da --- /dev/null +++ b/recordmydesktop/src/rmd_wm_check.c @@ -0,0 +1,79 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include + +#include "rmd_types.h" + +#include "rmd_wm_check.h" + + +char *rmdWMCheck(Display *dpy,Window root){ + + Window *wm_child=NULL; + Atom nwm_atom, + utf8_string, + wm_name_atom, + rt; + unsigned long nbytes, + nitems; + + char *wm_name_str=NULL; + int fmt; + + utf8_string = XInternAtom(dpy, "UTF8_STRING", False); + + nwm_atom =XInternAtom(dpy,"_NET_SUPPORTING_WM_CHECK",True); + wm_name_atom =XInternAtom(dpy,"_NET_WM_NAME",True); + + if(nwm_atom!=None && wm_name_atom!=None){ + if(XGetWindowProperty( dpy,root,nwm_atom,0,100, + False,XA_WINDOW, + &rt,&fmt,&nitems, &nbytes, + (unsigned char **)((void*)&wm_child)) + != Success ){ + fprintf(stderr,"Error while trying to get a" + " window to identify the window manager.\n"); + } + if((wm_child == NULL)|| + (XGetWindowProperty(dpy,*wm_child,wm_name_atom,0,100, + False,utf8_string,&rt, + &fmt,&nitems, &nbytes, + (unsigned char **)((void*)&wm_name_str)) + !=Success)){ + fprintf(stderr,"Warning!!!\nYour window manager appears" + " to be non-compliant!\n"); + } + } + fprintf(stderr,"Your window manager appears to be %s\n\n", + ((wm_name_str!=NULL)?wm_name_str:"Unknown")); + + + return wm_name_str; +} + diff --git a/recordmydesktop/src/rmd_wm_check.h b/recordmydesktop/src/rmd_wm_check.h new file mode 100644 index 0000000..12f33dd --- /dev/null +++ b/recordmydesktop/src/rmd_wm_check.h @@ -0,0 +1,45 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef WM_CHECK_H +#define WM_CHECK_H 1 + +#include "rmd_types.h" + + +/** +*Check current running window manager. +* +* \param dpy Connection to the server +* +* \param root root window of the display +* +* \returns Window manager name +*/ +char *rmdWMCheck(Display *dpy,Window root); + + +#endif diff --git a/recordmydesktop/src/rmd_yuv_utils.c b/recordmydesktop/src/rmd_yuv_utils.c new file mode 100644 index 0000000..8996ad7 --- /dev/null +++ b/recordmydesktop/src/rmd_yuv_utils.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 "config.h" + +#include "rmd_yuv_utils.h" + +// Keep these global (for performance reasons I assume). +unsigned char Yr[256], Yg[256], Yb[256], + Ur[256], Ug[256], UbVr[256], + Vg[256], Vb[256]; + +void MakeMatrices (void) { + int i; + + for (i = 0; i < 256; i++) + Yr[i] = (2104.0 * i) / 8192.0 + 8.0; + for (i = 0; i < 256; i++) + Yg[i] = (4130.0 * i) / 8192.0 + 8.0; + for (i = 0; i < 256; i++) + Yb[i] = (802.0 * i) / 8192.0; + + for (i = 0; i < 256; i++) + Ur[i] = 37.8 - (1204.0 * i) / 8192.0 + 8.0; + for (i = 0; i < 256; i++) + Ug[i] = 74.2 - (2384.0 * i) / 8192.0 + 8.0; + for (i = 0; i < 256; i++) + UbVr[i] = (3598.0 * i) / 8192.0 ; + + for (i = 0; i < 256; i++) + Vg[i] = 93.8 - (3013.0 * i) / 8192.0 + 8.0; + for (i = 0; i < 256; i++) + Vb[i] = 18.2 - (585.0 * i) / 8192.0 + 8.0; +} diff --git a/recordmydesktop/src/rmd_yuv_utils.h b/recordmydesktop/src/rmd_yuv_utils.h new file mode 100644 index 0000000..b1af63b --- /dev/null +++ b/recordmydesktop/src/rmd_yuv_utils.h @@ -0,0 +1,247 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 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 * +******************************************************************************/ + +#ifndef YUV_UTILS_H +#define YUV_UTILS_H 1 + +#include "rmd_block_utils.h" +#include "rmd_macro.h" +#include "rmd_types.h" + + +// The macros work directly on this data (for performance reasons I +// suppose) so we keep this global +extern unsigned char Yr[256], Yg[256], Yb[256], + Ur[256], Ug[256], UbVr[256], + Vg[256], Vb[256]; + + +//when adding the r values, we go beyond +//the (16 bit)range of the t_val variable, but we are performing +//32 bit arithmetics, so there's no problem. +//(This note is useless, I'm just adding because +//the addition of the A components in CALC_TVAL_AVG_32, +//now removed as uneeded, produced an overflow which would have caused +//color distrtion, where it one of the R,G or B components) +#define CALC_TVAL_AVG_16(t_val,datapi,datapi_next){\ + register u_int16_t t1,t2,t3,t4;\ + t1=*datapi;\ + t2=*(datapi+1);\ + 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);\ +} + +//the 4 most significant bytes represent the A component which +//does not need to be added on t_val, as it is always unused +#define CALC_TVAL_AVG_32(t_val,datapi,datapi_next){\ + register unsigned int t1,t2,t3,t4;\ + t1=*datapi;\ + t2=*(datapi+1);\ + t3=*datapi_next;\ + t4=*(datapi_next+1);\ + t_val=((((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 UPDATE_Y_PLANE(data,\ + x_tm,\ + y_tm,\ + height_tm,\ + width_tm,\ + yuv,\ + __bit_depth__){ \ + int k,i;\ + register u_int##__bit_depth__##_t t_val;\ + register unsigned char *yuv_y=yuv->y+x_tm+y_tm*yuv->y_width,\ + *_yr=Yr,*_yg=Yg,*_yb=Yb;\ + register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data;\ + for(k=0;ky_width-width_tm;\ + }\ +} + +#define UPDATE_A_UV_PIXEL(yuv_u,\ + yuv_v,\ + t_val,\ + datapi,\ + datapi_next,\ + _ur,_ug,_ubvr,_vg,_vb,\ + __sampling_type,\ + __bit_depth__)\ + if(__sampling_type==__PXL_AVERAGE){\ + CALC_TVAL_AVG_##__bit_depth__(t_val,datapi,datapi_next)\ + }\ + else\ + t_val=*datapi;\ + *yuv_u=\ + _ur[__RVALUE_##__bit_depth__(t_val)] +\ + _ug[__GVALUE_##__bit_depth__(t_val)] +\ + _ubvr[__BVALUE_##__bit_depth__(t_val)];\ + *yuv_v=\ + _ubvr[__RVALUE_##__bit_depth__(t_val)] +\ + _vg[__GVALUE_##__bit_depth__(t_val)] +\ + _vb[__BVALUE_##__bit_depth__(t_val)];\ + + +#define UPDATE_UV_PLANES(data,\ + x_tm,\ + y_tm,\ + height_tm,\ + width_tm,\ + yuv,\ + __sampling_type,\ + __bit_depth__){ \ + int k,i;\ + register u_int##__bit_depth__##_t t_val;\ + register unsigned char *yuv_u=yuv->u+x_tm/2+(y_tm*yuv->uv_width)/2,\ + *yuv_v=yuv->v+x_tm/2+(y_tm*yuv->uv_width)/2,\ + *_ur=Ur,*_ug=Ug,*_ubvr=UbVr,\ + *_vg=Vg,*_vb=Vb;\ + register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\ + *datapi_next=NULL;\ + if(__sampling_type==__PXL_AVERAGE){\ + datapi_next=datapi+width_tm;\ + }\ + for(k=0;ky_width-width_tm)/2;\ + yuv_v+=(yuv->y_width-width_tm)/2;\ + datapi+=width_tm;\ + if(__sampling_type==__PXL_AVERAGE)\ + datapi_next+=width_tm;\ + }\ +} + +#define UPDATE_YUV_BUFFER(yuv,\ + data,\ + data_back,\ + x_tm,\ + y_tm,\ + width_tm,\ + height_tm,\ + __sampling_type,\ + __color_depth){\ + if(data_back==NULL){\ + if((__color_depth==24)||(__color_depth==32)){\ + UPDATE_Y_PLANE(data,x_tm,y_tm,height_tm,width_tm,yuv,32)\ + UPDATE_UV_PLANES(data,x_tm,y_tm,height_tm,width_tm,\ + yuv,__sampling_type,32)\ + }\ + else if(__color_depth==16){\ + UPDATE_Y_PLANE(data,x_tm,y_tm,height_tm,width_tm,yuv,16)\ + UPDATE_UV_PLANES(data,x_tm,y_tm,height_tm,width_tm,\ + yuv,__sampling_type,16)\ + }\ + }\ + else{\ + if((__color_depth==24)||(__color_depth==32)){\ + UPDATE_Y_PLANE_DBUF(data,data_back,x_tm,y_tm,\ + height_tm,width_tm,yuv,32)\ + UPDATE_UV_PLANES_DBUF(data,data_back,x_tm,y_tm,height_tm,width_tm,\ + yuv,__sampling_type,32)\ + }\ + else if(__color_depth==16){\ + UPDATE_Y_PLANE_DBUF(data,data_back,x_tm,y_tm,\ + height_tm,width_tm,yuv,16)\ + UPDATE_UV_PLANES_DBUF(data,data_back,x_tm,y_tm,height_tm,width_tm,\ + yuv,__sampling_type,16)\ + }\ + }\ +} + +#define DUMMY_POINTER_TO_YUV(yuv,\ + data_tm,\ + x_tm,\ + y_tm,\ + width_tm,\ + height_tm,\ + x_offset,\ + y_offset,\ + no_pixel){\ + int i,k,j=0;\ + int x_2=x_tm/2,y_2=y_tm/2,y_width_2=(yuv)->y_width/2;\ + for(k=y_offset;ky[x_tm+(i-x_offset)+((k-y_offset)+y_tm)*(yuv)->y_width]=\ + Yr[data_tm[(j*4)+__RBYTE]] +\ + Yg[data_tm[(j*4)+__GBYTE]] +\ + Yb[data_tm[(j*4)+__BBYTE]];\ + if((k%2)&&(i%2)){\ + yuv->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*y_width_2]=\ + Ur[data_tm[(k*width_tm+i)*4+__RBYTE]] +\ + Ug[data_tm[(k*width_tm+i)*4+__GBYTE]] +\ + UbVr[data_tm[(k*width_tm+i)*4+__BBYTE]];\ + yuv->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*y_width_2]=\ + UbVr[data_tm[(k*width_tm+i)*4+__RBYTE]] +\ + Vg[data_tm[(k*width_tm+i)*4+__GBYTE]] +\ + Vb[data_tm[(k*width_tm+i)*4+__BBYTE]] ;\ + }\ + }\ + }\ + }\ +} + +/** +* Fill Yr,Yg,Yb,Ur,Ug.Ub,Vr,Vg,Vb arrays(globals) with values. +*/ +void MakeMatrices(void); + + +#endif diff --git a/recordmydesktop/src/rmdmacro.h b/recordmydesktop/src/rmdmacro.h deleted file mode 100644 index c02adc2..0000000 --- a/recordmydesktop/src/rmdmacro.h +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef RMDMACRO_H -#define RMDMACRO_H 1 - -#include "config.h" - -#include - -#include "rmdtypes.h" - - -//define which way we are reading a pixmap -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define __ABYTE 3 -#define __RBYTE 2 -#define __GBYTE 1 -#define __BBYTE 0 - -#elif __BYTE_ORDER == __BIG_ENDIAN - -#define __ABYTE 0 -#define __RBYTE 1 -#define __GBYTE 2 -#define __BBYTE 3 - -#else -#error Only little-endian and big-endian systems are supported -#endif - -#define __RVALUE_32(tmp_val) (((tmp_val)&0x00ff0000)>>16) -#define __GVALUE_32(tmp_val) (((tmp_val)&0x0000ff00)>>8) -#define __BVALUE_32(tmp_val) (((tmp_val)&0x000000ff)) - -#define __R16_MASK 0xf800 -#define __G16_MASK 0x7e0 -#define __B16_MASK 0x1f - -#define __RVALUE_16(tmp_val) ((((tmp_val)&__R16_MASK)>>11)*8) -#define __GVALUE_16(tmp_val) ((((tmp_val)&__G16_MASK)>>5)*4) -#define __BVALUE_16(tmp_val) ((((tmp_val)&__B16_MASK))*8) - -//xfixes pointer data are written as unsigned long -//(even though the server returns CARD32) -//so we need to set the step accordingly to -//avoid problems (amd64 has 8byte ulong) -#define RMD_ULONG_SIZE_T (sizeof(unsigned long)) - -//size of stride when comparing planes(depending on type) -//this is just to avoid thousands of sizeof's -#ifdef HAVE_U_INT64_T - #define COMPARE_STRIDE 8 -#else - #define COMPARE_STRIDE 4 -#endif - -//The width, in bytes, of the blocks -//on which the y,u and v planes are broken. -//These blocks are square. -#define Y_UNIT_WIDTH 0x0010 -#define UV_UNIT_WIDTH 0x0008 - -#ifdef HAVE_LIBASOUND - #define DEFAULT_AUDIO_DEVICE "hw:0,0" -#else - #define DEFAULT_AUDIO_DEVICE "/dev/dsp" -#endif - -#define I16TOA(number,buffer){\ - int t_num=(number),__k=0,__i=0;\ - char *t_buf=malloc(8);\ - t_num=t_num&((2<<15)-1);\ - while(t_num>0){\ - int digit=t_num%10;\ - t_buf[__k]=digit+48;\ - t_num-=digit;\ - t_num/=10;\ - __k++;\ - }\ - while(__k>0)\ - (buffer)[__i++]=t_buf[--__k];\ - (buffer)[__i]='\0';\ - free(t_buf);\ -};\ - - -#endif diff --git a/recordmydesktop/src/rmdthreads.c b/recordmydesktop/src/rmdthreads.c deleted file mode 100644 index 6fac928..0000000 --- a/recordmydesktop/src/rmdthreads.c +++ /dev/null @@ -1,166 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include -#include -#include - -#include "cache_audio.h" -#include "cache_frame.h" -#include "capture_sound.h" -#include "encode_image_buffer.h" -#include "encode_sound_buffer.h" -#include "flush_to_ogg.h" -#include "get_frame.h" -#include "register_callbacks.h" -#include "rmd_jack.h" -#include "rmd_timer.h" -#include "rmdthreads.h" -#include "rmdtypes.h" - - -void rmdThreads(ProgData *pdata){ - pthread_t image_capture_t, - image_encode_t, - image_cache_t, - sound_capture_t, - sound_encode_t, - sound_cache_t, - flush_to_ogg_t, - timer_t; - - if(pdata->args.delay>0){ - fprintf(stderr,"Will sleep for %d seconds now.\n",pdata->args.delay); - sleep(pdata->args.delay); - } - - /*start threads*/ - pthread_create(&image_capture_t, - NULL, - (void *)GetFrame, - (void *)pdata); - if(pdata->args.encOnTheFly) - pthread_create(&image_encode_t, - NULL, - (void *)EncodeImageBuffer, - (void *)pdata); - else - pthread_create(&image_cache_t, - NULL, - (void *)CacheImageBuffer, - (void *)pdata); - - if(!pdata->args.nosound){ - 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, - (void *)EncodeSoundBuffer, - (void *)pdata); - else - pthread_create(&sound_cache_t, - NULL, - (void *)CacheSoundBuffer, - (void *)pdata); - } - if(pdata->args.encOnTheFly) - pthread_create(&flush_to_ogg_t, - NULL, - (void *)FlushToOgg, - (void *)pdata); - - RegisterCallbacks(pdata); - pdata->timer_alive=1; - pthread_create(&timer_t, - NULL, - (void *)rmdTimer, - (void *)pdata); - 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); - fprintf(stderr,"Shutting down."); - //if no damage events have been received the thread will get stuck - while(!pdata->th_enc_thread_waiting && !pdata->th_encoding_clean){ - usleep(10000); - pthread_mutex_lock(&pdata->img_buff_ready_mutex); - pthread_cond_signal(&pdata->image_buffer_ready); - pthread_mutex_unlock(&pdata->img_buff_ready_mutex); - } - - if(pdata->args.encOnTheFly){ - pthread_join(image_encode_t,NULL); - } - else - pthread_join(image_cache_t,NULL); - fprintf(stderr,"."); - - if(!pdata->args.nosound){ -#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){ - usleep(10000); - pthread_mutex_lock(&pdata->snd_buff_ready_mutex); - pthread_cond_signal(&pdata->sound_data_read); - pthread_mutex_unlock(&pdata->snd_buff_ready_mutex); - } - if(pdata->args.encOnTheFly){ - pthread_join(sound_encode_t,NULL); - } - else{ - pthread_join(sound_cache_t,NULL); - } - } - else - fprintf(stderr,".."); - - if(pdata->args.encOnTheFly) - pthread_join(flush_to_ogg_t,NULL); - fprintf(stderr,"."); - - //Now that we are done with recording we cancel the timer - pdata->timer_alive=0; - pthread_join(timer_t,NULL); - - -} diff --git a/recordmydesktop/src/rmdthreads.h b/recordmydesktop/src/rmdthreads.h deleted file mode 100644 index c832c1c..0000000 --- a/recordmydesktop/src/rmdthreads.h +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef RMDTHREADS_H -#define RMDTHREADS_H 1 - -#include "rmdtypes.h" - - -/** -* Launch and wait capture threads. -* Also creates and waits the encoding threads when -* encode-on-the-fly is enabled. -* -* \param pdata ProgData struct containing all program data -*/ -void rmdThreads(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/rmdtypes.h b/recordmydesktop/src/rmdtypes.h deleted file mode 100644 index e520c84..0000000 --- a/recordmydesktop/src/rmdtypes.h +++ /dev/null @@ -1,369 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef RMDTYPES_H -#define RMDTYPES_H 1 - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_LIBASOUND - #include -#else - #include - #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. -//The performance gain comes from casting the unsigned char -//buffers to this type before comparing the two blocks. -//This is made possible by the fact that blocks -//for the Y plane are 16 bytes in width and blocks -//for the U,V planes are 8 bytes in width -#ifdef HAVE_U_INT64_T -typedef u_int64_t cmp_int_t; -#else -typedef u_int32_t cmp_int_t; -#endif - -//type of pixel proccessing for the Cb,Cr planes -//when converting from full rgb to 4:2:2 Ycbcr -enum{ - __PXL_DISCARD, //only select 1 pixel in every block of four - __PXL_AVERAGE //calculate the average of all four pixels -}; - -// Boolean type -typedef int boolean; -#define FALSE (0) -#define TRUE (!FALSE) - -// Forward declarations -typedef struct _ProgData ProgData; - -typedef struct _DisplaySpecs{ //this struct holds some basic information - int screen; //about the display,needed mostly for - unsigned int width; //validity checks at startup - unsigned int height; - Window root; - Visual *visual; - GC gc; - int depth; - unsigned long bpixel; - unsigned long wpixel; -}DisplaySpecs; - -typedef struct _WGeometry{ //basic geometry of a window or area - int x; - int y; - int width; - int height; -}WGeometry; - -typedef struct _RectArea{ //an area that has been damaged gets stored - WGeometry geom; //in a list comprised of structs of this type - struct _RectArea *prev,*next; -}RectArea; - -typedef struct _BRWindow{ //'basic recorded window' specs - WGeometry geom; //window attributes - WGeometry rgeom; //part of window that is recorded - int nbytes; //size of zpixmap when screenshoting - Window windowid; //id -}BRWindow; - -//defaults in the following comment lines may be out of sync with reality -//check DEFAULT_ARGS macro further bellow -typedef struct _ProgArgs{ - int delay; //start up delay - Window windowid; //window to record(default root) - char *display; //display to connect(default :0) - int x,y; //x,y offset(default 0,0) - int width,height; //defaults to window width and height - char *filename; //output file(default out.[ogg|*]) - int cursor_color; //black or white=>1 or 0 - int have_dummy_cursor; //disable/enable drawing of the dummy cursor - int xfixes_cursor; //disable/enable drawing of a cursor obtained - //through the xfixes extension - float fps; //desired framerate(default 15) - unsigned int frequency; //desired frequency (default 22050) - unsigned int channels; //no of channels(default 2) - char *device; //default sound device -#ifdef HAVE_LIBASOUND - snd_pcm_uframes_t buffsize; //buffer size(in frames) for sound capturing -#else - u_int32_t buffsize; -#endif - int nosound; //do not record sound(default 0) - int noshared; //do not use shared memory extension(default 0) - int nowmcheck; //do not check if there's a 3d comp window manager - //(which changes full-shots and with-shared to 1) - int full_shots; //do not poll damage, take full screenshots - int follow_mouse; //capture area follows the mouse(fullshots auto enabled) - int no_encode; //do not encode or delete the temporary files(debug opt) - int no_quick_subsample; //average pixels in chroma planes - int v_bitrate,v_quality,s_quality; //video bitrate,video-sound quality - int encOnTheFly; //encode while recording, no caching(default 0) - char *workdir; //directory to be used for cache files(default $HOME) - char *pause_shortcut; //pause/unpause shortcut sequence(Control+Alt+p) - char *stop_shortcut; //stop shortcut sequence(Control+Alt+s) - int noframe; //don't draw a frame around the recording area - 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; - float jack_ringbuffer_secs; -}ProgArgs; - -//this struct holds anything related to encoding AND -//writting out to file. -typedef struct _EncData{ - ogg_stream_state m_ogg_ts; //theora - ogg_stream_state m_ogg_vs; //vorbis - ogg_page m_ogg_pg; //this could be avoided since - // it is used only while initializing - ogg_packet m_ogg_pckt1; //theora stream - ogg_packet m_ogg_pckt2; //vorbis stream -//theora data - theora_state m_th_st; - theora_info m_th_inf; - theora_comment m_th_cmmnt; - yuv_buffer yuv; -//vorbis data - vorbis_info m_vo_inf; - vorbis_comment m_vo_cmmnt; - vorbis_dsp_state m_vo_dsp; - vorbis_block m_vo_block; -//these should be 0, since area is quantized -//before input - int x_offset, - y_offset; -//our file - FILE *fp; -}EncData; - -//this struct will hold a few basic -//information, needed for caching the frames. -typedef struct _CacheData{ - char *workdir, //The directory were the project - //will be stored, while recording. - //Since this will take a lot of space, the user must be - //able to change the location. - *projname, //This is the name of the folder that - //will hold the project. - //It is rMD-session-%d where %d is the pid - //of the current proccess. - //This way, running two instances - //will not create problems - //and also, a frontend can identify - //leftovers from a possible crash - //and delete them - *specsfile, //workdir+projname+specs.txt - *imgdata, //workdir+projname+img.out.gz - *audiodata; //workdir+projname+audio.pcm - - gzFile *ifp; //image data file pointer - FILE *uncifp; //uncompressed image data file pointer - - FILE *afp; //audio data file pointer - -}CacheData; - -//sound buffer -//sound keeps coming so we que it in this list -//which we then traverse -typedef struct _SndBuffer{ - signed char *data; - struct _SndBuffer *next; -}SndBuffer; - -#ifdef HAVE_JACK_H -typedef struct _JackData{ - ProgData *pdata; //pointer to prog data - 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. - float ringbuffer_secs; - 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 - -typedef struct _HotKey{ //Hold info about the shortcuts - int modnum; //modnum is the number of modifier masks - unsigned int mask[4]; //that should be checked (the initial - int key; //user requested modifier plus it's -}HotKey; //combinations with LockMask and NumLockMask). - -//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 -//at the same time usage of any globals. -struct _ProgData { -/**recordMyDesktop specific structs*/ - ProgArgs args; //the program arguments - DisplaySpecs specs; //Display specific information - BRWindow brwin; //recording window - RectArea *rect_root; //the interchanging list roots for storing - //the changed regions - SndBuffer *sound_buffer; - EncData *enc_data; - CacheData *cache_data; - HotKey pause_key, //Shortcuts - stop_key; -#ifdef HAVE_JACK_H - JackData *jdata; -#endif -/**X related info*/ - Display *dpy; //curtrent display -/** Mutexes*/ - pthread_mutex_t sound_buffer_mutex, - snd_buff_ready_mutex, - img_buff_ready_mutex, - theora_lib_mutex, - vorbis_lib_mutex, - libogg_mutex, //libogg is not thread safe, - yuv_mutex; //this might not be needed since we only have - //one read-only and one write-only thread - //also on previous versions, - //y component was looped separately - //and then u and v so this was needed - //to avoid wrong coloring to render - //Currently this mutex only prevents - //the cursor from flickering -/**Condition Variables*/ - pthread_cond_t time_cond, //this gets a broadcast by the handler - //whenever it's time to get a screenshot - pause_cond, //this is blocks execution, - //when program is paused - sound_buffer_ready, //sound encoding finished - sound_data_read, //a buffer is ready for proccessing - image_buffer_ready, //image encoding finished - theora_lib_clean, //the flush_ogg thread cannot - //procceed to creating last - vorbis_lib_clean; //packages until these two libs - //are no longer used, by other threads -/**Buffers,Flags and other vars*/ - unsigned char *dummy_pointer, //a dummy pointer to be drawn - //in every frame - //data is casted to unsigned for - //later use in YUV buffer - npxl; //this is the no pixel convention - //when drawing the dummy pointer - unsigned int periodtime,//time that a sound buffer lasts (microsecs) - frametime; //time that a frame lasts (microsecs) - char *window_manager; //name of the window manager at program launch - Window shaped_w; //frame - int damage_event, //damage event base code - damage_error, //damage error base code - shm_opcode, //MIT-Shm opcode - dummy_p_size, //dummy pointer size,initially 16x16,always square - th_encoding_clean, //thread exit inidcator - v_encoding_clean, // >> >> - v_enc_thread_waiting, //these indicate a wait - th_enc_thread_waiting, //condition on the cond vars. - timer_alive, //determines loop of timer thread - hard_pause, //if sound device doesn't support pause - //we have to close and reopen - avd, //syncronization among audio and video - sound_framesize; //size of each sound frame - - /** Progam state vars */ - boolean running; //1 while the program is capturing/paused/encoding - boolean paused; //1 while the program is paused - boolean aborted; //1 if we should abort - boolean pause_state_changed; //1 if pause state changed - - //the following values are of no effect - //but they might be usefull later for profiling - unsigned int frames_total, //frames calculated by total time expirations - frames_lost; //the value of shame - - //used to determine frame drop which can - //happen on failure to receive a signal over a condition variable - boolean capture_busy, - encoder_busy; - - pthread_mutex_t pause_mutex; - pthread_mutex_t time_mutex; - -#ifdef HAVE_LIBASOUND - snd_pcm_t *sound_handle; - snd_pcm_uframes_t periodsize; -#else - int sound_handle; - u_int32_t periodsize; -#endif -}; - - -//This is the header of every frame. -//Reconstruction will be correct only if made on -//the same platform. - -//We need the total number of blocks -//for each plane. - -//The number of the frame compared to the -//number of time expirations at the time of -//caching, will enable us to make up for lost frames. - - -typedef struct _FrameHeader{ - char frame_prefix[4]; //always FRAM - u_int32_t frameno, //number of frame(cached frames) - current_total; //number of frames that should have been - //taken at time of caching this one - u_int32_t Ynum, //number of changed blocks in the Y plane - Unum, //number of changed blocks in the U plane - Vnum; //number of changed blocks in the V plane -}FrameHeader; - -#endif - diff --git a/recordmydesktop/src/setbrwindow.c b/recordmydesktop/src/setbrwindow.c deleted file mode 100644 index edc4d14..0000000 --- a/recordmydesktop/src/setbrwindow.c +++ /dev/null @@ -1,213 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include "rmdtypes.h" - -#include "setbrwindow.h" - - -/** -*Align the recording window to a divisible by 2 pixel start and -*and a size divisible by 16. -* -* \param start x or y of the recording window -* -* \param size width or height of the recording window -* -* \param limit width or height of the Display -* -* \note This is called separately for width and height. -*/ -static void SizePack2_8_16(int *start, int *size, int limit) { - int octoffset,hexoffset; - - //align in two - //an odd x can always go down and still be in recording area. - //Resolutions come in even numbers - //so if x is an odd numer, width max is an odd number, too - //thus since x will go down one then width can go up one too and still - //be inbounds - (*size)+=((*size)%2)|((*start)%2); - //but if x goes down 1 and width is already even,it becomes odd so: - (*size)+=((*size)%2); - (*start)-=(*start)%2; - - - //32 bit pack align - //we already have disible by two width,so - //it's 2, 4 or 6 - octoffset=((*size)%8); - if(octoffset==2){ - (*size)-=2; - - } - else if(octoffset==6){ - if((*size)+(*start)+2<=limit) - (*size)+=2; - else if((*start)>=2){ - (*start)-=2; - (*size)+=2; - } - else{ - (*start)+=2; - (*size)-=4; - } - } - - else if(octoffset==4){ - if(((*size)+(*start)+2<=limit)&&((*start)>=2)){ - (*start)-=2; - (*size)+=4; - } - else if((*size)+(*start)+4<=limit){ - (*size)+=4; - } - else if((*start)>=4){ - (*start)-=4; - (*size)+=4; - } - else{ - (*start)+=2; - (*size)-=4; - } - } - - //16 divisble width(needed for shared memory only, - //but applied anyway since theora wants it, too) - //we already have divisibility by 8 so module - //by 16 is euther 8 or 0 - hexoffset=((*size)%16); - if(hexoffset){ - if(((*size)+(*start)+4<=limit)&&((*start)>=4)){ - (*start)-=4; - (*size)+=8; - } - else if((*size)+(*start)+8<=limit){ - (*size)+=8; - } - else if((*start)>=8){ - (*start)-=8; - (*size)+=8; - } - else{ - (*start)+=4; - (*size)-=8; - } - } - -} - - - -int SetBRWindow(Display *dpy, - BRWindow *brwin, - DisplaySpecs *specs, - ProgArgs *args){ - //before we start recording we have to make sure the ranges are valid - if(args->windowid==0){//root window - //first set it up - brwin->windowid=specs->root; - brwin->geom.x=brwin->geom.y=0; - brwin->geom.width=specs->width; - brwin->geom.height=specs->height; - brwin->rgeom.x=args->x; - brwin->rgeom.y=args->y; - brwin->rgeom.width=((args->width)? - args->width:specs->width-brwin->rgeom.x); - brwin->rgeom.height=((args->height)? - args->height:specs->height-brwin->rgeom.y); - //and then check validity - if((brwin->rgeom.x+brwin->rgeom.width>specs->width)|| - (brwin->rgeom.y+brwin->rgeom.height>specs->height)){ - fprintf(stderr,"Window size specification out of bounds!" - "(current resolution:%dx%d)\n", - specs->width,specs->height); - return 1; - } - } - else{ - Window wchid; - int transl_x,transl_y; - - XWindowAttributes attribs; - XGetWindowAttributes(dpy,args->windowid,&attribs); - if((attribs.map_state==IsUnviewable)||(attribs.map_state==IsUnmapped)){ - fprintf(stderr,"Window must be mapped and visible!\n"); - return 1; - } - XTranslateCoordinates(dpy, - specs->root, - args->windowid, - attribs.x, - attribs.y, - &transl_x, - &transl_y, - &wchid); - - brwin->geom.x=attribs.x-transl_x; - brwin->geom.y=attribs.y-transl_y; - brwin->geom.width=attribs.width; - brwin->geom.height=attribs.height; - if((brwin->geom.x+brwin->geom.width>specs->width)|| - (brwin->geom.y+brwin->geom.height>specs->height)){ - fprintf(stderr,"Window must be on visible screen area!\n"); - return 1; - } - - brwin->rgeom.x=brwin->geom.x+args->x; - brwin->rgeom.y=brwin->geom.y+args->y; - brwin->rgeom.width=((args->width)? - args->width:brwin->geom.width-args->x); - brwin->rgeom.height=((args->height)? - args->height:brwin->geom.height-args->y); - if((args->x+brwin->rgeom.width>brwin->geom.width)|| - (args->y+brwin->rgeom.height>brwin->geom.height)){ - fprintf(stderr,"Specified Area is larger than window!\n"); - return 1; - } - } - fprintf(stderr, "Initial recording window is set to:\n" - "X:%d Y:%d Width:%d Height:%d\n", - brwin->rgeom.x,brwin->rgeom.y, - brwin->rgeom.width,brwin->rgeom.height); - SizePack2_8_16(&brwin->rgeom.x,&brwin->rgeom.width,specs->width); - SizePack2_8_16(&brwin->rgeom.y,&brwin->rgeom.height,specs->height); - - fprintf(stderr, "Adjusted recording window is set to:\n" - "X:%d Y:%d Width:%d Height:%d\n", - brwin->rgeom.x,brwin->rgeom.y, - brwin->rgeom.width,brwin->rgeom.height); - - - - brwin->nbytes=(((brwin->rgeom.width+15)>>4)<<4)* - (((brwin->rgeom.height+15)>>4)<<4)* - ((specs->depth==16)?2:4); - - return 0; -} diff --git a/recordmydesktop/src/setbrwindow.h b/recordmydesktop/src/setbrwindow.h deleted file mode 100644 index 0ed9c93..0000000 --- a/recordmydesktop/src/setbrwindow.h +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef SETBRWINDOW_H -#define SETBRWINDOW_H 1 - -#include "rmdtypes.h" - - -/** -* Check and align window size -* -* \param dpy Connection to the server -* -* \param brwin BRWindow struct contaning the initial and final window -* -* \param specs DisplaySpecs struct with -* information about the display to be recorded -* -* \param args ProgArgs struct containing the user-set options -* -* \returns 0 on Success 1 on Failure -*/ -int SetBRWindow(Display *dpy, - BRWindow *brwin, - DisplaySpecs *specs, - ProgArgs *args); - - -#endif diff --git a/recordmydesktop/src/shortcuts.c b/recordmydesktop/src/shortcuts.c deleted file mode 100644 index a449f57..0000000 --- a/recordmydesktop/src/shortcuts.c +++ /dev/null @@ -1,152 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include -#include -#include -#include -#include - -#include "rmdtypes.h" -#include "shortcuts.h" - -int RegisterShortcut(Display *dpy, - Window root, - const char *shortcut, - HotKey *hotkey){ - - int keycode=0, - i, j ; - KeySym key=0; - unsigned int modifier_mask=0, - numlock_mask=0; - char *keystr=NULL; - XModifierKeymap *modmap; - - if(strstr(shortcut,"Shift")) - modifier_mask = modifier_mask|ShiftMask; - if(strstr(shortcut,"Control")) - modifier_mask = modifier_mask|ControlMask; - if(strstr(shortcut,"Mod1")) - modifier_mask = modifier_mask|Mod1Mask; - if(strstr(shortcut,"Mod2")) - modifier_mask = modifier_mask|Mod2Mask; - if(strstr(shortcut,"Mod3")) - modifier_mask = modifier_mask|Mod3Mask; - if(strstr(shortcut,"Mod4")) - modifier_mask = modifier_mask|Mod4Mask; - if(strstr(shortcut,"Mod5")) - modifier_mask = modifier_mask|Mod5Mask; - - //we register the shortcut on the root - //window, which means on every keypress event, - //so I think it's neccessary to have at least one - //modifier. - if(modifier_mask == 0) - return 1; - if((keystr=rindex(shortcut,'+'))!=NULL){ - keystr++; - if((key=XStringToKeysym(keystr))==NoSymbol) - return 1; - else - keycode=XKeysymToKeycode(dpy,key); - } - else - return 1; - - - /* Key grabbing stuff taken from tilda who took it from yeahconsole - * who took it from evilwm */ - - modmap = XGetModifierMapping(dpy); - for(i=0;i<8;i++){ - for(j=0;jmax_keypermod;j++){ - if(modmap->modifiermap[i*modmap->max_keypermod+j]== - XKeysymToKeycode(dpy,XK_Num_Lock)) - numlock_mask=(1<modnum=0; - hotkey->key=keycode; - - XGrabKey(dpy, - keycode, - modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[0]=modifier_mask; - hotkey->modnum++; - - XGrabKey(dpy, - keycode, - LockMask | modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[1]=LockMask | modifier_mask; - hotkey->modnum++; - - if(numlock_mask){ - - XGrabKey(dpy, - keycode, - numlock_mask | modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[2]=numlock_mask | modifier_mask; - hotkey->modnum++; - - XGrabKey(dpy, - keycode, - numlock_mask | LockMask | modifier_mask, - root, - True, - GrabModeAsync, - GrabModeAsync); - hotkey->mask[3]=numlock_mask | LockMask | modifier_mask; - hotkey->modnum++; - - } - - return 0; - -} - - - - - - diff --git a/recordmydesktop/src/shortcuts.h b/recordmydesktop/src/shortcuts.h deleted file mode 100644 index ea93ba2..0000000 --- a/recordmydesktop/src/shortcuts.h +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef SHORTCUTS_H -#define CHORTCUTS_H 1 - -#include "rmdtypes.h" - - -/* - * Check a shortcut combination and if valid, - * register it, on the root window. - * - * \param dpy Connection to the X Server - * - * \param root Root window id - * - * \param shortcut String represantation of the shortcut - * - * \param HotKey Pre-allocated struct that is filled with the - * modifiers and the keycode, for checks on incoming - * keypress events. Left untouched if the call fails. - * - * - * \returns 0 on Success, 1 on Failure. - * - */ -int RegisterShortcut(Display *dpy, - Window root, - const char *shortcut, - HotKey *hotkey); - - -#endif diff --git a/recordmydesktop/src/specsfile.c b/recordmydesktop/src/specsfile.c deleted file mode 100644 index a34037f..0000000 --- a/recordmydesktop/src/specsfile.c +++ /dev/null @@ -1,167 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include - -#include "rmdtypes.h" -#include "specsfile.h" - - -int WriteSpecsFile(ProgData *pdata){ - - FILE *fp; - - - fp=fopen(pdata->cache_data->specsfile,"wb"); - if(fp==NULL) - return 1; - else{ - - fprintf(fp,"recordMyDesktop = %s\n",VERSION); - fprintf(fp,"Width = %d\n",pdata->brwin.rgeom.width); - fprintf(fp,"Height = %d\n",pdata->brwin.rgeom.height); - fprintf(fp,"Filename = %s\n",pdata->args.filename); - fprintf(fp,"FPS = %f\n",pdata->args.fps); - fprintf(fp,"NoSound = %d\n",pdata->args.nosound); - fprintf(fp,"Frequency = %d\n",pdata->args.frequency); - fprintf(fp,"Channels = %d\n",pdata->args.channels); - fprintf(fp,"BufferSize = %lu\n",pdata->args.buffsize); - fprintf(fp,"SoundFrameSize = %d\n",pdata->sound_framesize); - fprintf(fp,"PeriodSize = %lu\n",pdata->periodsize); - fprintf(fp,"UsedJack = %d\n",pdata->args.use_jack); - fprintf(fp,"v_bitrate = %d\n",pdata->args.v_bitrate); - fprintf(fp,"v_quality = %d\n",pdata->args.v_quality); - fprintf(fp,"s_quality = %d\n",pdata->args.s_quality); - fprintf(fp,"ZeroCompression = %d\n",pdata->args.zerocompression); - - - } - - fclose(fp); - return 0; - -} - -int ReadSpecsFile(ProgData *pdata){ - - - FILE *fp; - - - fp=fopen(pdata->cache_data->specsfile,"rb"); - if(fp==NULL) - return 1; - else{ - - char Cached_Version[256]; - free(pdata->args.filename); - pdata->args.filename=malloc(512); - - //Take that single-point-of-exit advocates !!! - //15 points of exit, just for your pleasure. - //Also, Vi(m) rules, emacs sucks. - - if(fscanf(fp,"recordMyDesktop = %s\n",Cached_Version)!=1){ - fprintf(stderr,"Error reading VERSION attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Width = %d\n",&pdata->brwin.rgeom.width)!=1){ - fprintf(stderr,"Error reading Width attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Height = %d\n",&pdata->brwin.rgeom.height)!=1){ - fprintf(stderr,"Error reading Height attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Filename = %s\n",pdata->args.filename)!=1){ - fprintf(stderr,"Error reading Filename attribute!!!\n"); - return 1; - } - if(fscanf(fp,"FPS = %f\n",&pdata->args.fps)!=1){ - fprintf(stderr,"Error reading FPS attribute!!!\n"); - return 1; - } - if(fscanf(fp,"NoSound = %d\n",&pdata->args.nosound)!=1){ - fprintf(stderr,"Error reading NoSound attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Frequency = %d\n",&pdata->args.frequency)!=1){ - fprintf(stderr,"Error reading Frequency attribute!!!\n"); - return 1; - } - if(fscanf(fp,"Channels = %d\n",&pdata->args.channels)!=1){ - fprintf(stderr,"Error reading Channels attribute!!!\n"); - return 1; - } - if(fscanf(fp,"BufferSize = %lu\n",&pdata->args.buffsize)!=1){ - fprintf(stderr,"Error reading BufferSize attribute!!!\n"); - return 1; - } - if(fscanf(fp,"SoundFrameSize = %d\n",&pdata->sound_framesize)!=1){ - fprintf(stderr,"Error reading SoundFrameSize attribute!!!\n"); - return 1; - } - if(fscanf(fp,"PeriodSize = %lu\n",&pdata->periodsize)!=1){ - fprintf(stderr,"Error reading PeriodSize attribute!!!\n"); - return 1; - } - if(fscanf(fp,"UsedJack = %u\n",&pdata->args.use_jack)!=1){ - fprintf(stderr,"Error reading UsedJack attribute!!!\n"); - return 1; - } - if(fscanf(fp,"v_bitrate = %d\n",&pdata->args.v_bitrate)!=1){ - fprintf(stderr,"Error reading v_bitrate attribute!!!\n"); - return 1; - } - if(fscanf(fp,"v_quality = %d\n",&pdata->args.v_quality)!=1){ - fprintf(stderr,"Error reading v_quality attribute!!!\n"); - return 1; - } - if(fscanf(fp,"s_quality = %d\n",&pdata->args.s_quality)!=1){ - fprintf(stderr,"Error reading s_quality attribute!!!\n"); - return 1; - } - if(fscanf(fp,"ZeroCompression = %d\n",&pdata->args.zerocompression)!=1){ - fprintf(stderr,"Error reading ZeroCompression attribute!!!\n"); - return 1; - } - - - } - - fclose(fp); - return 0; - -} - - - - - - diff --git a/recordmydesktop/src/specsfile.h b/recordmydesktop/src/specsfile.h deleted file mode 100644 index eed0942..0000000 --- a/recordmydesktop/src/specsfile.h +++ /dev/null @@ -1,59 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef SPECSFILE_H -#define SPECSFILE_H 1 - -#include "rmdtypes.h" - - -/* - * Create a text file that holds the required - * capture attributes, in the cache directory. - * - * \param pdata ProgData struct containing all program data - * - * \returns 0 on Success, 1 on failure - * - */ -int WriteSpecsFile(ProgData *pdata); - - - -/* - * Read the text file that holds the required - * capture attributes, in the cache directory. - * - * \param pdata ProgData struct that will be fille - * with all program data - * - * \returns 0 on Success, 1 on failure - * - */ -int ReadSpecsFile(ProgData *pdata); - - -#endif diff --git a/recordmydesktop/src/test-rectinsert-types.h b/recordmydesktop/src/test-rectinsert-types.h index dd2425e..b9f0c32 100644 --- a/recordmydesktop/src/test-rectinsert-types.h +++ b/recordmydesktop/src/test-rectinsert-types.h @@ -24,7 +24,7 @@ #define TEST_RECTINSERT_TYPES_H -#include "rmdtypes.h" +#include "rmd_types.h" #define STATE_WIDTH 20 diff --git a/recordmydesktop/src/test-rectinsert.c b/recordmydesktop/src/test-rectinsert.c index d79d2f8..28eb665 100644 --- a/recordmydesktop/src/test-rectinsert.c +++ b/recordmydesktop/src/test-rectinsert.c @@ -22,10 +22,10 @@ #include "config.h" -#include "rmdtypes.h" -#include "test-rectinsert-types.h" +#include "rmd_types.h" +#include "rmd_rectinsert.h" -#include "rectinsert.h" +#include "test-rectinsert-types.h" #include "test-rectinsert-data.h" diff --git a/recordmydesktop/src/update_image.c b/recordmydesktop/src/update_image.c deleted file mode 100644 index 7d22cc9..0000000 --- a/recordmydesktop/src/update_image.c +++ /dev/null @@ -1,86 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include -#include -#include - -#include "rmdtypes.h" - -#include "getzpixmap.h" -#include "update_image.h" -#include "yuv_utils.h" - - -void UpdateImage(Display * dpy, - yuv_buffer *yuv, - DisplaySpecs *specs, - RectArea **root, - BRWindow *brwin, - EncData *enc, - char *datatemp, - int noshmem, - XShmSegmentInfo *shminfo, - int shm_opcode, - int no_quick_subsample){ - RectArea *temp; - unsigned char *dtap=(unsigned char*)datatemp; - temp=*root; - - if(temp!=NULL){ - do{ - if(noshmem){ - GetZPixmap( dpy, - specs->root, - datatemp, - temp->geom.x, - temp->geom.y, - temp->geom.width, - temp->geom.height); - } - else{ - GetZPixmapSHM(dpy, - specs->root, - shminfo, - shm_opcode, - datatemp,temp->geom.x, - temp->geom.y, - temp->geom.width, - temp->geom.height); - } - UPDATE_YUV_BUFFER(yuv,dtap,NULL, - (temp->geom.x-brwin->rgeom.x+enc->x_offset), - (temp->geom.y-brwin->rgeom.y+enc->y_offset), - (temp->geom.width),(temp->geom.height), - no_quick_subsample, - specs->depth); - temp=temp->next; - }while(temp!=NULL); - } -} - diff --git a/recordmydesktop/src/update_image.h b/recordmydesktop/src/update_image.h deleted file mode 100644 index 7c67e25..0000000 --- a/recordmydesktop/src/update_image.h +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef UPDATE_IMAGE_H -#define UPDATE_IMAGE_H 1 - -#include "rmdtypes.h" - - -/** -* Retrieve and apply all changes, if xdamage is used. -* -* \param dpy Connection to the server -* -* \param yuv yuv_buffer that is to be modified -* -* \param specs DisplaySpecs struct with -* information about the display to be recorded -* -* \param root Root entry of the list with damaged areas -* -* \param brwin BRWindow struct contaning the recording window specs -* -* \param enc Encoding options -* -* \param datatemp Buffer for pixel data to be -* retrieved before placed on the yuv buffer -* -* \param noshmem don't use MIT_Shm extension -* -* \param no_quick_subsample Don't do quick subsampling -* -*/ -void UpdateImage(Display * dpy, - yuv_buffer *yuv, - DisplaySpecs *specs, - RectArea **root, - BRWindow *brwin, - EncData *enc, - char *datatemp, - int noshmem, - XShmSegmentInfo *shminfo, - int shm_opcode, - int no_quick_subsample); - - -#endif diff --git a/recordmydesktop/src/wm_check.c b/recordmydesktop/src/wm_check.c deleted file mode 100644 index 79bff6b..0000000 --- a/recordmydesktop/src/wm_check.c +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include - -#include "rmdtypes.h" - -#include "wm_check.h" - - -char *rmdWMCheck(Display *dpy,Window root){ - - Window *wm_child=NULL; - Atom nwm_atom, - utf8_string, - wm_name_atom, - rt; - unsigned long nbytes, - nitems; - - char *wm_name_str=NULL; - int fmt; - - utf8_string = XInternAtom(dpy, "UTF8_STRING", False); - - nwm_atom =XInternAtom(dpy,"_NET_SUPPORTING_WM_CHECK",True); - wm_name_atom =XInternAtom(dpy,"_NET_WM_NAME",True); - - if(nwm_atom!=None && wm_name_atom!=None){ - if(XGetWindowProperty( dpy,root,nwm_atom,0,100, - False,XA_WINDOW, - &rt,&fmt,&nitems, &nbytes, - (unsigned char **)((void*)&wm_child)) - != Success ){ - fprintf(stderr,"Error while trying to get a" - " window to identify the window manager.\n"); - } - if((wm_child == NULL)|| - (XGetWindowProperty(dpy,*wm_child,wm_name_atom,0,100, - False,utf8_string,&rt, - &fmt,&nitems, &nbytes, - (unsigned char **)((void*)&wm_name_str)) - !=Success)){ - fprintf(stderr,"Warning!!!\nYour window manager appears" - " to be non-compliant!\n"); - } - } - fprintf(stderr,"Your window manager appears to be %s\n\n", - ((wm_name_str!=NULL)?wm_name_str:"Unknown")); - - - return wm_name_str; -} - diff --git a/recordmydesktop/src/wm_check.h b/recordmydesktop/src/wm_check.h deleted file mode 100644 index 1867dc2..0000000 --- a/recordmydesktop/src/wm_check.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef WM_CHECK_H -#define WM_CHECK_H 1 - -#include "rmdtypes.h" - - -/** -*Check current running window manager. -* -* \param dpy Connection to the server -* -* \param root root window of the display -* -* \returns Window manager name -*/ -char *rmdWMCheck(Display *dpy,Window root); - - -#endif diff --git a/recordmydesktop/src/yuv_utils.c b/recordmydesktop/src/yuv_utils.c deleted file mode 100644 index 742905e..0000000 --- a/recordmydesktop/src/yuv_utils.c +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 "config.h" - -#include "yuv_utils.h" - -// Keep these global (for performance reasons I assume). -unsigned char Yr[256], Yg[256], Yb[256], - Ur[256], Ug[256], UbVr[256], - Vg[256], Vb[256]; - -void MakeMatrices (void) { - int i; - - for (i = 0; i < 256; i++) - Yr[i] = (2104.0 * i) / 8192.0 + 8.0; - for (i = 0; i < 256; i++) - Yg[i] = (4130.0 * i) / 8192.0 + 8.0; - for (i = 0; i < 256; i++) - Yb[i] = (802.0 * i) / 8192.0; - - for (i = 0; i < 256; i++) - Ur[i] = 37.8 - (1204.0 * i) / 8192.0 + 8.0; - for (i = 0; i < 256; i++) - Ug[i] = 74.2 - (2384.0 * i) / 8192.0 + 8.0; - for (i = 0; i < 256; i++) - UbVr[i] = (3598.0 * i) / 8192.0 ; - - for (i = 0; i < 256; i++) - Vg[i] = 93.8 - (3013.0 * i) / 8192.0 + 8.0; - for (i = 0; i < 256; i++) - Vb[i] = 18.2 - (585.0 * i) / 8192.0 + 8.0; -} diff --git a/recordmydesktop/src/yuv_utils.h b/recordmydesktop/src/yuv_utils.h deleted file mode 100644 index 7b417b6..0000000 --- a/recordmydesktop/src/yuv_utils.h +++ /dev/null @@ -1,247 +0,0 @@ -/****************************************************************************** -* recordMyDesktop * -******************************************************************************* -* * -* Copyright (C) 2006,2007,2008 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 * -******************************************************************************/ - -#ifndef YUV_UTILS_H -#define YUV_UTILS_H 1 - -#include "rmdtypes.h" -#include "block_utils.h" -#include "rmdmacro.h" - - -// The macros work directly on this data (for performance reasons I -// suppose) so we keep this global -extern unsigned char Yr[256], Yg[256], Yb[256], - Ur[256], Ug[256], UbVr[256], - Vg[256], Vb[256]; - - -//when adding the r values, we go beyond -//the (16 bit)range of the t_val variable, but we are performing -//32 bit arithmetics, so there's no problem. -//(This note is useless, I'm just adding because -//the addition of the A components in CALC_TVAL_AVG_32, -//now removed as uneeded, produced an overflow which would have caused -//color distrtion, where it one of the R,G or B components) -#define CALC_TVAL_AVG_16(t_val,datapi,datapi_next){\ - register u_int16_t t1,t2,t3,t4;\ - t1=*datapi;\ - t2=*(datapi+1);\ - 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);\ -} - -//the 4 most significant bytes represent the A component which -//does not need to be added on t_val, as it is always unused -#define CALC_TVAL_AVG_32(t_val,datapi,datapi_next){\ - register unsigned int t1,t2,t3,t4;\ - t1=*datapi;\ - t2=*(datapi+1);\ - t3=*datapi_next;\ - t4=*(datapi_next+1);\ - t_val=((((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 UPDATE_Y_PLANE(data,\ - x_tm,\ - y_tm,\ - height_tm,\ - width_tm,\ - yuv,\ - __bit_depth__){ \ - int k,i;\ - register u_int##__bit_depth__##_t t_val;\ - register unsigned char *yuv_y=yuv->y+x_tm+y_tm*yuv->y_width,\ - *_yr=Yr,*_yg=Yg,*_yb=Yb;\ - register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data;\ - for(k=0;ky_width-width_tm;\ - }\ -} - -#define UPDATE_A_UV_PIXEL(yuv_u,\ - yuv_v,\ - t_val,\ - datapi,\ - datapi_next,\ - _ur,_ug,_ubvr,_vg,_vb,\ - __sampling_type,\ - __bit_depth__)\ - if(__sampling_type==__PXL_AVERAGE){\ - CALC_TVAL_AVG_##__bit_depth__(t_val,datapi,datapi_next)\ - }\ - else\ - t_val=*datapi;\ - *yuv_u=\ - _ur[__RVALUE_##__bit_depth__(t_val)] +\ - _ug[__GVALUE_##__bit_depth__(t_val)] +\ - _ubvr[__BVALUE_##__bit_depth__(t_val)];\ - *yuv_v=\ - _ubvr[__RVALUE_##__bit_depth__(t_val)] +\ - _vg[__GVALUE_##__bit_depth__(t_val)] +\ - _vb[__BVALUE_##__bit_depth__(t_val)];\ - - -#define UPDATE_UV_PLANES(data,\ - x_tm,\ - y_tm,\ - height_tm,\ - width_tm,\ - yuv,\ - __sampling_type,\ - __bit_depth__){ \ - int k,i;\ - register u_int##__bit_depth__##_t t_val;\ - register unsigned char *yuv_u=yuv->u+x_tm/2+(y_tm*yuv->uv_width)/2,\ - *yuv_v=yuv->v+x_tm/2+(y_tm*yuv->uv_width)/2,\ - *_ur=Ur,*_ug=Ug,*_ubvr=UbVr,\ - *_vg=Vg,*_vb=Vb;\ - register u_int##__bit_depth__##_t *datapi=(u_int##__bit_depth__##_t *)data,\ - *datapi_next=NULL;\ - if(__sampling_type==__PXL_AVERAGE){\ - datapi_next=datapi+width_tm;\ - }\ - for(k=0;ky_width-width_tm)/2;\ - yuv_v+=(yuv->y_width-width_tm)/2;\ - datapi+=width_tm;\ - if(__sampling_type==__PXL_AVERAGE)\ - datapi_next+=width_tm;\ - }\ -} - -#define UPDATE_YUV_BUFFER(yuv,\ - data,\ - data_back,\ - x_tm,\ - y_tm,\ - width_tm,\ - height_tm,\ - __sampling_type,\ - __color_depth){\ - if(data_back==NULL){\ - if((__color_depth==24)||(__color_depth==32)){\ - UPDATE_Y_PLANE(data,x_tm,y_tm,height_tm,width_tm,yuv,32)\ - UPDATE_UV_PLANES(data,x_tm,y_tm,height_tm,width_tm,\ - yuv,__sampling_type,32)\ - }\ - else if(__color_depth==16){\ - UPDATE_Y_PLANE(data,x_tm,y_tm,height_tm,width_tm,yuv,16)\ - UPDATE_UV_PLANES(data,x_tm,y_tm,height_tm,width_tm,\ - yuv,__sampling_type,16)\ - }\ - }\ - else{\ - if((__color_depth==24)||(__color_depth==32)){\ - UPDATE_Y_PLANE_DBUF(data,data_back,x_tm,y_tm,\ - height_tm,width_tm,yuv,32)\ - UPDATE_UV_PLANES_DBUF(data,data_back,x_tm,y_tm,height_tm,width_tm,\ - yuv,__sampling_type,32)\ - }\ - else if(__color_depth==16){\ - UPDATE_Y_PLANE_DBUF(data,data_back,x_tm,y_tm,\ - height_tm,width_tm,yuv,16)\ - UPDATE_UV_PLANES_DBUF(data,data_back,x_tm,y_tm,height_tm,width_tm,\ - yuv,__sampling_type,16)\ - }\ - }\ -} - -#define DUMMY_POINTER_TO_YUV(yuv,\ - data_tm,\ - x_tm,\ - y_tm,\ - width_tm,\ - height_tm,\ - x_offset,\ - y_offset,\ - no_pixel){\ - int i,k,j=0;\ - int x_2=x_tm/2,y_2=y_tm/2,y_width_2=(yuv)->y_width/2;\ - for(k=y_offset;ky[x_tm+(i-x_offset)+((k-y_offset)+y_tm)*(yuv)->y_width]=\ - Yr[data_tm[(j*4)+__RBYTE]] +\ - Yg[data_tm[(j*4)+__GBYTE]] +\ - Yb[data_tm[(j*4)+__BBYTE]];\ - if((k%2)&&(i%2)){\ - yuv->u[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*y_width_2]=\ - Ur[data_tm[(k*width_tm+i)*4+__RBYTE]] +\ - Ug[data_tm[(k*width_tm+i)*4+__GBYTE]] +\ - UbVr[data_tm[(k*width_tm+i)*4+__BBYTE]];\ - yuv->v[x_2+(i-x_offset)/2+((k-y_offset)/2+y_2)*y_width_2]=\ - UbVr[data_tm[(k*width_tm+i)*4+__RBYTE]] +\ - Vg[data_tm[(k*width_tm+i)*4+__GBYTE]] +\ - Vb[data_tm[(k*width_tm+i)*4+__BBYTE]] ;\ - }\ - }\ - }\ - }\ -} - -/** -* Fill Yr,Yg,Yb,Ur,Ug.Ub,Vr,Vg,Vb arrays(globals) with values. -*/ -void MakeMatrices(void); - - -#endif -- cgit v1.2.3