/*	Chromatic Transpose Tool

	© 1997, Ian Stirling 

	This is a modified version of transpose.c supplied
	with Rules For Tools. To compile this file see the
	file "Rules.doc" supplied with RFT. This file must
	not be altered and subsequently redistributed.

	Litigation culture disclaimer ...
	This programme is supplied WITHOUT ANY WARRANTY and
	with no implied FITNESS FOR A PARTICULAR PURPOSE.
	The user uses it ENTIRELY AT HIS OR HER OWN RISK.

	mailto:ian@opus131.demon.co.uk
	16th December 1997
*/

#include "bars.h"
#include <libraries/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <exec/memory.h>
#include <intuition/intuition.h>

#define ID_TRAN	0x4352414E      /* CRAN */


static UWORD chip chromtranicon[]=
{
/*-------- plane # 0 --------*/

  0x0000,  0x0000,
  0x3fff,  0xfc00,
  0x3000,  0x0c00,
  0x3000,  0x0c00,
  0x3000,  0x0c00,
  0x3000,  0x0c00,
  0x3000,  0x0c00,
  0x3000,  0x0c00,
  0x3000,  0x0c00,
  0x3000,  0x0c00,
  0x3fff,  0xfc00,
  0x0000,  0x0000,

/*-------- plane # 1 --------*/

  0x0000,  0x0000,
  0x0000,  0x0400,
  0x0f7f,  0xfc00,
  0x0f3f,  0xfc00,
  0xcf1f,  0xff00,
  0xcf4f,  0xff00,
  0xce67,  0xff00,
  0xc87f,  0xff00,
  0x087f,  0xfc00,
  0x0fff,  0xfc00,
  0x1fff,  0xfc00,
  0x00ff,  0x0000,

/*-------- plane # 2 --------*/

  0x0000,  0x0000,
  0x0000,  0x0000,
  0x0001,  0x8000,
  0x0003,  0xc000,
  0x0007,  0xe000,
  0x000d,  0xb000,
  0x0001,  0x8000,
  0x0001,  0x8000,
  0x0001,  0x8000,
  0x0000,  0x0000,
  0x0000,  0x0000,
  0x0000,  0x0000
};

static struct Image transposeupimage=
{
  0,0,24,12,3,
  chromtranicon,
  0x7,0x0,NULL
};

static struct Image transposedownimage=
{
  0,0,24,12,3,
  chromtranicon,
  0x7,0x0,NULL
};



struct TransposeTool {
    struct Tool tool;
    short transpose;
    char octave;
    char interval;
};

static struct PropInfo transposetransposeGadget2SInfo = {
	AUTOKNOB+FREEHORIZ,
	23305,-1,
	10922,-1,
};

static struct Image transposeImage1 = {
	41,0,
	24,5,
	0,
	NULL,
	0x0000,0x0000,
	NULL
};

static struct IntuiText transposeIText1 = {
	2,0,JAM1,
	-106,1,
	NULL,
	"    Interval:",
	NULL
};

static struct Gadget transposeGadget2 = {
	NULL,
	115,16,
	148,9,
	GADGHBOX+GADGHIMAGE,
	RELVERIFY+GADGIMMEDIATE,
	PROPGADGET,
	(APTR)&transposeImage1,
	NULL,
	&transposeIText1,
	NULL,
	(APTR)&transposetransposeGadget2SInfo,
	2,
	NULL
};

static struct PropInfo transposetransposeGadget1SInfo = {
	AUTOKNOB+FREEHORIZ,
	21323,-1,
	10922,-1,
};

static struct Image transposeImage2 = {
	37,0,
	24,5,
	0,
	NULL,
	0x0000,0x0000,
	NULL
};

static struct IntuiText transposeIText2 = {
	2,0,JAM1,
	-74,1,
	NULL,
	"  Octave:",
	NULL
};

static struct Gadget transposeGadget1 = {
	&transposeGadget2,
	115,31,
	148,9,
	GADGHBOX+GADGHIMAGE,
	RELVERIFY+GADGIMMEDIATE,
	PROPGADGET,
	(APTR)&transposeImage2,
	NULL,
	&transposeIText2,
	NULL,
	(APTR)&transposetransposeGadget1SInfo,
	1,
	NULL
};

#define transposeGadgetList1 transposeGadget1

static struct NewWindow transposeNewWindowStructure1 = {
	156,46,
	310,46,
	6,1,
	GADGETDOWN+GADGETUP,
	WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+REPORTMOUSE+ACTIVATE+NOCAREREFRESH,
	&transposeGadget1,
	NULL,
	"Chromatic Transpose",
	NULL,
	NULL,
	5,5,
	-1,-1,
	CUSTOMSCREEN
};

extern struct Functions *functions;

extern printf();

static struct Event *processeventcode(event)

struct NoteEvent *event;

{
    struct TransposeTool *tool = (struct TransposeTool *) event->tool;
    short value;
    struct NoteEvent *copy;
    event->tool = event->tool->next;
    if (!(event->type & EVENT_VOICE)) return((struct Event *)event);
    if ((event->status == MIDI_NOTEON) || (event->status == MIDI_NOTEOFF) ||
	(event->status == MIDI_PTOUCH)) {
	value = event->value;
	value += tool->transpose;
	while (value < 0) value += 12;
	while (value > 127) value -= 12;
	if (tool->tool.branch) {
	    copy = (struct NoteEvent *) (*functions->allocevent)();
	    if (copy) {
		copy->value = value;
		copy->velocity = event->velocity;
		copy->duration = event->duration;
		copy->type = event->type;
		copy->status = event->status;
		event->next = copy;
		copy->time = event->time;
		copy->tool = tool->tool.branch;
		copy->type |= EVENT_BRANCH;
	    }
	}
	else event->value = value;
    }
    return((struct Event *)event);
}

static transposeroutine(window,gadget,x)

struct Window *window;
struct Gadget *gadget;
long x;

{
    char text[20];
    struct RastPort *rp = window->RPort;
    Move(rp,270,38);
    SetAPen(rp,1);
    SetBPen(rp,0);
    SetDrMd(rp,JAM2);
    x -= 10;
    if (x <= 0) sprintf(text,"%ld  ",x);
    else sprintf(text,"+%ld  ",x);
    Text(rp,text,3);
    return((long)x);
}

static intervalroutine(window,gadget,x)

struct Window *window;
struct Gadget *gadget;
long x;

{
    char text[20];
    struct RastPort *rp = window->RPort;
    Move(rp,270,23);
    SetAPen(rp,1);
    SetBPen(rp,0);
    SetDrMd(rp,JAM2);
    x -= 11;
    if (x <= 0) sprintf(text,"%ld  ",x);
    else sprintf(text,"+%ld  ",x);
    Text(rp,text,3);
    return((long)x);
}

void edittoolcode(tool)

struct TransposeTool *tool;

{
    struct IntuiMessage *message;
    struct Window *window;
    long class,code;
    char refresh = 1;
    struct Gadget *gadget;
    struct NewWindow *newwindow;
    static struct Menu TitleMenu = {	
	NULL,0,0,0,0,MENUENABLED,
	"Chromatic Transpose  v1.0 © 1997 Ian Stirling <ian@opus131.demon.co.uk>",0
    };
    transposeNewWindowStructure1.Screen = functions->screen;
    if (tool->tool.touched & TOUCH_EDIT) {
	transposeNewWindowStructure1.LeftEdge = tool->tool.left;
	transposeNewWindowStructure1.TopEdge = tool->tool.top;
    }
    newwindow = (struct NewWindow *) 
	(*functions->DupeNewWindow)(&transposeNewWindowStructure1);
    if (!newwindow) return;
    newwindow->Title = 0;
    newwindow->Flags |= BORDERLESS;
    newwindow->Flags &= ~0xF;
    newwindow->DetailPen = 0;
    newwindow->BlockPen = 0;
    window = (struct Window *) (*functions->FlashyOpenWindow)(newwindow);
    if (!window) return;
    SetMenuStrip(window,&TitleMenu);
    tool->tool.window = window;
    (*functions->EmbossWindowOn)(window,WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,
	"Chromatic Transpose",(short)-1,(short)-1,0,0);
    (*functions->FatEmbossedPropOn)(window,1,3,4,transposeroutine,21,1);
    (*functions->FatEmbossedPropOn)(window,2,5,6,intervalroutine,23,1);
    for (;;) {
	if (refresh) {
	    tool->transpose = (tool->octave * 12) + tool->interval;
	    (*functions->ModifyEmbossedProp)(window,1,tool->octave+10,0,0,0,0,0);
	    (*functions->DrawEmbossedProp)(window,1);
	    (*functions->ModifyEmbossedProp)(window,2,tool->interval+11,0,0,0,0,0);
	    (*functions->DrawEmbossedProp)(window,2);
	}
	refresh = 0;
	message = (struct IntuiMessage *) (*functions->GetIntuiMessage)(window);
	code = message->Code;
	class = message->Class;
	gadget = (struct Gadget *) message->IAddress;
	class = (*functions->SystemGadgets)(window,class,gadget,code);
	ReplyMsg((struct Message *)message);
	if (class == CLOSEWINDOW) break;
	else if (class == GADGETDOWN) {
	    refresh = 1;
	    switch (gadget->GadgetID) {
		case 1 :
		    tool->octave = (*functions->DragEmbossedProp)(window,1);
		    break;
		case 2 :
		    tool->interval = (*functions->DragEmbossedProp)(window,2);
		    break;
		case 3 :
		    tool->octave = (*functions->ShiftEmbossedProp)(window,1,-1,0);
		    break;
		case 4 :
		    tool->octave = (*functions->ShiftEmbossedProp)(window,1,1,0);
		    break;
		case 5 :
		    tool->interval = (*functions->ShiftEmbossedProp)(window,2,-1,0);
		    break;
		case 6 :
		    tool->interval = (*functions->ShiftEmbossedProp)(window,2,1,0);
		    break;
	    }
	}
    }
    (*functions->FatEmbossedPropOff)(window,1,3,4);
    (*functions->FatEmbossedPropOff)(window,2,5,6);
    tool->tool.window = 0;
    tool->tool.left = window->LeftEdge;
    tool->tool.top = window->TopEdge;
    tool->tool.touched = TOUCH_EDIT | TOUCH_INIT;
    ClearMenuStrip(window);
    (*functions->FlashyCloseWindow)(window);
    (*functions->DeleteNewWindow)(newwindow);
}

static struct ToolMaster master;

extern long stdout;

struct ToolMaster *inittoolmaster()

{
    memset((char *)&master,0,sizeof(struct ToolMaster));
    master.toolid = ID_TRAN;
    master.image = &transposedownimage;
    master.upimage = &transposeupimage;
    master.toolsize = sizeof(struct TransposeTool);
    strcpy(master.name,"Chromatic Transpose");
    master.edittool = edittoolcode;
    master.processevent = processeventcode;
    master.tooltype = TOOL_NORMAL | TOOL_BRANCHOUT;
    return(&master);
}

