source: cmedia/trunk/Drv16/midimsg.cpp

Last change on this file was 354, checked in by stevenhl, 17 years ago

Import untested baseline cmedia sources, work products and binaries
Binaries and work products should be deleted from repository.
once new builds are verified to work.

File size: 7.3 KB
Line 
1/* $Id: midimsg.cpp,v 1.1 2000/04/23 14:55:17 ktk Exp $ */
2
3/* SCCSID = %W% %E% */
4/****************************************************************************
5 * *
6 * Copyright (c) IBM Corporation 1994 - 1997. *
7 * *
8 * The following IBM OS/2 source code is provided to you solely for the *
9 * the purpose of assisting you in your development of OS/2 device drivers. *
10 * You may use this code in accordance with the IBM License Agreement *
11 * provided in the IBM Device Driver Source Kit for OS/2. *
12 * *
13 ****************************************************************************/
14/**@internal %W%
15 * MIDIMSG object implementation.
16 * @version %I%
17 * @context
18 * Unless otherwise noted, all interfaces are Ring-0, 16-bit, kernel stack.
19 * @notes
20 * For reference, this is the format of the IBM Sysex command. Many more
21 * commands are defined by the IBM MMPM/2 command reference, but the subset
22 * noted here is all that is implemented. Most of the other commands are
23 * historical for an IBM proprietary sound card, now withdrawn from market.
24 *
25 * Sysex command format: F0 00 00 3A cmd [ subCmd | data ] data *
26 *
27 * cmd subCmd (cmdName) Data
28 * ------------- ----------- ---------------------------------
29 * 1 tc long lsb msb (discard *)
30 * 3 1 ppqn ctl (discard 1) PPQN_byte (discard *)
31 * 3 2 tempo lsb msb
32 * 7-127 tc short (none)
33 *
34 * 'tc' = time compression
35 *
36 * @history
37 */
38
39#ifndef OS2_INCLUDED // Doesn't like being included twice.
40extern "C" { // 16-bit header files are not C++ aware
41 #define INCL_NOPMAPI
42 #include <os2.h>
43}
44#endif // end OS2_INCLUDED
45
46#include <string.h> // _fmemcpy()
47#include "maudio.hpp" // Object definition MIDIAUDIO
48#include "midimsg.hpp" // Object definition
49
50
51/**@external eMidiByteType
52 * Determine the type of the Midi status byte.
53 * @param MIDIBYTE b
54 * @return MIDIBYTETYPE, as enumerated in midimsg.hpp.
55 * @notes Ref. .hpp file for definition of the enumerated values.
56 */
57MIDIBYTETYPE eMidiByteType( MIDIBYTE b )
58{
59 if (b < 0x80)
60 return MBT_Data;
61 else if (b < 0xF0)
62 return MBT_ChannelStatus;
63 else if (b == 0xF0)
64 return MBT_Sysex;
65 else if (b < 0xF8)
66 return MBT_SystemCommon;
67 else
68 return MBT_SystemRT;
69}
70
71
72// Do we have a complete message?
73BOOL MIDIMSG::isComplete( void )
74{
75 int expectedLength = _queryExpectedLength();
76 return (expectedLength > 0) && (_length >= expectedLength) ;
77}
78
79
80// Is the message unsupported?
81/*
82BOOL MIDIMSG::isUnsupported( void )
83{
84 return _queryExpectedLength() < 0;
85}
86*/
87
88// Concatenate 1 byte to end of message.
89/*
90VOID MIDIMSG::addByte( MIDIBYTE b )
91{
92 if (_length < MAX_MidiMsgLen) {
93 _msg[ _length ] = b;
94 ++ _length;
95 }
96}
97*/
98
99// Flush message to a MIDI hardware object using writeByte() method.
100VOID MIDIMSG::flush( MIDIAUDIO* pmhw )
101{
102 for ( int i=0; i<_length; ++i) pmhw->writeByte( _msg[i] );
103}
104
105
106/**@external MIDIMSG::discardSignature
107 * Delete the IBM signature prefix from the front of an IBM Sysex msg,
108 * shift the remaining bytes to the front of the string.
109 * @notes We assume that the IBM signature is there; we don't check for it.
110 */
111VOID MIDIMSG::discardSignature( void )
112{
113// Rudi: moved from below
114 _length -= IBMSysexSigLen;
115 for (int i=0; i < _length; ++i) {
116 _msg[i] = _msg[i + IBMSysexSigLen];
117 }
118
119// _length -= IBMSysexSigLen;
120}
121
122
123/**@internal MIDIMSG::_queryExpectedLength()
124 * Given a status byte, returns expected length of a message,
125 * (including the status byte).
126 * @param None. Examines _msg[].
127 * @return int >0 - Expected length of complete message.
128 * @return int 0 - Don't have enough bytes to determine length
129 * of complete message.
130 * @return negative int MIDIMSG_Err_NotStatus when 1st byte in
131 * message isn't a status byte.
132 * @return negative int MIDIMSG_Err_BadSysex when buffered message
133 * is recognized as an unsupported IBM sysex.
134 * @notes A nonzero value for _expectedLength indicates we've already
135 * computed this. We'll use it if we've got it, otherwise we'll compute
136 * it and save the value.
137 */
138int MIDIMSG::_queryExpectedLength( void )
139{
140 MIDIBYTE b;
141 int iResult;
142
143 // Check if already figured out the expected length. Once the expected
144 // message length is computed for a given message, it doesn't change.
145 // This function is called for every byte received, can optimize here.
146 if (_expectedLength) {
147 return _expectedLength;
148 }
149
150 b = _msg[0];
151 switch( eMidiByteType( b )) {
152 case MBT_ChannelStatus:
153 {
154 int cmdIndex = (b >> 4) - 8; // Transform 0x80..0xE0 to 0..6
155 static UCHAR channelMsgLen[] = { 3, 3, 3, 3, 2, 2, 3 };
156 iResult = channelMsgLen[ cmdIndex ];
157 }
158 break;
159
160 case MBT_Sysex:
161 iResult = _queryExpectedSysexLength();
162 break;
163
164 case MBT_SystemCommon:
165 {
166 int cmdIndex = (b & 7) - 1; // Transform 0xF1..0xF7 to 0..6
167 static UCHAR sysMsgLen[] = { 2, 3, 2, 1, 1, 1, 1 };
168 iResult = sysMsgLen[ cmdIndex ];
169 }
170 break;
171
172 case MBT_SystemRT:
173 iResult = 1; // All 0xF8 - 0xFF are 1 byte.
174 break;
175
176 case MBT_Data:
177 default:
178 iResult = MIDIMSG_Err_NotStatus;
179 break;
180 }
181
182 _expectedLength = iResult;
183 return iResult;
184}
185
186
187/**@internal MIDIMSG::_queryExpectedSysexLength
188 * Returns expected length of an IBM sysex command (incl. signature prefix).
189 * @param None. Examines _msg[].
190 * @return int Expected length of IBM sysex command.
191 * @return 0 If command cannot be determined (some commands
192 * require several command bytes).
193 * @return negative int MIDIMSG_Err_BadSysex If this is a Sysex command that
194 * we don't handle.
195 * @notes The expected return length includes the length of the IBM Sysex
196 * signature prefix, but not the 0xF7 "EOX" byte. The length returned
197 * counts only up to the number of bytes we need to interpret the command,
198 * which might not be all the bytes in the message definition.
199 */
200int MIDIMSG::_queryExpectedSysexLength( void )
201{
202 MIDIBYTE b1 = _msg[ IBMSysexSigLen ]; // First Sysex cmd byte.
203 MIDIBYTE b2 = _msg[ IBMSysexSigLen+1 ]; // Second Sysex cmd byte.
204
205 if (_length <= IBMSysexSigLen)
206 return 0;
207
208 switch( b1 ) {
209 case 1: // Timing compression Long: 2 data bytes follow.
210 return IBMSysexSigLen + 3;
211 case 7: // Timing compression short: No data bytes.
212 return IBMSysexSigLen + 1;
213 case 3: // Device driver control.
214 if (_length <= IBMSysexSigLen+1) // Have 2nd cmd byte? Return 0 if not.
215 return 0;
216 else if (b2 == 1)
217 return IBMSysexSigLen + 4;
218 else if (b2 == 2)
219 return IBMSysexSigLen + 4;
220 else
221 return MIDIMSG_Err_BadSysex;
222 default:
223 return MIDIMSG_Err_BadSysex;
224 }
225}
226
227
Note: See TracBrowser for help on using the repository browser.