/*
 * Gnophone: A client for the Asterisk PBX
 *
 * Copyright (C) 2000-2005, Digium, Inc.
 *
 * Written by Mark Spencer
 *
 * Linux/UNIX version distributed under the terms of
 * the GNU General Public License
 *
 * gnophone.c: General initialization code
 *
 */

#include "gnophone.h"

char home_page[256] = DEFAULT_HOME_PAGE;

static int nobrowser=0;
static int quiet;
static int rtt;
static struct option options[] =
{
	{ "nobrowser", 0, &nobrowser, 1 },
	{ "quiet", 0, &quiet, 1 },
	{ "realtime", 0, &rtt, 1 },
	{ NULL, },
};

extern int grab_picture(unsigned char *buf);
extern int set_rec_source(void);

int is_phone_number(char *s)
{
	char *digits = "()-,0123456789*# ";
	int found = 1;
	
	if (!strlen(s))
		return 0;
	while(found && *s) {
		found = found && strchr(digits, *(s++));
	}
	return found;
}

#ifdef USE_FORK
static void sigchld(int sig)
{
	pid_t p;
	int status;
	p = waitpid(-1, &status, WNOHANG);
	if (p < 0) 
		return;
	if (p == pid) {
		fprintf(stderr, "Phone Core Died!  Please submit a bug report at\n"
						"http://www.gnophone.com/bugs\n"
						"Bug Code: PCDEATH-%d-%d-%d\n", 
							WEXITSTATUS(status), 
							WTERMSIG(status),
							 WSTOPSIG(status));
		exit(1);
	}
	fprintf(stderr, "Huh?  Some child %d died but it wasn't the phone core?\n", p);
}

#endif

int interpret_call_strict(char *s)
{
	char *proto, *dest, *ihr;
	if (!s || !strlen(s))
		return -1;
	if (!strchr(s, ':'))
		return -1;
	proto = strdup(s);
	dest = proto;
	while(*dest != ':') dest++;
	*dest = '\0';
	dest++;
	if (!strcasecmp(proto, "tel")) {
		fprintf(stderr, "I should dial %s\n", dest);
		ihr = telco_to_irl(dest);
		if (ihr) {
			fprintf(stderr, "Using: %s\n", ihr);
			launch_call(ihr, dest, 0);
		}
	} else if (!strcasecmp(proto, "iax")) {
		if (strncmp(dest, "//", 2)) {
			fprintf(stderr, "Destination '%s' lacks // \n", dest);
			return -1;
		}
		launch_call(dest + 2, dest + 2, 0);
	} else if (!strcasecmp(proto, "dtmf")) {
		while(*dest) {
			digit_ready(*dest, 0, 1);
			dest++;
		}
	} else {
		fprintf(stderr, "Don't know what to do with %s\n", proto);
	}
	free(proto);
	return 0;
}

int interpret_call(char *s)
{
	char *ihr;
	char *proto, *dest;
	/* Try to interpret what they type in the space... */
	if (strchr(s, ' ')) {
		/* It's probably a name...  Maybe one day we'll look it
		   up in their address book */
		return -1;
	}
	if (strchr(s, ':')) {
		/* It's either a URL, or an IAX string */
		proto = strdup(s);
		dest = proto;
		while(*dest && (*dest != ':')) dest++;
		*dest = 0;
		dest++;
		if (!strcasecmp(proto, "http") ||
		    !strcasecmp(proto, "https") ||
		    !strcasecmp(proto, "ftp") ||
			!strcasecmp(proto, "mailto") ||
			!strcasecmp(proto, "about") ||
			!strcasecmp(proto, "file") ||
			!strcasecmp(proto, "finger") ||
			!strcasecmp(proto, "keyword")) {
				/* Send it to the primary browser widget */
				start_load_url(s);
				free(proto);
		} else if (!strcasecmp(proto, "iax") && (strlen(dest) > 3)) {
			/* It's an iax:// address */
			free(proto);
			launch_call(s + 6, s + 6, 0);
		} else if (!strcasecmp(proto,"dtmf") && strlen(dest)) {
			while(*dest) {
				digit_ready(*dest, 0, 1);
				dest++;
			}
		} else if (!strcasecmp(proto, "gnophone")) {
			/* An internal gnophone thingy */
			if (!strcasecmp(dest, "audiocontrol"))
				show_audio_control();
/*			else if (!strcasecmp(dest, "videocontrol"))
				image_callback();*/
			else if (!strcasecmp(dest, "telephonecontrol"))
				telco_prefs();
		}
	} else {

		if (is_phone_number(s)) {
			printf("%s is a phone number\n", s);
			ihr = telco_to_irl(s);
			if (ihr && strlen(ihr)) {
				printf("Using: %s\n", ihr);
				launch_call(ihr, s, 0);
			} else {
				if (ihr)
					fprintf(stderr, "Couldn't make it: %s\n", ihr + 1);
				return -1;
			}
		} else {
/*			ihr = telco_to_irl(s);
			if (ihr && strlen(ihr)) {
				printf("Using: %s\n", ihr);
				launch_call(ihr, s, 0);
			} else {
				if (ihr)
					fprintf(stderr, "Couldn't make it: %s\n", ihr + 1);

				return -1;
			}*/
			printf("Didn't find anything better to do than send it to browser.\n");
			start_load_url(s);
		}
	}
	return 0;
}

void list_devices()
{
    struct iaxc_audio_device *devs;
    int nDevs, input, output, ring;
    int i;

    iaxc_audio_devices_get(&devs,&nDevs, &input, &output, &ring);
    for(i=0;i<nDevs;i++) {
        fprintf(stderr, "DEVICE ID=%d NAME=%s CAPS=%lx\n", devs[i].devID, devs[i]
.name, devs[i].capabilities);
    }
}

int main(int argc, char *argv[])
{
	int res;
	int fd;
	char fn[256];
	char *arg= NULL;
	struct rlimit l;
	
	memset(&l, 0, sizeof(l));
	l.rlim_cur = RLIM_INFINITY;
	l.rlim_max = RLIM_INFINITY;
	setrlimit(RLIMIT_CORE, &l);

	for(;;) {
		res = getopt_long(argc, argv, "", options, NULL);
		if (res < 0)
			break;
		if (res == '?')
			exit(0);
	}
	
	if (quiet) {
		/* XXX Ugh, this is nasty, but hopefully this will
		   get everything quiet, even mozilla's chatter XXX */
		fd = open("/dev/null", O_WRONLY);
		dup2(fd, STDOUT_FILENO);
		dup2(fd, STDERR_FILENO);
		close(fd);
	}
	if (rtt && geteuid()) {
		fprintf(stderr, "Realtime thread requires root priviledges.\n");
		exit(1);
	}
	
	if (optind < argc)
		arg = argv[optind];

	load_modules();

	telco_load_settings();
	/*video_load_settings();*/

	if (iaxc_initialize(AUDIO_INTERNAL_PA, 20))
		return 1;
	iaxc_set_formats(IAXC_FORMAT_ULAW,IAXC_FORMAT_ULAW|IAXC_FORMAT_GSM);
	iaxc_set_speex_settings(1,-1.0f, 9000, 0, 0, 3);
/*	iaxc_input_level_set(1.0);
	iaxc_output_level_set(2.0);*/
	list_devices();

	if (nobrowser) {
		html_select_engine(NULL);
	} else if (!engine)
		html_select_engine(engines);
	
	set_rec_source();
	if (init_gphx_subsystem(&argc, &argv)) {
		fprintf(stderr, "Failed to intiialize graphics subsystem\n");
		return 1;
	}
	if (build_gui()) {
		fprintf(stderr, "Failed to build GUI\n");
		return 1;
	}

	/* Here we should check to see if we've run gnophone before.
	* If not, we should show the congratulations page. Otherwise,
	* we should carry them over to the login page */

	if (getenv("HOME"))
		snprintf(fn, sizeof(fn), "%s/.gnophone/%s", getenv("HOME"), GNOPHONE_CONFIG);
	else
		snprintf(fn, sizeof(fn), "%s", GNOPHONE_CONFIG);

	printf("Running GUI\n");
	if (run_gui()) {
		fprintf(stderr, "Failed to run GUI\n");
		return 1;
	}
	iaxc_stop_processing_thread();
#ifdef USE_FORK	
	kill(pid, SIGTERM);
#endif	
	exit(0);
}
