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

	FILE....: dialans.cpp
	TYPE....: C++ Console program
	AUTHOR..: Ben Kramer
	DATE....: xx/01/2005

	This program is used for testing Voicetronix.  It works like this:
	
	./dialand <channel> <number> <cid> <play audiofile>
	Dials the number on the selected channel, presenting the callerid
	requested, and once the call has been answered plays the audio file.
	If a call comes in it, will answer the call and record the call to a
	file.


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

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

         Voicetronix Voice Processing Board (VPB) Software

         Copyright (C) 1999-2004 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
	 USA

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

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "vpbapi.h"
#include "verbose.h"
#include "../kbhit.h"
#include "../threads.h"

#define CALL_IDLE 0
#define CALL_ANS  1
#define CALL_FIN  2
#define CALL_RING 3

void *port_thread(void *pv);
int arg_exists(int argc, char *argv[], char *arg);

int             threads_active; // the number of active threads.
pthread_mutex_t mutex;          // mutex to protect shared data
int             finito;         // flag to signal the program is finished.
float           gain;           // option software record gain

int main(int argc, char * argv[])
{

	int	port=-1;
	char	number[21];
	char	cid[21];
	char	wav_file[256];
	int	*h,*state,dh=-1;
	int	finito=0;
	int 	newstate;
	char	recfile[256];
	VPB_CALL_INFO call_info;

	int	ret;
	VPB_EVENT e;

	if (argc != 5){
		printf("%s <port> <number> <cid> <wav file>\n",argv[0]);
		exit(1);
	}
	else {
		port = atoi(argv[1]);
		strcpy(number,argv[2]);
		strcpy(cid,argv[3]);
		strcpy(wav_file,argv[4]);
		printf("Making call to %s from %s on port %d playing %s\n",number,cid,port,wav_file);
	}

	// count the cards and ports
	int num_cards = vpb_get_num_cards();
	int num_ch = 0;

	int ports_per_card[num_cards];

	for (int i = 0; i < num_cards; ++i)
		num_ch += (ports_per_card[i] = vpb_get_ports_per_card(i));

	printf("Found [%d] channels...\n",num_ch);

	h = new int[num_ch];
	state = new int[num_ch];

	// verbose(1);

	// now init each port and start one thread per port
	int x=0;
	for(int i=0; i<num_cards; i++) {
		for(int j=0;j<ports_per_card[i];j++){
			h[x] = vpb_open(i,j);
			if ((dh == -1 )&&(x == port)){
				dh = h[x];
			}
			state[x] = 0;
			x++;
		}
	}
	printf("%d ports opened!\n", num_ch);

	sleep(5);  // give D channel enough time to come up
	vpb_isdn_call(dh,number,cid,0,0);

	// do nothing in main loop until return pressed
	while((!kbhit())&&!finito){
//		ret = vpb_get_event_ch_sync(h,&e,500);
		ret = vpb_get_event_sync(&e,500);
		if (ret == VPB_OK) {
			printf("Got an event [%d] on [%d]\n",e.type,e.handle);
			if (e.handle == dh){
				switch(e.type){
					case VPB_ISDN_ANS:
						printf("Call was answered, playing file!\n");
	//					vpb_play_file_sync(h,wav_file);
						vpb_play_file_async(dh,wav_file,69);
	/*
						vpb_play_buf_start(h,VPB_LINEAR);
						retw = vpb_wave_open_read(&wf,wav_file);
						if (retw == VPB_OK){
							bytes  = vpb_wave_read(wf,buf,sizeof(buf));
							while(bytes>0){
								vpb_play_buf_sync(h,buf,bytes);
								bytes  = vpb_wave_read(wf,buf,sizeof(buf));
							} 
						}
						vpb_play_buf_finish(h);
						vpb_dial_sync(h,"12321231232121##");
						printf("Finished playing file!\n");
	*/
						break;
					case VPB_DROP:
						printf("The caller hung up :(\n");
						//finito=1;
						break;

					case VPB_DTMF:
						printf("Got DTMF [%d]\n",e.data);
						break;

					case VPB_TONEDETECT:
						printf("Got Tone [%d]\n",e.data);
						break;
					case VPB_PLAYEND:
						printf("Finished playing, hanging up\n");
						vpb_sethook_sync(dh,VPB_ONHOOK);
					default:
						break;
				}
			}
			else {
				switch(state[e.handle]){
					case CALL_IDLE:
						if (e.type == VPB_RING){
							newstate = CALL_RING;
							vpb_isdn_get_cinfo(e.handle,&call_info);
							printf("New call on handle [%d]!\n",e.handle);
						}
						else {
							printf("Dont know what to do with event[%d] when IDLE\n",e.type);
						}
						break;
					case CALL_ANS:
						if (e.type == VPB_DROP){
							vpb_record_terminate(e.handle);
							newstate=CALL_IDLE;
							printf("Caller hangup on handle [%d]!\n",e.handle);
						}
						else {
							printf("Dont know what to do with event[%d] when ANS\n",e.type);
						}
						break;
					case CALL_RING:
						if (e.type == VPB_RING){
							vpb_sethook_sync(e.handle,VPB_OFFHOOK);
							sprintf(recfile,"recfile-%02d.wav",e.handle);
							vpb_record_file_async(e.handle,recfile,VPB_ALAW);
							newstate = CALL_ANS;
						}
						else if (e.type == VPB_ISDN_CINFO){
							printf("Got caller ID [%s]!\n",call_info.callingnum);
						}
						else {
							printf("Dont know what to do with event[%d] when RING\n",e.type);
						}
						break;
					default:
						break;
				}
				state[e.handle] = newstate;
			}

		}


//		vpb_sleep(500);
	}

	printf("shutting down....\n");

	for(int i=0; i<num_ch; i++) {
		vpb_close(h[i]);
	}

	return 0;
}
