/*
 *  outker.C from ObjectProDSP 0.1
 *  Copyright (C) 1994, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  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 version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
#include <string.h>
#include <unistd.h>
#include "yacintfc.h"
#include "outfile.h"
#include "outnode.h"
#include "cgidbg.h"
#include "drvout.h"
#ifndef TI_C30
#define O_BINARY 0
#endif
#include <fcntl.h>
#include <libc.h>
#include "ramio.h"
#include "sysconst.h"
#include "remcom.h"
#include "rtktest.h"
#include "environ.h"

int OutputNode::read_binary()
{
	return binary_read_flag ;
}

#ifdef INTERACTIVE
int OutputNode::InitAfterLinked()
{
    return set_read_binary_flag(binary_read_flag) ;
}

void OutputNode::input_linked(int )
{
	// after one channel is linked set all other channels to be
	// identical
	if (already_set) return;
	already_set = 1 ;
	ArithType::ArithCapabilities typ = ArithType::ArithTypeUndefined ;
	for (int i = 0 ; i < GetIn() ; i++) {
		typ = GetInStream(i)->GetArithType();
		if (typ != ArithType::ArithCapabilityAny) break ;
	}
	if (typ ==  ArithType::ArithTypeUndefined) {
		State.Error("no arithmetic type set, cannot link node");
		return ;
	}
	
	for (i = 0 ; i < GetIn() ; i++)  GetInStream(i)->SetArithType(typ) ;
}
#endif



void OutputNode::FileInit()
{
	TheOutputFile = new OutputFile(this,GetFileName());
	FileName_1 = TheOutputFile->GetFileName();
}



void OutputNode::Ctor()
{
	TheOutputFile = 0 ;
	TheNetworkReader = 0 ;
	if (!GetFileName()) SetFileName(GetName());
	TheReaderOutputInterface = &DefaultDriverOutputInterface ;
#ifdef INTERACTIVE
	if (State.IsInteractive()) FileInit();
#else
	FileInit();
	#endif
}

ErrCode OutputNode::NodeReset()
{
	ErrCode Return = OK ;
	// LogOut << "OutputNode::NodeReset() for `" << GetName() << "'\n" ;
	if (TheOutputFile) {
		// LogOut << "Calling TheReaderOutputInterface\n" ;
		MachWord x = (MachWordCast) 0 ;
		if (TheReaderOutputInterface(this, ResetDriverSystemInterface,
			0, &x) < 0) return FatalError ;
		ErrCode Loc = TheOutputFile->Reset();
		if (Loc > Return) Return = Loc ;
	}
	return Return ;
}

ErrCode OutputNode::TheKernel(int32 k)
{
	// LogOut << "OutputNode::TheKernel(" << k << ")\n" ;
	ErrCode Ret = OK ;
	ErrCode Loc ;
#ifdef INTERACTIVE
	if (!TheOutputFile) {
		FileInit() ;
		if (!TheOutputFile->CreateOk()) {
			delete TheOutputFile ;
			TheOutputFile = 0 ;
			// LogOut << "returning FatalError\n" ;
			return FatalError ;
		}
	}
#endif
	ErrCode Return = OK ;
	int32 block_size = GetBlockSize();
	if (!block_size) block_size = 1 ;
	int32 SaveTotal = k * block_size * GetInEltSize() * GetDeltaIn();
	// LogOut << "SaveTotal = " << SaveTotal << "\n" ;
	int32 DataSize ;
	for (int Chan = 0; Chan < GetIn(); Chan++) {
	    int32 Left = SaveTotal ;
	    while(DataSize = GetContiguousAvailableData(Chan)) {
			// LogOut << "DataSize = " << DataSize << ", chan = " << Chan <<
				"\n" ;
			if (DataSize > Left) DataSize = Left ;
			if (DataSize < 1) break ;
			const MachWord * Ptr  = GetReadPtr(Chan);
			// LogOut << "DataSize = " << DataSize << "\n" ;
			int32 DataWritten = TheReaderOutputInterface(this,Chan,DataSize,
				(MachWord *) Ptr) ;
			// LogOut << GetName() << " wr " << DataWritten << "\n" ;
			if (DataWritten < 1) {
				Return = EndOfData ;
				break ;
			} else {
				UpdateRead(DataWritten,Chan);
				Left -= DataWritten ;
			}
        }
	}
	// LogOut << "Returning " << Return << "\n" ;
	return Return ;
}

void OutputNode::Dtor()
{
	// LogOut << "OutputNode::Dtor for `" << GetName() << "'\n" ;
	delete TheOutputFile ;
	SetFileName(0);
}

