/*

  $Id: waitcall.c,v 1.2 2006/07/30 15:27:27 dforsi Exp $

  G N O K I I

  A Linux/Unix toolset and driver for the mobile phones.

  This file is part of gnokii.

  Gnokii 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.

  Gnokii 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 gnokii; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Copyright (C) 2006 by Daniele Forsi

  An utility program that using libgnokii waits for a call, prints caller number to stdout, hangs up, then exits.

  compile with
  gcc -Wall -o waitcall waitcall.c `pkg-config --libs gnokii`

  and use like this

#!/bin/bash
while true; do
    result=$(waitcall)
    if [ "$?" -eq "0" ]; then
        echo "NUMBER: $result"
    else
        echo "ERROR: $?"
    fi
done

*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

#include <gnokii.h>

/* prepare for i18n */
#define _(x) x

struct gn_statemachine *state;
int quit = 0;
int call_detected = -1;

void businit(void) {
	gn_error	error;
	
	error = gn_lib_phoneprofile_load(NULL, &state);
	if (GN_ERR_NONE == error) {
		error = gn_lib_phone_open(state);
	}
	
	if (GN_ERR_NONE != error) {
		fprintf(stderr, "%s\n", gn_error_print(error));
		exit(2);
	}
}
	
void busterminate(void) {
	gn_lib_phone_close(state);
	gn_lib_phoneprofile_free(&state);
	gn_lib_library_free();
}

void signal_handler(int signal) {
	quit = 1;
}

void incoming_call(int lowlevel_id, char *number) {
	/* sometimes the callback function gets called twice for the same call */
	if (call_detected == lowlevel_id) return;
	
	printf("%s\n", number);
	call_detected = lowlevel_id;
	quit = 1;
}

gn_error hangup(int lowlevel_id) {
	gn_call_info	callinfo;
	gn_data		data;
	
	memset(&callinfo, 0, sizeof(callinfo));
	callinfo.call_id = lowlevel_id;

	gn_data_clear(&data);
	data.call_info = &callinfo;

	return gn_sm_functions(GN_OP_CancelCall, &data, state);
}

void notify_call(gn_call_status call_status, gn_call_info *call_info, struct gn_statemachine *state) {
	/* in this callback function you can't use those libgnokii functions that send a packet */
	
	if (call_status != GN_CALL_Incoming) return;
	
	incoming_call(call_info->call_id, call_info->number);
	
	return;
}

int main(int argc, char *argv[]) {
	gn_data		data;
	gn_error	error;
	int		call_id;
	gn_call         *call;
	int		notify;
	
	if (argc != 1) {
		fprintf(stderr, _("waitcall 0.5 by Daniele Forsi\nUsage: %s {without arguments}\nPurpose: wait for a call, print caller number to stdout, hang up, then exit\n"), argv[0]);
		exit(1);
	}
	
	fprintf(stderr, _("Initializing...\n"));
	businit();
	
	signal(SIGINT, signal_handler);
	
        /* Set up so that we get notified of incoming calls, if supported by the driver */
	gn_data_clear(&data);
	data.call_notification = notify_call;
	error = gn_sm_functions(GN_OP_SetCallNotification, &data, state);
	notify = (error == GN_ERR_NONE ? 1 : 0);
	
	fprintf(stderr, _("Waiting for a call.\n"));
	while (!quit) {
		sleep(1);
		
		error = gn_call_check_active(state);
		switch (error) {
		case GN_ERR_NONE:
			if (!notify) {
				/* act only on the first incoming call found */
				for (call_id = 0; call_id < GN_CALL_MAX_PARALLEL; call_id++) {
					call = gn_call_get_active(call_id);
					if (call && (call->status == GN_CALL_Incoming)) {
						incoming_call(call->call_id, call->remote_number);
						break;
					}
				}
			}
			break;
		case GN_ERR_UNHANDLEDFRAME:
			break;
		default:
			fprintf(stderr, "%s\n", gn_error_print(error));
			quit = 1;
		}
	}
	
	if (call_detected != -1) {
		error = hangup(call_detected);
		if (error != GN_ERR_NONE) {
			fprintf(stderr, _("Hang up failed: %s\n"), gn_error_print(error));
		} else {
			fprintf(stderr, _("Hang up ok\n"));
		}
	}
	
	busterminate();
	
	return 0;
}
