/******************************************************************************
*                            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 <X11/Xlib.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

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(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;
}