NiCMidi 1.1.0
A MIDI library derived from J.D.Koftinoff jdksmidi
test_component.cpp

Example of a basic custom MIDITickComponent which only plays a note every second. The file shows how to redefine the base class methods and how to add the component to the MIDIManager queue, making it effective.

/*
* Example file for NiCMidi - A C++ Class Library for MIDI
*
* Copyright (C) 2021, 2022 Nicola Cassetta
* https://github.com/ncassetta/NiCMidi
*
* This file is part of NiCMidi.
*
* NiCMidi 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 3 of
* the License, or (at your option) any later version.
*
* NiCMidi 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 NiCMidi. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Example of a basic custom MIDITickComponent which only plays a note
every second. The file shows how to redefine the base class methods
making it effective.
*/
#include "../include/tick.h"
#include "../include/manager.h"
using namespace std;
// If you want to implement your own MIDITickComponent derived class you must at least redefine
// the Reset(), StaticTickProc() and TickProc() methods (and probably Start() and Stop() also).
// This is a very simple example which plays a fixed note every second; see the comments
// to every method for details.
//
class TestComp : public MIDITickComponent {
public:
TestComp();
virtual void Reset() {} // here Reset() does nothing
virtual void Start();
virtual void Stop();
protected:
static void StaticTickProc(tMsecs sys_time, void* pt);
virtual void TickProc(tMsecs sys_time);
static const tMsecs NOTE_INTERVAL = 1000; // the time (in msecs) between two note on
static const tMsecs NOTE_LENGTH = 400; // the time between note on and note off
tMsecs next_note_on;
tMsecs next_note_off;
};
// The constructor must call the base class constructor with the priority and the StaticTickProc
// pointer as parameters.
// In our case, as we have only this component in the MIDIManager queue, the priority is irrelevant.
//
TestComp::TestComp() : MIDITickComponent(PR_PRE_SEQ, StaticTickProc) {}
// The Start() method should initialize the class and then call the base class Start(),
// which loads the sys_time_offset variable with the start time and enables the callback.
//
void TestComp::Start() {
cout << "Starting the component ... " << endl;
// opens MIDI out 0 port before playing the notes
next_note_on = 0; // relative time of the 1st note on
next_note_off = NOTE_LENGTH; // relative time of the 1st note off
}
// The Stop() method should first call the base class Stop() which disables the callback.
//
void TestComp::Stop() {
cout << "Stopping the component ... " << endl;
}
// This is the typical implementation of the static callback.
// The MIDIManager gives it two parameters: the now absolute time (sys_time) and the object
// "this" pointer (as a void*); the callback only should cast the void pointer to a class
// pointer and then call the (virtual) derived class callback (i.e. TickProc).
//
void TestComp::StaticTickProc(tMsecs sys_time, void* pt) {
TestComp* class_pt = static_cast<TestComp*>(pt);
class_pt->TickProc(sys_time);
}
// This is finally the object callback, which does all the work. Its parameter is the absolute
// now time (remember you have the start time in the sys_time_offset variable).
//
void TestComp::TickProc(tMsecs sys_time) {
tMsecs deltat = sys_time - sys_time_offset; // the relative time (now time - start time)
if (deltat >= next_note_off) { // we must turn off the note
msg.SetNoteOff(0, 60, 0);
// sends a note off message to the MIDI 0 port
cout << "and off" << endl;
next_note_off += NOTE_INTERVAL; // updates the next note off time
}
if (deltat >= next_note_on) { // we must turn on the note
msg.SetNoteOn(0, 60, 127);
// sends a note on message to the MIDI 0 port
cout << "Note on . . . ";
next_note_on += NOTE_INTERVAL; // updates the next note on time
}
}
// The main() creates a class instance and then calls Start() and Stop() for enabling and
// disabling the callback
int main() {
TestComp comp; // creates the component
comp.Start(); // starts the callback
cout << "Waiting 10 secs ... " << endl;
MIDITimer::Wait(10000); // waits 10 secs
comp.Stop(); // stops the callback
cout << "Waiting 5 secs without playing ... " << endl;
MIDITimer::Wait(5000); // waits 5 secs
cout << "Exiting" << endl;
return EXIT_SUCCESS;
}
static MIDIOutDriver * GetOutDriver(unsigned int n)
Returns a pointer to the MIDIOutDriver with given port id.
void SetNoteOff(unsigned char chan, unsigned char note, unsigned char vel)
Makes the message a note off message with given channel, note and velocity.
void SetNoteOn(unsigned char chan, unsigned char note, unsigned char vel)
Makes the message a note on message with given channel, note and velocity.
virtual void OpenPort()
Opens the hardware out port.
virtual void OutputMessage(const MIDITimedMessage &msg)
Makes a copy of the message, processes it with the out processor and then sends it to the hardware po...
virtual void ClosePort()
Closes the hardware out port.
A pure virtual class implementing an object which has a callback procedure to be called at every tick...
Definition: tick.h:65
virtual void Reset()=0
A pure virtual method which should reinitialize the class parameters.
static void StaticTickProc(tMsecs sys_time, void *pt)
This is the static callback procedure which the MIDIManager will call at every MIDITimer tick.
Definition: tick.h:116
virtual void Start()
Sets the running status as true and starts to call the callback.
virtual void TickProc(tMsecs sys_time)=0
This is the pure virtual function you must implement in your subclass.
virtual void Stop()
Sets the running status as false and stops the callback.
The MIDITimedMessage class inherits from the MIDIMessage and represents a message associated with a s...
Definition: msg.h:382
static void Wait(unsigned int msecs)
Stops the calling thread for the given number of milliseconds.
Definition: timer.h:105
unsigned long long tMsecs
The type of a variable which can hold the elapsed time in milliseconds.
Definition: timer.h:44
@ PR_PRE_SEQ
The component is inserted before the sequencer.
Definition: tick.h:46