/*---------------------------------------------------------------------------*\

    FXS port test program - rings port while port is on hook, stops
    ringing when port goes off hook and plays a 10sec dialtone.
    Rinse, wash, repeat, until you press a key.


         Voicetronix Voice Processing Board (VPB) Software

         Copyright (C) 1999-2008 Voicetronix www.voicetronix.com.au

         This library is free software; you can redistribute it and/or
         modify it under the terms of the GNU Lesser General Public
         License as published by the Free Software Foundation; either
         version 2.1 of the License, or (at your option) any later version.

         This library 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
         Lesser General Public License for more details.

         You should have received a copy of the GNU Lesser General Public
         License along with this library; if not, write to the Free Software
         Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
         MA  02110-1301  USA

\*---------------------------------------------------------------------------*/

#include "vpbapi.h"

#include "verbose.h"
#include "kbhit.h"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <csignal>


#define MAX_CH 64

static volatile sig_atomic_t sigint;


static void sigterm_handler(int sig)
{
	if(sig == SIGINT || sig == SIGTERM) sigint = 1;
}


static int arg_exists(int argc, char *argv[], const char *arg)
{
	for(int i = 0; i < argc; ++i)
		if(strcmp(argv[i],arg) == 0) return i;

	return 0;
}

int main(int argc, char *argv[])
{
	VPBPortHandle	h[MAX_CH];
	HookState	state[MAX_CH];
	int		CH     = 8;
	int		FROM   = 0;
	int		bd     = 0;
	int		arg;

	// setup SIGTERM/SIGINT handler to allow for an orderly exit
	struct sigaction new_action;
	sigemptyset(&new_action.sa_mask);

	new_action.sa_handler = sigterm_handler;
	new_action.sa_flags   = SA_RESTART | SA_RESETHAND;
	sigaction(SIGINT,  &new_action, NULL);
	sigaction(SIGTERM, &new_action, NULL);


	//verbose(1);
	if(arg_exists(argc, argv, "-?") || arg_exists(argc, argv, "--help")) {
		printf("%s --card [0..] --module [0|1]\n",argv[0]);
		return 0;
	}
	if((arg = arg_exists(argc, argv, "--card")) != 0) {
		bd = strtol(argv[arg+1], NULL, 16);
	}
	if((arg = arg_exists(argc, argv, "--module")) != 0) {
		FROM   = strtol(argv[arg+1], NULL, 16) * 4;
		CH     = FROM + 4;
	}

	for(int i = FROM; i < CH; ++i)
	{
		VPBPortHandle	handle = vpb_open(bd,i);

		if( handle >= MAX_CH ) {
			printf("Uh Oh, silly hardcoded limit of %d ports hit again\n",
									MAX_CH);
			goto uh_oh;
		}
		vpb_disable_event(handle, VPB_MRING);
		state[handle] = vpb_get_hookstate(handle);
		if( state[handle] == VPB_ONHOOK )
			vpb_ring_station_async(handle, VPB_RING_STATION_ON);

		h[i] = handle;
	}

	while( ! kbhit() && ! sigint )
	{
		VPB_EVENT  e;

		// Time out occasionally here to check if the user hit a key.
		if( vpb_get_event_sync(&e,500) != VPB_OK )
			continue;

		char  s[VPB_MAX_STR];

		vpb_translate_event(&e, s);
		printf("%s",s);

		switch(state[e.handle])
		{
		    case VPB_ONHOOK:
			if (e.type == VPB_STATION_OFFHOOK) {
				vpb_playtone_async(e.handle, VPB_TONE_DIAL);
				state[e.handle] = VPB_OFFHOOK;
			}
			break;

		    case VPB_OFFHOOK:
			if (e.type == VPB_STATION_ONHOOK) {
				vpb_tone_terminate(e.handle);
				vpb_ring_station_async(e.handle, VPB_RING_STATION_ON);
				state[e.handle] = VPB_ONHOOK;
			}
			break;

		    case VPB_FASTOFFHOOK:
			break;
		}
	}
	printf("exiting ...\n");

	for(int i = FROM; i < CH; ++i)
		vpb_ring_station_async(h[i], VPB_RING_STATION_OFF);

	vpb_sleep(2000);

uh_oh:
	vpb_close();

	return 0;
}

