// bergmark - Spring 1999 - ITX project - PhonePlayer (Version 1)

// PhonePlayer is an ITX application that lets you use your telephone
// to hear a message contained in a file.  It also tests the concept
// of a *single* application being both the server and the client

// Details:  connection is half-duplex
//           input channel: null
//           output channel: StreamSource -> NetworkDestination
//                              (a file)       (a telephone)

// Instructions for running:
//    jview PhonePlayer [ phone-number [ filename [msec delay]]]
//    [ 
//      Make sure there is a file in your Current Working Directory of
//          the filename specified (default is "file1")
//      Also make sure there is a "resolv.conf" in the current working dir.
//      Listen to the message, using the receiver on your handset
//      Hangup 
//    ]

import java.io.*; // for InputStream

import cnrg.itx.signal.*;              // for DesktopSignaling
import cnrg.itx.signal.SignalEvent.*;  // for Hangup event
import cnrg.itx.datax.devices.*;       // for AudioConnection, etc.
import cnrg.itx.datax.*;               // for Channel

public class PhonePlayer extends AbstractSignalingObserver {

   private final String ME = "PhonePlayer ";
   private final boolean LOG = true;

   // handle for our signaling component
   private DesktopSignaling myDS = null;

   // these are features of our file->telephone channel
   private NetworkDestination dest = null;
   private StreamSource source = null;
   private Channel out = new Channel();    
   private FileInputStream ourFile = null;
   private String savedString;  // save Custom Message, restore later

   // these are defaults over-rideable by command-line arguments
   private String phone;
   private static final String defaultPhone = "51183";
   private String soundFile;
   private static final String defaultFileName = "file1";

   // here is a constant that sets flow control (how many ms of sound
   // are to be buffered before being sent out over the network 
   private static int DELAY = 50;  

   // Default constructor
   public PhonePlayer ( String[] args ) {
      try {
	 myDS = new DesktopSignaling ( this, "guest", "guest");
      } catch ( Exception e ) {
	 System.out.println ("Could not get a DesktopSignaling because " +
	    e.toString() );
	 System.exit( 0 );
      }

      try {
      savedString = myDS.getDirectory().getCustomMessage();
      myDS.getDirectory().setCustomMessage("Trying out Phone Player");
      } catch (Exception e){savedString=null;}

      // parse the arguments
      if ( args.length > 0 ) phone = args[0];
      else phone = defaultPhone;

      if ( args.length > 1 ) soundFile = args[1];
      else soundFile = defaultFileName;

      if ( args.length > 2 ) DELAY = Integer.valueOf(args[2]).intValue();
   }

   // Main program sets up a data channel and then inokes onStartCall
   public static void main ( String[] args ) {
      PhonePlayer me = new PhonePlayer( args );
      me.setupChannel(); me.checkChannel(me.out);
      try {
	 SignalConnection sc = me.myDS.Dial (me.phone, null, me.out);
	 me.onStartCall (sc);  
      } catch ( Exception e ) {
	 System.out.println ("The Dial failed because " + e.toString());
	 System.exit(0);
      }
   }

   // +++++  SignalingObserver methods +++++++++++++

   // This method is not invoked by DesktopSignaling because we never
   // get StartCallSignalEvent (because we never accepted an invite).
   // Instead, we call this routine upon successful dial.

   public void onStartCall (SignalConnection sc) {

      if ( LOG ) System.out.println ( ME + "is in StartCall");

      try {
	 sc.open();
      } catch ( Exception e ) {
	 System.out.println ("Could not open up the AudioConnection because " +
	    e.toString() );
	 System.exit( 0 );
      }

      // If we get to here, we have an open data connection
      if ( LOG ) System.out.println(ME + "opened a data connection");

      //  At this point, the data connection is open and audio data
      //  is streaming from our input file to the gateway.
      //  We should hear the message over the telephone

   }

   // This method is invoked when the caller hangs up.
   public void onHangup(HangupSignalEvent hse) {
      if ( LOG ) System.out.println ( ME + "got hangup ... close the file "
	 + " and log out");   // TBD: actually just stop this thread
      try {
	 ourFile.close();
      } catch ( Exception e ) {}
      System.out.println ( ME + " Statistics: ");
      System.out.println ( source.getStatistics() );
      System.out.println ( dest.getStatistics() );
      try {
      myDS.getDirectory().setCustomMessage(savedString);
      } catch (Exception e){}
      myDS.logout();
   }

   // +++++++++++  Private methods +++++++++++++++++=
   private void setupChannel () {

      System.out.println (ME+"in setupChannel...");

      // Open the input file
      try {
	 ourFile = new FileInputStream ( soundFile );
      } catch ( Exception e ) {
	 System.out.println (ME + "could not open the source input " +
	    " file because " + e.toString() );
	 System.exit( 0 );
      }
      System.out.println(ME+"opened the source input file");
      try {
	 // DELAY msec flow control on the buffers
	 source = new StreamSource( ourFile, out, DELAY );
	 out.setSource(source);
	 dest = new NetworkDestination();
	 out.addDestination(dest);
      } catch (DataException e){
	 System.out.println(ME+"could not attach source/destingation " +
	 "to our out channel because " + e.toString() );
	 System.exit(0);
      }
   }

   private void checkChannel (Channel c) {
      // for debugging, print various characteristics of channel c
      if ( c == null ) {
	 System.out.println (ME+"null channel");
	 return;
      }
      // have a non-null channel
      PropertiesCollection pc = c.getProperties();
      System.out.println (ME+"c.properties collection is" +
	 pc==null? "null" : "not null");
      Source s = c.getSource();
      System.out.println (ME+"c.source is" + s==null? "null" : "not null");
      Stats numbers = c.getStatistics();
   }

}

