Jump to content

MMPM/2 Device Driver Reference:Real-Time MIDI Subsystem: Difference between revisions

From EDM2
Created page with "=Real-Time MIDI Subsystem= The real-time MIDI subsystem (RTMIDI) provides real-time processing of MIDI data within the driver itself. The following sections describe how devic..."
 
No edit summary
Line 1: Line 1:
=Real-Time MIDI Subsystem=
=Real-Time MIDI Subsystem=
The real-time MIDI subsystem (RTMIDI) provides real-time processing of MIDI data within the driver itself. The following sections describe how device drivers communicate with RTMIDI:
The real-time MIDI subsystem (RTMIDI) provides real-time processing of MIDI data within the driver itself. The following sections describe how device drivers communicate with RTMIDI:
*[[IDC Interface]]
*[[#IDC Interface|IDC Interface]]
*[[Type-A Drivers]]
*[[#Type-A Drivers|Type-A Drivers]]
*[[Registering a Type-A Driver]]
*[[#Registering a Type-A Driver|Registering a Type-A Driver]]
Refer to the ''[[Multimedia Subsystem Programming Guide]]'' (included with the IBM Developer's Toolkit for OS/2) for more information on the real-time MIDI subsystem.


Refer to the ''Multimedia Subsystem Programming Guide'' (included with the IBM Developer's Toolkit for OS/2) for more information on the real-time MIDI subsystem.
==IDC Interface==
IDC stands for inter-device-driver communication. It is a technique for making function calls from one driver to another, thereby allowing the two drivers to communicate with one another. For more information on IDC, refer to the ''[[OS/2 Physical Device Driver Reference]]''.


=== IDC Interface ===
Function prototypes and other declarations are found in MIDI_IDC.H. Note that "function pointers" and "entry points" are synonymous. All pointers, function or otherwise, are 16:16 (far) pointers.
IDC stands for inter-device-driver communication. It is a technique for making function calls from one driver to another, thereby allowing the two drivers to communicate with one another. For more information on IDC, refer to the ''OS/2 Physical Device Driver Reference''.


Function prototypes and other declarations are found in MIDI_IDC.H. Note that "function pointers" and "entry points" are synonymous. All pointers, function or otherwise, are 16:16 (far) pointers.
===Supported IDC Interfaces===
 
=== Supported IDC Interfaces ===
The RTMIDI IDC interface is designed to support multiple "types" of client device drivers. An RTMIDI client device driver is a 16-bit physical device driver that registers itself with RTMIDI as a particular type. Currently, only Type A drivers are supported. The Type A drivers send and receive single MIDI bytes. This type is primarily intended for supporting the UART MIDI port on standard sound cards.
The RTMIDI IDC interface is designed to support multiple "types" of client device drivers. An RTMIDI client device driver is a 16-bit physical device driver that registers itself with RTMIDI as a particular type. Currently, only Type A drivers are supported. The Type A drivers send and receive single MIDI bytes. This type is primarily intended for supporting the UART MIDI port on standard sound cards.


Line 19: Line 18:
The header file MIDI_IDC.H contains the function prototype for the entry points of RTMIDI. The initial call to the RTMIDI's main IDC entry point is used to obtain additional function entry points, one of each type.
The header file MIDI_IDC.H contains the function prototype for the entry points of RTMIDI. The initial call to the RTMIDI's main IDC entry point is used to obtain additional function entry points, one of each type.


=== Initializing IDC Communication ===
===Initializing IDC Communication===
To initialize communication between your driver and RTMIDI:
To initialize communication between your driver and RTMIDI:


Line 25: Line 24:


This routine is normally executed when processing the init_complete strategy call. Make sure that DDTable is located in the current data segment (DS) and not on the stack (SS).
This routine is normally executed when processing the init_complete strategy call. Make sure that DDTable is located in the current data segment (DS) and not on the stack (SS).
 
<pre>
<pre class="western">MIDI_ATTACH_DD  DDTable;
MIDI_ATTACH_DD  DDTable;
MIDI_REGISTER  reg;
MIDI_REGISTER  reg;


if (DevHelp_AttachDD(&quot;MIDI$ &quot;, (NPBYTE) &amp;DDTable ) )
if (DevHelp_AttachDD("MIDI$ ", (NPBYTE) &amp;DDTable ) )
{
{
   // Error
   // Error
Line 36: Line 35:


reg.usSize=sizeof( MIDI_REGISTER );
reg.usSize=sizeof( MIDI_REGISTER );
DDTable.pfn(&amp;reg);</pre>
DDTable.pfn(&amp;reg);
 
</pre>
=== Type-A Drivers ===
==Type-A Drivers==
Type-A drivers send and receive single bytes to and from RTMIDI. They are typically used for simple UART MIDI ports or simple synthesizers, such as those found on most sound cards.
Type-A drivers send and receive single bytes to and from RTMIDI. They are typically used for simple UART MIDI ports or simple synthesizers, such as those found on most sound cards.


=== Type-A Driver Capabilities ===
===Type-A Driver Capabilities===
When Type-A drivers register with RTMIDI, they must provide information on their capabilities by setting the appropriate bits in the ''flCapabilities''field of the MIDIREG_TYPEA structure that is passed for registration. (See [[00097.htm|Registering a Type-A Driver]]for an example of registering a Type-A driver.) Flags marked with an asterisk (*) are not currently supported and should not be set. The flags are:
When Type-A drivers register with RTMIDI, they must provide information on their capabilities by setting the appropriate bits in the ''flCapabilities''field of the MIDIREG_TYPEA structure that is passed for registration. (See [[#Registering a Type-A Driver|Registering a Type-A Driver]] for an example of registering a Type-A driver.) Flags marked with an asterisk (*) are not currently supported and should not be set. The flags are:


MIDICAPSA_INPUT Set this flag to indicate that this device can receive MIDI messages from RTMIDI. If set, then the pfnRecvByte and pfnRecvString fields in the MIDIREG_TYPEA structure must be properly initialized. If not set, then the corresponding hardware node cannot be enabled for receive.
;MIDICAPSA_INPUT :Set this flag to indicate that this device can receive MIDI messages from RTMIDI. If set, then the pfnRecvByte and pfnRecvString fields in the MIDIREG_TYPEA structure must be properly initialized. If not set, then the corresponding hardware node cannot be enabled for receive.


MIDICAPSA_OUTPUT Set this flag to indicate that this device can send MIDI messages to RTMIDI. If not set, then the corresponding hardware node cannot be enabled for send.
;MIDICAPSA_OUTPUT :Set this flag to indicate that this device can send MIDI messages to RTMIDI. If not set, then the corresponding hardware node cannot be enabled for send.


MIDICAPSA_USES_BRIDGE * Set this flag to indicate that the device is a candidate for the MMPM/2 bridge.
;MIDICAPSA_USES_BRIDGE :Set this flag to indicate that the device is a candidate for the MMPM/2 bridge.


MIDICAPSA_NOT_DEFAULT * Set this flag to indicate that this device should be selectable as the default device used by MIDISimpleOpen.
;MIDICAPSA_NOT_DEFAULT :Set this flag to indicate that this device should be selectable as the default device used by MIDISimpleOpen.


MIDICAPSA_RUNNING_STATUS Set this flag to tell RTMIDI that the device or the driver, or both, support running status.
;MIDICAPSA_RUNNING_STATUS :Set this flag to tell RTMIDI that the device or the driver, or both, support running status.


=== Registering a Type-A Driver ===
=== Registering a Type-A Driver ===
The following is an example of registering a Type-A driver:
The following is an example of registering a Type-A driver:
 
<pre>
<pre class="western">USHORT __far __loadds __cdecl Open( USHORT  usPort, USHORT  usMode )
USHORT __far __loadds __cdecl Open( USHORT  usPort, USHORT  usMode )
{
{
   // Open hardware
   // Open hardware
Line 67: Line 66:
   // Close hardware
   // Close hardware
   // For example:  detach IRQ
   // For example:  detach IRQ
}</pre>
}


<pre class="western">USHORT __far __loadds __cdecl RecvByte( USHORT  usPort, BYTE  b )
USHORT __far __loadds __cdecl RecvByte( USHORT  usPort, BYTE  b )
{
{
   // Send byte bData to hardware
   // Send byte bData to hardware
Line 80: Line 79:
   // Send byte bData to hardware
   // Send byte bData to hardware
   // For example:  via an outp() command
   // For example:  via an outp() command
}</pre>
}


<pre class="western">void __far __loadds __cdecl *Ioctl( PIOCTL_RP  pioc )
void __far __loadds __cdecl *Ioctl( PIOCTL_RP  pioc )
{
{
   // Process MMPM/2 IOCtl commands here, like volume change
   // Process MMPM/2 IOCtl commands here, like volume change
   // pioc is a pointer to the actual IOCtl request packet
   // pioc is a pointer to the actual IOCtl request packet
}</pre>
}
 


<pre class="western">HW_REGISTER  hwreg;
HW_REGISTER  hwreg;
ULONG  ulHandle;
ULONG  ulHandle;
PFNSENDBYTE  pfnSendByte;
PFNSENDBYTE  pfnSendByte;
Line 94: Line 94:
hwreg.usSize=sizeof( HW_REGISTER );
hwreg.usSize=sizeof( HW_REGISTER );
hwreg.in.flCapabilities = MIDICAPSA_INPUT | MIDICAPSA_OUTPUT;
hwreg.in.flCapabilities = MIDICAPSA_INPUT | MIDICAPSA_OUTPUT;
hwreg.in.pszDeviceName=&quot;My Device&quot;;
hwreg.in.pszDeviceName="My Device";
hwreg.in.pfnOpen=Open;
hwreg.in.pfnOpen=Open;
hwreg.in.pfnClose=Close;
hwreg.in.pfnClose=Close;
hwreg.in.pfnRecvByte=RecvByte;
hwreg.in.pfnRecvByte=RecvByte;
hwreg.in.pfnRecvString=RecvString;</pre>
hwreg.in.pfnRecvString=RecvString;




<code>
  if(!reg.pfnHWRegister(&hwreg))
  if(!reg.pfnHWRegister(&hwreg))
  {
  {
Line 110: Line 109:
  ulHandle=hwreg.out.ulHandle;
  ulHandle=hwreg.out.ulHandle;
  pfnSendByte=hwreg.out.pfnSendByte;
  pfnSendByte=hwreg.out.pfnSendByte;
</code>
</pre>





Revision as of 21:29, 12 April 2016

Real-Time MIDI Subsystem

The real-time MIDI subsystem (RTMIDI) provides real-time processing of MIDI data within the driver itself. The following sections describe how device drivers communicate with RTMIDI:

Refer to the Multimedia Subsystem Programming Guide (included with the IBM Developer's Toolkit for OS/2) for more information on the real-time MIDI subsystem.

IDC Interface

IDC stands for inter-device-driver communication. It is a technique for making function calls from one driver to another, thereby allowing the two drivers to communicate with one another. For more information on IDC, refer to the OS/2 Physical Device Driver Reference.

Function prototypes and other declarations are found in MIDI_IDC.H. Note that "function pointers" and "entry points" are synonymous. All pointers, function or otherwise, are 16:16 (far) pointers.

Supported IDC Interfaces

The RTMIDI IDC interface is designed to support multiple "types" of client device drivers. An RTMIDI client device driver is a 16-bit physical device driver that registers itself with RTMIDI as a particular type. Currently, only Type A drivers are supported. The Type A drivers send and receive single MIDI bytes. This type is primarily intended for supporting the UART MIDI port on standard sound cards.

An individual physical device driver can be of multiple types and it can register itself with RTMIDI as many times as necessary. For instance, a sound card with four physical MIDI ports would make four Type-A registrations. RTMIDI would not realize that these four devices actually existed on one physical sound card and are handled by one driver.

The header file MIDI_IDC.H contains the function prototype for the entry points of RTMIDI. The initial call to the RTMIDI's main IDC entry point is used to obtain additional function entry points, one of each type.

Initializing IDC Communication

To initialize communication between your driver and RTMIDI:

Use the following code segment to obtain the main IDC entry point to RTMIDI and the entry points used to register the driver with RTMIDI. DevHelp_ AttachDD is used to obtain the main entry point, and DDTable.pfn retrieves the registration entry points.

This routine is normally executed when processing the init_complete strategy call. Make sure that DDTable is located in the current data segment (DS) and not on the stack (SS).

MIDI_ATTACH_DD  DDTable;
MIDI_REGISTER  reg;

if (DevHelp_AttachDD("MIDI$ ", (NPBYTE) &DDTable ) )
{
  // Error
  // Return
}

reg.usSize=sizeof( MIDI_REGISTER );
DDTable.pfn(&reg);

Type-A Drivers

Type-A drivers send and receive single bytes to and from RTMIDI. They are typically used for simple UART MIDI ports or simple synthesizers, such as those found on most sound cards.

Type-A Driver Capabilities

When Type-A drivers register with RTMIDI, they must provide information on their capabilities by setting the appropriate bits in the flCapabilitiesfield of the MIDIREG_TYPEA structure that is passed for registration. (See Registering a Type-A Driver for an example of registering a Type-A driver.) Flags marked with an asterisk (*) are not currently supported and should not be set. The flags are:

MIDICAPSA_INPUT
Set this flag to indicate that this device can receive MIDI messages from RTMIDI. If set, then the pfnRecvByte and pfnRecvString fields in the MIDIREG_TYPEA structure must be properly initialized. If not set, then the corresponding hardware node cannot be enabled for receive.
MIDICAPSA_OUTPUT
Set this flag to indicate that this device can send MIDI messages to RTMIDI. If not set, then the corresponding hardware node cannot be enabled for send.
MIDICAPSA_USES_BRIDGE
Set this flag to indicate that the device is a candidate for the MMPM/2 bridge.
MIDICAPSA_NOT_DEFAULT
Set this flag to indicate that this device should be selectable as the default device used by MIDISimpleOpen.
MIDICAPSA_RUNNING_STATUS
Set this flag to tell RTMIDI that the device or the driver, or both, support running status.

Registering a Type-A Driver

The following is an example of registering a Type-A driver:

USHORT __far __loadds __cdecl Open( USHORT  usPort, USHORT  usMode )
{
  // Open hardware
  // For example:  grab IRQ, send I/O commands to initialize the chips
}

USHORT __far __loadds __cdecl Close( USHORT  usPort, USHORT  usMode )
{
  // Close hardware
  // For example:  detach IRQ
}

USHORT __far __loadds __cdecl RecvByte( USHORT  usPort, BYTE  b )
{
  // Send byte bData to hardware
  // For example:  via an outp() command
}

USHORT __far __loadds __cdecl RecvString( USHORT  usPort, BYTE __far *pb,
                                          USHORT  usLength )
{
  // Send byte bData to hardware
  // For example:  via an outp() command
}

void __far __loadds __cdecl *Ioctl( PIOCTL_RP  pioc )
{
  // Process MMPM/2 IOCtl commands here, like volume change
  // pioc is a pointer to the actual IOCtl request packet
}


HW_REGISTER  hwreg;
ULONG  ulHandle;
PFNSENDBYTE  pfnSendByte;

hwreg.usSize=sizeof( HW_REGISTER );
hwreg.in.flCapabilities = MIDICAPSA_INPUT | MIDICAPSA_OUTPUT;
hwreg.in.pszDeviceName="My Device";
hwreg.in.pfnOpen=Open;
hwreg.in.pfnClose=Close;
hwreg.in.pfnRecvByte=RecvByte;
hwreg.in.pfnRecvString=RecvString;


 if(!reg.pfnHWRegister(&hwreg))
 {
  // Error
  // Return
 }
 
 ulHandle=hwreg.out.ulHandle;
 pfnSendByte=hwreg.out.pfnSendByte;


Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation