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

    FILE....: TLOAD.CPP
    TYPE....: C++ Program
    AUTHOR..: David Rowe
    DATE....: 21/2/01

    This program tests the VPB4 by loading it with 4 simultaneous
    channels of audio I/O.

    1. Start this program: ./tload.
    2. The card should take the port off hook.
    3. It will play a prompt continuously on all channels.
    4. Try loading the PC (open a window etc), running top etc.  See if
       audio breaks up (sign of DSP buffer under/overflow). 
    5. Press return to end (will take up to 2 seconds to finish)

    Expected Results:  
    
    DR 24/8/00 - no evidence of breakup, top showed CPU load of only 
    0.1% for 4 channels (P133 running Red Hat 6.2).

    NOTE: DR 18/2/04
    - max DSP load occurs when all 4 ports are connected to phone lines
    - listen to audio quality on ch4, as this channel will be affected first 
      if any DSP load issues

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

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

         Voicetronix Voice Processing Board (VPB) Software

         Copyright (C) 1999-2001 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 "vpbapi.h"
#include "verbose.h"
#include "generic.h"

#include <cstdio>

#define BUF_LENGTH  16000

void channel_thread(void *pv);
int WINAPI vpb_echo_canc_force_adapt_on();
int WINAPI vpb_echo_canc_force_adapt_off();
int WINAPI vpb_comp_load(unsigned short board);
#ifdef WIN32
#include <conio.h>
#else
int kbhit();
#endif

int finito,event_finito;
int active_threads;
GENERIC_CRITICAL_SECTION mutex;
int *h;
int *cycles;
int station_port;
VPB_TONE   tone = {400,600,800,-12,-100,-100,3000,1000};

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

	active_threads = 0;
	GenericInitializeCriticalSection(&mutex);

	event_finito = finito = 0;

	int num_ch = 4;
	h = new int[num_ch];
	cycles = new int[num_ch];

	// start a thread for each channel

	for(int i=0; i<num_ch; i++) {
		h[i] = vpb_open(0,i);

		if( i == 0 ) switch( vpb_get_card_type(h[i]) )
		{
		    case VPB_V4PCI:
		    case VPB_V4LOG: break;
		    default:
			printf("%s: ERROR: Card 0 is not a V4PCI\n", argv[0]);
			goto done;
		}

		cycles[i] = 0;
		Generic_beginthread(channel_thread, 0, (void*)&h[i]);
	}

	verbose(1);
	printf("Press return to finish.....\n");

	// simulate max computational load of DSP by forcing all echo canc
	// to adapt - RD 18/2/04 - very important to really test system,
	// make sure DSP load average is beneath 40, if u get strange
	// numbers it probably means too much DSP loading.

	vpb_echo_canc_force_adapt_on(); // worst case comp load

	while(!kbhit()) {
		vpb_comp_load(0);

		for(int i=0; i<num_ch; i++)
		  printf("%6d ", cycles[i]);
		printf("\n");

		vpb_sleep(1000);
		vpb_get_event_async(&trash);
	}
	vpb_echo_canc_force_adapt_off();

	// signal all threads and wait for all to finish

	finito = 1;
	while(active_threads)
		vpb_sleep(10);

    done:
	vpb_close();
	delete [] h;
	delete [] cycles;
	GenericDeleteCriticalSection(&mutex);

	return 0;
}

void channel_thread(void *pv)
{
	int        h = *(int*)pv;
	VPB_RECORD record;
	char       file_name[VPB_MAX_STR];
	VPB_EVENT	trash;

	// keep count of how many threads active

	GenericEnterCriticalSection(&mutex);
	active_threads++;
	GenericLeaveCriticalSection(&mutex);

	// init this port

	vpb_sethook_sync(h, VPB_OFFHOOK);
	sprintf(file_name,"ch%d.wav",h+1);
	record.term_digits = "";
	record.time_out = 2000;
	vpb_record_set(h, &record);

	// beep, record, play,.........

	while(!finito) {
		// playing a wave file was found to maximise DSP
		// loading.  Record one using recwave before running
		// this test, about 5 secs is OK.
		vpb_play_file_sync(h, "../dev/hiload.wav");
		cycles[h]++;
		vpb_get_event_ch_async(h, &trash);
	}

	// hangup
	vpb_sethook_sync(h, VPB_ONHOOK);

	// decrement active thread count

	GenericEnterCriticalSection(&mutex);
	active_threads--;
	GenericLeaveCriticalSection(&mutex);

}

