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 *                                                                             *
23 *                                                                             *
24 *   For further information contact me at johnvarouhakis@gmail.com            *
25 ******************************************************************************/
26 
27 #include "config.h"
28 #include "rmd_parseargs.h"
29 
30 #include "rmd_types.h"
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 
PrintConfig(void)37 static void PrintConfig(void) {
38     fprintf(stderr,"\nrecordMyDesktop was compiled with"
39                    " the following options:\n\n");
40 #ifdef HAVE_LIBJACK
41     fprintf(stdout,"Jack\t\t\t:Enabled\n");
42 #else
43     fprintf(stdout,"Jack\t\t\t:Disabled\n");
44 #endif
45 #ifdef HAVE_LIBASOUND
46     fprintf(stdout,"Default Audio Backend\t:ALSA\n");
47 #else
48     fprintf(stdout,"Default Audio Backend\t:OSS\n");
49 #endif
50     fprintf(stderr,"\n\n");
51 }
52 
53 /**
54  * Still has backwards compatible options like -this, but --this is
55  * what is documented.
56  */
ParseArgs(int argc,char ** argv,ProgArgs * arg_return)57 boolean ParseArgs(int argc, char **argv, ProgArgs *arg_return) {
58     int i;
59     char *usage="\nUsage:\n"
60     "\trecordmydesktop [OPTIONS]^filename\n\n\n"
61 
62     "General Options:\n"
63     "\t-h or --help\t\tPrint this help and exit.\n"
64     "\t--version\t\tPrint program version and exit.\n"
65     "\t--print-config\t\tPrint info about options "
66     "selected during compilation and exit.\n\n"
67 
68     "Image Options:\n"
69     "\t--windowid id_of_window\tid of window to be recorded.\n"
70     "\t--display DISPLAY\tDisplay to connect to.\n"
71     "\t-x X\t\t\tOffset in x direction.\n"
72     "\t-y Y\t\t\tOffset in y direction.\n"
73     "\t--width N\t\tWidth of recorded window.\n"
74     "\t--height N\t\tHeight of recorded window.\n\n"
75 
76     "\t--dummy-cursor color\tColor of the dummy cursor [black|white]\n"
77     "\t--no-cursor\t\tDisable drawing of the cursor.\n"
78     "\t--no-shared\t\tDisable usage of"
79     " MIT-shared memory extension(Not Recommended!).\n"
80 
81     "\t--full-shots\t\tTake full screenshot at every frame(Not recomended!).\n"
82     "\t--quick-subsampling\tDo subsampling"
83     " of the chroma planes by discarding,not averaging.\n"
84 
85     "\t--fps N(number>0.0)\tA positive number denoting desired framerate.\n\n"
86 
87     "Sound Options:\n"
88     "\t--channels N\t\t\tA positive number denoting"
89     " desired sound channels in recording.\n"
90 
91     "\t--freq N\t\t\t\tA positive number denoting desired sound frequency.\n"
92     "\t--buffer-size N\t\t\tA positive number denoting the desired"
93     " sound buffer size (in frames,when using ALSA or OSS)\n"
94     "\t--ring-buffer-size N\t\tA float number denoting the desired"
95     " ring buffer size (in seconds,when using JACK only).\n"
96 
97     "\t--device SOUND_DEVICE\t\tSound device(default "
98     DEFAULT_AUDIO_DEVICE
99     ").\n"
100     "\t--use-jack port1 port2... portn\tRecord audio from the specified\n"
101     "\t\t\t\t\tlist of space-separated jack ports.\n"
102     "\t--no-sound\t\t\tDo not record sound.\n\n"
103 
104     "Encoding Options\n"
105     "\t--on-the-fly-encoding\tEncode the audio-video data, while recording.\n"
106     "\t--v_quality n\t\tA number from 0 to 63 for"
107     " desired encoded video quality(default 63).\n"
108 
109     "\t--v_bitrate n\t\tA number from 0 to 2000000"
110     " for desired encoded video bitrate(default 0).\n"
111 
112     "\t--s_quality n\t\tDesired audio quality(-1 to 10).\n\n"
113 
114     "Misc Options:\n"
115     "\t--rescue path_to_data\tEncode data from a previous, crashed, session.\n"
116     "\t--no-wm-check\t\tDo not try to detect"
117     " the window manager(and set options according to it)\n"
118 
119     "\t--pause-shortcut MOD+KEY\tShortcut that will be used for (un)pausing"
120     "(default Control+Mod1+p).\n"
121     "\t--stop-shortcut MOD+KEY\tShortcut that will be used to stop the "
122     "recording (default Control+Mod1+s).\n"
123 
124     "\t--compress-cache\tImage data are cached with light compression.\n"
125     "\t--workdir DIR\t\tLocation where a temporary directory"
126     " will be created to hold project files(default $HOME).\n"
127 
128     "\t--delay n[H|h|M|m]\tNumber of secs(default),minutes or hours"
129     " before capture starts(number can be float)\n"
130 
131     "\t--overwrite\t\tIf there is already a file with the same name,"
132     " delete it\n"
133 
134     "\t\t\t\t(default is to add a number postfix to the new one).\n"
135     "\t-o filename\t\tName of recorded video(default out.ogv).\n"
136     "\n\tIf no other options are specified, filename can be given "
137     "without the -o switch.\n\n\n";
138 
139     if(argc==2){
140         if(argv[1][0]!='-'){
141             free(arg_return->filename);
142             arg_return->filename=malloc(strlen(argv[1])+1);
143             strcpy(arg_return->filename,argv[1]);
144             return TRUE;
145         }
146     }
147     for(i=1;i<argc;i++){
148         if (strcmp(argv[i], "--delay") == 0 ||
149             strcmp(argv[i], "-delay")  == 0) {
150             if(i+1<argc){
151                 float num=atof(argv[i+1]);
152                 if(num>0.0){
153                     int k;
154                     for(k=0;k<strlen(argv[i+1]);k++){
155                         if((argv[i+1][k]=='M')||(argv[i+1][k]=='m')){
156                             num*=60.0;
157                             break;
158                         }
159                         else if((argv[i+1][k]=='H')||(argv[i+1][k]=='h')){
160                             num*=3600.0;
161                             break;
162                         }
163                     }
164                     arg_return->delay=(int)num;
165                 }
166                 else{
167                     fprintf(stderr,"Argument Usage: --delay n[H|h|M|m]\n"
168                                    "where n is a float number\n");
169                     return FALSE;
170                 }
171             }
172             else{
173                 fprintf(stderr,"Argument Usage: --delay n[H|h|M|m]\n"
174                                "where n is a float number\n");
175                 return FALSE;
176             }
177             i++;
178         }
179         else if (strcmp(argv[i], "--windowid") == 0 ||
180                  strcmp(argv[i], "-windowid")  == 0) {
181             if(i+1<argc){
182                 Window num=strtod(argv[i+1],NULL);
183                 if(num>0)
184                     arg_return->windowid=num;
185                 else{
186                     fprintf(stderr,"Argument Usage:"
187                                    " --windowid id_of_window(number)\n");
188                     return FALSE;
189                 }
190             }
191             else{
192                 fprintf(stderr,"Argument Usage:"
193                                " --windowid id_of_window(number)\n");
194                 return FALSE;
195             }
196             i++;
197         }
198         else if (strcmp(argv[i], "--display") == 0 ||
199                  strcmp(argv[i], "-display")  == 0) {
200             if(i+1<argc){
201                 if(arg_return->display!=NULL)
202                     free(arg_return->display);
203                 arg_return->display=malloc(strlen(argv[i+1])+1);
204                 strcpy(arg_return->display,argv[i+1]);
205             }
206             else{
207                 fprintf(stderr,"Argument Usage: --display DISPLAY\n");
208                 return FALSE;
209             }
210             i++;
211         }
212         else if(!strcmp(argv[i],"-x")){
213             if(i+1<argc){
214                 int num=atoi(argv[i+1]);
215                 if(num>0)
216                     arg_return->x=num;
217                 else{
218                     fprintf(stderr,"Argument Usage: -x X(number>0)\n");
219                     return FALSE;
220                 }
221             }
222             else{
223                 fprintf(stderr,"Argument Usage: -x X(number>0)\n");
224                 return FALSE;
225             }
226             i++;
227         }
228         else if(!strcmp(argv[i],"-y")){
229             if(i+1<argc){
230                 int num=atoi(argv[i+1]);
231                 if(num>0)
232                     arg_return->y=num;
233                 else{
234                     fprintf(stderr,"Argument Usage: -y Y(number>0)\n");
235                     return FALSE;
236                 }
237             }
238             else{
239                 fprintf(stderr,"Argument Usage: -y Y(number>0)\n");
240                 return FALSE;
241             }
242             i++;
243         }
244         else if (strcmp(argv[i], "--width") == 0 ||
245                  strcmp(argv[i], "-width")  == 0) {
246             if(i+1<argc){
247                 int num=atoi(argv[i+1]);
248                 if(num>0)
249                     arg_return->width=num;
250                 else{
251                     fprintf(stderr,"Argument Usage: --width N(number>0)\n");
252                     return FALSE;
253                 }
254             }
255             else{
256                 fprintf(stderr,"Argument Usage: --width N(number>0)\n");
257                 return FALSE;
258             }
259             i++;
260         }
261         else if (strcmp(argv[i], "--height") == 0 ||
262                  strcmp(argv[i], "-height")  == 0) {
263             if(i+1<argc){
264                 int num=atoi(argv[i+1]);
265                 if(num>0)
266                     arg_return->height=num;
267                 else{
268                     fprintf(stderr,"Argument Usage: --height N(number>0)\n");
269                     return FALSE;
270                 }
271             }
272             else{
273                 fprintf(stderr,"Argument Usage: --height N(number>0)\n");
274                 return FALSE;
275             }
276             i++;
277         }
278         else if(!strcmp(argv[i],"-o")){
279             if(i+1<argc){
280                 free(arg_return->filename);
281                 arg_return->filename=malloc(strlen(argv[i+1])+1);
282                 strcpy(arg_return->filename,argv[i+1]);
283             }
284             else{
285                 fprintf(stderr,"Argument Usage: -o filename\n");
286                 return FALSE;
287             }
288             i++;
289         }
290         else if (strcmp(argv[i], "--fps") == 0 ||
291                  strcmp(argv[i], "-fps")  == 0) {
292             if(i+1<argc){
293                 float num=atof(argv[i+1]);
294                 if(num>0.0)
295                     arg_return->fps=num;
296                 else{
297                     fprintf(stderr,"Argument Usage: --fps N(number>0)\n");
298                     return FALSE;
299                 }
300             }
301             else{
302                 fprintf(stderr,"Argument Usage: --fps N(number>0)\n");
303                 return FALSE;
304             }
305             i++;
306         }
307         else if (strcmp(argv[i], "--v_quality") == 0 ||
308                  strcmp(argv[i], "-v_quality")  == 0) {
309             if(i+1<argc){
310                 int num=atoi(argv[i+1]);
311                 if((num>=0)&&(num<64))
312                     arg_return->v_quality=num;
313                 else{
314                     fprintf(stderr,"Argument Usage:"
315                                    " --v_quality n(number 0-63)\n");
316                     return FALSE;
317                 }
318             }
319             else{
320                 fprintf(stderr,"Argument Usage:"
321                                " --v_quality n(number 0-63)\n");
322                 return FALSE;
323             }
324             i++;
325         }
326         else if (strcmp(argv[i], "--v_bitrate") == 0 ||
327                  strcmp(argv[i], "-v_bitrate")  == 0) {
328             if(i+1<argc){
329                 int num=atoi(argv[i+1]);
330                 if((num>=0)&&(num<=2000000))
331                     arg_return->v_bitrate=num;
332                 else{
333                     fprintf(stderr,"Argument Usage:"
334                                    " --v_bitrate n(number 0-2000000)\n");
335                     return FALSE;
336                 }
337             }
338             else{
339                 fprintf(stderr,"Argument Usage:"
340                                " --v_bitrate n(number 0-2000000)\n");
341                 return FALSE;
342             }
343             i++;
344         }
345         else if (strcmp(argv[i], "--dummy-cursor") == 0 ||
346                  strcmp(argv[i], "-dummy-cursor")  == 0) {
347             if(i+1<argc){
348                 if(!strcmp(argv[i+1],"white"))
349                     arg_return->cursor_color=0;
350                 else if(!strcmp(argv[i+1],"black"))
351                     arg_return->cursor_color=1;
352                 else{
353                     fprintf(stderr,"Argument Usage:"
354                                    " --dummy-cursor [black|white]\n");
355                     return FALSE;
356                 }
357                 arg_return->have_dummy_cursor=1;
358                 arg_return->xfixes_cursor=0;
359             }
360             else{
361                 fprintf(stderr,"Argument Usage:"
362                                " --dummy-cursor [black|white]\n");
363                 return FALSE;
364             }
365             i++;
366         }
367         else if(!strcmp(argv[i],"--no-cursor"))
368             arg_return->xfixes_cursor=0;
369         else if (strcmp(argv[i], "--freq") == 0 ||
370                  strcmp(argv[i], "-freq")  == 0) {
371             if(i+1<argc){
372                 int num=atoi(argv[i+1]);
373                 if(num>0)
374                     arg_return->frequency=num;
375                 else{
376                     fprintf(stderr,"Argument Usage: --freq N(number>0)\n");
377                     return FALSE;
378                 }
379             }
380             else{
381                 fprintf(stderr,"Argument Usage: --freq N(number>0)\n");
382                 return FALSE;
383             }
384             i++;
385         }
386         else if (strcmp(argv[i], "--channels") == 0 ||
387                  strcmp(argv[i], "-channels")  == 0) {
388             if(i+1<argc){
389                 int num=atoi(argv[i+1]);
390                 if(num>0)
391                     arg_return->channels=num;
392                 else{
393                     fprintf(stderr,"Argument Usage: --channels N(number>0)\n");
394                     return FALSE;
395                 }
396             }
397             else{
398                 fprintf(stderr,"Argument Usage: --channels N(number>0)\n");
399                 return FALSE;
400             }
401             i++;
402         }
403         else if (strcmp(argv[i], "--s_quality") == 0 ||
404                  strcmp(argv[i], "-s_quality")  == 0) {
405             if(i+1<argc){
406                 int num=atoi(argv[i+1]);
407                 if((num>=-1)&&(num<=10))
408                     arg_return->s_quality=num;
409                 else{
410                     fprintf(stderr,"Argument Usage:"
411                                    " --s_quality n(number -1 to 10)\n");
412                     return FALSE;
413                 }
414             }
415             else{
416                 fprintf(stderr,"Argument Usage:"
417                                " --s_quality n(number -1 to 10)\n");
418                 return FALSE;
419             }
420             i++;
421         }
422         else if (strcmp(argv[i], "--device") == 0 ||
423                  strcmp(argv[i], "-device")  == 0) {
424             if(i+1<argc){
425                 free(arg_return->device);
426                 arg_return->device=malloc(strlen(argv[i+1])+1);
427                 strcpy(arg_return->device,argv[i+1]);
428             }
429             else{
430                 fprintf(stderr,"Argument Usage: -device SOUND_DEVICE\n");
431                 return FALSE;
432             }
433             i++;
434         }
435         else if (strcmp(argv[i], "--workdir") == 0 ||
436                  strcmp(argv[i], "-workdir")  == 0) {
437             if(i+1<argc){
438                 free(arg_return->workdir);
439                 arg_return->workdir=malloc(strlen(argv[i+1])+1);
440                 strcpy(arg_return->workdir,argv[i+1]);
441             }
442             else{
443                 fprintf(stderr,"Argument Usage: --workdir DIR\n");
444                 return FALSE;
445             }
446             i++;
447         }
448         else if (strcmp(argv[i], "--pause-shortcut") == 0 ||
449                  strcmp(argv[i], "-pause-shortcut")  == 0) {
450             if(i+1<argc){
451                 free(arg_return->pause_shortcut);
452                 arg_return->pause_shortcut=malloc(strlen(argv[i+1])+1);
453                 strcpy(arg_return->pause_shortcut,argv[i+1]);
454             }
455             else{
456                 fprintf(stderr,"Argument Usage: --pause-shortcut MOD+KEY\n");
457                 return FALSE;
458             }
459             i++;
460         }
461         else if (strcmp(argv[i], "--stop-shortcut") == 0 ||
462                  strcmp(argv[i], "-stop-shortcut")  == 0) {
463             if(i+1<argc){
464                 free(arg_return->stop_shortcut);
465                 arg_return->stop_shortcut=malloc(strlen(argv[i+1])+1);
466                 strcpy(arg_return->stop_shortcut,argv[i+1]);
467             }
468             else{
469                 fprintf(stderr,"Argument Usage: --stop-shortcut MOD+KEY\n");
470                 return FALSE;
471             }
472             i++;
473         }
474         else if (strcmp(argv[i], "--buffer-size") == 0 ||
475                  strcmp(argv[i], "-buffer-size")  == 0) {
476             if(i+1<argc){
477                 int num=atoi(argv[i+1]);
478                 if(num>0)
479                     arg_return->buffsize=num;
480                 else{
481                     fprintf(stderr,"Argument Usage:"
482                                    " --buffer-size N(number>0)\n");
483                     return FALSE;
484                 }
485             }
486             else{
487                 fprintf(stderr,"Argument Usage: --buffer-size N(number>0)\n");
488                 return FALSE;
489             }
490             i++;
491         }
492         else if (strcmp(argv[i], "--use-jack") == 0 ||
493                  strcmp(argv[i], "-use-jack")  == 0) {
494             if(i+1<argc){
495 #ifdef HAVE_LIBJACK
496                 int k=i+1;
497                 arg_return->jack_nports=0;
498                 while((k<argc)&&(argv[k][0]!='-')){
499                     arg_return->jack_nports++;
500                     k++;
501                 }
502                 if(arg_return->jack_nports>0){
503                     arg_return->jack_port_names=malloc(sizeof(char*)*
504                                                        arg_return->jack_nports);
505                     for(k=i+1;k<i+1+arg_return->jack_nports;k++){
506                         arg_return->jack_port_names[k-i-1]=
507                             malloc(strlen(argv[k])+1);
508                         strcpy(arg_return->jack_port_names[k-i-1],
509                                argv[k]);
510                     }
511                     i+=arg_return->jack_nports;
512                     arg_return->use_jack=1;
513                 }
514                 else{
515                     fprintf(stderr,"Argument Usage: --use-jack port1"
516                                    " port2... portn\n");
517                     return FALSE;
518                 }
519 #else
520                 fprintf(stderr,"recordMyDesktop is not compiled"
521                                " with Jack support!\n");
522                 return FALSE;
523 #endif
524             }
525             else{
526                 fprintf(stderr,"Argument Usage: --use-jack port1"
527                                " port2... portn\n");
528                 return FALSE;
529             }
530         }
531         else if (strcmp(argv[i], "--ring-buffer-size") == 0 ||
532                  strcmp(argv[i], "-ring-buffer-size")  == 0) {
533             if(i+1<argc){
534                 float num=atof(argv[i+1]);
535                 if(num>0.0)
536                     arg_return->jack_ringbuffer_secs=num;
537                 else{
538                     fprintf(stderr,"Argument Usage: --ring-buffer-size"
539                                    " N(floating point number>0.0)\n");
540                     return FALSE;
541                 }
542             }
543             else{
544                 fprintf(stderr,"Argument Usage: --ring-buffer-size"
545                                 " N(floating point number>0.0)\n");
546                 return FALSE;
547             }
548             i++;
549         }
550         else if (strcmp(argv[i], "--rescue") == 0 ||
551                  strcmp(argv[i], "-rescue") == 0) {
552             if(i+1<argc){
553                 arg_return->rescue_path = argv[i + 1];
554             }
555             else{
556                 fprintf(stderr,"Argument Usage: --rescue path_to_data\n");
557                 return FALSE;
558             }
559             i++;
560         }
561         else if(!strcmp(argv[i],"--no-sound"))
562             arg_return->nosound=1;
563         else if(!strcmp(argv[i],"--no-shared")){
564             arg_return->noshared=1;
565         }
566         else if(!strcmp(argv[i],"--full-shots")){
567             arg_return->full_shots=1;
568         }
569         else if(!strcmp(argv[i],"--no-frame")){
570             arg_return->noframe=1;
571         }
572         else if(!strcmp(argv[i],"--follow-mouse")){
573             arg_return->full_shots=1;
574             arg_return->follow_mouse=1;
575         }
576         else if(!strcmp(argv[i],"--no-encode"))
577             arg_return->no_encode=1;
578         else if(!strcmp(argv[i],"--quick-subsampling")){
579             arg_return->no_quick_subsample=0;
580         }
581         else if(!strcmp(argv[i],"--on-the-fly-encoding")){
582             arg_return->encOnTheFly=1;
583         }
584         else if(!strcmp(argv[i],"--overwrite"))
585             arg_return->overwrite=1;
586         else if(!strcmp(argv[i],"--no-wm-check"))
587             arg_return->nowmcheck=1;
588         else if(!strcmp(argv[i],"--compress-cache")){
589             arg_return->zerocompression=0;
590         }
591         else if(!strcmp(argv[i],"--help")||!strcmp(argv[i],"-h")){
592             fprintf(stderr,"%s",usage);
593             exit(0);
594         }
595         else if(!strcmp(argv[i],"--version")){
596             fprintf(stderr,"recordMyDesktop v%s\n\n",VERSION);
597             exit(0);
598         }
599         else if(!strcmp(argv[i],"--print-config")){
600             PrintConfig();
601             exit(0);
602         }
603         else{
604             fprintf(stderr,"\n\tError parsing arguments.\n\t"
605                            "Type --help or -h for usage.\n\n");
606             return FALSE;
607         }
608     }
609 
610     return TRUE;
611 }
612