/* TieTracking.c */
/*****************************************************************************/
/*                                                                           */
/*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
/*    Copyright (C) 1994  Thomas R. Lawrence                                 */
/*                                                                           */
/*    This program is free software; you can redistribute it and/or modify   */
/*    it under the terms of the GNU General Public License as published by   */
/*    the Free Software Foundation; either version 2 of the License, or      */
/*    (at your option) any later version.                                    */
/*                                                                           */
/*    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 the GNU General Public License      */
/*    along with this program; if not, write to the Free Software            */
/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"

#include "TieTracking.h"
#include "NoteObject.h"
#include "Array.h"
#include "Memory.h"


typedef struct
	{
		long							SourcePixelIndexX;
		long							SourcePixelIndexY;
		NoteObjectRec*		SourceNote;
		NoteObjectRec*		DestinationNote;
	} TiePairRec;


struct TieTrackRec
	{
		ArrayRec*					ListOfRecords; /* TiePairRec's */
	};


/* create a new tie tracking record */
TieTrackRec*			NewTieTracker(void)
	{
		TieTrackRec*		TieTracker;

		TieTracker = (TieTrackRec*)AllocPtrCanFail(sizeof(TieTrackRec),"TieTrackRec");
		if (TieTracker == NIL)
			{
			 FailurePoint1:
				return NIL;
			}
		TieTracker->ListOfRecords = NewArray();
		if (TieTracker->ListOfRecords == NIL)
			{
			 FailurePoint2:
				ReleasePtr((char*)TieTracker);
				goto FailurePoint1;
			}
		return TieTracker;
	}


/* dump the tie tracker thing */
void							DisposeTieTracker(TieTrackRec* TieTracker)
	{
		long						Limit;
		long						Scan;

		CheckPtrExistence(TieTracker);
		Limit = ArrayGetLength(TieTracker->ListOfRecords);
		for (Scan = 0; Scan < Limit; Scan += 1)
			{
				TiePairRec*			TiePair;

				TiePair = (TiePairRec*)ArrayGetElement(TieTracker->ListOfRecords,Scan);
				ReleasePtr((char*)TiePair);
			}
		DisposeArray(TieTracker->ListOfRecords);
		ReleasePtr((char*)TieTracker);
	}


/* find out if there is a tie source in the object for the destination. */
/* the pair is removed from the list */
MyBoolean					GetTieSourceFromDestination(TieTrackRec* TieTracker,
										long* SourcePixelX, long* SourcePixelY,
										struct NoteObjectRec** SourceNote,
										struct NoteObjectRec* CurrentNote)
	{
		long						Limit;
		long						Scan;

		CheckPtrExistence(TieTracker);
		Limit = ArrayGetLength(TieTracker->ListOfRecords);
		for (Scan = 0; Scan < Limit; Scan += 1)
			{
				TiePairRec*			TiePair;

				TiePair = (TiePairRec*)ArrayGetElement(TieTracker->ListOfRecords,Scan);
				CheckPtrExistence(TiePair);
				if (TiePair->DestinationNote == CurrentNote)
					{
						*SourcePixelX = TiePair->SourcePixelIndexX;
						*SourcePixelY = TiePair->SourcePixelIndexY;
						*SourceNote = TiePair->SourceNote;
						ArrayDeleteElement(TieTracker->ListOfRecords,Scan);
						ReleasePtr((char*)TiePair);
						return True;
					}
			}
		return False;
	}


/* add a new tie pair to the list of tie pairs */
MyBoolean					AddTiePairToTieTracker(TieTrackRec* TieTracker,
										struct NoteObjectRec* SourceNote, long SourcePixelX,
										long SourcePixelY, struct NoteObjectRec* DestinationNote)
	{
		TiePairRec*			TiePair;

		CheckPtrExistence(TieTracker);
		TiePair = (TiePairRec*)AllocPtrCanFail(sizeof(TiePairRec),"TiePairRec");
		if (TiePair == NIL)
			{
			 FailurePoint1:
				return False;
			}
		TiePair->SourcePixelIndexX = SourcePixelX;
		TiePair->SourcePixelIndexY = SourcePixelY;
		TiePair->SourceNote = SourceNote;
		TiePair->DestinationNote = DestinationNote;
		if (!ArrayAppendElement(TieTracker->ListOfRecords,TiePair))
			{
			 FailurePoint2:
				ReleasePtr((char*)TiePair);
				goto FailurePoint1;
			}
		return True;
	}
