summaryrefslogtreecommitdiff
path: root/doxygen/html/RtMidi_8cpp-source.html
blob: 1b65b96cbb02076e817072a388d287d545d121d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
<HTML>
<HEAD>
<TITLE>The Synthesis ToolKit in C++ (STK)</TITLE>
<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<CENTER>
<img src="princeton.gif"> &nbsp; <img src="ccrma.gif"><P>
<a class="qindex" href="index.html">Home</a> &nbsp; <a class="qindex" href="information.html">Information</a> &nbsp; <a class="qindex" href="classes.html">Classes</a> &nbsp; <a class="qindex" href="download.html">Download</a> &nbsp; <a class="qindex" href="usage.html">Usage</a> &nbsp; <a class="qindex" href="maillist.html">Mail List</a> &nbsp; <a class="qindex" href="system.html">Requirements</a> &nbsp; <a class="qindex" href="links.html">Links</a> &nbsp; <a class="qindex" href="tutorial.html">Tutorial</a></CENTER>
<HR>
<!-- Generated by Doxygen 1.3-rc3 -->
<h1>RtMidi.cpp</h1><div class="fragment"><pre>00001 <span class="comment">/**********************************************************************/</span>
00010 <span class="comment">/**********************************************************************/</span>
00011 
00012 <span class="preprocessor">#include "RtMidi.h"</span>
00013 <span class="preprocessor">#include &lt;sstream&gt;</span>
00014 
00015 RtMidi :: RtMidi()
00016   : apiData_( 0 ), connected_( false )
00017 {
00018 }
00019 
00020 <span class="keywordtype">void</span> RtMidi :: error( RtError::Type type )
00021 {
00022   <span class="keywordflow">if</span> (type == RtError::WARNING) {
00023     std::cerr &lt;&lt; <span class="charliteral">'\n'</span> &lt;&lt; errorString_ &lt;&lt; <span class="stringliteral">"\n\n"</span>;
00024   }
00025   <span class="keywordflow">else</span> <span class="keywordflow">if</span> (type == RtError::DEBUG_WARNING) {
00026 <span class="preprocessor">#if defined(__RTMIDI_DEBUG__)</span>
00027 <span class="preprocessor"></span>    std::cerr &lt;&lt; <span class="charliteral">'\n'</span> &lt;&lt; errorString_ &lt;&lt; <span class="stringliteral">"\n\n"</span>;
00028 <span class="preprocessor">#endif</span>
00029 <span class="preprocessor"></span>  }
00030   <span class="keywordflow">else</span> {
00031     std::cerr &lt;&lt; <span class="charliteral">'\n'</span> &lt;&lt; errorString_ &lt;&lt; <span class="stringliteral">"\n\n"</span>;
00032     <span class="keywordflow">throw</span> <a class="code" href="classRtError.html#a0">RtError</a>( errorString_, type );
00033   }
00034 }
00035 
<a name="l00036"></a><a class="code" href="classRtMidiIn.html#a0">00036</a> <a class="code" href="classRtMidiIn.html#a0">RtMidiIn :: RtMidiIn</a>() : <a class="code" href="classRtMidi.html">RtMidi</a>()
00037 {
00038 }
00039 
<a name="l00040"></a><a class="code" href="classRtMidiIn.html#a1">00040</a> <a class="code" href="classRtMidiIn.html#a0">RtMidiIn :: RtMidiIn</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> portNumber, RtMidiCallback callback, <span class="keywordtype">void</span> *userData ) : <a class="code" href="classRtMidi.html">RtMidi</a>()
00041 
00042 {
00043   <span class="comment">// Attempt to make the connection.</span>
00044   this-&gt;<a class="code" href="classRtMidiIn.html#a3">openPort</a>( portNumber, callback, userData );
00045 }
00046 
<a name="l00047"></a><a class="code" href="classRtMidiIn.html#a2">00047</a> <a class="code" href="classRtMidiIn.html#a2">RtMidiIn :: ~RtMidiIn</a>()
00048 {
00049   <a class="code" href="classRtMidiIn.html#a4">closePort</a>();
00050 }
00051 
<a name="l00052"></a><a class="code" href="classRtMidiOut.html#a0">00052</a> <a class="code" href="classRtMidiOut.html#a0">RtMidiOut :: RtMidiOut</a>() : <a class="code" href="classRtMidi.html">RtMidi</a>()
00053 {
00054 }
00055 
<a name="l00056"></a><a class="code" href="classRtMidiOut.html#a1">00056</a> <a class="code" href="classRtMidiOut.html#a0">RtMidiOut :: RtMidiOut</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> portNumber ) : <a class="code" href="classRtMidi.html">RtMidi</a>()
00057 {
00058   <span class="comment">// Attempt to make the connection.</span>
00059   this-&gt;<a class="code" href="classRtMidiOut.html#a3">openPort</a>( portNumber );
00060 }
00061 
<a name="l00062"></a><a class="code" href="classRtMidiOut.html#a2">00062</a> <a class="code" href="classRtMidiOut.html#a2">RtMidiOut :: ~RtMidiOut</a>()
00063 {
00064   <a class="code" href="classRtMidiOut.html#a4">closePort</a>();
00065 }
00066 
00067 
00068 <span class="preprocessor">#if defined(__MACOSX_CORE__)</span>
00069 <span class="preprocessor"></span>
00070 <span class="comment">// The CoreMIDI API is based on the use of a callback function for</span>
00071 <span class="comment">// MIDI input.  We convert the system specific time stamps to delta</span>
00072 <span class="comment">// time values.</span>
00073 
00074 <span class="comment">// OS-X CoreMIDI header files.</span>
00075 <span class="preprocessor">#include &lt;CoreMIDI/CoreMIDI.h&gt;</span>
00076 <span class="preprocessor">#include &lt;CoreAudio/HostTime.h&gt;</span>
00077 
00078 <span class="comment">// A structure to hold variables related to the CoreMIDI API</span>
00079 <span class="comment">// implementation.</span>
00080 <span class="keyword">struct </span>CoreMidiData {
00081   MIDIClientRef client;
00082   MIDIPortRef port;
00083   MIDIEndpointRef destinationId;
00084 };
00085 
00086 <span class="keywordtype">void</span> midiInputCallback( <span class="keyword">const</span> MIDIPacketList *list, <span class="keywordtype">void</span> *procRef, <span class="keywordtype">void</span> *srcRef )
00087 {
00088   RtMidiIn::RtMidiInData *data = static_cast&lt;RtMidiIn::RtMidiInData *&gt; (procRef);
00089 
00090   <span class="keywordtype">bool</span> continueSysex = <span class="keyword">false</span>;
00091   <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> status;
00092   <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> nBytes, iByte, size;
00093   <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> time;
00094   RtMidiIn::MidiMessage message;
00095   <span class="keyword">const</span> MIDIPacket *packet = &amp;list-&gt;packet[0];
00096   <span class="keywordflow">for</span> ( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; i&lt;list-&gt;numPackets; ++i ) {
00097 
00098     <span class="comment">// My interpretation of the CoreMIDI documentation: all message</span>
00099     <span class="comment">// types, except sysex, are complete within a packet and there may</span>
00100     <span class="comment">// be several of them in a single packet.  Sysex messages can be</span>
00101     <span class="comment">// broken across multiple packets but are bundled alone within a</span>
00102     <span class="comment">// packet.  I'm assuming that sysex messages, if segmented, must</span>
00103     <span class="comment">// be complete within the same MIDIPacketList.</span>
00104 
00105     nBytes = packet-&gt;length;
00106     <span class="keywordflow">if</span> ( nBytes == 0 ) <span class="keywordflow">continue</span>;
00107 
00108     <span class="comment">// Calculate time stamp.</span>
00109     message.timeStamp = 0.0;
00110     time = packet-&gt;timeStamp;
00111     time -= data-&gt;lastTime;
00112     data-&gt;lastTime = packet-&gt;timeStamp;
00113     time = AudioConvertHostTimeToNanos( time );
00114     message.timeStamp = time * 0.000000001;
00115 
00116     iByte = 0;
00117     <span class="keywordflow">if</span> ( continueSysex ) {
00118       <span class="comment">// We have a continuing, segmented sysex message.</span>
00119       <span class="keywordflow">if</span> ( !(data-&gt;ignoreFlags &amp; 0x01) ) {
00120         <span class="comment">// If we're not ignoring sysex messages, copy the entire packet.</span>
00121         message.bytes.assign( packet-&gt;data, &amp;packet-&gt;data[nBytes] );
00122       }
00123       <span class="keywordflow">if</span> ( packet-&gt;data[nBytes] == 0xF7 ) continueSysex = <span class="keyword">false</span>;
00124       <span class="keywordflow">if</span> ( !continueSysex ) {
00125         <span class="comment">// If not a continuing sysex message, invoke the user callback function or queue the message.</span>
00126         <span class="keywordflow">if</span> ( data-&gt;usingCallback &amp;&amp; message.bytes.size() &gt; 0 ) {
00127           <a class="code" href="classRtMidiIn.html#s0">RtMidiIn::RtMidiCallback</a> callback = (RtMidiIn::RtMidiCallback) data-&gt;userCallback;
00128           callback( message.timeStamp, &amp;message.bytes, data-&gt;userData );
00129         }
00130         <span class="keywordflow">else</span> {
00131           <span class="comment">// As long as we haven't reached our queue size limit, push the message.</span>
00132           <span class="keywordflow">if</span> ( data-&gt;queueLimit &gt; data-&gt;queue.size() )
00133             data-&gt;queue.push( message );
00134           <span class="keywordflow">else</span>
00135             std::cerr &lt;&lt; <span class="stringliteral">"\nRtMidiIn: message queue limit reached!!\n\n"</span>;
00136         }
00137         message.bytes.clear();
00138       }
00139     }
00140     <span class="keywordflow">else</span> {
00141       <span class="keywordflow">while</span> ( iByte &lt; nBytes ) {
00142         size = 0;
00143         <span class="comment">// We are expecting that the next byte in the packet is a status byte.</span>
00144         status = packet-&gt;data[iByte];
00145         <span class="keywordflow">if</span> ( !(status &amp; 0x80) ) <span class="keywordflow">break</span>;
00146         <span class="comment">// Determine the number of bytes in the MIDI message.</span>
00147         <span class="keywordflow">if</span> ( status &lt; 0xC0 ) size = 3;
00148         <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( status &lt; 0xE0 ) size = 2;
00149         <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( status &lt; 0xF0 ) size = 3;
00150         <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( status == 0xF0 ) {
00151           <span class="comment">// A MIDI sysex</span>
00152           <span class="keywordflow">if</span> ( data-&gt;ignoreFlags &amp; 0x01 ) {
00153             size = 0;
00154             iByte = nBytes;
00155           }
00156           <span class="keywordflow">else</span> size = nBytes - iByte;
00157           <span class="keywordflow">if</span> ( packet-&gt;data[nBytes] == 0xF7 ) continueSysex = <span class="keyword">false</span>;
00158         }
00159         <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( status &lt; 0xF3 ) {
00160           <span class="keywordflow">if</span> ( status == 0xF1 &amp;&amp; (data-&gt;ignoreFlags &amp; 0x02) ) {
00161             <span class="comment">// A MIDI time code message and we're ignoring it.</span>
00162             size = 0;
00163             iByte += 3;
00164           }
00165           <span class="keywordflow">else</span> size = 3;
00166         }
00167         <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( status == 0xF3 ) size = 2;
00168         <span class="keywordflow">else</span> <span class="keywordflow">if</span> ( status == 0xFE &amp;&amp; (data-&gt;ignoreFlags &amp; 0x04) ) {
00169           <span class="comment">// A MIDI active sensing message and we're ignoring it.</span>
00170           size = 0;
00171           iByte += 1;
00172         }
00173         <span class="keywordflow">else</span> size = 1;
00174 
00175         <span class="comment">// Copy the MIDI data to our vector.</span>
00176         <span class="keywordflow">if</span> ( size ) {
00177           message.bytes.assign( &amp;packet-&gt;data[iByte], &amp;packet-&gt;data[iByte+size] );
00178           <span class="keywordflow">if</span> ( !continueSysex ) {
00179             <span class="comment">// If not a continuing sysex message, invoke the user callback function or queue the message.</span>
00180             <span class="keywordflow">if</span> ( data-&gt;usingCallback ) {
00181               <a class="code" href="classRtMidiIn.html#s0">RtMidiIn::RtMidiCallback</a> callback = (RtMidiIn::RtMidiCallback) data-&gt;userCallback;
00182               callback( message.timeStamp, &amp;message.bytes, data-&gt;userData );
00183             }
00184             <span class="keywordflow">else</span> {
00185               <span class="comment">// As long as we haven't reached our queue size limit, push the message.</span>
00186               <span class="keywordflow">if</span> ( data-&gt;queueLimit &gt; data-&gt;queue.size() )
00187                 data-&gt;queue.push( message );
00188               <span class="keywordflow">else</span>
00189                 std::cerr &lt;&lt; <span class="stringliteral">"\nRtMidiIn: message queue limit reached!!\n\n"</span>;
00190             }
00191             message.bytes.clear();
00192           }
00193           iByte += size;
00194         }
00195       }
00196     }
00197     packet = MIDIPacketNext(packet);
00198   }
00199 }
00200 
00201 <span class="keywordtype">void</span> <a class="code" href="classRtMidiIn.html#a3">RtMidiIn :: openPort</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> portNumber, RtMidiCallback callback, <span class="keywordtype">void</span> *userData )
00202 {
00203   <span class="keywordflow">if</span> ( connected_ ) {
00204     errorString_ = <span class="stringliteral">"RtMidiIn::openPort: a valid connection already exists!"</span>;
00205     error( RtError::WARNING );
00206     <span class="keywordflow">return</span>;
00207   }
00208 
00209   <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> nSrc = MIDIGetNumberOfSources();
00210   <span class="keywordflow">if</span> (nSrc &lt; 1) {
00211     errorString_ = <span class="stringliteral">"RtMidiIn::openPort: no MIDI input sources found!"</span>;
00212     error( RtError::NO_DEVICES_FOUND );
00213   }
00214 
00215   std::ostringstream ost;
00216   <span class="keywordflow">if</span> ( portNumber &gt;= nSrc ) {
00217     ost &lt;&lt; <span class="stringliteral">"RtMidiIn::openPort: the 'portNumber' argument ("</span> &lt;&lt; portNumber &lt;&lt; <span class="stringliteral">") is invalid."</span>;
00218     errorString_ = ost.str();
00219     error( RtError::INVALID_PARAMETER );
00220   }
00221 
00222   MIDIClientRef client;
00223   OSStatus result = MIDIClientCreate( CFSTR(<span class="stringliteral">"RtMidi Input Client"</span>), NULL, NULL, &amp;client );
00224   <span class="keywordflow">if</span> ( result != noErr ) {
00225     errorString_ = <span class="stringliteral">"RtMidiIn::openPort: error creating OS-X MIDI client object."</span>;
00226     error( RtError::DRIVER_ERROR );
00227   }
00228 
00229   MIDIPortRef port;
00230   result = MIDIInputPortCreate( client, CFSTR(<span class="stringliteral">"RtMidi Virtual MIDI Input Port"</span>), midiInputCallback, (<span class="keywordtype">void</span> *)&amp;inputData_, &amp;port );
00231   <span class="keywordflow">if</span> ( result != noErr ) {
00232     MIDIClientDispose( client );
00233     errorString_ = <span class="stringliteral">"RtMidiIn::openPort: error creating OS-X MIDI input port."</span>;
00234     error( RtError::DRIVER_ERROR );
00235   }
00236 
00237   <span class="comment">// Get the desired input source identifier.</span>
00238   MIDIEndpointRef src = MIDIGetSource( portNumber );
00239   <span class="keywordflow">if</span> ( src == NULL ) {
00240     MIDIPortDispose( port );
00241     MIDIClientDispose( client );
00242     errorString_ = <span class="stringliteral">"RtMidiIn::openPort: error getting MIDI input source reference."</span>;
00243     error( RtError::DRIVER_ERROR );
00244   }
00245 
00246   <span class="comment">// Make the connection.</span>
00247   result = MIDIPortConnectSource(port, src, NULL );
00248   <span class="keywordflow">if</span> ( result != noErr ) {
00249     MIDIPortDispose( port );
00250     MIDIClientDispose( client );
00251     errorString_ = <span class="stringliteral">"RtMidiIn::openPort: error connecting OS-X MIDI input port."</span>;
00252     error( RtError::DRIVER_ERROR );
00253   }
00254 
00255   <span class="comment">// Save our api-specific connection information.</span>
00256   CoreMidiData *data = (CoreMidiData *) <span class="keyword">new</span> CoreMidiData;
00257   data-&gt;client = client;
00258   data-&gt;port = port;
00259   apiData_ = (<span class="keywordtype">void</span> *) data;
00260 
00261   <span class="keywordflow">if</span> ( callback ) {
00262     inputData_.userCallback = (<span class="keywordtype">void</span> *) callback;
00263     inputData_.userData = userData;
00264     inputData_.usingCallback = <span class="keyword">true</span>;
00265   }
00266 
00267   inputData_.lastTime = AudioGetCurrentHostTime();
00268 
00269   connected_ = <span class="keyword">true</span>;
00270 }
00271 
00272 <span class="keywordtype">void</span> <a class="code" href="classRtMidiIn.html#a4">RtMidiIn :: closePort</a>( <span class="keywordtype">void</span> )
00273 {
00274   <span class="keywordflow">if</span> ( connected_ ) {
00275     CoreMidiData *data = static_cast&lt;CoreMidiData *&gt; (apiData_);
00276     MIDIClientDispose( data-&gt;client );
00277     MIDIPortDispose( data-&gt;port );
00278     <span class="keyword">delete</span> data;
00279     apiData_ = 0;
00280   }
00281 
00282   connected_ = <span class="keyword">false</span>;
00283 }
00284 
00285 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classRtMidiIn.html#a5">RtMidiIn :: getPortCount</a>()
00286 {
00287   <span class="keywordflow">return</span> MIDIGetNumberOfSources();
00288 }
00289 
00290 std::string <a class="code" href="classRtMidiIn.html#a6">RtMidiIn :: getPortName</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> portNumber )
00291 {
00292   CFStringRef nameRef;
00293   MIDIEndpointRef portRef;
00294   std::ostringstream ost;
00295   <span class="keywordtype">char</span> name[128];
00296 
00297   <span class="keywordflow">if</span> ( portNumber &gt;= MIDIGetNumberOfSources() ) {
00298     ost &lt;&lt; <span class="stringliteral">"RtMidiIn::getPortName: the 'portNumber' argument ("</span> &lt;&lt; portNumber &lt;&lt; <span class="stringliteral">") is invalid."</span>;
00299     errorString_ = ost.str();
00300     error( RtError::INVALID_PARAMETER );
00301   }
00302   portRef = MIDIGetSource( portNumber );
00303 
00304   MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &amp;nameRef );
00305   CFStringGetCString( nameRef, name, <span class="keyword">sizeof</span>(name), 0);
00306   CFRelease( nameRef );
00307   std::string stringName = name;
00308   <span class="keywordflow">return</span> stringName;
00309 }
00310 
00311 <span class="keywordtype">void</span> <a class="code" href="classRtMidiIn.html#a7">RtMidiIn :: setQueueSizeLimit</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> queueSize )
00312 {
00313   inputData_.queueLimit = queueSize;
00314 }
00315 
00316 <span class="keywordtype">void</span> <a class="code" href="classRtMidiIn.html#a8">RtMidiIn :: ignoreTypes</a>( <span class="keywordtype">bool</span> midiSysex, <span class="keywordtype">bool</span> midiTime, <span class="keywordtype">bool</span> midiSense )
00317 {
00318   inputData_.ignoreFlags = 0;
00319   <span class="keywordflow">if</span> ( midiSysex ) inputData_.ignoreFlags = 0x01;
00320   <span class="keywordflow">if</span> ( midiTime ) inputData_.ignoreFlags |= 0x02;
00321   <span class="keywordflow">if</span> ( midiSense ) inputData_.ignoreFlags |= 0x04;
00322 }
00323 
00324 <span class="keywordtype">double</span> <a class="code" href="classRtMidiIn.html#a9">RtMidiIn :: getMessage</a>( std::vector&lt;unsigned char&gt; *message )
00325 {
00326   message-&gt;clear();
00327   <span class="keywordflow">if</span> ( !connected_ ) {
00328     errorString_ = <span class="stringliteral">"RtMidiIn::getNextMessage: a port is not open!"</span>;
00329     error( RtError::WARNING );
00330     <span class="keywordflow">return</span> 0.0;
00331   }
00332 
00333   <span class="keywordflow">if</span> ( inputData_.usingCallback ) {
00334     errorString_ = <span class="stringliteral">"RtMidiIn::getNextMessage: a user callback is currently set for this port."</span>;
00335     error( RtError::WARNING );
00336     <span class="keywordflow">return</span> 0.0;
00337   }
00338 
00339   <span class="keywordflow">if</span> ( inputData_.queue.size() == 0 ) <span class="keywordflow">return</span> 0.0;
00340 
00341   <span class="comment">// Copy queued message to the vector pointer argument and then "pop" it.</span>
00342   std::vector&lt;unsigned char&gt; *bytes = &amp;(inputData_.queue.front().bytes);
00343   message-&gt;assign( bytes-&gt;begin(), bytes-&gt;end() );
00344   <span class="keywordtype">double</span> deltaTime = inputData_.queue.front().timeStamp;
00345   inputData_.queue.pop();
00346 
00347   <span class="keywordflow">return</span> deltaTime;
00348 }
00349 
00350 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classRtMidiOut.html#a5">RtMidiOut :: getPortCount</a>()
00351 {
00352   <span class="keywordflow">return</span> MIDIGetNumberOfDestinations();
00353 }
00354 
00355 std::string <a class="code" href="classRtMidiOut.html#a6">RtMidiOut :: getPortName</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> portNumber )
00356 {
00357   CFStringRef nameRef;
00358   MIDIEndpointRef portRef;
00359   std::ostringstream ost;
00360   <span class="keywordtype">char</span> name[128];
00361 
00362   <span class="keywordflow">if</span> ( portNumber &gt;= MIDIGetNumberOfDestinations() ) {
00363     ost &lt;&lt; <span class="stringliteral">"RtMidiOut::getPortName: the 'portNumber' argument ("</span> &lt;&lt; portNumber &lt;&lt; <span class="stringliteral">") is invalid."</span>;
00364     errorString_ = ost.str();
00365     error( RtError::INVALID_PARAMETER );
00366   }
00367   portRef = MIDIGetDestination( portNumber );
00368 
00369   MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &amp;nameRef );
00370   CFStringGetCString( nameRef, name, <span class="keyword">sizeof</span>(name), 0);
00371   CFRelease( nameRef );
00372   std::string stringName = name;
00373   <span class="keywordflow">return</span> stringName;
00374 }
00375 
00376 <span class="keywordtype">void</span> <a class="code" href="classRtMidiOut.html#a3">RtMidiOut :: openPort</a>( <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> portNumber )
00377 {
00378   <span class="keywordflow">if</span> ( connected_ ) {
00379     errorString_ = <span class="stringliteral">"RtMidiOut::openPort: a valid connection already exists!"</span>;
00380     error( RtError::WARNING );
00381     <span class="keywordflow">return</span>;
00382   }
00383 
00384   <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> nDest = MIDIGetNumberOfDestinations();
00385   <span class="keywordflow">if</span> (nDest &lt; 1) {
00386     errorString_ = <span class="stringliteral">"RtMidiOut::openPort: no MIDI output destinations found!"</span>;
00387     error( RtError::NO_DEVICES_FOUND );
00388   }
00389 
00390   std::ostringstream ost;
00391   <span class="keywordflow">if</span> ( portNumber &gt;= nDest ) {
00392     ost &lt;&lt; <span class="stringliteral">"RtMidiOut::openPort: the 'portNumber' argument ("</span> &lt;&lt; portNumber &lt;&lt; <span class="stringliteral">") is invalid."</span>;
00393     errorString_ = ost.str();
00394     error( RtError::INVALID_PARAMETER );
00395   }
00396 
00397   MIDIClientRef client;
00398   OSStatus result = MIDIClientCreate( CFSTR(<span class="stringliteral">"RtMidi Output Client"</span>), NULL, NULL, &amp;client );
00399   <span class="keywordflow">if</span> ( result != noErr ) {
00400     errorString_ = <span class="stringliteral">"RtMidiOut::openPort: error creating OS-X MIDI client object."</span>;
00401     error( RtError::DRIVER_ERROR );
00402   }
00403 
00404   MIDIPortRef port;
00405   result = MIDIOutputPortCreate( client, CFSTR(<span class="stringliteral">"RtMidi Virtual MIDI Output Port"</span>), &amp;port );
00406   <span class="keywordflow">if</span> ( result != noErr ) {
00407     MIDIClientDispose( client );
00408     errorString_ = <span class="stringliteral">"RtMidiOut::openPort: error creating OS-X MIDI output port."</span>;
00409     error( RtError::DRIVER_ERROR );
00410   }
00411 
00412   <span class="comment">// Get the desired output port identifier.</span>
00413   MIDIEndpointRef destinationId = MIDIGetDestination( portNumber );
00414   <span class="keywordflow">if</span> ( destinationId == NULL ) {
00415     MIDIPortDispose( port );
00416     MIDIClientDispose( client );
00417     errorString_ = <span class="stringliteral">"RtMidiOut::openPort: error getting MIDI output destination reference."</span>;
00418     error( RtError::DRIVER_ERROR );
00419   }
00420 
00421   <span class="comment">// Save our api-specific connection information.</span>
00422   CoreMidiData *data = (CoreMidiData *) <span class="keyword">new</span> CoreMidiData;
00423   data-&gt;client = client;
00424   data-&gt;port = port;
00425   data-&gt;destinationId = destinationId;
00426   apiData_ = (<span class="keywordtype">void</span> *) data;
00427 
00428   connected_ = <span class="keyword">true</span>;
00429 }
00430 
00431 <span class="keywordtype">void</span> <a class="code" href="classRtMidiOut.html#a4">RtMidiOut :: closePort</a>( <span class="keywordtype">void</span> )
00432 {
00433   <span class="keywordflow">if</span> ( connected_ ) {
00434     CoreMidiData *data = static_cast&lt;CoreMidiData *&gt; (apiData_);
00435     MIDIClientDispose( data-&gt;client );
00436     MIDIPortDispose( data-&gt;port );
00437     <span class="keyword">delete</span> data;
00438     apiData_ = 0;
00439   }
00440 
00441   connected_ = <span class="keyword">false</span>;
00442 }
00443 
00444 <span class="keywordtype">void</span> <a class="code" href="classRtMidiOut.html#a7">RtMidiOut :: sendMessage</a>( std::vector&lt;unsigned char&gt; *message )
00445 {
00446   <span class="keywordflow">if</span> ( !connected_ ) {
00447     errorString_ = <span class="stringliteral">"RtMidiOut::sendMessage: a port is not open!"</span>;
00448     error( RtError::WARNING );
00449     <span class="keywordflow">return</span>;
00450   }
00451 
00452   <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> nBytes = message-&gt;size();
00453   <span class="comment">// Pad the buffer for extra (unknown) structure data.</span>
00454   Byte buffer[nBytes+32];
00455   MIDIPacketList *pktlist = (MIDIPacketList *) buffer;
00456   MIDIPacket *curPacket = MIDIPacketListInit( pktlist );
00457 
00458   MIDITimeStamp timeStamp = 0;
00459   curPacket = MIDIPacketListAdd( pktlist, <span class="keyword">sizeof</span>(buffer), curPacket, timeStamp, nBytes, &amp;message-&gt;at(0) );
00460 
00461   CoreMidiData *data = static_cast&lt;CoreMidiData *&gt; (apiData_);
00462   OSStatus result = MIDISend( data-&gt;port, data-&gt;destinationId, pktlist );
00463   <span class="keywordflow">if</span> ( result != noErr ) {
00464     errorString_ = <span class="stringliteral">"RtMidiOut::sendMessage: error sending MIDI message."</span>;
00465     error( RtError::WARNING );
00466   }
00467 }
00468 
00469 <span class="preprocessor">#endif</span>
00470 <span class="preprocessor"></span>
</pre></div><HR>

<table>
  <tr><td><A HREF="http://www-ccrma.stanford.edu/software/stk/"><I>The Synthesis ToolKit in C++ (STK)</I></A></td></tr>
  <tr><td>&copy;1995-2002 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
</table>

</BODY>
</HTML>