#include <windows.h>
#include <cwchar>
#include "../../include/advancedsequencer.h"
#include "../../include/smpte.h"
#include "../../include/midi.h"
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
VOID LoadFile();
VOID SetControls();
const char* GetSmpteString();
VOID SetMIDIActivity();
VOID ResetDelays();
HWND hMainWin;
HWND hFileName;
HWND hTime;
HWND hKey;
HWND hTempo;
HWND hMeas;
HWND hSmpte;
HWND hMarker;
HWND hTrackNames[16];
HWND hTrackChans[16];
HWND hTrackPrgrs[16];
HWND hTrackVols[16];
HWND hTrackActs[16];
UINT NotifierMessage = 0;
int MIDIActDelays[16];
const int ACT_DELAY = 4;
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
MSG messages;
WNDCLASSEX wincl;
char szClassName[ ] = "Test AdvancedSequencer in WIN32";
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return 0;
hMainWin = CreateWindowEx (
0,
szClassName,
"test WIN32 (C) by N. Cassetta",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
HWND_DESKTOP,
NULL,
hThisInstance,
NULL
);
hMainWin
);
NotifierMessage = notifier.GetMsgId();
ShowWindow (hMainWin, nCmdShow);
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == NotifierMessage)
{
return 0;
}
switch (message) {
case WM_CREATE:
CreateWindowW(L"button",
L"Load",
WS_VISIBLE | WS_CHILD ,
10, 10, 50, 25,
hwnd,
(HMENU) 1,
NULL, NULL);
CreateWindowW(L"button", L"Rew",
WS_VISIBLE | WS_CHILD ,
100, 10, 50, 25,
hwnd, (HMENU) 2, NULL, NULL);
CreateWindowW(L"button", L"Play",
WS_VISIBLE | WS_CHILD ,
155, 10, 50, 25,
hwnd, (HMENU) 3, NULL, NULL);
CreateWindowW(L"button", L"Stop",
WS_VISIBLE | WS_CHILD ,
210, 10, 50, 25,
hwnd, (HMENU) 4, NULL, NULL);
CreateWindowW(L"button", L"<<",
WS_VISIBLE | WS_CHILD ,
265, 10, 50, 25,
hwnd, (HMENU) 5, NULL, NULL);
CreateWindowW(L"button", L">>",
WS_VISIBLE | WS_CHILD ,
320, 10, 50, 25,
hwnd, (HMENU) 6, NULL, NULL);
hFileName = CreateWindowW(L"static", L"UNLOADED",
WS_VISIBLE | WS_CHILD | SS_LEFTNOWORDWRAP,
400, 10, 375, 25,
hwnd, (HMENU) 7, NULL, NULL);
hTime = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_CENTER,
100, 45, 50, 25,
hwnd, (HMENU) 8, NULL, NULL);
hKey = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_CENTER,
155, 45, 50, 25,
hwnd, (HMENU) 7, NULL, NULL);
hTempo = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_CENTER,
210, 45, 50, 25,
hwnd, (HMENU) 8, NULL, NULL);
hMeas = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_CENTER,
265, 45, 50, 25,
hwnd, (HMENU) 7, NULL, NULL);
hSmpte = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_CENTER,
400, 45, 105, 25,
hwnd, (HMENU) 7, NULL, NULL);
hMarker = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_LEFT,
510, 45, 265, 25,
hwnd, (HMENU) 7, NULL, NULL);
for (int i = 0; i < 16; i++) {
wchar_t s[5];
_snwprintf(s, 5, L"%d", i+1);
CreateWindowW(L"static", s,
WS_VISIBLE | WS_CHILD | SS_LEFT,
10, 80+30*i, 30, 25,
hwnd, NULL, NULL, NULL);
hTrackNames[i] = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_LEFT,
45, 80+30*i, 180, 25,
hwnd, NULL, NULL, NULL);
hTrackChans[i] = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_LEFT,
230, 80+30*i, 70, 25,
hwnd, NULL, NULL, NULL);
hTrackPrgrs[i] = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_LEFT,
305, 80+30*i, 180, 25,
hwnd, NULL, NULL, NULL);
hTrackVols[i] = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_LEFT,
490, 80+30*i, 70, 25,
hwnd, NULL, NULL, NULL);
hTrackActs[i] = CreateWindowW(L"static", NULL,
WS_VISIBLE | WS_CHILD | SS_LEFT,
565, 83+30*i, 19, 19,
hwnd, NULL, NULL, NULL);
}
break;
case WM_COMMAND:
if (LOWORD(wParam) == 1) {
LoadFile();
}
if (LOWORD(wParam) == 2) {
ResetDelays();
}
if (LOWORD(wParam) == 3) {
ResetDelays();
SetTimer(hwnd,
1,
50,
NULL);
}
if (LOWORD(wParam) == 4) {
KillTimer(hMainWin, 1);
ResetDelays();
SetMIDIActivity();
}
if (LOWORD(wParam) == 5) {
ResetDelays();
}
if (LOWORD(wParam) == 6) {
ResetDelays();
}
break;
case WM_TIMER:
if (LOWORD(wParam) == 1) {
SetWindowText( hSmpte, GetSmpteString());
SetMIDIActivity();
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
VOID LoadFile() {
OPENFILENAME ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = "Midi Files (*.mid)\0*.mid\0\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "mid";
if(GetOpenFileName(&ofn)) {
if (!sequencer->
Load(szFileName)) {
MessageBox(
NULL,
(LPCSTR)"File loading failed!",
NULL,
MB_ICONEXCLAMATION
);
}
else {
MessageBox(
NULL,
(LPCSTR)"This file has more than 17 tracks!\nSome tracks won't be displayed",
(LPCSTR)"Warning!",
MB_ICONWARNING
);
}
SetWindowText( hFileName, szFileName );
SetControls();
}
}
}
VOID SetControls() {
char s[300];
SetWindowText(hTime, s);
SetWindowText (hTempo, s);
SetWindowText (hMeas, s);
SetWindowText (hSmpte, GetSmpteString());
SetWindowText (hMarker, "---");
else
unsigned int i = 1;
for (; i < std::min (sequencer->
GetNumTracks(), 17u); i++) {
SetWindowText (hTrackNames[i - 1], sequencer->
GetTrackName (i).c_str());
else {
sprintf(s, "(track %d)", i);
SetWindowText (hTrackNames[i - 1], s);
}
SetWindowText (hTrackChans[i - 1], "---" );
else {
SetWindowText(hTrackChans[i - 1], s);
}
SetWindowText(hTrackPrgrs[i - 1], "---");
else {
else
}
SetWindowText(hTrackVols[i - 1], "vol: ---");
else {
SetWindowText(hTrackVols[i -1], s);
}
}
for ( ; i < 17; i++) {
SetWindowText (hTrackNames[i - 1], "");
SetWindowText (hTrackChans[i - 1], "");
SetWindowText (hTrackPrgrs[i - 1], "");
SetWindowText (hTrackVols[i - 1], "");
}
}
const char* GetSmpteString() {
static char s[100];
return s;
}
char s[300];
SetControls();
break;
SetWindowText ( hTempo, s );
break;
SetWindowText( hTime, s );
break;
break;
break;
}
break;
SetWindowText ( hMeas, s );
}
break;
if (track == 0 || track >= 17)
break;
else
}
SetWindowText (hTrackVols[track - 1], s);
MIDIActDelays[track - 1] = ACT_DELAY;
break;
}
}
}
}
VOID SetMIDIActivity() {
char s[10];
for (int i = 1; i < active_tracks; i++) {
MIDIActDelays[i - 1] = ACT_DELAY;
else if (MIDIActDelays[i - 1] > 0)
MIDIActDelays[i - 1]--;
if (MIDIActDelays[i - 1] > 0)
sprintf (s, "X");
else
sprintf (s, " ");
SetWindowText ( hTrackActs[i - 1], s );
}
}
VOID ResetDelays() {
for (int i = 0; i < 17; i++)
MIDIActDelays[i] = 0;
}
An enhanced MIDISequencer, able to directly load and play MIDI files and many more.
Definition: advancedsequencer.h:93
std::string GetTrackName(unsigned int trk_num) const
Returns the name of the given track.
virtual void Stop()
Stops the sequencer playing.
virtual void GoToZero()
Sets the current time to the beginning of the song.
Definition: advancedsequencer.h:255
int GetKeySigSharpsFlats() const
Return the number of sharps or flats of the current key signature.
virtual bool Load(const char *fname)
Loads a MIDIFile into the internal MIDIMultiTrack.
unsigned int GetCurrentBeat() const
Returns the number of current beat (first is 0). See Numbering conventions.
int GetTrackProgram(unsigned int trk_num) const
Returns the current MIDI program (patch) for the given track (-1 if the program wasn't set at time 0)...
virtual bool GoToMeasure(int measure, int beat=0)
Sets the current time to the given measure and beat.
std::string GetCurrentMarker() const
Returns the current marker text.
int GetTimeSigDenominator() const
Returns the denominator of current time signature.
int GetTimeSigNumerator() const
Returns the numerator of current time signature.
unsigned int GetCurrentMeasure() const
Returns the current measure number (first is 0). See Numbering conventions.
int GetKeySigMode() const
Returns the mode (major/minor) of the he current key signature.
int GetTrackVolume(unsigned int trk_num) const
Returns the current MIDI volume for the given track (-1 if volume wasn't set at time 0).
int GetTrackNoteCount(unsigned int trk_num) const
Returns the number of notes currently sounding on the given track (0 if the sequencer is not playing)...
int GetTrackChannel(unsigned int trk_num)
If the track has channel messages all with same channel returns the channel, otherwise -1.
bool SetSMPTE(SMPTE *s)
Sets the parameters of the given SMPTE according to the loaded content.
Holds data for a message that the sequencer can send to the GUI to warn it when something happens.
Definition: notifier.h:53
@ GROUP_TRACK_VOLUME
Volume change.
Definition: notifier.h:112
@ GROUP_TRACK_PROGRAM
Program change.
Definition: notifier.h:110
int GetGroup() const
Returns the event group.
Definition: notifier.h:68
int GetItem() const
Returns the event item (i.e. the kind of the event).
Definition: notifier.h:73
@ GROUP_TRANSPORT_BEAT
Beat marker.
Definition: notifier.h:102
int GetSubGroup() const
Returns the event subgroup (only effective for GROUP_TRACK events, where it is the track of the event...
Definition: notifier.h:71
@ GROUP_CONDUCTOR_TEMPO
Tempo change.
Definition: notifier.h:90
@ GROUP_CONDUCTOR_KEYSIG
Keysig change.
Definition: notifier.h:92
@ GROUP_CONDUCTOR_TIMESIG
Timesig change.
Definition: notifier.h:91
@ GROUP_CONDUCTOR_MARKER
Marker.
Definition: notifier.h:93
@ GROUP_TRANSPORT
Transport events (start, stop, etc)
Definition: notifier.h:82
@ GROUP_ALL
Generic group: used by the MIDISequencer to request a full GUI reset.
Definition: notifier.h:80
@ GROUP_TRACK
Track events (the subgroup is the track of the event)
Definition: notifier.h:83
@ GROUP_CONDUCTOR
Conductor events (time, tempo, etc)
Definition: notifier.h:81
A MIDISequencerGUINotifier which sends messages to a Win32 window using the Windows PostMessage() fun...
Definition: notifier.h:226
virtual void Play()
This is an alias of Start().
Definition: sequencer.h:455
float GetCurrentTimeMs() const
Returns current time in milliseconds; it is effective even during playback.
MIDISequencerState * GetState()
Returns a pointer to the current MIDISequencerState (i.e.
Definition: sequencer.h:268
unsigned int GetNumTracks() const
Returns the number of tracks of the multitrack.
Definition: sequencer.h:240
float GetTempoWithoutScale() const
Returns current tempo (BPM) without scaling.
Definition: sequencer.h:244
signed char keysig_sharpflat
The current key signature accidents (.
Definition: sequencer.h:153
unsigned char keysig_mode
Major mode (0) or minor (1)
Definition: sequencer.h:154
Performs conversions between number of samples, milliseconds and smpte format (hours::minutes::second...
Definition: smpte.h:69
unsigned char GetMinutes()
Returns the smpte minutes.
unsigned char GetSeconds()
Returns the smpte seconds.
unsigned char GetHours()
Returns the smpte hours.
unsigned char GetFrames()
Returns the smpte frames.
void SetMilliSeconds(unsigned long msecs)
Loads the SMPTE with the given time in milliseconds.
const char * GetGMDrumkitName(unsigned char number, int format=0)
Returns a readable name for a GM program number on channel 10 (drumkit).
const char * KeyName(signed char sharp_flats, unsigned char major_minor, bool uppercase=true, bool space=false, bool use_Mm=true)
Converts a MIDI key signature into a readable form.
const char * GetGMProgramName(unsigned char number, int format=0)
Returns a readable name for a GM program number.