Copyright © 2013-2014 MultiMedia Soft

How to synchronize the container application with the control

Previous pageReturn to chapter overviewNext page

By default, Active MIDI DJ Console keeps the container application informed about events occurring on the MIDI system through a number of events; the list of supported events is available on the table below:

 

Situations

Corresponding event

 

 

The configuration of MIDI devices is changed

MidiDevicesConfigChanged

A MIDI device, previously opened through the MidiDevices.Open method, is disconnected from the system after a manual removal

MidiDevicesOpenRemoved

A MIDI event is received from a MIDI input device

MidiDevicesEventReceived

A physical button mapped into the DJ Console profile has been pressed

MidiDjConsoleEventButtonPressed

A physical button mapped into the DJ Console profile has been released.

MidiDjConsoleEventButtonReleased

A physical range control (sliders, jog wheels, rotary knobs, etc.) mapped into the DJ Console profile has been moved

MidiDjConsoleEventRangeMoved

A manual action (for example the pressing of a button, the movement of a slider or of a jog wheel) is performed on a console's physical control which has not been mapped into the DJ Console profile loaded inside the instance of the component or when the reception of events specific for mapped controls has been disabled through a call to the MidiDjConsole.EnableMappedEvents method.

MidiDjConsoleEventUnmapped

One of the keys on the virtual piano keyboard, previously created through the MidiVirtualKeyboard.Create method, is pressed or released

MidiKeyboardNotification

 

Events are for their own nature asynchronous, meaning that they are sent into a queue and managed by the container application with a first-in / first-out policy. Some of the listed events, for example events coming from the input device, may need to be processed in real-time immediately after happening: for this purpose there is the possibility to replace some of the events described above with callback functions provided by the container application; this task can be achieved for the following events:

 

Event

Corresponding method for setting the callback function

 

 

MidiDevicesEventReceived

MidiDevices.InputEventCallbackSet method setting the callback function for short MIDI events and for raw MIDI events

MidiDjConsoleEventButtonPressed

MidiDjConsole.CallbackEventSet method having the nEventType parameter set to DJC_EVENT_TYPE_BUTTON_PRESSED and setting the callback function for DJ console events

MidiDjConsoleEventButtonReleased

MidiDjConsole.CallbackEventSet method having the nEventType parameter set to DJC_EVENT_TYPE_BUTTON_RELEASED and setting the callback function for DJ console events

MidiDjConsoleEventRangeMoved

MidiDjConsole.CallbackEventSet method having the nEventType parameter set to DJC_EVENT_TYPE_RANGE_MOVED and setting the callback function for DJ console events

MidiDjConsoleEventUnmapped

MidiDjConsole.CallbackEventSet method having the nEventType parameter set to DJC_EVENT_TYPE_UNMAPPED and setting the callback function for DJ console events

 

Callback functions are predisposed inside the code of the container application and need to have a specific syntax and number of parameters.

 

 

Callback function for short MIDI events

 

[Visual Basic]

Public Sub MidiInputShortEventsCallback (

ByVal nDeviceUniqueId As Integer,

ByVal nMidiCommand As Integer,

ByVal nMidiChannel As Integer,

ByVal nMidiData1 As Integer,

ByVal nMidiData2 As Integer,

ByVal nTimeStamp As Long,

ByVal nUserData As Long

)


 

[Visual C++]

void CALLBACK MidiInputShortEventsCallback (

short nDeviceUniqueId,

short nMidiCommand,

short nMidiChannel,

short nMidiData1,

short nMidiData2,

long nTimeStamp,

long nUserData

);


 

Inside your code you could implement the callback by invoking the MidiDevices.InputEventCallbackSet method with the value returned by the AddressOf statement:

 

[Visual Basic]

 

Public Sub MidiInputEventsShortCallback(ByVal nDeviceUniqueId As Integer, ByVal nMidiCommand As Integer, _

                                       ByVal nMidiChannel As Integer, ByVal nMidiData1 As Integer, _

                                       ByVal nMidiData2 As Integer, ByVal nTimeStamp As Long, _

                                       ByVal nUserData As Long)

   Debug.Print "Received short event: " & "nCommand: 0x" & Hex(nMidiCommand) & _

                                           " - nData1: 0x" & Hex(nMidiData1) & _

                                           " - nData2: 0x" & Hex(nMidiData2)

End Sub

 

 

Private Sub CommandOpenInput_Click()

 

   ' open input device

   Dim nResult As enumDjcErrorCodes

   nResult = ActiveDjConsole1.MidiDevices.Open(BOOL_TRUE, ComboMidiInputs.ListIndex, m_nIdInputDevice)

   If nResult <> ERR_DJC_NOERROR Then

       MsgBox "MIDI device opening failed due to error " & nResult

       Exit Sub

   End If

 

   ' predispose the callback

   ActiveDjConsole1.MidiDevices.InputEventsCallbackSet m_nIdInputDevice, BOOL_FALSE, AddressOf MidiInputEventsShortCallback, 0

 

End Sub

 


 

[Visual C++ MFC]

void CALLBACK MidiInputShortEventsCallback (short nDeviceUniqueId, short nMidiCommand, short nMidiChannel,

                                                         short nMidiData1, short nMidiData2, long nTimeStamp, long nUserData)

{

   CMidiMonitorDlg        *pThis = (CMidiMonitorDlg *) CWnd::FromHandle (HWND (nUserData));

   if (pThis == NULL)

       return;

 

   // invoke the dialog box function that will manage incoming data

   pThis->ShowEventShort (nDeviceUniqueId, nMidiCommand, nMidiChannel, nMidiData1, nMidiData2, nTimeStamp);

}

 

 

void CMidiMonitorDlg::OnBnClickedButtonConnect()

{

   // open selected input device

   long        nResult = m_djConsole.GetMidiDevices ().Open (TRUE, m_comboInputDevices.GetCurSel (), &m_nIdInputDevice);

   if (nResult != ERR_DJC_NOERROR)

   {

       CString        strMsg;

       strMsg.Format (_T("MIDI input device opening failed due to error %d"), nResult);

       AfxMessageBox (strMsg);

       return;

   }

 

   // predispose callbacks passing the HWND of the dialog as "user data"

   m_djConsole.GetMidiDevices ().InputEventsCallbackSet (m_nIdInputDevice, FALSE,

                               long (MidiInputShortEventsCallback), long (GetSafeHwnd ()));

}

 


 

 

Callback function for raw MIDI events

 

[Visual Basic]

Public Sub MidiInputRawEventsCallback (

ByVal nDeviceUniqueId As Integer,

ByVal pBuffer As Long,

ByVal nBufferLenght As Long,

ByVal nTimeStamp As Long,

ByVal nUserData As Long

)


 

[Visual C++]

void CALLBACK MidiInputRawEventsCallback (

short nDeviceUniqueId,

void *pBuffer,

long nBufferLenght,

long nTimeStamp,

long nUserData

);


 

Inside your code you could implement the callback by invoking the MidiDevices.InputEventCallbackSet method with the value returned by the AddressOf statement:

 

[Visual Basic]

 

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, _

                                      ByRef Source As Any, ByVal bufferLength As Long)

 

Public Sub MidiInputRawEventsCallback(ByVal nDeviceUniqueId As Integer, ByVal pBuffer As Long, _

                                       ByVal nBufferLenght As Long, ByVal nTimeStamp As Long, _

                                       ByVal nUserData As Long)

   ' copy raw buffer locally

   Dim buffTemp() As Byte

   ReDim buffTemp(nBufferLenght) As Byte

   Call CopyMemory(buffTemp(0), ByVal pBuffer, nBufferLenght)

 

   Dim strEvent As String

   Dim i As Long

   For i = 0 To nBufferLenght - 1

       strEvent = strEvent & " 0x" & Hex(buffTemp(i))

   Next i

   Debug.Print "Received raw event: " & strEvent

End Sub

 

 

Private Sub CommandOpenInput_Click()

 

   ' open input device

   Dim nResult As enumDjcErrorCodes

   nResult = ActiveDjConsole1.MidiDevices.Open(BOOL_TRUE, ComboMidiInputs.ListIndex, m_nIdInputDevice)

   If nResult <> ERR_DJC_NOERROR Then

       MsgBox "MIDI device opening failed due to error " & nResult

       Exit Sub

   End If

 

   ' predispose the callback

   ActiveDjConsole1.MidiDevices.InputEventsCallbackSet m_nIdInputDevice, BOOL_FALSE, AddressOf MidiInputRawEventsCallback, 0

 

End Sub

 


 

[Visual C++ MFC]

void CALLBACK MidiInputRawEventsCallback (short nDeviceUniqueId, void *pBuffer, long nBufferLenght, long nTimeStamp, long nUserData)

{

   CMidiMonitorDlg        *pThis = (CMidiMonitorDlg *) CWnd::FromHandle (HWND (nUserData));

   if (pThis == NULL)

       return;

 

   // invoke the dialog box function that will manage incoming data

   pThis->ShowEventRaw (nDeviceUniqueId, (char *) pBuffer, nBufferLenght, nTimeStamp);

}

 

void CMidiMonitorDlg::OnBnClickedButtonConnect()

{

   // open selected input device

   long        nResult = m_djConsole.GetMidiDevices ().Open (TRUE, m_comboInputDevices.GetCurSel (), &m_nIdInputDevice);

   if (nResult != ERR_DJC_NOERROR)

   {

       CString        strMsg;

       strMsg.Format (_T("MIDI input device opening failed due to error %d"), nResult);

       AfxMessageBox (strMsg);

       return;

   }

 

   // predispose callbacks passing the HWND of the dialog as "user data"

   m_djConsole.GetMidiDevices ().InputEventsCallbackSet (m_nIdInputDevice, TRUE,

                                               long (MidiInputRawEventsCallback), long (GetSafeHwnd ()));

}

 


 

 

Callback function for DJ console events

 

[Visual Basic]

Public Sub UnmappedEventCallback (

ByVal nMidiCommand As Integer,

ByVal nMidiChannel As Integer,

ByVal nMidiData1 As Integer,

ByVal nMidiData2 As Integer,

ByVal nTimeStamp As Long,

ByVal nUserData As Long

)

 

Public Sub ButtonEventCallback (

ByVal strControlName As String,

ByVal nControlNameLength As Long,

ByVal nTimeStamp As Long,

ByVal nUserData As Long

)

 

Public Sub RangeCtrlMovedEventCallback (

ByVal strControlName As String,

ByVal nControlNameLength As Long,

ByVal nValue As Integer,

ByVal nTimeStamp As Long,

ByVal nUserData As Long

)


 

[Visual C++]

void CALLBACK UnmappedEventCallback (

short nMidiCommand,

short nMidiChannel,

short nMidiData1,

short nMidiData2,

long nTimeStamp,

long nUserData

);

 

void CALLBACK ButtonEventCallback (

wchar_t *strControlName,

long nControlNameLength,

long nTimeStamp,

long nUserData

);

 

void CALLBACK RangeCtrlMovedEventCallback (

wchar_t *strControlName,

long nControlNameLength,

short nValue,

long nTimeStamp,

long nUserData

);


 

Inside your code you could implement the callback by invoking the MidiDjConsole.CallbackEventSet method with the value returned by the AddressOf statement:

 

[Visual Basic]

 

Public Sub UnmappedEventCallback(ByVal nMidiCommand As Integer, _

                                       ByVal nMidiChannel As Integer, ByVal nMidiData1 As Integer, _

                                       ByVal nMidiData2 As Integer, ByVal nTimeStamp As Long, _

                                       ByVal nUserData As Long)

   Debug.Print "Unmapped event: " & "nCommand: " & nMidiCommand & _

                                           " - nData1: " & nMidiData1 & _

                                           " - nData2: " & nMidiData2

End Sub

 

Public Sub ButtonPressedEventCallback(ByVal strControlName As String, ByVal nControlNameLength As Long, _

                                       ByVal nTimeStamp As Long, ByVal nUserData As Long)

   Debug.Print "Button pressed event from " & strControlName & " - len: " & nControlNameLength

End Sub

 

Public Sub ButtonReleasedEventCallback(ByVal strControlName As String, ByVal nControlNameLength As Long, _

                                       ByVal nTimeStamp As Long, ByVal nUserData As Long)

   Debug.Print "Button released event from " & strControlName

End Sub

 

Public Sub RangeControlMovedEventCallback(ByVal strControlName As String, ByVal nControlNameLength As Long, _

                                       ByVal nValue As Integer, _

                                       ByVal nTimeStamp As Long, ByVal nUserData As Long)

   Debug.Print "Range control moved event from " & strControlName & " - value: " & nValue

End Sub

 

 

Private Sub CommandOpenInput_Click()

 

   ' open input device

   Dim nResult As enumDjcErrorCodes

   nResult = ActiveDjConsole1.MidiDevices.Open(BOOL_TRUE, ComboMidiInputs.ListIndex, m_nIdInputDevice)

   If nResult <> ERR_DJC_NOERROR Then

       MsgBox "MIDI device opening failed due to error " & nResult

       Exit Sub

   End If

 

   ' predispose the callbacks

   ActiveDjConsole1.MidiDjConsole.CallbackEventSet DJC_EVENT_TYPE_UNMAPPED, AddressOf UnmappedEventCallback, 0

   ActiveDjConsole1.MidiDjConsole.CallbackEventSet DJC_EVENT_TYPE_BUTTON_PRESSED, AddressOf ButtonPressedEventCallback, 0

   ActiveDjConsole1.MidiDjConsole.CallbackEventSet DJC_EVENT_TYPE_BUTTON_RELEASED, AddressOf ButtonReleasedEventCallback, 0

   ActiveDjConsole1.MidiDjConsole.CallbackEventSet DJC_EVENT_TYPE_RANGE_MOVED, AddressOf RangeControlMovedEventCallback, 0

End Sub

 


 

[Visual C++ MFC]

 

void CALLBACK UnmappedEventCallback (short nMidiCommand, short nMidiChannel,

                                   short nMidiData1, short nMidiData2,

                                   long nTimeStamp, long nUserData)

{

   CMidiMonitorDlg        *pThis = (CMidiMonitorDlg *) CWnd::FromHandle (HWND (nUserData));

   if (pThis == NULL)

       return;

 

   // invoke the dialog box function that will manage unmapped events

   pThis->ManageUnmappedEvent (nMidiCommand, nMidiChannel, nMidiData1,  nMidiData2, nTimeStamp);

}

 

void CALLBACK ButtonPressedEventCallback (wchar_t *wstrControlName,

                                   long nControlNameLength,

                                   long nTimeStamp, long nUserData)

{

   CString        strControlName = wstrControlName;

   TRACE1 ("\r\nButton pressed: %s", strControlName);

}

 

void CALLBACK ButtonReleasedEventCallback (wchar_t *wstrControlName,

                                   long nControlNameLength,

                                   long nTimeStamp, long nUserData)

{

   CString        strControlName = wstrControlName;

   TRACE1 ("\r\nButton released: %s", strControlName);

}

 

void CALLBACK RangeCtrlMovedEventCallback (wchar_t *wstrControlName,

                                   long nControlNameLength, short nValue,

                                   long nTimeStamp, long nUserData)

{

   CString        strControlName = wstrControlName;

   TRACE2 ("\r\nControl moved: %s - value: %d", strControlName, nValue);

}

 

void CMidiMonitorDlg::OnBnClickedButtonConnect()

{

   // open selected input device

   long        nResult = m_djConsole.GetMidiDevices ().Open (TRUE, m_comboInputDevices.GetCurSel (), &m_nIdInputDevice);

   if (nResult != ERR_DJC_NOERROR)

   {

       CString        strMsg;

       strMsg.Format (_T("MIDI input device opening failed due to error %d"), nResult);

       AfxMessageBox (strMsg);

       return;

   }

 

   // predispose callbacks passing the HWND of the dialog as "user data"

   m_djConsole.GetMidiDjConsole().CallbackEventSet (DJC_EVENT_TYPE_UNMAPPED,

                                   long (UnmappedEventCallback), long (GetSafeHwnd ());

   m_djConsole.GetMidiDjConsole().CallbackEventSet (DJC_EVENT_TYPE_BUTTON_PRESSED,

                                   long (ButtonPressedEventCallback), long (GetSafeHwnd ());

   m_djConsole.GetMidiDjConsole().CallbackEventSet (DJC_EVENT_TYPE_BUTTON_RELEASED,

                                   long (ButtonReleasedEventCallback), long (GetSafeHwnd ());

   m_djConsole.GetMidiDjConsole().CallbackEventSet (DJC_EVENT_TYPE_RANGE_MOVED,

                                   long (RangeCtrlMovedEventCallback), long (GetSafeHwnd ());

}