/*
__ __ _ ____ _ _________ __ ______ _ ____ __ _
| \/ || || _ \| | ( /_ _// \/_ _/| |/ \| \| |
| |\/| || || |_| | | \ \ | | | <> | | | | || <> || |\ |
|_| |_||_||____/|_| /___)|_| |_||_| |_| |_|\____/|_| \_|
////////////////////////////////////////////////////////////////////////
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (c) 2002-2003 by Carlos Jim�nez de Parga
All rights reserved.
For any suggestion or failure report, please contact me by e-mail:
cjimenez@servitel.es
///////////////////////////////////////////////////////////////////////
Module : Keyboard.cpp
Purpose: Code implementation for the CKeyboard class
Created: CJP / 4-10-2002
History: CJP / 3-24-2003
// 11-10-2002 Update
1. Solved problems with Midi port selection
2. Improved built-in keyboard
3. Supervised the multithread-safe application
4. Improved the interactive interface
5. Application restructured to the new CDirectMidi wrapper
6. Added the Microsoft Software Synthesizer
7. Added keyboard support
8. Fixed bugs in classes design
9. Improved playback thread using Events
10. Guide line on the list control
// 6 - 10 - 2003 Update
11. Added exception handling
12. Included the piano keyboard control
13. Enhanced implicit multitask synchronization system
14. Simplified the class hierarchy
15. Program structure grouped into new classes
16. Fixed bugs in calls to DirectMidi library
17. Program released under GNU (General Public License) terms
*/
#include "stdafx.h"
#include "Keyboard.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// Asigned array of the keys
const char KeyboardNotes[]={'Z','S','X','D','C','V','G','B','H','N','J','M'};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// Constructor
CKeyboard::CKeyboard()
{
for (int nKey = 0;nKey < MAX_KEYS;nKey++) // Sets the keys state
KeyPressed[nKey] = UNPRESSED; // to unpressed
m_nOctaveShift = 0; // left align selector
}
// Initilize controls
void CKeyboard::Initialize()
{
m_BlackKeyboard.GetWindowRect(&m_KeyRectBlack);
pMSDlg->ScreenToClient(&m_KeyRectBlack);
m_WhiteKeyboard.GetWindowRect(&m_KeyRectWhite);
pMSDlg->ScreenToClient(&m_KeyRectWhite);
}
// Move the label controls
void CKeyboard::MoveSelectors(int nShift)
{
m_BlackKeyboard.SetWindowPos(NULL,m_KeyRectBlack.left + nShift*126,m_KeyRectBlack.top,0,0,SWP_NOSIZE);
m_WhiteKeyboard.SetWindowPos(NULL,m_KeyRectWhite.left + nShift*127,m_KeyRectWhite.top,0,0,SWP_NOSIZE);
}
// Change the position of the octave selector
void CKeyboard::ChangeOctaves(char KeyCode)
{
if (KeyCode == VK_RIGHT)
{
m_nOctaveShift = (m_nOctaveShift + 1) %5; // Increases a position
MoveSelectors(m_nOctaveShift);
}
else
{
m_nOctaveShift = (m_nOctaveShift + 4) %5; // Decreases a position
MoveSelectors(m_nOctaveShift);
}
}
// Moves left the octaves selector
void CKeyboard::MoveLeft()
{
ChangeOctaves(VK_LEFT);
}
// Moves right the octaves selector
void CKeyboard::MoveRight()
{
ChangeOctaves(VK_RIGHT);
}
// Processes the specified key
void CKeyboard::KeyMessage(int nPosKey,BOOL bNoteType)
{
unsigned char Note;
switch(bNoteType)
{
case KEYBOARD_NOTE_ON: // A key was pressed
if (KeyPressed[nPosKey] == UNPRESSED) { // It was unpressed
// Calculates the note value;
Note = pMSDlg->m_Piano.m_nLoNote + m_nOctaveShift*MAX_KEYS + nPosKey;
pMSDlg->m_Piano.DrawPianoKeyFromNote(Note);
pMSDlg->PerformMidiMsgOut(Note,bNoteType); //Plays the note
pMSDlg->m_MessageList.AddItemListCtrl(Note,0x7f,LIST_ITEM_ORANGE); // Adds the note to the list
KeyPressed[nPosKey] = Note; // The key ramains pressed
}
break;
case KEYBOARD_NOTE_OFF: // A key was released
if ((Note = KeyPressed[nPosKey]) != UNPRESSED) {
pMSDlg->m_Piano.ReleasePianoKeyFromNote(Note);
pMSDlg->PerformMidiMsgOut(Note,bNoteType);
KeyPressed[nPosKey] = UNPRESSED; // The key is not pressed
}
break;
}
}
// Member function to extract the key index in the array
void CKeyboard::ProcessKey(char KeyCode,BOOL bState)
{
int nPosKey = strchr(KeyboardNotes,KeyCode)-KeyboardNotes;
if (nPosKey >= 0)
KeyMessage(nPosKey,bState);
pMSDlg->SetFocus();
}
// Destructor (nothing to destroy-release)
CKeyboard::~CKeyboard()
{
}