AeKeyFieldUI.c++ 4.29 KB
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <iostream.h>

#include "AeTypes.h"
#include "AeKeyFieldUI.h"
#include "AeAsset.h"
#include "AeAssetUI.h"
#include "AeBinView.h"


#define kKeyMin		0	// C-1
#define kKeyMax		127	// G9
#define kKeyDef		60	// C4


AeKeyFieldUI::AeKeyFieldUI (const char * name,
			    Boolean isEditable,
			    Boolean isSelectable,
			    Boolean isHierarchical,
			    TJustify justify,
			    TIntGetProc getProc,
			    TIntSetProc setProc)
    : AeIntFieldUI (name, isEditable, isSelectable, isHierarchical, justify,
		    getProc, setProc, kKeyMin, kKeyMax, kKeyDef)
{
}


AeKeyFieldUI::~AeKeyFieldUI (void)
{
}

void
AeKeyFieldUI::GetValueString (AeAsset * asset, String string)
{
    int value = fGetProc (asset);

    keynum2keystr (value, string);
}


Boolean
AeKeyFieldUI::SetValueString (AeAsset * asset, String string)
{
    assert (fSetProc);

    int value;

    keystr2keynum (string, value);

    if (value < fMin)
	value = fMin;
    else if (value > fMax)
	value = fMax;

    if (value == fGetProc(asset))
	return False;

    fSetProc (asset, value);
    return True;
}

Boolean
AeKeyFieldUI::VerifyValueString (String string)
{
   int value;
	
   // allow all key values and just clip to max and min if out of range
   // keystr2keynum (string, value);
   // if (value < fMin || value > fMax)
   //    return False;

    return True;
}

Boolean
AeKeyFieldUI::VerifyInput (XmTextVerifyCallbackStruct * verify, const char * prevStr)
{
    String	string = verify->text->ptr;

    if (string)
    {
	int pos = (int)verify->startPos;
	char ch = *string;

	if (pos > 4)
	    return False;

	// first char must be A-G
	if (pos == 0)
	{
	    if (ch >= 'a' && ch <= 'g')
		*string = toupper (ch);

	    else if (ch <'A' || ch > 'G')
		return False;
	}
	
	// second char can either be a sharp, flat, minus, or a digit
	else if (pos == 1)
	{
	    if (ch != 'b' && ch != '#' && !isdigit(ch) && ch != '-')
		return False;
	}

	// third char must be a minus if second char was sharp or flat,
	// or third char must be a digit if second char is a minus
	else if (pos == 2)
	{
	    if (ch != '-' && !isdigit(ch))
		return False;

	    if (ch == '-' && prevStr[1] != 'b' && prevStr[1] != '#')
		return False;

	    if (isdigit(ch) && prevStr[1] != '-' && prevStr[1] != 'b' && prevStr[1] != '#')
		return False;
	}

	// fourth char must be a digit only if the third char is a minus sign
	else if (pos == 3)
	{
	    if (!isdigit(ch))
		return False;

	    if (prevStr[2] != '-')
		return False;
	}
    }

    return True;
}


void
AeKeyFieldUI::keynum2keystr (int num, String str)
{
    int keyNorm = num - fMin;

    int keyOctave = keyNorm/12;

    int keyNote = keyNorm - keyOctave * 12;

    keyOctave -= 1;	// C4 = 60 = 5*12, so subtract 1 from 5 to get 4

    switch (keyNote)
    {
	case 0:
	    sprintf (str, "C%d", keyOctave);
	break;

	case 1:
	    sprintf (str, "Db%d", keyOctave);
	break;

	case 2:
	    sprintf (str, "D%d", keyOctave);
	break;

	case 3:
	    sprintf (str, "Eb%d", keyOctave);
	break;

	case 4:
	    sprintf (str, "E%d", keyOctave);
	break;

	case 5:
	    sprintf (str, "F%d", keyOctave);
	break;

	case 6:
	    sprintf (str, "Gb%d", keyOctave);
	break;

	case 7:
	    sprintf (str, "G%d", keyOctave);
	break;

	case 8:
	    sprintf (str, "Ab%d", keyOctave);
	break;

	case 9:
	    sprintf (str, "A%d", keyOctave);
	break;

	case 10:
	    sprintf (str, "Bb%d", keyOctave);
	break;

	case 11:
	    sprintf (str, "B%d", keyOctave);
	break;
    }
}


void
AeKeyFieldUI::keystr2keynum (String str, int & num)
{
    char	ch;
    int		keyNote;
    int		keyOctave;

    ch = str[0];

    switch (ch)
    {
	case 'c':
	case 'C':
	    keyNote = 0;
	break;

	case 'd':
	case 'D':
	    keyNote = 2;
	break;

	case 'e':
	case 'E':
	    keyNote = 4;
	break;

	case 'f':
	case 'F':
	    keyNote = 5;
	break;

	case 'g':
	case 'G':
	    keyNote = 7;
	break;

	case 'a':
	case 'A':
	    keyNote = 9;
	break;

	case 'b':
	case 'B':
	    keyNote = 11;
	break;
     }

    ch = str[1];

    if (ch == 'b')
    {
	keyNote--;
	ch = str[2];
    }
    else if (ch == '#')
    {
	keyNote++;
	ch = str[2];
    }

    // hack since atoi isn't working with -1
    if (ch == '-')
	keyOctave = 0;
    else
	keyOctave = atoi (&ch) + 1;    	// add 1 since C4 = 60 = 5*12

    num = keyOctave*12 + keyNote;
}