/*****************************************************************************

	Projet	: Pulsar Sample AddOn

	Fichier: sample_addon.cpp
	Partie	: Add-ons

	Auteur	: RM
	Date		: 040597 -- version 0.2 (C funcs)
	Date		: 010797 -- version 0.3 (CFilter)
	Date		: 180997 -- version 0.3.x, updated the comments and the code to keep in sync
	Format	: tabs==2 for better viewing

	This Sample Add-on does nothing. It is just a skeleton that you may use
	for building add-on.

	The simple way to do this :
	- implement & export the C function "CFilter * filterInit(uint32 index)",
	  where  you simply create your CFilter derived class.
	- derive a class from CFilter, you should at least implement two methods
	- CFilter::load() must be implemented, this is where you will fill info about
	  your add-on, name, auhtor, etc. You DON'T need to call the inherited function,
	  it does nothing.
	- CFilter::processFrame8() is where you draw the output, by using the info about
	  the sound and the stream.

	You can enhance this usage by implementing the other methods :
	- unload() called just before the add-on image is unloaded, the next call will be
	  the destructor.
	- prepare() is called just before the stream goes on, thus after load() but before
	  processFrame(). You can cache some info, as you may need.
	- terminate() is called when the stream is stopped, thus after any processFrame()
	  but before unload().

	The function always get called like this :
	- filterInit(), called once
	- constructor(), called once
	- load(), called once
	- loop :
			- prepare()
					- loop : several processFrame8(), up to 60 or 90 Hz... (more if you're lucky)
			- terminate()
	- unload()
	- destructor()
	- image unloaded.

	
	!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!
	>> In order to compile this, you need to get the Datatypes 1.6.3 package
	>> from BeWare to have the sources.
	>> Please go and surf on ftp.be.com/pub/contrib/lib or search into the
	>> BeWare page at http://www.be.com/beware and locate Datatypes163.zip,
	>> then unpack the archive by using the command line tool "unzip" or the
	>> Tracker add-on ExpandMe and go to BeIDE/Settings/Path and insert the
	>> correct path for the Datatype library sources.


*****************************************************************************/

#include "CFilter.h"

#pragma export on
CFilter * filterInit(uint32 index);
#pragma export reset

//--------------------------------------------------------------------

//**********************************
class CSampleFilter : public CFilter
//**********************************
{
public:

	CSampleFilter(void) : CFilter()	{ printf("constructor SampleFilter %p\n", this);}
	virtual ~CSampleFilter(void) 		{ printf("destructor SampleFilter %p\n", this);}

	virtual bool load(void);
	virtual bool prepare(void);
	virtual void processFrame8(SFrameInfo &info);
	virtual void terminate(void);
	virtual void unload(void);

private:
	// nothing yet

}; // end of class defs for CSampleFilter


//--------------------------------------------------------------------


//**********************************************
CFilter * filterInit(uint32 index)
//**********************************************
/*
	This function is called when the add-on is loaded.
	This occurs when Pulsar is starting.
	This function is called several times with index=0 then 1 etc
	until it returns NULL. This give you the opportunity to code
	several filters in one add-on.

	Here you must create a new instance of your derived CFilter class.
	You return the pointer on the instance.
	You get called several times until you return NULL.
	You must return a valid object pointer, since the caller will verify
	using ClassInfo that the class is derived from CFilter but is not a
	CFilter instance.
*/
{
	printf("filterInit -- index %d\n", index);

	// this add-on only declares ONE filter
	if (index > 0) return NULL;

	CSampleFilter *info = new CSampleFilter;
	if (!info) return NULL;		// memory error, give up

	// returns the instance -- the caller will check that this instance
	// is derived from CFilter but is _not_ a CFilter...
	printf("new info %p, class %s\n", info, class_name(info));
	return info;
} // end of filterInit


//****************************
bool CSampleFilter::load(void)
//****************************
/*
	Called just after the add-on has succesfully been loaded.
	If you return false, <the add-on will be unloaded immediatly
	and its unload() hook will be called>.
	Use this to set up the vital info about the filter, i.e. the
	strings (optional) and the supported color mode (currently fixed to 8 bits).
	This can also be done in you class constructor.
	The main difference with the constructor is that when you get here,
	the main program will have set up your main members, like the directories,
	the pointers onto buffers, etc. Also you can get back the index of the
	instance indicated by filterInit here. Check the CFilter.h for more info ;-)

	VALID STRUCTS : 'struct SLoadInfo sLoad'
	YOU MUST FIIL : 'struct SFilterInfo sFilter'
*/
{
	printf("CSampleFilter::load\n");
	sFilter.name = "Sample Code";		// <-- name that appears in the interface, keep unique and short
	sFilter.author = "R'alf";
	sFilter.info = "Sample code";
	sFilter.majorVersion = 0;				// useless for the moment
	sFilter.minorVersion = 3;
	sFilter.position = kFilterPositionAny;

	// return if you accept to be load, if you return false you will be unloaded
	// for example an addon managing some kind of hardware (camera) can check that
	// the device is present here...
	return true;
}  // end of load for CSampleFilter


//******************************
void CSampleFilter::unload(void)
//******************************
/*
	Called just before the add-on is unloaded, when the
	program quits.

	VALID STRUCTS : 'struct SLoadInfo sLoad'
								'struct SFilterInfo sFilter'
*/
{
	printf("CSampleFilter::unload\n");
}  // end of unload for CSampleFilter


//*******************************
bool CSampleFilter::prepare(void)
//*******************************
/*
	Called when the user wants to make the view pulse.
	Gives a chance to the filter to alloc memory or compute
	some tables.

	Important : in the structure "sPrepare", you will find here information
	concerning the output that will *never* change : resolution, depth, BScreen,
	BWindowScreen (if you're in full screen mode), bytes per row, etc.
	Currently, you don't know the exact address of the frame buffer since this
	can change at each frame when using double or tripple buffering.
	
	Your add-on MUST NOT assume the size is fixed (currently, it's always 640x480,
	but this WON'T be always the case), and here you know this size so HERE YOU MUST
	ALLOCATE ARRAYS USING sPrepare.sx and sPrepare.sy.
	Size is given in pixels. If the 'sx' size is 640, it really means you can access
	pixels ranging from 0 to 639.

	VALID STRUCTS : 'struct SLoadInfo sLoad'
								'struct SFilterInfo sFilter'
								'struct SPrepareInfo sPrepare'
*/
{
	printf("CSampleFilter::prepare\n");
	return true;
}  // end of prepare for CSampleFilter


//*********************************
void CSampleFilter::terminate(void)
//*********************************
/*
	Called when the user wants to stop pulse the view.
	Give a chance to the filter to free memory.

	VALID STRUCTS : 'struct SLoadInfo sLoad'
								'struct SFilterInfo sFilter'
								'struct SPrepareInfo sPrepare'
*/
{
	printf("CSampleFilter::terminate\n");
}  // end of terminate for CSampleFilter


//*************************************************
void CSampleFilter::processFrame8(SFrameInfo &frame)
//*************************************************
/*
	Real blit into the screen.
	Look at other add-ons to have an idea of what to do here, but below are the main cases.

	VALID STRUCTS : 'struct SLoadInfo sLoad'
								'struct SFilterInfo sFilter'
								'struct SPrepareInfo sPrepare'
								'struct SFrameInfo info'
*/
{
	printf("CSampleFilter::processFrame\n");

	/*
		Example 1:
		----------
		(Not tested nor compiled. Use at your own risk.)
		
		You want to fill in all the memory with a pattern.
		The full size of the buffer is available in sPrepare.sxy (sxy=bpr*sy, not sx*sy)
		and the start of the screen in frame.screen so here is the code :
		
		memset(frame.screen, 42, sPrepare.sxy);	// fill with light red
	*/

	/*
		Example 2:
		----------
		(Not tested nor compiled. Use at your own risk.)

		Same than example 1 one but using an accelerated hook if available :		

		blitRect8 (0, 0, sPrepare.sx, sPrepare.sy, 42);		
	*/

}  // end of processFrame for CSampleFilter


// eoc
