/* ***************************************************************************+
 * ITX package (cnrg.itx) for telephony application programming.              *
 * Copyright (c) 1999  Cornell University, Ithaca NY                          *
 *                                                                            *
 * This program is free software; you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public Liense as published by        *
 * the Free Software Foundation, either version 2 of the License, or (at      * 
 * your option) any later version.                                            *
 *                                                                            *
 * The ITX package 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.                                                          * 
 *                                                                            *
 * A copy of the license is distributed with this package.  Look in the docs  *
 * directory, filename GPL.                                                   *
 *                                                                            * 
 * Contact information:                                                       *
 * Donna Bergmark                                                             *
 * 484 Rhodes Hall                                                            *
 * Cornell University                                                         *
 * Ithaca, NY 14853-3801                                                      *
 * bergmark@cs.cornell.edu                                                    *
 ******************************************************************************/


package cnrg.itx.datax.jaudio;

class JAudioMessageThread extends Thread 
{
	//////////////////////////////////////////////////////////////////////
	//																	//
	//				 CLASS MEMBER VARIABLES								//
	//																	//
	//////////////////////////////////////////////////////////////////////

	protected int windowsID;
	protected boolean bRunning;

	//////////////////////////////////////////////////////////////////////
	//																	//
	//					  CLASS METHODS									//
	//																	//
	//////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////
	//
	//	JAudioMessageThread::JAudioMessageThread()
	//
	//	Description:
	//		JAudioMessageThread constructor.
	//	
	//	Parameters:
	//		None.
	//
	//	Returns:
	//		Nothing.
	//
	//////////////////////////////////////////////////////////////////////
	protected JAudioMessageThread() 
	{
	}

	//////////////////////////////////////////////////////////////////////
	//
	//	JAudioMessageThread::run()
	//
	//	Description:
	//		JAudioMessageThread thread method.
	//	
	//	Parameters:
	//		None.
	//
	//	Returns:
	//		Nothing.
	//
	//////////////////////////////////////////////////////////////////////
	public void run() 
	{
		JAudioDevice device;
		JAudioBlock block;
		JAudioMessage msg = new JAudioMessage();
		JAudioDevice.println("Message thread started (ID = " + windowsID + ")");

		// Get the windows thread ID
		windowsID = getThreadIDN();

		// Notify everybody who is waiting for us to start
		synchronized(this) 
		{
			this.notifyAll();
		}

		bRunning = true;

		// Main loop
		while (bRunning) 
		{
			try 
			{
				// Get yet another message...
				msg.message = 0;
				msg.param1 = msg.param2 = 0;
				getMessageN(msg);

				switch(msg.message) 
				{
				case msg.WOM_OPEN:
					JAudioDevice.println("Device output opened -> " + msg.toString());
					break;

				case msg.WOM_CLOSE:
					JAudioDevice.println("Device output closed -> " + msg.toString());
					break;

				case msg.WOM_DONE:
					JAudioDevice.println("Device done -> " + msg.toString());

					// Mark the block as finished
					device = JAudioDevice.getDeviceByHwo(msg.param1);
					// the device has been closed
					if (device == null)
					{
					   bRunning = false;
					   break;
					}
					block = (JAudioBlock)device.out.blockQueue.Pop();
					if (block == null || msg.param2 != block.wpHeader) 
					{
						JAudioDevice.println("Can't find finished block");
						break;
					}
					block.markAsFinished();
					break;

				case msg.WIM_OPEN:
					JAudioDevice.println("Device input opened -> " + msg.toString());
					break;

				case msg.WIM_CLOSE:
					JAudioDevice.println("Device input closed -> " + msg.toString());
					break;

				case msg.WIM_DATA:
					JAudioDevice.println("Device data -> " + msg.toString());

					// Mark the block as finished
					device = JAudioDevice.getDeviceByHwi(msg.param1);
					// the device has been closed
					if (device == null)
					{
					   bRunning = false;
					   break;
					}
					block = (JAudioBlock)device.in.blockQueue.Pop();
					if (block == null || msg.param2 != block.wpHeader)
					{
						JAudioDevice.println("Can't find incoming block");
						break;
					}
					block.markAsFinished();
					break;
					
				case msg.WM_STOP_JAUDIO:
					JAudioDevice.println("JAudioMessageThread: Exiting...");
					bRunning = false;
					break;

				default:
					JAudioDevice.println("Unknown message -> " + msg.toString());
				}
			} 
			catch (NullPointerException e)
			{
			   JAudioDevice.println("JAudioMessageThread: Caught the null pointer.");
			}

			catch (ThreadDeath e) 
			{
				throw e;
			}
			catch (Throwable e) 
			{
				e.printStackTrace(System.out);
			}
		}
	}

    public void shutdown()
    { 
		JAudioMessage stopMessage = new JAudioMessage();
		stopMessage.message = JAudioMessage.WM_STOP_JAUDIO;
		
		// Send the Windows message thread a WM_JAUDIO_MESSAGE
		postThreadMessageN(windowsID, stopMessage);
    }

	//////////////////////////////////////////////////////////////////////
	//																	//
	//					  CLASS HELPER METHODS							//
	//																	//
	//////////////////////////////////////////////////////////////////////

	// All native methods
	static native int getThreadIDN();
	static native int getMessageN(JAudioMessage msg);
	static native int postThreadMessageN(int threadID, JAudioMessage msg);
}
