/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <stream.h>

#include "ObjProArith/hrdcmp.h"
#include "ObjProShare/shared.h"
#include "ObjProArith/hrdarth.h"

#include "ObjProGui/sigintfc.h"
#include "ObjProGui/intfc.h"
#include "ObjProGui/user.h"
#include "ObjProGui/remcom.h"
#include "ObjProGui/dspcom.h"
#include "ObjProGen/newaloc.h"
#include "ObjProDSPint/netlnk.h"

#include "ObjProGui/plotdatd.h"

#include "ObjProComGui/cgidbg.h"
#include "ObjProGui/yacintfc.h"
#include "ObjProUsr/plotnd.h"


void PlotNode::NewSampleRate()
{
 	// LogOut << "PlotNode::NewSampleRate called for `" << GetName() << "'\n" ;
	if (SetupState != RemoteSetupDone) return ;
	const Length = sizeof(int) + sizeof(double);
	char Buf[Length];
	for (int i = 0 ; i < GetIn(); i ++) {
		MoveNBytes(Buf,(char *) &i, sizeof(int)) ;
		MoveNBytes(Buf + sizeof(int), (char *)
			&(GetInLink(i)->GetTiming()->SampleRate),
			sizeof(double));
		PacketHeader Head = PlotPacketHeader(PacketWindowPlotControl,
			GetPlotId(),PlotControlNewSampleRate,Length);
		WriteSeg->WritePacket(Head,Buf);
/*
 *		LogOut << "Sent new sample rate " << GetInLink(i)->GetTiming()
 *			->SampleRate << " for node `" << GetName() << "'.\n"  ;
 */
	}
}

void PlotNode::RemoteSetup(RemoteSetupState Goal)
{
	AllocateBuffers();
/*
 *	LogOut << "PlotNode::RemoteSetup: Goal = " << Goal << 
 *		", State = " << SetupState << "\n" ;
 */ 
	if (SetupState >= Goal) return ;
	switch (SetupState) {
case RemoteSetupClear:
		ThePlotController.GetPlotId(this) ;
		SetupState = RemoteSetupIdReq;
		if (SetupState >= Goal) return ;
case RemoteSetupIdReq:
		// LogOut << "PlotNode::RemoteSetup - Checking for PlotId\n";
		while (!PlotId) CheckReadAndSleep() ;
		 // LogOut << "Got plot Id = " <<  PlotId << "\n" ;
		SetupState = RemoteSetupIdRec ;
		if (SetupState >= Goal) return ;
case RemoteSetupIdRec:
		// LogOut << "Sending header\n";
		SendHeader() ;
		SetupState = RemoteSetupSendResample ;
		// LogOut << "Header sent\n";
		if (SetupState >= Goal) return ;
case RemoteSetupSendResample:
		
		while (!HeaderComplete) {
			CheckReadAndSleep() ;
			// LogOut << "Header not complete.\n" ;
		}
		SetupState = RemoteSetupDone ;
case RemoteSetupDone:
		return ;
	}
}


// void TestAlloc(const char * Msg);

void PlotNode::AllocateBuffers()
{
	if (State.IsX()) {
		if (X_DataBufPtrs) return ;
    	NextWordInBuf = new int [Channels] ;
		X_DataBufPtrs = new MachWord * [Channels] ;
    	for (int i = 0 ; i < Channels ; i++) {
        	X_DataBufPtrs[i] = (MachWord *)
				new MachWordCast [MaxPacketSize/sizeof(MachWord)];
        	NextWordInBuf[i] = 0;
    	}
		return;
	}
	if (DataBufPtrs) return ;
	// LogOut << "Allocating " <<Channels << "\n" ;
	DataBufPtrs = new int16 * [Channels] ;
	NextWordInBuf = new int [Channels] ;
    for (int i = 0 ; i < Channels ; i++) {
        DataBufPtrs[i] = new int16 [MaxPacketSize>>1];
        NextWordInBuf[i] = 0;
    }
	// LogOut << "Allocating done\n" ;

}

void PlotNode::CheckRemoteSetup()
{
	// LogOut << "PlotNode::CheckRemoteSetup\n" ;
	RemoteSetup() ;
}


void PlotNode::SendHeader()
{
	DbgError("PlotNode::SendHeader", "base function called");
}

void PlotNode::X_CheckBuffer(int Channel)
{
	if (NextWordInBuf[Channel] >= ((MaxPacketSize-sizeof(MachWord)) /
			sizeof(MachWord)) -1) X_WriteBuffer(Channel);

}

void PlotNode::X_WriteBuffer(int Channel)
{
/*
 *	LogOut << "PlotNode::X_WriteBuffer(" << Channel << ") plotid = "
 *		<< GetPlotId() <<  ", NextWord = " << NextWordInBuf[Channel] << "\n" ;
 */
	if (!NextWordInBuf[Channel]) return ;
	PacketHeader Head = PlotPacketHeader(PacketWindowPlotData,
		GetPlotId(),Channel,NextWordInBuf[Channel]* sizeof(MachWord));
	WriteSeg->WritePacket(Head,(char *) X_DataBufPtrs[Channel]);
/*
 *	LogOut << "PlotNode::Wrote buffer of " <<
 *		(NextWordInBuf[Channel] << 1) << " bytes.\n" ;
 */
/*
 *	LogOut << "NextWordInBuf = " << (void *) NextWordInBuf <<
 *		", Channel = " << Channel << "\n" ;
 */
	NextWordInBuf[Channel] = 0;
}
void PlotNode::CheckBuffer(int Channel)
{
	if (NextWordInBuf[Channel] >= ((MaxPacketSize-2) >> 1) -1)
		WriteBuffer(Channel);

}

void PlotNode::WriteBuffer(int Channel)
{
/*
 *	LogOut << "PlotNode::WriteBuffer(" << Channel << ") plotid = "
 *		<< GetPlotId() << "\n" ;
 */	
	if (State.IsX()) {
		X_WriteBuffer(Channel);
		return ;
	}
	if (!NextWordInBuf[Channel]) return ;
	PacketHeader Head = PlotPacketHeader(PacketWindowPlotData,
		GetPlotId(),Channel,NextWordInBuf[Channel]<<1);
	WriteSeg->WritePacket(Head,(char *) DataBufPtrs[Channel]);
/*
 *	LogOut << "PlotNode::Wrote buffer of " <<
 *		(NextWordInBuf[Channel] << 1) << " bytes.\n" ;
 */
/*
 *	LogOut << "NextWordInBuf = " << (void *) NextWordInBuf <<
 *		", Channel = " << Channel << "\n" ;
 */
	NextWordInBuf[Channel] = 0;
}

void PlotNode::WriteDataWord(CxMachWord Word,int Channel)
{
	DataPlotHeader& TheDataPlot = *(GetDataPlot());
	MachWord RealWord = MachReal(Word);
	MachWord ImagWord = MachImag(Word);
	if (!State.IsX())
		if (TheDataPlot.GetStreamType() == PlotPairs) {
		double Temp ;
/*
 *		LogOut << "Scaling (" << RealWord << ", " << ImagWord
 *			<< ")\n" ;
 */
		RealWord=TheDataPlot.GetScaleX().DoScale(RealWord,Temp);
		ImagWord=TheDataPlot.GetScaleY(Channel).DoScale(ImagWord,Temp);
/*
 *		LogOut << "Scaled to (" << RealWord << ", " << ImagWord
 *			<< ")\n" ;
 */
	}
	WriteDataWord(RealWord,Channel);
	WriteDataWord(ImagWord,Channel);
}


void PlotNode::WriteDataWord(MachWord Word,int Channel)
{
	if (State.IsX()) {
		X_CheckBuffer(Channel);
		X_DataBufPtrs[Channel][NextWordInBuf[Channel]++] = Word ;
		X_CheckBuffer(Channel);
		return;
	}
	DbgError("PlotNode::WriteDataWord","only X interface");
}

void PlotNode::WriteDataPacket()
{

}



