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

    FILE....: playdtmf.cpp
    TYPE....: C++ Console program
    AUTHOR..: Ben Kramer
    DATE....: xx/11/2004

    This program is used for testing Voicetronix.  It works like this:

    It intiliazed all ports with loopback turned on.
    1. It waits for ringing on any channel.
    2. It then takes the channel off hook 
    3. plays a string of DTMF's and hangs up
    4. Press return to finish, otherwise it waits for the next ring (step 1)


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

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

         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"

int ctwaitforevent(int h, int event_type, int timeout_ms);
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	        *h;
	VPB_RECORD	record;
	pthread_t       *aport_thread;

	// verbose(1);
	record.term_digits = "1234567890*#";  // any digit terminates record
	record.time_out = 4000;               // record finishes after 4 seconds
	pthread_mutex_init(&mutex,NULL);
	finito = 0;

	// 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));

	h = new int[num_ch];
	aport_thread = new pthread_t[num_ch];

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

	// 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);
			pthread_create(&aport_thread[x], NULL, port_thread, (void*)&h[x]);
			x++;
		}
	}
	printf("%d ports opened!\n", num_ch);

	// do nothing in main loop until return pressed
	while(!kbhit()){
		vpb_sleep(500);
	}
	finito = 1;

	printf("shutting down....\n");
	while(threads_active) {
		vpb_sleep(100);
		printf("threads active: %d\r", threads_active);
	}

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

	return 0;
}

void *port_thread(void *pv) {
	int       h = *(int*)pv;
	int       ev;
	char      file_name[VPB_MAX_STR];


	pthread_mutex_lock(&mutex);
	threads_active++;
	pthread_mutex_unlock(&mutex);
	sprintf(file_name,"linear%02d.wav",h);
//	vpb_loopback_on(h);

	while(!finito) {

		if(VPB_RING == (ev= ctwaitforevent(h, VPB_RING, 0))) {
//			ev = ctwaitforevent(h, VPB_RING, 6000);
//		if ((ev == VPB_RING) || (ev == VPB_STATION_OFFHOOK)) {
			printf("[%02d] answering.....\n",h);
			vpb_sethook_sync(h,VPB_OFFHOOK);

			
			printf("[%02d] Playing some dtmfs\n",h);
//			vpb_dial_async(h,"1");
//			vpb_dial_async(h,"2");
//			vpb_dial_async(h,"3");
//			vpb_dial_async(h,"4");
//			vpb_dial_async(h,"5");
//			vpb_dial_async(h,"6");
//			vpb_dial_async(h,"7");
//			vpb_dial_async(h,"8");
//			vpb_dial_async(h,"9");
//			vpb_dial_async(h,"0");
//			vpb_dial_async(h,"a");
//			vpb_dial_async(h,"b");
//			vpb_dial_async(h,"c");
//			vpb_dial_async(h,"d");
			vpb_dial_sync(h,"1234567890abcd");
//			vpb_dial_sync(h,"1,2,3,4,5,6,7,8,9,0,a,b,c,d");
			printf("[%02d] Played some dtmfs\n",h);
//			vpb_dial_sync(h,"1234567890abcd");
//			vpb_sleep(10000);
			

			vpb_sethook_sync(h, VPB_ONHOOK);
			printf("[%02d] done.....\n",h);
		}
	}
//	vpb_loopback_off(h);

	pthread_mutex_lock(&mutex);
	threads_active--;
	pthread_mutex_unlock(&mutex);

	return NULL;
}
	
int ctwaitforevent(int h, int event_type, int timeout_ms) {
	char      s[VPB_MAX_STR];
	int       ret, state;
	VPB_EVENT e;   
	void      *timer;

	vpb_timer_open(&timer, h, 0, timeout_ms);
	if (timeout_ms != 0)
		vpb_timer_start(timer);

	state = 1;
	while(state && !finito) {
		ret = vpb_get_event_ch_async(h, &e);

		if (ret == VPB_OK) {
			vpb_translate_event(&e, s);
			printf("%s",s);

			if (e.type == event_type) {
				state = 0;
			}
			if (e.type == VPB_TIMEREXP) {
				state = 0;
			}
			if(e.type == VPB_STATION_OFFHOOK) {
				state = 0;
			}	
		}
		else
			vpb_sleep(100);
	}
	  
	vpb_timer_close(timer);	
	if (state == 0)
		return e.type;
	else
		return -1;
}

int arg_exists(int argc, char *argv[], char *arg) {
  int i;

  for(i=0; i<argc; i++)
    if (strcmp(argv[i],arg) == 0)
      return i;

  return 0;
}
