// audiorx. 
// A simple and amusing program for testing basic features of ccRTP.
// Copyright (C) 2001,2002  Federico Montesino <fedemp@altern.org>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//  
// This program 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 General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// A very simple mu-law encoded audio player.

// This is an introductory example file that illustrates basic usage
// of ccRTP. You will also see a bit on how to use CommonC++ threads and
// TimerPort.

// I am a player of \mu-law encoded RTP audio packets. I 
// do not accept any arguments.

#include <cstdio>
#include <cstdlib>
// Some consts common to audiorx and audiotx
#include <audio.h>
// In order to use ccRTP, the RTP stack of CommonC++, you only need to
// include ...
#include <ccrtp/rtp.h>

#ifdef	CCXX_NAMESPACES
using namespace ost;
using namespace std;
#endif

/**
 * @class ccRTP_AudioReceiver
 * This is the class that will do almost everything.
 */
class ccRTP_AudioReceiver: public Thread, public TimerPort
{
private:
	// This is the file we will write to (/dev/audio)
	int audiooutput;
	// The aforementioned file will be transmitted through this socket
	RTPSession *socket;

public:
	// Constructor
	ccRTP_AudioReceiver(){
		audiooutput=open("/dev/audio",O_WRONLY/*|O_NDELAY*/);

		if( audiooutput > 0 ){
			cout << "Audio device is ready to play." << endl;
		}else{
			cout << "I could not open /dev/audio " << endl;
			exit();
		}

		socket=NULL;
	}
	
	// Destructor. 
	~ccRTP_AudioReceiver(){
		terminate();
		delete socket;  
		::close(audiooutput);
	}

	// This method does almost everything.
	void run(void){    
		// redefined from Thread.
		
		// Before using ccRTP you should learn something about other
		// CommonC++ classes. We need InetHostAddress...

		// Construct loopback address
		InetHostAddress local_ip;
		local_ip = "127.0.0.1";
		
		// Is that correct?
		if( ! local_ip ){  
		// this is equivalent to `! local_ip.isInetAddress()'
			cerr << ": IP address is not correct!" << endl;
			exit();
		}
		
		cout << local_ip.getHostname() << 
			" is going to listen to perself through " <<
			local_ip << "..." << endl;
		
		// ____Here comes the real RTP stuff____
		
		// Construct the RTP socket
		socket = new RTPSession(local_ip,RECEIVER_BASE,0);
		
		// Set up receiver's connection
		socket->setSchedulingTimeout(10000);  
		if( !socket->addDestination(local_ip,TRANSMITTER_BASE) )
			cerr << "The receiver could not connect.";
		
		// Let's check the queue (you should read the documentation
		// so that you know what the queue is for).
		socket->startRunning();
		cout << "The RTP queue is ";
		if( socket->isActive() )
			cout << "active." << endl;
		else
			cerr << "not active." << endl;
		
		cout << "Waiting for audio packets..." << endl;
		
		// This will be useful for periodic execution.
		TimerPort::setTimer(PERIOD);

		setCancel(cancelImmediate);
		// This is the main loop, where packets are sent and receipt.
		socket->setPayloadFormat(StaticPayloadFormat(sptPCMU));
		for( int i=0 ; true ; i++ ){
			const AppDataUnit* adu;
			do{
				adu = socket->getData(socket->getFirstTimestamp());
				if ( NULL == adu )
					Thread::sleep(5);
				else cout << ".";
			}while ( (NULL == adu) || (adu->getSize() <= 0) );

			
			// This is for buffering some packets at the
			// receiver side, since playing smoothly
			// without any reception buffer is almost
			// impossible.  Try commenting the two lines
			// below, or stop transmission and continue
			// later: you will probably hear noise or
			// cracks.  
			if (i==0)
				Thread::sleep(20);
			
			::write(audiooutput,adu->getData(),adu->getSize());

			cout << "." << flush;

			// Let's wait for the next cycle
			Thread::sleep(TimerPort::getTimer());
			TimerPort::incTimer(PERIOD);
		}

	} // end of run
};


int main(int argc, char *argv[])
{
	cout << "This is audiorx, a simple test program for ccRTP." << endl;
	cout << "I am waiting for audio packets on port " << RECEIVER_BASE
	     << "." << endl;
	cout << "Do you want to hear something? Run audiotx." << endl;
	cout << "Strike [Enter] when you are fed up. Enjoy!." << endl; 

	// Construct the main thread. 
	ccRTP_AudioReceiver *receiver = new ccRTP_AudioReceiver();
	
	// Run it.
	receiver->start();

	cin.get();

	cout << endl << "That's all." << endl;

	delete receiver;

	exit(0);
}

/** EMACS **
 * Local variables:
 * mode: c++
 * c-basic-offset: 8
 * End:
 */





syntax highlighted by Code2HTML, v. 0.9.1