1 /******************************************************************************
2 *                            recordMyDesktop                                  *
3 *******************************************************************************
4 *                                                                             *
5 *            Copyright (C) 2006,2007,2008 John Varouhakis                     *
6 *                                                                             *
7 *                                                                             *
8 *   This program is free software; you can redistribute it and/or modify      *
9 *   it under the terms of the GNU General Public License as published by      *
10 *   the Free Software Foundation; either version 2 of the License, or         *
11 *   (at your option) any later version.                                       *
12 *                                                                             *
13 *   This program is distributed in the hope that it will be useful,           *
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
16 *   GNU General Public License for more details.                              *
17 *                                                                             *
18 *   You should have received a copy of the GNU General Public License         *
19 *   along with this program; if not, write to the Free Software               *
20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *
21 *                                                                             *
22 *   For further information contact me at johnvarouhakis@gmail.com            *
23 ******************************************************************************/
24 
25 #ifndef RMDTYPES_H
26 #define RMDTYPES_H 1
27 
28 #include "config.h"
29 
30 #include <stdio.h>
31 #include <pthread.h>
32 #include <zlib.h>
33 #include <X11/Xlib.h>
34 #include <theora/theora.h>
35 #include <vorbis/codec.h>
36 #include <vorbis/vorbisenc.h>
37 #include <ogg/ogg.h>
38 
39 #ifdef HAVE_LIBASOUND
40     #include <alsa/asoundlib.h>
41 
42     #define DEFAULT_AUDIO_DEVICE "hw:0,0"
43 #else
44     #include <sys/ioctl.h>
45     #include <sys/soundcard.h>
46 
47     #define DEFAULT_AUDIO_DEVICE "/dev/dsp"
48 #endif
49 
50 #ifdef HAVE_LIBJACK
51     #include <jack/jack.h>
52     #include <jack/ringbuffer.h>
53 #endif
54 
55 
56 //this type exists only
57 //for comparing the planes at caching.
58 //u_int64_t mught not be available everywhere.
59 //The performance gain comes from casting the unsigned char
60 //buffers to this type before comparing the two blocks.
61 //This is made possible by the fact that blocks
62 //for the Y plane are 16 bytes in width and blocks
63 //for the U,V planes are 8 bytes in width
64 #ifdef HAVE_U_INT64_T
65 typedef u_int64_t cmp_int_t;
66 #else
67 typedef u_int32_t cmp_int_t;
68 #endif
69 
70 //type of pixel proccessing for the Cb,Cr planes
71 //when converting from full rgb to 4:2:2 Ycbcr
72 enum{
73     __PXL_DISCARD,  //only select 1 pixel in every block of four
74     __PXL_AVERAGE   //calculate the average of all four pixels
75 };
76 
77 // Boolean type
78 typedef int boolean;
79 #ifndef FALSE
80 #define FALSE (0)
81 #endif
82 #ifndef TRUE
83 #define TRUE  (!FALSE)
84 #endif
85 
86 // Forward declarations
87 typedef struct _ProgData ProgData;
88 
89 typedef struct _DisplaySpecs{   //this struct holds some basic information
90     int screen;                 //about the display,needed mostly for
91     unsigned int width, height; //validity checks at startup
92     Window root;
93     Visual *visual;
94     GC gc;
95     int depth;
96 }DisplaySpecs;
97 
98 typedef struct _RectArea{   //an area that has been damaged gets stored
99     XRectangle rect;         //in a list comprised of structs of this type
100     struct _RectArea *prev,*next;
101 }RectArea;
102 
103 typedef struct _BRWindow{   //'basic recorded window' specs
104     XRectangle rect;         //window attributes
105     XRectangle rrect;        //part of window that is recorded
106     int nbytes;             //size of zpixmap when screenshoting
107     Window windowid;        //id
108 }BRWindow;
109 
110 //defaults in the following comment lines may be out of sync with reality
111 //check the SetupDefaultArgs() function further bellow
112 typedef struct _ProgArgs{
113     int delay;          //start up delay
114     Window windowid;    //window to record(default root)
115     char *display;      //display to connect(default :0)
116     int x,y;            //x,y offset(default 0,0)
117     unsigned int width,height;   //defaults to window width and height
118     char *filename;     //output file(default out.[ogg|*])
119     int cursor_color;   //black or white=>1 or 0
120     int have_dummy_cursor;  //disable/enable drawing of the dummy cursor
121     int xfixes_cursor;      //disable/enable drawing of a cursor obtained
122                             //through the xfixes extension
123     float fps;              //desired framerate(default 15)
124     unsigned int frequency;     //desired frequency (default 22050)
125     unsigned int channels;      //no of channels(default 2)
126     char *device;               //default sound device
127 #ifdef HAVE_LIBASOUND
128     snd_pcm_uframes_t buffsize; //buffer size(in frames) for sound capturing
129 #else
130     u_int32_t buffsize;
131 #endif
132     const char* rescue_path;
133     int nosound;        //do not record sound(default 0)
134     int noshared;       //do not use shared memory extension(default 0)
135     int nowmcheck;      //do not check if there's a 3d comp window manager
136                         //(which changes full-shots and with-shared to 1)
137     int full_shots;     //do not poll damage, take full screenshots
138     int follow_mouse;   //capture area follows the mouse(fullshots auto enabled)
139     int no_encode;      //do not encode or delete the temporary files(debug opt)
140     int no_quick_subsample;             //average pixels in chroma planes
141     int v_bitrate,v_quality,s_quality;  //video bitrate,video-sound quality
142     int encOnTheFly;    //encode while recording, no caching(default 0)
143     char *workdir;      //directory to be used for cache files(default $HOME)
144     char *pause_shortcut;   //pause/unpause shortcut sequence(Control+Alt+p)
145     char *stop_shortcut;    //stop shortcut sequence(Control+Alt+s)
146     int noframe;            //don't draw a frame around the recording area
147     int zerocompression;    //image data are always flushed uncompressed
148     int overwrite;          //overwite a previously existing file
149                             //(do not add a .number postfix)
150     int use_jack;           //record audio with jack
151     unsigned int jack_nports;
152     char **jack_port_names;
153     float jack_ringbuffer_secs;
154 }ProgArgs;
155 
156 //this struct holds anything related to encoding AND
157 //writting out to file.
158 typedef struct _EncData{
159     ogg_stream_state m_ogg_ts;  //theora
160     ogg_stream_state m_ogg_vs;  //vorbis
161     ogg_page         m_ogg_pg;  //this could be avoided since
162                                 // it is used only while initializing
163     ogg_packet       m_ogg_pckt1;   //theora stream
164     ogg_packet       m_ogg_pckt2;   //vorbis stream
165 //theora data
166     theora_state     m_th_st;
167     theora_info      m_th_inf;
168     theora_comment   m_th_cmmnt;
169     yuv_buffer       yuv;
170 //vorbis data
171     vorbis_info      m_vo_inf;
172     vorbis_comment   m_vo_cmmnt;
173     vorbis_dsp_state m_vo_dsp;
174     vorbis_block     m_vo_block;
175 //these should be 0, since area is quantized
176 //before input
177     int             x_offset,
178                     y_offset;
179 //our file
180     FILE            *fp;
181 }EncData;
182 
183 //this struct will hold a few basic
184 //information, needed for caching the frames.
185 typedef struct _CacheData{
186     char    *workdir,   //The directory were the project
187                         //will be stored, while recording.
188                         //Since this will take a lot of space, the user must be
189                         //able to change the location.
190             *projname,  //This is the name of the folder that
191                         //will hold the project.
192                         //It is rMD-session-%d where %d is the pid
193                         //of the current proccess.
194                         //This way, running two instances
195                         //will not create problems
196                         //and also, a frontend can identify
197                         //leftovers from a possible crash
198                         //and delete them
199             *specsfile, //workdir+projname+specs.txt
200             *imgdata,   //workdir+projname+img.out.gz
201             *audiodata; //workdir+projname+audio.pcm
202 
203     gzFile  *ifp;       //image data file pointer
204     FILE    *uncifp;    //uncompressed image data file pointer
205 
206     FILE    *afp;       //audio data file pointer
207 
208 }CacheData;
209 
210 //sound buffer
211 //sound keeps coming so we que it in this list
212 //which we then traverse
213 typedef struct _SndBuffer{
214     signed char *data;
215     struct _SndBuffer *next;
216 }SndBuffer;
217 
218 #ifdef HAVE_LIBJACK
219 typedef struct _JackData{
220     ProgData *pdata;            //pointer to prog data
221     jack_client_t   *client;
222     unsigned int    buffersize, //buffer size for every port in frames.
223                     frequency,  //samplerate with which jack server was started.
224                     nports;     //number of ports.
225     float           ringbuffer_secs;
226     char **port_names;          //names of ports(as specified in args).
227     jack_port_t **ports;        //connections to thes ports.
228     jack_default_audio_sample_t **portbuf;  //retrieval of audio buffers.
229     pthread_mutex_t *snd_buff_ready_mutex;  //mutex and cond_var
230     pthread_cond_t *sound_data_read;        //in the pdata struct
231     jack_ringbuffer_t *sound_buffer;        //data exchange happens through this
232     int capture_started;        //used to hold recording in the beginning
233 }JackData;
234 #endif
235 
236 typedef struct _HotKey{     //Hold info about the shortcuts
237     int modnum;             //modnum is the number of modifier masks
238     unsigned int mask[4];  //that should be checked (the initial
239     int key;                //user requested modifier plus it's
240 }HotKey;                    //combinations with LockMask and NumLockMask).
241 
242 //this structure holds any data related to the program
243 //It's usage is mostly to be given as an argument to the
244 //threads,so they will have access to the program data, avoiding
245 //at the same time usage of any globals.
246 struct _ProgData {
247 /**recordMyDesktop specific structs*/
248     ProgArgs args;          //the program arguments
249     DisplaySpecs specs;     //Display specific information
250     BRWindow brwin;         //recording window
251     RectArea *rect_root;    //the interchanging list roots for storing
252                             //the changed regions
253     SndBuffer   *sound_buffer;
254     EncData     *enc_data;
255     CacheData   *cache_data;
256     HotKey      pause_key,  //Shortcuts
257                 stop_key;
258 #ifdef HAVE_LIBJACK
259     JackData    *jdata;
260 #endif
261 /**X related info*/
262     Display *dpy;           //curtrent display
263 /** Mutexes*/
264     pthread_mutex_t sound_buffer_mutex,
265                     snd_buff_ready_mutex,
266                     img_buff_ready_mutex,
267                     theora_lib_mutex,
268                     vorbis_lib_mutex,
269                     libogg_mutex,   //libogg is not thread safe,
270                     yuv_mutex;  //this might not be needed since we only have
271                                 //one read-only and  one write-only thread
272                                 //also on previous versions,
273                                 //y component was looped separately
274                                 //and then u and v so this was needed
275                                 //to avoid wrong coloring to render
276                                 //Currently this mutex only prevents
277                                 //the cursor from flickering
278 /**Condition Variables*/
279     pthread_cond_t  time_cond,  //this gets a broadcast by the handler
280                                 //whenever it's time to get a screenshot
281                     pause_cond, //this is blocks execution,
282                                 //when program is paused
283                     sound_data_read,    //a buffer is ready for proccessing
284                     image_buffer_ready, //image encoding finished
285                     theora_lib_clean,   //the flush_ogg thread cannot
286                                         //procceed to creating last
287                     vorbis_lib_clean;   //packages until these two libs
288                                         //are no longer used, by other threads
289 /**Buffers,Flags and other vars*/
290     unsigned char *dummy_pointer,   //a dummy pointer to be drawn
291                                     //in every frame
292                                     //data is casted to unsigned for
293                                     //later use in YUV buffer
294                   npxl;     //this is the no pixel convention
295                             //when drawing the dummy pointer
296     unsigned int periodtime,//time that a sound buffer lasts (microsecs)
297                 frametime;  //time that a frame lasts (microsecs)
298     Window  shaped_w;       //frame
299     int damage_event,       //damage event base code
300         damage_error,       //damage error base code
301         shm_opcode,         //MIT-Shm opcode
302         dummy_p_size,       //dummy pointer size,initially 16x16,always square
303         th_encoding_clean,      //thread exit inidcator
304         v_encoding_clean,       //  >>  >>
305         v_enc_thread_waiting,   //these indicate a wait
306         th_enc_thread_waiting,  //condition on the cond vars.
307         timer_alive,        //determines loop of timer thread
308         hard_pause,         //if sound device doesn't support pause
309                             //we have to close and reopen
310         avd,                //syncronization among audio and video
311         sound_framesize;    //size of each sound frame
312 
313     /** Progam state vars */
314     boolean running;             //1 while the program is capturing/paused/encoding
315     boolean paused;              //1 while the program is paused
316     boolean aborted;             //1 if we should abort
317     boolean pause_state_changed; //1 if pause state changed
318 
319     //the following values are of no effect
320     //but they might be usefull later for profiling
321     unsigned int    frames_total,   //frames calculated by total time expirations
322                     frames_lost;    //the value of shame
323 
324     //used to determine frame drop which can
325     //happen on failure to receive a signal over a condition variable
326     boolean capture_busy,
327             encoder_busy;
328 
329     pthread_mutex_t pause_mutex;
330     pthread_mutex_t time_mutex;
331 
332 #ifdef HAVE_LIBASOUND
333     snd_pcm_t *sound_handle;
334     snd_pcm_uframes_t periodsize;
335 #else
336     int sound_handle;
337     u_int32_t periodsize;
338 #endif
339 };
340 
341 
342 //This is the header of every frame.
343 //Reconstruction will be correct only if made on
344 //the same platform.
345 
346 //We need the total number of blocks
347 //for each plane.
348 
349 //The number of the frame compared to the
350 //number of time expirations at the time of
351 //caching, will enable us to make up for lost frames.
352 
353 
354 typedef struct _FrameHeader{
355     char        frame_prefix[4];    //always FRAM
356     u_int32_t   frameno,            //number of frame(cached frames)
357                 current_total;      //number of frames that should have been
358                                     //taken at time of caching this one
359     u_int32_t   Ynum,   //number of changed blocks in the Y plane
360                 Unum,   //number of changed blocks in the U plane
361                 Vnum;   //number of changed blocks in the V plane
362 }FrameHeader;
363 
364 #endif
365 
366