1/*! 2 \file MidiProducer.h 3 \ingroup midi2 4 \ingroup libbe 5 \brief Defines producer classes for the MIDI Kit. 6*/ 7 8 9/*! 10 \class BMidiProducer MidiProducer.h 11 \ingroup midi2 12 \ingroup libmidi2 13 \ingroup libbe 14 \brief Streams MIDI events to connected consumers. 15 16 A producer is an object that generate a stream of MIDI events. Each 17 producer has a list of BMidiConsumer objects to which it is connected, 18 and may be asked to connect to or disconnect from a BMidiConsumer. A 19 producer can spray its events to multiple consumers at the same time. 20 A BMidiProducer either represents a local producer, i.e. a class extending 21 from BMidiLocalProducer, or is a proxy for a remote object published by 22 another app. 23*/ 24 25 26/*! 27 \fn status_t BMidiProducer::Connect(BMidiConsumer* cons) 28 \brief Connects a consumer to this producer. 29 30 Establishes a connection between this producer and the specified consumer 31 endpoint. From now on, any events that this producer sprays will be sent 32 to that consumer. You may connect multiple consumers to a producer. 33 34 \return B_OK on success, or an error code when the connection could not be 35 established. If the consumer is a proxy for a remote object and that 36 object no longer exists, Connect() returns B_ERROR. It also returns 37 \c B_ERROR if you try to connect the same producer and consumer more 38 than once. 39 40 \sa Disconnect() 41*/ 42 43 44/*! 45 \fn status_t BMidiProducer::Disconnect(BMidiConsumer* cons) 46 \brief Disconnects a consumer from this producer. 47 48 Terminates the connection between this producer and the specified consumer 49 endpoint. From now on, any events that this producer sprays no longer go 50 to that consumer. 51 52 \return B_OK on success, or an error code if there was no connection to break 53 \sa Connect() 54*/ 55 56 57/*! 58 \fn bool BMidiProducer::IsConnected(BMidiConsumer* cons) const 59 \brief Determines whether a consumer is connected to this producer. 60 61 \sa Connect() 62 \sa Disconnect() 63*/ 64 65 66/*! 67 \fn BList* BMidiProducer::Connections() const 68 \brief Returns a list with all connected consumers. 69 70 Returns a BList with pointers to BMidiEndpoint objects for all consumers 71 that are connected to this producer. You can examine the contents of the 72 list as follows: 73\code 74BList* list = prod->Connections(); 75for (int32 t = 0; t < list->CountItems(); ++t) 76{ 77 BMidiEndpoint* endp = (BMidiEndpoint*) list->ItemAt(t); 78 ...do stuff... 79 endp->Release(); // yes, here too! 80} 81delete list; 82\endcode 83 Every time you call this function, a new BList is allocated. The caller 84 (that is you) is responsible for freeing this list. The BMidiEndpoint 85 objects in the list have their reference counts bumped, so you need to 86 Release() them before you delete the list or they will go all leaky on 87 you. 88*/ 89 90 91/*! 92 \class BMidiLocalProducer MidiProducer.h 93 \ingroup midi2 94 \ingroup libmidi2 95 \ingroup libbe 96 \brief A producer endpoint that is created by your own application. 97 98 You create a BMidiLocalProducer if you want your application to send MIDI 99 events. You use the various spray functions to send events to all connected 100 consumers. If no consumers are connected to the producer, any calls to the 101 spray functions are ignored. 102 103 Most spray functions accept a channel argument. Even though MIDI channels are 104 really numbered 1 through 16, the spray functions work with channels 0 through 105 15. You can also specify the performance time for the event using the time 106 argument. Specify 0 (or any time in the past) to perform the event "now", i.e. 107 as soon as possible. You can also schedule events to be performed in the 108 future, by passing a time such as system_time() + 5000000, which means 5 109 seconds from now. 110 111 Unlike BMidiLocalConsumer, which should be subclassed almost always, you hardly 112 ever need to derive a class from BMidiLocalProducer. The only reason for 113 subclassing is when you need to know when the producer gets connected or 114 disconnected. 115 116 Also unlike consumers, local producers have no thread of control directly 117 associated with them. If you want to send out the MIDI events from a different 118 thread, you will have to create one yourself. 119*/ 120 121 122/*! 123 \fn BMidiLocalProducer::BMidiLocalProducer(const char *name = NULL) 124 \brief Creates a new local producer endpoint. 125 126 The new endpoint is not visible to other applications until you Register() it. 127 You can tell the constructor what the name of the new producer will be. If you 128 pass NULL (or use the default argument), then the producer's name will be an 129 empty string. It won't be NULL, since endpoint names cannot be NULL. 130 There is no guarantee that the endpoint will be successfully created. For 131 example, the Midi Server may not be running. Therefore, you should always call 132 IsValid() after creating a new endpoint to make sure that everything went okay. 133 If not, Release() the object to reclaim memory and abort gracefully. 134\code 135BMidiLocalProducer* prod = new BMidiLocalProducer(...); 136if (!prod->IsValid()) 137{ 138 prod->Release(); 139 ...exit gracefully... 140} 141\endcode 142*/ 143 144 145/*! 146 \fn void BMidiLocalProducer::Connected(BMidiConsumer* cons) 147 \brief Invoked when a new consumer is connected to this producer 148 149 Although typical notifications (i.e. from BMidiRoster's "watching" facility) 150 are only sent if it is some other app that is performing the operation, 151 Connected() is also called if you are making the connection yourself. 152 If you override this hook, you don't have to call the default implementation, 153 because that does nothing. 154 155 \param cons The newly connected consumer. The reference count of the 156 consumer object is not increased, so you should not Release() it. 157 However, if you want to keep track of the consumer beyond this 158 function, you should first Acquire() it, and Release() it when you 159 are done. 160 161 \sa Disconnected() 162*/ 163 164 165/*! 166 \fn void BMidiLocalProducer::Disconnected(BMidiConsumer* cons) 167 \brief Invoked when a consumer is disconnected from this producer. 168 169 \sa Connected() 170*/ 171 172 173/*! 174 \fn void BMidiLocalProducer::SprayData(void* data, size_t length, 175 bool atomic = false, bigtime_t time = 0) const 176 \brief Sends raw MIDI data downstream to all connected consumers. 177 178 Typically you won't have to call SprayData(); the other spray functions 179 will do just fine. If you do call it, remember that you retain ownership 180 of the data and that you are responsible for freeing it at some point. 181 (Even though data is not declared const, the function does not change it.) 182 With atomic set to false, you can send a MIDI message in segments (perhaps 183 for a large sysex dump). However, when you do this, you are on your own. 184 The Midi Kit only tags the data as being non-atomic, but offers no] 185 additional support. 186 187 The default implementation of BMidiLocalConsumer completely ignores such 188 events. To handle non-atomic MIDI data, you should override the 189 BMidiLocalConsumer::Data() hook and process the MIDI event yourself. All of 190 BMidiLocalProducer's other spray functions always send atomic data. 191 192 \param data the MIDI event data. 193 \param length byte size of the data buffer. 194 \param atomic whether the data buffer contains a single complete 195 MIDI event. 196 \param time the required performance time of the event. 197 198 \sa BMidiLocalConsumer::Data() 199*/ 200 201 202/*! 203 \fn void BMidiLocalProducer::SprayNoteOff(uchar channel, uchar note, 204 uchar velocity, bigtime_t time = 0) const 205 \brief Sends a Note Off event to all connected consumers. 206 207 \sa BMidiLocalConsumer::NoteOff() 208*/ 209 210 211/*! 212 \fn void BMidiLocalProducer::SprayNoteOn(uchar channel, uchar note, 213 uchar velocity, bigtime_t time = 0) const 214 \brief Sends a Note On event to all connected consumers. 215 216 \sa BMidiLocalConsumer::NoteOn() 217*/ 218 219 220/*! 221 \fn void BMidiLocalProducer::SprayKeyPressure(uchar channel, uchar note, 222 uchar pressure, bigtime_t time = 0) const 223 \brief Sends a Polyphonic Pressure (Aftertouch) event to all connected 224 consumers. 225 226 \sa BMidiLocalConsumer::KeyPressure() 227*/ 228 229 230/*! 231 \fn void BMidiLocalProducer::SprayControlChange(uchar channel, 232 uchar controlNumber, uchar controlValue, bigtime_t time = 0) const 233 \brief Sends a Controller Change event to all connected consumers. 234 235 \sa Midi2Defs.h 236 \sa BMidiLocalConsumer::ControlChange() 237*/ 238 239 240/*! 241 \fn void BMidiLocalProducer::SprayProgramChange(uchar channel, 242 uchar programNumber, bigtime_t time = 0) const 243 \brief Sends a Program Change event to all connected consumers. 244 245 \sa BMidiLocalConsumer::ProgramChange() 246*/ 247 248 249/*! 250 \fn void BMidiLocalProducer::SprayChannelPressure(uchar channel, 251 uchar pressure, bigtime_t time = 0) const 252 \brief Sends a Channel Pressure event to all connected consumers. 253 254 \sa BMidiLocalConsumer::ChannelPressure() 255*/ 256 257 258/*! 259 \fn void BMidiLocalProducer::SprayPitchBend(uchar channel, uchar lsb, 260 uchar msb, bigtime_t time = 0) const 261 \brief Sends a Pitch Bend event to all connected consumers. 262 263 \sa BMidiLocalConsumer::PitchBend() 264*/ 265 266 267/*! 268 \fn void BMidiLocalProducer::SpraySystemExclusive(void* data, 269 size_t length, bigtime_t time = 0) const 270 \brief Sends a System Exclusive event to all connected consumers. 271 272 You retain ownership of the data and are responsible for freeing it. Even 273 though data is not declared const, the function does not change it. Even 274 though the amount of data may be quite large, this function always sends 275 sysex messages as an atomic block of data. 276 277 \sa BMidiLocalConsumer::SystemExclusive() 278*/ 279 280 281/*! 282 \fn void BMidiLocalProducer::SpraySystemCommon(uchar status,\ 283 uchar data1, uchar data2, bigtime_t time = 0) const 284 \brief Sends a System Common event to the connected consumers. 285 286 The status byte must be one of the following: 287 <table border="1"> 288 <tr> 289 <td>0xF1</td> 290 <td>\c B_MIDI_TIME_CODE</td> 291 <td>data1 only</td> 292 </tr> 293 <tr> 294 <td>0xF2</td> 295 <td>\c B_SONG_POSITION</td> 296 <td>data1 and data2</td> 297 </tr> 298 <tr> 299 <td>0xF3</td> 300 <td>\c B_SONG_SELECT</td> 301 <td>data1 only</td> 302 </tr> 303 <tr> 304 <td>0xF5</td> 305 <td>\c B_CABLE_MESSAGE</td> 306 <td>data1 only</td> 307 </tr> 308 <tr> 309 <td>0xF6</td> 310 <td>\c B_TUNE_REQUEST</td> 311 <td>no data</td> 312 </tr> 313 <tr> 314 <td>0xF7</td> 315 <td>\c B_SYS_EX_END</td> 316 <td>no data</td> 317 </tr> 318 </table> 319 320 \sa BMidiLocalConsumer::SystemCommon() 321*/ 322 323 324/*! 325 \fn void BMidiLocalProducer::SpraySystemRealTime(uchar status, 326 bigtime_t time = 0) const 327 \brief Sends a Real Time event to the connected consumers. 328 329 The status byte must be one of the following: 330 <table border="1"> 331 <tr><td>0xf8</td><td>\c B_TIMING_CLOCK</td></tr> 332 <tr><td>0xfa</td><td>\c B_START</td></tr> 333 <tr><td>0xfb</td><td>\c B_CONTINUE</td></tr> 334 <tr><td>0xfc</td><td>\c B_STOP</td></tr> 335 <tr><td>0xfe</td><td>\c B_ACTIVE_SENSING</td></tr> 336 <tr><td>0xff</td><td>\c B_SYSTEM_RESET</td></tr> 337 </table> 338 339 Because of their high priority, the MIDI specification allows real time 340 messages to "interleave" with other MIDI messages. A large sysex dump, for 341 example, may be interrupted by a real time event. The Midi Kit, however, 342 doesn't care. If you (or another producer) have just sent a big system 343 exclusive to a consumer, any following real time message will simply have 344 to wait until the consumer has dealt with the sysex. 345 346 \sa BMidiLocalConsumer::SystemRealTime() 347*/ 348 349 350/*! 351 \fn void BMidiLocalProducer::SprayTempoChange(int32 bpm, 352 bigtime_t time = 0) const 353 \brief Sends a Tempo Change event to the connected consumers. 354 355 This kind of Tempo Change event is not really part of the MIDI spec, 356 rather it is an extension from the SMF (Standard MIDI File) format. 357 358 \sa BMidiLocalConsumer::TempoChange() 359*/ 360