/****************************************************************************** * 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_cache.h" #include "rmd_encode_cache.h" #include "rmd_error.h" #include "rmd_initialize_data.h" #include "rmd_parseargs.h" #include "rmd_queryextensions.h" #include "rmd_rescue.h" #include "rmd_setbrwindow.h" #include "rmd_shortcuts.h" #include "rmd_threads.h" #include "rmd_wm_is_compositing.h" #include "rmd_types.h" #include #include #include #include #include int main(int argc, char **argv) { ProgData pdata = {}; EncData enc_data = {}; CacheData cache_data = {}; int exit_status = 0; #ifdef HAVE_LIBJACK JackData jdata; // Give jack access to program data, mainly for program state jdata.pdata = &pdata; pdata.jdata = &jdata; #endif rmdSetupDefaultArgs(&pdata.args); if (!rmdParseArgs(argc, argv, &pdata.args)) exit(1); if (pdata.args.rescue_path != NULL) exit(rmdRescue(pdata.args.rescue_path)); if (XInitThreads() == 0) { fprintf(stderr, "Couldn't initialize thread support!\n"); exit(7); } if (pdata.args.display != NULL) { pdata.dpy = XOpenDisplay(pdata.args.display); XSetErrorHandler(pdata.args.need_shortcuts ? rmdGrabErrorsFatalErrorHandler : rmdErrorHandler); } else { fprintf(stderr, "No display specified for connection!\n"); exit(8); } if (pdata.dpy == NULL) { fprintf(stderr, "Cannot connect to X server %s\n", pdata.args.display); exit(9); } // Query display specs pdata.specs.screen = DefaultScreen(pdata.dpy); pdata.specs.width = DisplayWidth(pdata.dpy, pdata.specs.screen); pdata.specs.height = DisplayHeight(pdata.dpy, pdata.specs.screen); pdata.specs.root = RootWindow(pdata.dpy, pdata.specs.screen); pdata.specs.visual = DefaultVisual(pdata.dpy, pdata.specs.screen); pdata.specs.gc = DefaultGC(pdata.dpy, pdata.specs.screen); pdata.specs.depth = DefaultDepth(pdata.dpy, pdata.specs.screen); if (pdata.specs.depth != 32 && pdata.specs.depth != 24 && pdata.specs.depth != 16) { fprintf(stderr, "Only 32bpp, 24bpp, and 16bpp" " color depth modes are currently supported.\n"); exit(10); } if (!rmdSetBRWindow(pdata.dpy, &pdata.brwin, &pdata.specs, &pdata.args)) exit(11); if (!pdata.args.nowmcheck && rmdWMIsCompositing(pdata.dpy, pdata.specs.screen)) { fprintf(stderr, "\nDetected compositing window manager.\n" "Reverting to full screen capture at every frame.\n" "To disable this check run with --no-wm-check\n" "(though that is not advised, since it will " "probably produce faulty results).\n\n"); pdata.args.full_shots = 1; pdata.args.noshared = 0; } rmdQueryExtensions( pdata.dpy, &pdata.args, &pdata.damage_event, &pdata.damage_error, &pdata.shm_opcode); exit_status = rmdInitializeData(&pdata, &enc_data, &cache_data); if (exit_status) exit(exit_status); if ( !strcmp(pdata.args.pause_shortcut, pdata.args.stop_shortcut) || rmdRegisterShortcut( pdata.dpy, pdata.specs.root, pdata.args.pause_shortcut, &(pdata.pause_key)) || rmdRegisterShortcut( pdata.dpy, pdata.specs.root, pdata.args.stop_shortcut, &(pdata.stop_key))) { fprintf(stderr, "Invalid shortcut, or shortcuts are the same!\n\nUsing defaults.\n"); rmdRegisterShortcut( pdata.dpy, pdata.specs.root, "Control+Mod1+p", &(pdata.pause_key)); rmdRegisterShortcut( pdata.dpy, pdata.specs.root, "Control+Mod1+s", &(pdata.stop_key)); } //this is where the capturing happens. if (rmdThreads(&pdata)) return 1; XCloseDisplay(pdata.dpy); fprintf(stderr, ".\n"); //encode and then cleanup cache if (!pdata.args.encOnTheFly && !pdata.args.no_encode) { if (!pdata.aborted) { if (rmdEncodeCache(&pdata)) return 1; } fprintf(stderr, "Cleaning up cache...\n"); if (rmdPurgeCache(pdata.cache_data, !pdata.args.nosound)) fprintf(stderr, "Some error occurred while cleaning up cache!\n"); fprintf(stderr, "Done!!!\n"); } if (pdata.aborted && pdata.args.encOnTheFly) { if (remove(pdata.args.filename)) { perror("Error while removing file:\n"); return 1; } else { fprintf(stderr, "SIGABRT received, file %s removed\n", pdata.args.filename); return 0; } } else fprintf(stderr, "Goodbye!\n"); rmdCleanUp(); return exit_status; }