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

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

    initialise all ports with loopback turned on.
    1. wait for ringing on any channel.
    2. take the channel off hook.
    3. wait 10 seconds then hang 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"

void *port_thread(void *pv);

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.

int main(int argc, char * argv[])
{
	int	        *h;
	pthread_t       *aport_thread;

	// verbose(1);
	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));

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

	h = new int[num_ch];
	aport_thread = new pthread_t[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>0) {
		vpb_sleep(100);
		printf("threads active: %d\r", threads_active);
	}
	printf("All channel threads have shut down...\n");

	vpb_close();
	delete h;

	return 0;
}

void *port_thread(void *pv) {
	int       	h = *(int*)pv;
	VPB_EVENT 	e;
	char		s[VPB_MAX_STR];

	pthread_mutex_lock(&mutex);
	threads_active++;
	pthread_mutex_unlock(&mutex);
	vpb_loopback_on(h);
//	vpb_hostecho_on(h);

	while(!finito) {

		if( vpb_get_event_ch_sync(h, &e, 1000) != VPB_OK ) continue;
		vpb_translate_event(&e,s);
		printf("Event Type[%d] chan %s", e.type,s);
		if ((e.type == VPB_RING) /*|| (e.type == VPB_STATION_OFFHOOK)*/) {
			printf("[%02d] answering.....\n",h);
			vpb_sethook_async(h,VPB_OFFHOOK);
			printf("[%02d] sleeping for 10 sec ...\n",h);
			vpb_sleep(10000);
			vpb_sethook_async(h, VPB_ONHOOK);
			printf("[%02d] done.....\n",h);
		}
	}
	vpb_loopback_off(h);
	printf("[%02d] Loop back off....\n",h);
	vpb_sleep(350);

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

	return NULL;
}

