/*
 * 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
 *
 * gui.c Graphical User Interface Code
 *
 */

#include "gnophone.h"

#define GP_EVENT_SALT	(0xff << 8)
#define GP_EVENT_HANGUP	(GP_EVENT_SALT | 1)
#define GP_EVENT_REJECT	(GP_EVENT_SALT | 2)
#define GP_EVENT_ACCEPT	(GP_EVENT_SALT | 3)
#define GP_EVENT_ANSWER	(GP_EVENT_SALT | 4)
#define GP_EVENT_RINGA	(GP_EVENT_SALT | 5)
#define GP_EVENT_CONNECT (GP_EVENT_SALT | 6)
/* The frequencey that we send lag requests, in ms. */
#define LAG_TIMEOUT 15000

GtkWidget *mw;		/* Main Window */
GtkWidget *nb;
GtkWidget *dialpadbuttons[12];

int link_pcid = -1;
int regid = -1;
int tbd_pcid = -1;
char my_callerid[32];
struct peerwindow *self;
struct peerwindow *peers;
struct peerwindow *current_peer;
struct peerwindow *most_recent_answer;
struct peerwindow *urlpeer;

static char extension[10] = "jpg";
static char *labels[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#" };
static int iaxloading = 0;
static GtkWidget *scrolled;
static GtkWidget *scrolledvbox;
static GtkWidget *fixedstatus;
static GtkWidget *history;
static GtkWidget *menubar;
static GtkAccelGroup *gag;
static GtkWidget *callbttn;
static GtkWidget *callwin;
static GtkWidget *calladdr;
static GtkWidget *cancelbttn;
static GtkWidget *selfb;
static GtkWidget *gwin;
static GtkWidget *callanswer;

extern struct browser *build_browser(void);
extern struct browser *pbrowser;

/* No more than 4 concurrent IAX sessions */
#define MAX_SESSIONS 4
static int sessions = 0;
static int accelerators_are_active = 0;

static void build_accelerators(void);
static void select_peer(struct peerwindow *p);
static int iax_reg_timer(void*);
void show_call_window(int, int);

void sethistory(char *his)
{
	char tmp[64];
	time_t tme;
	GString *historytext;
	GtkTextIter start, end;  /* start is dummy var */
	
	if (history != NULL) {

		time(&tme);
		gtk_text_buffer_get_bounds(gtk_text_view_get_buffer(
				GTK_TEXT_VIEW(history)),
				&start, &end);
		historytext = g_string_new(NULL);
		
		strftime(tmp, sizeof(tmp), "( %H:%M:%S )  ", localtime(&tme));
		g_string_append(historytext, tmp);
		g_string_append(historytext, his);
		g_string_append(historytext, "\n");
		
		gtk_text_buffer_insert(gtk_text_view_get_buffer(
				GTK_TEXT_VIEW(history)),
				&end, historytext->str, historytext->len); 
		
/*		gtk_text_insert(GTK_LABEL(history), NULL, NULL, NULL, tmp, strlen(tmp));
		gtk_text_insert(GTK_LABEL(history), NULL, NULL, NULL, his, strlen(his));
		gtk_text_insert(GTK_LABEL(history), NULL, NULL, NULL, "\n", 1);
*/
/*		gtk_text_buffer_set_text(gtk_text_view_get_buffer(history), g_strcat(gtk_text_buffer_get_text(history), */
	}
}

static void setpeerstatus(struct peerwindow *p, char *text)
{
	GtkWidget *statusbar;
/*	if (p) 
		statusbar = p->status;
	else */
		statusbar = fixedstatus;
	gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1);
	gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, text);
}
#ifdef ENABLE_HANDLE
#error ENABLE_HANDLE is active
static void detached_cb(GtkHandleBox *h, GtkWidget *w, struct browser *b)
{
	gdk_window_resize(GTK_WIDGET(h)->window, b->outerbox->allocation.width,
											 b->outerbox->allocation.height);
	gtk_handle_box_set_shadow_type(h, GTK_SHADOW_IN);									
	NOTE;
}
static void attached_cb(GtkHandleBox *h, GtkWidget *w, struct browser *b)
{
	gtk_handle_box_set_shadow_type(h, GTK_SHADOW_NONE);									
	NOTE;
}
#endif

static void dialdigit(GtkWidget *w, char *digit)
{
	int position = -1;
	/*send_digit(*digit);*/
	if (current_peer && (current_peer->pcid > -1)) {
		printf("Sending digit %c\n", *digit);
		iaxc_send_dtmf(*digit);
	} else {
		if (!callwin) {
			show_call_window(0, 0);
			position = 0;
		}
		gtk_editable_insert_text(GTK_EDITABLE(calladdr), digit, 1, &position);
		gtk_editable_set_position(GTK_EDITABLE(calladdr), -1);

	}
}

static void build_accelerators()
{
	int x = 0;
	while (x < 12)
	{
		if ((labels[x][0] >='0') && (labels[x][0] <= '9')) {
			gtk_widget_add_accelerator(dialpadbuttons[x], "clicked", gag, GDK_KP_0+atoi(&labels[x][0]), 0, 0);
			gtk_widget_add_accelerator(dialpadbuttons[x], "clicked", gag, GDK_0+atoi(&labels[x][0]), 0, 0);
		} else {
			gtk_widget_add_accelerator(dialpadbuttons[x], "clicked", gag, labels[x][0], GDK_SHIFT_MASK, 0);
		}
		
		x++;
	}
}
			       

static GtkWidget *build_dialpad()
{
	GtkWidget *table;
	GtkWidget *frame;
	int x;
	frame = gtk_frame_new(NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
	table = gtk_table_new(4, 3, TRUE);
	gtk_container_set_border_width(GTK_CONTAINER(table), 10);
	for (x=0;x<12;x++) {
		dialpadbuttons[x] = gtk_button_new_with_label(labels[x]);
		g_signal_connect(GTK_OBJECT(dialpadbuttons[x]), "clicked", GTK_SIGNAL_FUNC(dialdigit), labels[x]);
		gtk_widget_set_usize(dialpadbuttons[x], 40, 25);
		gtk_object_set_user_data(GTK_OBJECT(dialpadbuttons[x]), labels[x]);
		gtk_table_attach(GTK_TABLE(table), dialpadbuttons[x],
						 x % 3, x % 3 + 1,
						 x / 3, x / 3 + 1,
						 GTK_FILL, GTK_FILL,
						 5, 5);
	}
	gtk_container_add(GTK_CONTAINER(frame), table);
	return frame;
}

GtkWidget *mk_image(char *filename)
{
	GtkWidget *temp = NULL;
	char pathway[256];

	snprintf(pathway, 256, "%sshare/gnophone/graphics/%s", INSTALL_PREFIX, filename);
	temp = gtk_image_new_from_file(pathway);
	return temp;
}
GdkPixbuf *mk_pixbuf(char *filename)
{
	GError **gerror = NULL;
	GdkPixbuf *temp = NULL;
	char pathway[256];

	snprintf(pathway, 256, "%sshare/gnophone/graphics/%s", INSTALL_PREFIX, filename);
	temp = gdk_pixbuf_new_from_file(pathway, gerror);
	return temp;
}
int init_gphx_subsystem(int *argc, char **argv[])
{
	if (gtk_init_check(argc, argv)) {
		/* GUI mode success */
		gtk_init(argc, argv);
	} else {
		/* No GUI? */
		fprintf(stderr, "Unable to initialize X-windows\n");
		return -1;
	}
	return 0;
}

int quit(GtkWidget *widget, void *data)
{
	signal(SIGCHLD, NULL);
	gtk_main_quit();
	return TRUE;
}

void notebook_change_page_cb(GtkNotebook *localnb, GtkNotebookPage *localpage, guint page_num, gpointer data)
{
	GtkWidget *currentpagewidget = gtk_notebook_get_nth_page(GTK_NOTEBOOK(nb), page_num);
	if (currentpagewidget != NULL && pbrowser != NULL && currentpagewidget == pbrowser->box) { /* We're on the browser tab */
		if (accelerators_are_active) {
			gtk_window_remove_accel_group(GTK_WINDOW(mw), gag);
			accelerators_are_active = 0;
		}
	} else {
		if (!accelerators_are_active) {
			build_accelerators();
			gtk_window_add_accel_group(GTK_WINDOW(mw), gag);
			accelerators_are_active = 1;
		}
	}
		
}

struct peerwindow *find_peerwindow(int pcid)
{
	struct peerwindow *cur = peers;
	while(cur) {
		if (cur->pcid == pcid)
			return cur;
		cur = cur->next;
	}
	return NULL;
}


char *user_image_filename()
{
	static char buf[1024];

	if (getenv("HOME")) {
		snprintf(buf, sizeof(buf), "%s/.gnophone", getenv("HOME"));
		mkdir(buf, 0700);

		snprintf(buf, sizeof(buf), "%s/.gnophone/my_picture.%s", getenv("HOME"), extension);
		return buf;
	}
	return NULL;		
}


static void audio_prefs(void)
{
	gtk_widget_set_sensitive(mw, FALSE);
	show_audio_control();
	gtk_widget_set_sensitive(mw, TRUE);
}

void telco_prefs(void)
{
	gtk_widget_set_sensitive(mw, FALSE);
	telco_show_gui();
	gtk_widget_set_sensitive(mw, TRUE);
}

char *get_image_filename()
{
	struct stat s;

	if (!stat(user_image_filename(), &s) /*&& (video_options & OPT_VIDEO_SEND_IMAGE)*/)
		return user_image_filename();

	return (char*)BR_DATADIR(DEFAULT_IMAGE);
}

static GtkWidget *build_self_win(void)
{
	GtkWidget *f;
	selfb = gtk_button_new();
	gwin = gtk_drawing_area_new();
	gtk_drawing_area_size(GTK_DRAWING_AREA(gwin), VIDEO_WIDTH,VIDEO_HEIGHT);
	f = gtk_frame_new(NULL);
	gtk_container_add(GTK_CONTAINER(f), gwin);
	gtk_container_add(GTK_CONTAINER(selfb), f);
	return selfb;
	
}

void send_text_cb(GtkWidget *w, gpointer data)
{
	printf("inside send_text_cb()\n");
}

static int real_destroy_peer_timeout(void *vp)
{
	struct peerwindow *p = vp;
	gtk_widget_destroy(p->box);
	free(p);
	if (!peers)
		gtk_notebook_set_page(GTK_NOTEBOOK(nb), 0);
	return FALSE;
}


static void remove_peer(struct peerwindow *p)
{
	struct peerwindow *cur, *prev = NULL;
	cur = peers;
	while(cur) {
		if (cur == p) {
			if (prev)
				prev->next = p->next;
			else
				peers = p->next;
		}
		prev = cur;
		cur = cur->next;
	}
}			

static void handle_hangup(struct peerwindow *p, char *reason)
{
	char buf[80];

	/* Got a hangup, destroy the peer */

	/* If we have linked browsers, let's close'em up */
	if (link_pcid == p->pcid)
		link_pcid = -1;
	
	/* Make sure we don't have any timeouts going 
	while (p->laglock) {
	}*/

	/* Remove the timeout
	if (p->lagfd > -1) {
		gtk_timeout_remove(p->lagfd);
		p->lagfd = -1;
	}*/

	iaxc_quelch(p->pcid, 0);
	remove_peer(p);
	if (most_recent_answer == p)
		most_recent_answer = NULL;
	if (p == current_peer) {
		current_peer = peers;
	} else
		printf("Hm... it's not me, it's someone else\n");
	p->pcid = -1;
	if (urlpeer == p)
		urlpeer = NULL;
	p->pcid = -1;
/*	 if (p->holdid > 0)
		gtk_timeout_remove(p->holdid);
	p->holdid = -1;*/
	setpeerstatus(p, reason);
	gtk_widget_set_sensitive(p->frame2, FALSE);
	g_timeout_add(5000, real_destroy_peer_timeout, p);
	sessions--;
	fprintf(stderr, "Sessions=%d?\n", sessions);
	if (sessions < 0) {
		fprintf(stderr, "Sessions is now %d?\n", sessions);
	}
	if (sessions > 0) {
		snprintf(buf, sizeof(buf), "%d active call%s", sessions, (sessions != 1 ? "s" : ""));
		setpeerstatus(NULL, buf);
	} else
		setpeerstatus(NULL, "Call disconnected.");
}

static void peerhangup_cb(GtkWidget *w, struct peerwindow *p)
{
	iaxc_select_call(p->pcid);
	iaxc_dump_call();
	handle_hangup(p, "Call disconnected.");
}


static void select_peer(struct peerwindow *p)
{
	current_peer = p;
	if (current_peer)
		iaxc_select_call(current_peer->pcid);
	else
		iaxc_select_call(-1);
}

static void do_answer(struct peerwindow *p)
{
	char buf[80];

	iaxc_answer_call(p->pcid);
	/*p->mute = 0;*/
	gtk_widget_set_sensitive(p->answer, FALSE);
	setpeerstatus(p, "Connected.");
	snprintf(buf, sizeof(buf), "%d active call%s", sessions, (sessions != 1 ? "s" : ""));
	setpeerstatus(NULL, buf);
	select_peer(p);
	if (most_recent_answer == p)	
		most_recent_answer = NULL;

	iaxc_unquelch(p->pcid);
}

void answer(void)
{
	if (most_recent_answer)
		do_answer(most_recent_answer);
}

static void peeranswer_cb(GtkWidget *w, struct peerwindow *p)
{
	do_answer(p);
}

static void callwin_destroy(void)
{
	gtk_grab_remove(callwin);
	callwin = NULL;
	gtk_widget_set_sensitive(mw, TRUE);
}

static void place_call()
{
	char *s = strdup(gtk_entry_get_text(GTK_ENTRY(calladdr)));
	gtk_widget_destroy(callwin);

	puts("got entry.");

	if (strlen(s)) {

		/* We don't want it to default to http:// as the protocol. This was 
		* changed as per Mark's request. */

		if (!strstr(s, "://")) {
			char *s2 = (char *)malloc((strlen(s) + 7) * sizeof(char));

			if (!is_phone_number(s))
			{

				/* Ok, we don't have a phone number. Is it 
				* a host name or an extension */

				if (strstr(s, ".")) {

					/* Looks like it's a host name. */
					sprintf(s2, "iax://%s", s);

					free(s);
					s = strdup(s2);
				}
			}

			free(s2);
		}

		if (interpret_call(s)) {
			setpeerstatus(NULL, "Invalid call address");
			/*html_setstatus(pbrowser, "Invalid call address");*/
		}
	}

	free(s);
}

static void callwin_response(GtkWidget *w, int response, gpointer data)
{
/*	printf("response=%d\n", response);*/
	if (response == -2) /* hit cancel */
		g_signal_emit_by_name(callwin, "destroy");
	if (response == -3) /* Hit "Dial" button */
		place_call();
}

void hangup()
{
	if (current_peer) {
		if (current_peer->pcid >= 0) {
			iaxc_select_call(current_peer->pcid);
			iaxc_dump_call();
			handle_hangup(current_peer, "Call disconnected.");
		}

	} else if (callwin) {
		gtk_button_clicked(GTK_BUTTON(cancelbttn));
	}
	if (self && self->level) 
		gtk_progress_bar_update(GTK_PROGRESS_BAR(self->level), 0.0);
}

void show_call_window(int block, int disable)
{
	GtkWidget *hbox;
	GtkWidget *vbox;
	GtkWidget *label;
	GtkWidget *frame;
	GtkWidget *mbox;
	GtkWidget *outerbox;

	callwin = gtk_dialog_new();
	g_signal_connect(GTK_OBJECT(callwin), "response", GTK_SIGNAL_FUNC(callwin_response), NULL);
	gtk_window_set_title(GTK_WINDOW(callwin), "Gnophone: Dial");
        gtk_dialog_add_buttons(GTK_DIALOG(callwin),
			"Dial", GTK_RESPONSE_ACCEPT,
			"Cancel", GTK_RESPONSE_REJECT,
			NULL);
	g_signal_connect(GTK_OBJECT(callwin), "destroy", GTK_SIGNAL_FUNC(callwin_destroy), NULL);
			
	
	/* Make our boxes */	
	vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(callwin)->vbox), vbox);
	hbox = gtk_hbox_new(FALSE, 5);
	outerbox = gtk_vbox_new(FALSE,5);
	
	frame = gtk_frame_new("New Call");
	gtk_container_set_border_width(GTK_CONTAINER(frame), 5);

	mbox = gtk_vbox_new(FALSE, 5);
	gtk_container_set_border_width(GTK_CONTAINER(mbox), 5);

	gtk_container_add(GTK_CONTAINER(frame), mbox);

	/* Make a label */
	label = gtk_label_new("Please enter an Internet URL, Internet host supporting IAX\nor a simple telephone phone number that you want to call.");
	
	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
	gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
	
	/* Make a spot for them to put in who they want to call */
	calladdr = gtk_entry_new();
	gtk_widget_set_usize(calladdr, 300, 0);
	g_signal_connect(GTK_OBJECT(calladdr), "activate", GTK_SIGNAL_FUNC(place_call), NULL);
	
	/* Make our buttons */

	gtk_box_pack_start(GTK_BOX(mbox), label, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(mbox), calladdr, FALSE, FALSE, 5);

	gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
	
	if (disable)
		gtk_widget_set_sensitive(mw, FALSE);

	gtk_widget_show_all(callwin);

	if (disable)
		gtk_grab_add(callwin);

	gtk_widget_grab_focus(calladdr);
	gtk_editable_set_position(GTK_EDITABLE(calladdr), -1);
	
	if (block)
		while(callwin && !gtk_main_iteration_do(TRUE));
}

void digit_ready(char digit, int startok, int useurl)
{
	char s[2];
	gint position = -1;

	if (useurl) {
		if (urlpeer && (urlpeer->pcid > -1))
			iaxc_send_dtmf(digit);
		return;
	}

	if (current_peer && (current_peer->pcid > -1)) {
		/* We're in a call, so send a digit */
		iaxc_send_dtmf(digit);
	} else if (startok) {
		/* We're not in a call, so send our digit to the "call" window, bringing
		   it up if it's not already */
		if (!callwin)
		{
			show_call_window(0, 0);
			position = 0;
		}
		s[0] = digit;
		s[1] = '\0';
		if ((digit >= '0') && (digit <= '9')) 
			gtk_editable_insert_text(GTK_EDITABLE(calladdr), s, 1, &position);
		else {	
			if (strlen(gtk_entry_get_text(GTK_ENTRY(calladdr)))) {
				/* If this isn't the first character of the string, like
				   "*67", then we treat a "*" as a "." for IP addresses. */
				if (digit == '*')
					s[0] = '.';
				/* If it's a "#" and not at the beginning, we treat it as
				   an "enter" and don't want to append it */
				if (digit == '#') {
					gtk_button_clicked(GTK_BUTTON(callbttn));
					s[0] = '\0';
					return;
				}
			}
			if (s[0])
				gtk_editable_insert_text(GTK_EDITABLE(calladdr), s, 1, &position);
		}

		if (telco_get_mode() == TELCO_MODE_ASTERISK) {
			/* If we're using asterisk, send a dial plan request */
			if (tbd_pcid >= 0)
				/*iaxc_send_dpreq(tbd_pcid, gtk_entry_get_text(GTK_ENTRY(calladdr)))*/;
		} else {
			/* Otherwise, compare it to our hard coded dial plan */
			if (telco_match_nbrc((char*)gtk_entry_get_text(GTK_ENTRY(calladdr)))) {
				fprintf(stderr, "%s is a phone number!\n", gtk_entry_get_text(GTK_ENTRY(calladdr)));
				gtk_button_clicked(GTK_BUTTON(callbttn));
			}
		}
	}
}

static void callanswer_cb(GtkWidget *w, void *data)
{
	if (!callwin)
		show_call_window(1, 1);
	else
		gtk_button_clicked(GTK_BUTTON(callbttn));
}


static int peerevent(GtkWidget *w, GdkEvent *event, struct peerwindow *p)
{
	switch(event->type) {
	case GDK_BUTTON_PRESS:
		printf("peerevent(): inside BUTTON_PRESS\n");
		/*p->xoff = event->button.x;
		p->yoff = event->button.y;
		p->moving = 1;*/
		break;
	case GDK_MOTION_NOTIFY:
		printf("peerevent(): inside MOTION_NOTIFY\n");
		break;
	case GDK_BUTTON_RELEASE:
		printf("peerevent(): inside BUTTON_RELEASE\n");
		/*p->moving = 0;*/
		break;
	default:
		break;
	}
	return FALSE;
}

struct peerwindow *new_peerwindow(int self, int flags, char *label)
{
	struct peerwindow *p;
	GtkWidget *vbox;
	GtkWidget *hbox;
	GtkAdjustment *a;
	GtkWidget *eventbox;

	p = g_new0(struct peerwindow, 1);

	/* Start muted */
	/*p->mute = 1;*/

/*	p->laglock = 0;
	p->lagfd = -1;*/


	/* This used to be done better, reusing code where possible, however I am no
	 * longer going to do that.  The new code builds self and !self very differently,
	 * so it's time to just break it up into two chunks completely.
	 */ 
	if (self)  /* right side bar for self/dialing */
	{
		p->outerbox = gtk_vbox_new(FALSE, 5);
		gtk_box_pack_start(GTK_BOX(p->outerbox), build_self_win(), FALSE, FALSE, 10);
		p->level = gtk_progress_bar_new();

		/* Build the volume */
		a = (GtkAdjustment *)gtk_adjustment_new(DEFAULT_SUPPRESSION, 0.0, 100.0, 1.0, 1.0, 0.0);
		p->volume = gtk_hscale_new(a);
		p->pcid = -1;
		
		/* We want a separate event box so that moving the slider doesn't move the window */
		eventbox = gtk_event_box_new();
		gtk_container_add(GTK_CONTAINER(eventbox), p->volume);
		gtk_widget_set_usize(p->level, 100, 25);

		vbox = gtk_vbox_new(FALSE, 0);
		p->frame = gtk_frame_new("Level");
		gtk_frame_set_shadow_type(GTK_FRAME(p->frame), GTK_SHADOW_IN);

		gtk_box_pack_start(GTK_BOX(vbox), p->level, FALSE, FALSE, 0);
		gtk_box_pack_start(GTK_BOX(vbox), eventbox, FALSE, FALSE, 0);
		gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
		gtk_container_add(GTK_CONTAINER(p->frame), vbox);
		gtk_box_pack_start(GTK_BOX(p->outerbox), p->frame, FALSE, FALSE, 0);
		gtk_box_pack_start(GTK_BOX(p->outerbox), build_dialpad(), FALSE, FALSE, 0);

		p->box = gtk_frame_new(label);
		hbox = gtk_hbox_new(FALSE, 5);
		callanswer = gtk_button_new_with_label("Call");
		g_signal_connect(GTK_OBJECT(callanswer), "clicked", GTK_SIGNAL_FUNC(callanswer_cb), p);

		gtk_widget_set_usize(callanswer, 80, 30);
		gtk_box_pack_start(GTK_BOX(hbox), gtk_event_box_new(), TRUE, TRUE, 5);
		gtk_box_pack_start(GTK_BOX(hbox), callanswer, FALSE, FALSE, 5);
		gtk_box_pack_start(GTK_BOX(hbox), gtk_event_box_new(), TRUE, TRUE, 5);
		gtk_box_pack_start(GTK_BOX(p->outerbox), hbox, FALSE, FALSE, 0);

		p->status = gtk_statusbar_new();
		gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(p->status), FALSE);
		gtk_box_pack_start(GTK_BOX(p->outerbox), p->status, FALSE, FALSE, 0);
		gtk_container_set_border_width(GTK_CONTAINER(p->outerbox), 5);
		gtk_container_add(GTK_CONTAINER(p->box), p->outerbox);

	} else {  /* peer window for other caller */
		p->outerbox = gtk_hbox_new(FALSE, 5);
		
		gtk_box_pack_start(GTK_BOX(p->outerbox), build_self_win(), FALSE, FALSE, 10);
		
		p->level = gtk_progress_bar_new();
		gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(p->level), GTK_PROGRESS_BOTTOM_TO_TOP);
		/* Build the volume */
		a = (GtkAdjustment *)gtk_adjustment_new(DEFAULT_SUPPRESSION, 0.0, 100.0, 1.0, 1.0, 0.0);
		p->volume = gtk_vscale_new(a);
		gtk_widget_set_usize(p->volume, 30, 40);
		p->pcid = -1;

		/* We want a separate event box so that moving the slider doesn't move the window */
		eventbox = gtk_event_box_new();
		gtk_container_add(GTK_CONTAINER(eventbox), p->volume);
		gtk_widget_set_usize(p->level, 30, 40);

		p->lagmeter = gtk_progress_bar_new();
		gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(p->lagmeter), GTK_PROGRESS_BOTTOM_TO_TOP);
		gtk_widget_set_usize(p->lagmeter, 30, 40);

		hbox = gtk_hbox_new(FALSE, 0);
		p->frame = gtk_frame_new("Level");
		gtk_frame_set_shadow_type(GTK_FRAME(p->frame), GTK_SHADOW_IN);
		gtk_box_pack_start(GTK_BOX(hbox), p->level, FALSE, FALSE, 5);
		gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 5);
		gtk_box_pack_start(GTK_BOX(hbox), p->lagmeter, FALSE, FALSE, 5);
		
		gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
		gtk_container_add(GTK_CONTAINER(p->frame), hbox);
		gtk_box_pack_start(GTK_BOX(p->outerbox), p->frame, FALSE, FALSE, 0);

		p->box = gtk_frame_new(label);
		gtk_frame_set_shadow_type(GTK_FRAME(p->box), GTK_SHADOW_OUT);
		
		vbox = gtk_vbox_new(FALSE, 5);
		p->hangup = gtk_button_new_with_label("Hangup");
		g_signal_connect(GTK_OBJECT(p->hangup), "clicked", GTK_SIGNAL_FUNC(peerhangup_cb), p);
		p->answer = gtk_button_new_with_label("Answer");
                if (flags & PW_FLAG_NO_ANSWER_BUTTON)
		{
			gtk_widget_set_child_visible(p->answer, FALSE);
			gtk_widget_set_no_show_all(p->answer, TRUE);
		}
		
		g_signal_connect(GTK_OBJECT(p->answer), "clicked", GTK_SIGNAL_FUNC(peeranswer_cb), p);
		gtk_box_pack_start(GTK_BOX(vbox), p->answer, FALSE, FALSE, 5);
		gtk_box_pack_end(GTK_BOX(vbox), p->hangup, FALSE, FALSE, 5);
		gtk_box_pack_start(GTK_BOX(p->outerbox), vbox, FALSE, FALSE, 0);

		gtk_container_set_border_width(GTK_CONTAINER(p->outerbox), 5);
		gtk_container_add(GTK_CONTAINER(p->box), p->outerbox);

		eventbox = gtk_event_box_new();
		g_signal_connect(GTK_OBJECT(eventbox), "event", GTK_SIGNAL_FUNC(peerevent), p);
		gtk_container_add(GTK_CONTAINER(eventbox), p->box);
		p->frame2 = p->box;
		p->box = eventbox;

		gtk_box_pack_start(GTK_BOX(scrolledvbox), p->box, TRUE, FALSE, 0);

#if 0  /*  A copy of the old code for now */
		p->label = gtk_label_new(label);
		gtk_label_set_line_wrap(GTK_LABEL(p->label), TRUE);
		gtk_box_pack_start(GTK_BOX(p->outerbox), p->label, FALSE, FALSE, 5);
		gtk_box_pack_start(GTK_BOX(p->outerbox), build_generic_win(p), FALSE, FALSE, 10);
		p->level = gtk_progress_bar_new();

		/* Build the volume */
		a = (GtkAdjustment *)gtk_adjustment_new(DEFAULT_SUPPRESSION, 0.0, 100.0, 1.0, 1.0, 0.0);
		p->volume = gtk_hscale_new(a);
		p->pcid = -1;

		/* We want a separate event box so that moving the slider doesn't move the window */
		eventbox = gtk_event_box_new();
		gtk_container_add(GTK_CONTAINER(eventbox), p->volume);
		gtk_widget_set_usize(p->level, 100, 25);

		vbox = gtk_vbox_new(FALSE, 0);
		p->frame = gtk_frame_new("Level");
		gtk_frame_set_shadow_type(GTK_FRAME(p->frame), GTK_SHADOW_IN);
		gtk_box_pack_start(GTK_BOX(vbox), p->level, FALSE, FALSE, 0);
		gtk_box_pack_start(GTK_BOX(vbox), eventbox, FALSE, FALSE, 0);

		p->lagmeter = gtk_label_new("Lag/Jitter: (calculating)");
		gtk_box_pack_start(GTK_BOX(p->outerbox), p->lagmeter, FALSE, FALSE, 0);
		gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
		gtk_container_add(GTK_CONTAINER(p->frame), vbox);
		gtk_box_pack_start(GTK_BOX(p->outerbox), p->frame, FALSE, FALSE, 0);

		p->box = gtk_frame_new(NULL);
		gtk_frame_set_shadow_type(GTK_FRAME(p->box), GTK_SHADOW_OUT);
		hbox = gtk_hbox_new(FALSE, 5);
		p->hangup = gtk_button_new_with_label("Hangup");
		gtk_signal_connect(GTK_OBJECT(p->hangup), "clicked", GTK_SIGNAL_FUNC(peerhangup_cb), p);
		p->answer = gtk_button_new_with_label("Answer");

		gtk_signal_connect(GTK_OBJECT(p->answer), "clicked", GTK_SIGNAL_FUNC(peeranswer_cb), p);
		gtk_widget_set_usize(p->answer, 70, 30);
		gtk_widget_set_usize(p->hangup, 70, 30);
		gtk_box_pack_start(GTK_BOX(hbox), p->answer, FALSE, FALSE, 5);
		gtk_box_pack_end(GTK_BOX(hbox), p->hangup, FALSE, FALSE, 5);
		gtk_box_pack_start(GTK_BOX(p->outerbox), hbox, FALSE, FALSE, 0);

		p->status = gtk_statusbar_new();
		gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(p->status), FALSE);
		gtk_box_pack_start(GTK_BOX(p->outerbox), p->status, FALSE, FALSE, 0);
		gtk_container_set_border_width(GTK_CONTAINER(p->outerbox), 5);
		gtk_container_add(GTK_CONTAINER(p->box), p->outerbox);

		eventbox = gtk_event_box_new();
		gtk_signal_connect(GTK_OBJECT(eventbox), "event", GTK_SIGNAL_FUNC(peerevent), p);
		gtk_container_add(GTK_CONTAINER(eventbox), p->box);
		p->frame2 = p->box;
		p->box = eventbox;
#endif
	}
	return p;	
}

static void send_url_home(void)
{
	interpret_call(DEFAULT_HOME_PAGE);
}

static void send_url_register(void)
{
	interpret_call(REGISTER_URL);
}

static void send_url_bugs(void)
{
	interpret_call(BUGS_URL);
}

static void send_url_support(void)
{
	interpret_call(SUPPORT_URL);
}

static void send_url_developers(void)
{
	interpret_call(DEVELOPERS_URL);
}

static void send_url_demo(void)
{
	interpret_call(INTRODUCTORY_CALL);
}

int build_gui(void)
{
	GtkWidget *hbox;
	GtkWidget *vbox;
	GtkWidget *frame;
	GtkItemFactory *gif;
	
	static GtkItemFactoryEntry menu_items[] = {
	{ "/_File", NULL, NULL, 0, "<Branch>" },
	{ "/File/New _Call", "<control>C", GTK_SIGNAL_FUNC(open_new_call) },
	{ "/File/_Open URL","<control>O", GTK_SIGNAL_FUNC(open_new_url) },
#ifdef ENABLE_UPGRADE
	{ "/File/_Upgrade","<control>U", GTK_SIGNAL_FUNC(upgrade_init) },
#endif
	{ "/File/", NULL, NULL, 0, "<Separator>" },
	{ "/File/_Quit", "<control>Q", GTK_SIGNAL_FUNC(quit) },
	{ "/_Gnophone.com", NULL, NULL, 0, "<Branch>" },
	{ "/_Gnophone.com/Home", "<control>H", GTK_SIGNAL_FUNC(send_url_home) },
	{ "/_Gnophone.com/Introduction", "<control>I", GTK_SIGNAL_FUNC(send_url_demo) },
	{ "/_Gnophone.com/Register", "<control>R", GTK_SIGNAL_FUNC(send_url_register) },
	{ "/_Gnophone.com/", NULL, NULL, 0, "<Separator>" },
	{ "/_Gnophone.com/Bug Reports", "<control>B", GTK_SIGNAL_FUNC(send_url_bugs) },
	{ "/_Gnophone.com/Support", "<control>S", GTK_SIGNAL_FUNC(send_url_support) },
	{ "/_Gnophone.com/Developers", "<control>D", GTK_SIGNAL_FUNC(send_url_developers) },
	{ "/_Preferences", NULL, NULL, 0, "<Branch>" },
	{ "/Preferences/_Audio...", "<control>A", GTK_SIGNAL_FUNC(audio_prefs) },
/*	{ "/Preferences/_Video...", "<control>V", GTK_SIGNAL_FUNC(image_callback) },*/
	{ "/Preferences/_Telephone...", "<control>T", GTK_SIGNAL_FUNC(telco_prefs) },
	{ "/_Help", NULL, NULL, 0, "<LastBranch>" },
	{ "/Help/_About Gnophone", NULL, GTK_SIGNAL_FUNC(show_about) },
	
	};
	int items = sizeof(menu_items) / sizeof(menu_items[0]);

	/* Build the top level window */
	mw = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_realize(mw);
	g_signal_connect(GTK_OBJECT(mw), "destroy", GTK_SIGNAL_FUNC(quit), NULL);
	gtk_window_set_title(GTK_WINDOW(mw), "Gnophone");

	/* Build our accelerator group */
	gag = gtk_accel_group_new();
	
	/* Build the menubar */
	gif = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", gag);
	gtk_item_factory_create_items (gif, items, menu_items, NULL);
  	menubar = gtk_item_factory_get_widget(gif, "<main>");
	
	/* Build the notebook itself */
	nb = gtk_notebook_new();

        /* Build the browser */
        pbrowser = build_browser();

        if (pbrowser) {
                /* Add the browser as a page */
                gtk_notebook_append_page(GTK_NOTEBOOK(nb), pbrowser->box, gtk_label_new("Browser"));
		start_load_url(STARTING_URL);
        }

	/* Call Notebook Tab */
	frame = gtk_frame_new(NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
	
	scrolled = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
	scrolledvbox = gtk_vbox_new(TRUE, 5);
	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), scrolledvbox);

	fixedstatus = gtk_statusbar_new();
	gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(fixedstatus), FALSE);
	vbox = gtk_vbox_new(FALSE, 5);
	gtk_container_add(GTK_CONTAINER(frame), scrolled);
	gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
	
	gtk_box_pack_start(GTK_BOX(vbox), fixedstatus, FALSE, FALSE, 5);
	gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);

	gtk_notebook_append_page(GTK_NOTEBOOK(nb), vbox, gtk_label_new("Calls"));

	frame = gtk_frame_new(NULL);

	history = gtk_text_view_new();
	/* set word wrap to history for long calls to sethistory */
	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(history), GTK_WRAP_WORD);

	vbox = gtk_vbox_new(FALSE, 5);
	gtk_container_add(GTK_CONTAINER(frame), history);
	gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
	gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);

	gtk_notebook_append_page(GTK_NOTEBOOK(nb), vbox, gtk_label_new("History"));

	/* No peers right now -- don't confuse the user */
	setpeerstatus(NULL, "You have no calls.");

	/* Build the first vbox and place the notebook in it */
	vbox = gtk_vbox_new(FALSE, 5);
	gtk_box_pack_start(GTK_BOX(vbox), nb, TRUE, TRUE, 5);

	/* Connect the nb signal now after the events so to skip the initial set up signals */
	g_signal_connect(GTK_OBJECT(nb), "switch-page", GTK_SIGNAL_FUNC(notebook_change_page_cb), NULL);

	/* Build the hbox and place the vbox in it */
	hbox = gtk_hbox_new(FALSE, 5);
	gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);

	/* Make ourselves and put us "in the box" */
	self = new_peerwindow(1, PW_FLAG_EMPTY, "You!");
	vbox = gtk_vbox_new(FALSE, 5);
	gtk_box_pack_end(GTK_BOX(vbox), self->box, FALSE, FALSE, 5);
	gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);

	/* Put the hbox in a vbox, with the menu above it */
	vbox = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);

	gtk_container_add(GTK_CONTAINER(mw), vbox);
	gtk_widget_set_usize(mw, 705, 600);
	gtk_window_add_accel_group(GTK_WINDOW(mw), gag);
	gtk_widget_show_all(mw);
	return 0;
}

void open_new_call(GtkWidget *w)
{
	show_call_window(0, 0);
}

void open_new_url(GtkWidget *w)
{
	show_call_window(0, 0);
}

static float loudness(struct peerwindow *p, int level)
{
	float sum=level + 50.0;
	sum /= 50;
	if (level <= -80.0)
		return 0.0;
	if (sum > p->history)
		p->history = sum;
	else
		p->history = sum/4 + 3.0 * p->history/4.0;
	if (p->history > 1.0)
		p->history = 1.0;
	p->blah = p->history;
	/*if (p->blah <= 0.0 && p->blah > -99.0)
		p->blah = (- p->blah) / 100.0;*/
	if (p->blah < 0.0)
		p->blah = 0.0;
	else if (p->blah > 1.0)
		p->blah = 1.0;
	return p->blah;
}


static void handle_event(iaxc_event *e, struct peerwindow *p)
{
	switch(e->type) {
	case IAXC_EVENT_TEXT:
		{
			if (!strstr(e->ev.text.message, "Call disconnected"))
			{
				handle_hangup(p, e->ev.text.message);
			}
		}
		
		break;
	case IAXC_EVENT_LEVELS:
		{
			gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(p->level), loudness(p, e->ev.levels.output));
		}
		break;
	case IAXC_EVENT_STATE:
		{
/*			struct iaxc_ev_levels *templevels;*/
			if (PW_CALL_STATE_ACTIVE(e))
			{
			/*	templevels = iaxc_get_event_levels*/
			}
		}
		break;
	case IAXC_EVENT_NETSTAT:
		{
		}
		break;
	case IAXC_EVENT_URL:
		iaxloading = 1;
	
		break;
	default:
		printf("Unknown peerwindow event: %d\n", e->type);
	}
}

static int gnophone_iaxc_callback(iaxc_event e)
{
	struct peerwindow * peer;
	char buf[80];
	char buf2[80];
	char *exten;
	int res = 0;

	peer = find_peerwindow(e.ev.call.callNo);
	/*if (e.type == IAXC_EVENT_STATE)
		e.type = gnophone_translate_state(e.type, peer);*/
	if (peer) {
		printf("Inside if (peer)\n");
		handle_event(&e, peer);
	} else {
		switch(e.type) {
			case IAXC_EVENT_TEXT:
				printf("iaxc_callback(): event text\n");
				if (!strstr(e.ev.text.message, "Error")) {
					printf("iaxc_callback(): Received Text event: %s\n", e.ev.text.message);
					/* Check to see if this is a bad iax register event */
					if (!strcmp(e.ev.text.message, "Event (type 11) for a non-existant session.  Dropping"))
					{
						sethistory("There is a problem with registering with IAX.  The program will attempt to register with the server again in 10 seconds.");
						g_timeout_add( (1000 * 60), iax_reg_timer, NULL);
					} else {
						sethistory(e.ev.text.message);
					}
					
				}	
				break;
			case IAXC_EVENT_LEVELS:
				printf("iaxc_callback(): event levels in = %f | out = %f\n", e.ev.levels.input, e.ev.levels.output);
			/*	gtk_progress_bar_set_fraction(self->level, (double)e.ev.levels.*/
				gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(self->level), (double)loudness(self, e.ev.levels.output));

				/* volume levels */
				/* XXX Do we need to do anything with these? XXX
				   XXX They come every second or so ...      XXX */
				break;
			case IAXC_EVENT_URL:
				/* eventually, we would make this pop up in our
				   integreated browser */
				printf("iaxc_callback(): Received URL: %s\n", e.ev.url.url);
				sethistory(e.ev.url.url);
				break;	
			case IAXC_EVENT_STATE:
				printf("iaxc_callback(): event state\n");
				/*printf("Received State: (%d) -- callNo: %d -- format: %d -- remote: %s -- remote_name: %s -- local: %s -- local_context:\n", e.ev.call.state, e.ev.call.callNo, e.ev.call.remote, e.ev.call.remote_name, e.ev.call.local);*/	
				exten = strrchr(e.ev.call.remote_name, '/');
				if (exten)
					exten++;
				else
					exten = e.ev.call.remote_name;
				
				if ((e.ev.call.state & IAXC_CALL_STATE_RINGING) && !(e.ev.call.state & IAXC_CALL_STATE_OUTGOING))
				{
					peer = new_peerwindow(0, PW_FLAG_EMPTY, exten);
					sessions++;
					peer->next = peers;
					peers = peer;
					peer->pcid = e.ev.call.callNo;
					if (strlen(e.ev.call.remote) && strlen(e.ev.call.local)) {
						snprintf(buf, sizeof(buf), "Call from '%s' for '%s'",
								e.ev.call.remote, 
								e.ev.call.local);
						g_snprintf(buf2, sizeof(buf2), "%s", e.ev.call.remote);
					} else if (strlen(e.ev.call.local)) {
						snprintf(buf, sizeof(buf), "Call for '%s'", e.ev.call.local);
					} else if (strlen(e.ev.call.remote)) {
						snprintf(buf, sizeof(buf), "Call from '%s'", e.ev.call.remote);
						g_snprintf(buf2, sizeof(buf2), "%s", e.ev.call.remote);
					} else {
						snprintf(buf, sizeof(buf), "Call from %s",
								/* inet_ntoa(e.ev.call.addr.sin_addr) */
								"<unknown caller>");
						g_snprintf(buf2, sizeof(buf2), "%s", 
								/* inet_ntoa(e.ev.call.addr.sin_addr) */
								"<unknown caller>");
					}
					g_snprintf(peer->cid, sizeof(peer->cid), "%s", buf2);
					gtk_widget_show_all(peer->box);

					/*iaxc_answer_call(peer->pcid);
					iaxc_ring_announce(peer->pcid);*/
					most_recent_answer = peer;
					gtk_widget_show_all(peer->box);
					
/*					get_best_pos(&x, &y);
					gtk_fixed_put(GTK_FIXED(fixed), peer->box, x, y);*/
					gtk_notebook_set_page(GTK_NOTEBOOK(nb), 1);		
					setpeerstatus(NULL, "Incoming call!");
					sethistory(buf);
					/*iaxc_answer_call(e.ev.call.callNo);	*/
				} else { /* ringing and outgoing */
					iaxc_unquelch(e.ev.call.callNo);
					peer = new_peerwindow(0, PW_FLAG_NO_ANSWER_BUTTON, exten);
					peer->next = peers;
					peers = peer;
					peer->pcid = e.ev.call.callNo;
					if (strlen(e.ev.call.remote) && strlen(e.ev.call.local)) {
						snprintf(buf, sizeof(buf), "Call from '%s' for '%s'",
								e.ev.call.remote, 
								e.ev.call.local);
						g_snprintf(buf2, sizeof(buf2), "%s", e.ev.call.remote);
					} else if (strlen(e.ev.call.local)) {
						snprintf(buf, sizeof(buf), "Call for '%s'", e.ev.call.local);
					} else if (strlen(e.ev.call.remote)) {
						snprintf(buf, sizeof(buf), "Call from '%s'", e.ev.call.remote);
						g_snprintf(buf2, sizeof(buf2), "%s", e.ev.call.remote);
					} else {
						snprintf(buf, sizeof(buf), "Call from %s",
								/* inet_ntoa(e.ev.call.addr.sin_addr) */
								"<unknown caller>");
						g_snprintf(buf2, sizeof(buf2), "%s", 
								/* inet_ntoa(e.ev.call.addr.sin_addr) */
								"<unknown caller>");
					}
					g_snprintf(peer->cid, sizeof(peer->cid), "%s", buf2);
					gtk_widget_show_all(peer->box);
					gtk_widget_hide_all(peer->answer);
					/*iaxc_answer_call(peer->pcid);
					iaxc_ring_announce(peer->pcid);*/
					most_recent_answer = peer;
					gtk_widget_show_all(peer->box);
	
					/* TODO:  Add ringing, outgoing call */
				}
				/*iaxc_set_filters((IAXC_FILTER_AGC | IAXC_FILTER_AAGC | IAXC_FILTER_CN |
						  IAXC_FILTER_DENOISE | IAXC_FILTER_ECHO));*/
				break;
			case IAXC_EVENT_NETSTAT:
				printf("Received NetStat: callno: %d rtt: %d\n", e.ev.netstats.callNo,
					e.ev.netstats.rtt);
				printf("\tlocal jitter=%d losspct=%d losscnt=%d packets=%d delay=%d dropped=%d ooo=%d\n", e.ev.netstats.local.jitter, e.ev.netstats.local.losspct, e.ev.netstats.local.losscnt, e.ev.netstats.local.packets, e.ev.netstats.local.delay, e.ev.netstats.local.dropped, e.ev.netstats.local.ooo); 
				printf("\tremote jitter=%d losspct=%d losscnt=%d packets=%d delay=%d dropped=%d ooo=%d\n", e.ev.netstats.remote.jitter, e.ev.netstats.remote.losspct, e.ev.netstats.remote.losscnt, e.ev.netstats.remote.packets, e.ev.netstats.remote.delay, e.ev.netstats.remote.dropped, e.ev.netstats.remote.ooo); 
				break;
			default:
				res = -1;	
				printf("Unhandled Event - Type: %d\n", e.type);	
				break;
		}
	}

	return 0;
}

int launch_call(char *destination, char *title, int tbd)
{
	char buf[80];
	char callerid[80];
	iaxc_set_callerid("Test Phone", "69");
	iaxc_call(destination);
	sessions++;
	if (gethostname(callerid, sizeof(callerid)))
		strcpy(callerid, "Gnophone User");

	iaxc_set_callerid(callerid, destination);
	snprintf(buf, sizeof(buf), "Call to %s", title);
	sethistory(buf);
	setpeerstatus(NULL, "Attempting connection");
	return 0;
}

void iax_reg(void)
{
	char *peer = telco_get_peer();
	char *secret = telco_get_secret();
	char *server = telco_get_server();
	char buf[256];
	
	if (server && strlen(server) && peer && strlen(peer)) {
		if (secret && strlen(secret)) 
			snprintf(buf, sizeof(buf), "%s:%s@%s", peer, secret, server);
		else
			snprintf(buf, sizeof(buf), "%s@%s", peer, server);
	} else
		strcpy(buf, "");
			
	if (strlen(buf)) {	
		snprintf(buf, sizeof(buf), "Attempting to register '%s' at '%s'", peer, server);
		/*html_setstatus(pbrowser, buf);*/
		sethistory(buf);
		iaxc_register(peer, secret, server);
	}
}

static int iax_reg_timer(void *notused)
{
	iax_reg();
	return FALSE;
}

int run_gui(void)
{
	iaxc_set_event_callback(gnophone_iaxc_callback);
	iaxc_start_processing_thread();
	iax_reg();
	gtk_main();
	return 0;
}

