#include "Glue.h"
#include "Gain.h"
#include "ModGetSetSamples.h"


pascal OSErr effect(ModParamsPtr modInfo, GluePtr glue, ModSettingsHandle *prefs)
{
	Handle			channelHand;
	StringHandle	progressString;
	Ptr				loopPtr, startPtr, endPtr;
	signed long		mySample, min, max;
	unsigned long	start, end;
	unsigned long	channelSize, processedSamples, samplesToProcess;
	short			myGain;
	short			frameSize, timeToCallProgress;
	short			channel;
	OSErr			progressResult = kModNoError;
	OSErr			result = kModCancel;
	
	// effect can receive in prefs either nil or a valid handle. If the effect does
	// not have any settings, prefs will be nil and we wont do anything with it.
	
	UseResFile(modInfo->refNum);
	
	
	// read the settings.
	
	myGain = (**prefs)->gain;
	DisposHandle((Handle)*prefs);
	*prefs = 0L;
	
	
	// lets load the string well show in the progress window.
	
	progressString = (StringHandle)Get1Resource('STR ', 128);
	if (progressString == 0L)
		return kModCouldntLoadMyRes;
	
	
	// set up the progress window.
	
	(*glue->ModSetupProgress)(modInfo, &timeToCallProgress, progressString);
	ReleaseResource((Handle)progressString);
	
	
	// if the selection is empty, select the whole channels.
	
	if (modInfo->selSt == modInfo->selEnd)
	{
		modInfo->selSt = 0L;
		(*glue->ModMaxRelChSize)(&modInfo, &modInfo->selEnd);
	}
	
	
	(*glue->ModGetSampleValueLimits)(modInfo->bps, &min, &max);
	frameSize = modInfo->bps/8 + (modInfo->bps%8 != 0);
	samplesToProcess = (*glue->GetBytesToProcess)(modInfo) / frameSize;
	processedSamples = 0L;
	
	
	for (channel = modInfo->firstSelCh-1; channel < modInfo->lastSelCh; channel++)
	{
		start = modInfo->selSt;
		end = modInfo->selEnd;
		
		channelSize = (*modInfo->hands)[channel].size;
		if ( start > channelSize )
			start = channelSize;
		if ( end > channelSize )
			end = channelSize;
		
		start -= start%frameSize;
		end -= end%frameSize;
		
		if (start != end)
		{
			channelHand = (*modInfo->hands)[channel].chan;
			HLock(channelHand);
			
			startPtr = *channelHand + start;
			endPtr = *channelHand + end;
			
			if (frameSize == 1)
			{
				for (loopPtr = startPtr; loopPtr < endPtr; loopPtr++, processedSamples++)
				{
					mySample = GetSample8(loopPtr);
					
					mySample = mySample*myGain/100;
					
					if (mySample & 0x80000000)	// Equivalent to if mySample < 0L
					{
						if (mySample < min)
							mySample = min;
					}
					else if (mySample > max)
						mySample = max;
					
					SetSample8(loopPtr, mySample);
					
					if (timeToCallProgress)
						if (progressResult = (*glue->ModShowProgress)(processedSamples, samplesToProcess, &timeToCallProgress, false))
							break;
				}
			}
			else
			{
				for (loopPtr = startPtr; loopPtr < endPtr; loopPtr += frameSize, processedSamples++)
				{
					mySample = GetSample16(loopPtr, modInfo->bps);
					
					mySample = mySample*myGain/100;
					
					if (mySample & 0x80000000)	// Equivalent to if mySample < 0L
					{
						if (mySample < min)
							mySample = min;
					}
					else if (mySample > max)
						mySample = max;
					
					SetSample16(loopPtr, mySample, modInfo->bps);
					
					if (timeToCallProgress)
						if (progressResult = (*glue->ModShowProgress)(processedSamples, samplesToProcess, &timeToCallProgress, false))
							break;
				}
			}
			
			HUnlock(channelHand);
			result = kModNoError;
		}
		
		if (progressResult)
			break;
	}
	
	(*glue->ModCloseProgress)();
	
	return result;
}