1 /* 2 * Copyright 2002-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * 7 * Matthijs Hollemans 8 * Michael Pfeiffer 9 * Jérôme Leveque 10 * Paul Stadler 11 */ 12 13 #include <List.h> 14 #include <Midi.h> 15 #include <MidiProducer.h> 16 17 #include "MidiGlue.h" 18 #include "debug.h" 19 20 using namespace BPrivate; 21 22 23 status_t 24 _run_thread(void* data) 25 { 26 BMidi* midi = (BMidi*) data; 27 midi->Run(); 28 midi->fIsRunning = false; 29 return 0; 30 } 31 32 33 BMidi::BMidi() 34 { 35 fConnections = new BList; 36 fThreadId = -1; 37 fIsRunning = false; 38 39 fProducer = new BMidiLocalProducer("MidiGlue(out)"); 40 fConsumer = new BMidiGlue(this, "MidiGlue(in)"); 41 } 42 43 44 BMidi::~BMidi() 45 { 46 Stop(); 47 48 status_t result; 49 wait_for_thread(fThreadId, &result); 50 51 fProducer->Release(); 52 fConsumer->Release(); 53 54 delete fConnections; 55 } 56 57 58 void 59 BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time) 60 { 61 // do nothing 62 } 63 64 65 void 66 BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time) 67 { 68 // do nothing 69 } 70 71 72 void 73 BMidi::KeyPressure( 74 uchar channel, uchar note, uchar pressure, uint32 time) 75 { 76 // do nothing 77 } 78 79 80 void 81 BMidi::ControlChange( 82 uchar channel, uchar controlNumber, uchar controlValue, uint32 time) 83 { 84 // do nothing 85 } 86 87 88 void 89 BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time) 90 { 91 // do nothing 92 } 93 94 95 void 96 BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time) 97 { 98 // do nothing 99 } 100 101 102 void 103 BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time) 104 { 105 // do nothing 106 } 107 108 109 void 110 BMidi::SystemExclusive(void* data, size_t length, uint32 time) 111 { 112 // do nothing 113 } 114 115 116 void 117 BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time) 118 { 119 // do nothing 120 } 121 122 123 void 124 BMidi::SystemRealTime(uchar status, uint32 time) 125 { 126 // do nothing 127 } 128 129 130 void 131 BMidi::TempoChange(int32 beatsPerMinute, uint32 time) 132 { 133 // do nothing 134 } 135 136 137 void 138 BMidi::AllNotesOff(bool justChannel, uint32 time) 139 { 140 for (uchar channel = 1; channel <= 16; ++channel) { 141 SprayControlChange(channel, B_ALL_NOTES_OFF, 0, time); 142 143 if (!justChannel) { 144 for (uchar note = 0; note <= 0x7F; ++note) { 145 SprayNoteOff(channel, note, 0, time); 146 } 147 } 148 } 149 } 150 151 152 status_t 153 BMidi::Start() 154 { 155 if (fIsRunning) 156 return B_OK; 157 158 status_t err = spawn_thread( 159 _run_thread, "MidiRunThread", B_URGENT_PRIORITY, this); 160 161 if (err < B_OK) 162 return err; 163 164 fThreadId = err; 165 fIsRunning = true; 166 167 err = resume_thread(fThreadId); 168 if (err != B_OK) { 169 fThreadId = -1; 170 fIsRunning = false; 171 } 172 173 return err; 174 } 175 176 177 void 178 BMidi::Stop() 179 { 180 fThreadId = -1; 181 } 182 183 184 bool 185 BMidi::IsRunning() const 186 { 187 return fIsRunning; 188 } 189 190 191 void 192 BMidi::Connect(BMidi* toObject) 193 { 194 if (toObject != NULL) { 195 if (fProducer->Connect(toObject->fConsumer) == B_OK) { 196 fConnections->AddItem(toObject); 197 } 198 } 199 } 200 201 202 void 203 BMidi::Disconnect(BMidi* fromObject) 204 { 205 if (fromObject == NULL) 206 return; 207 208 if (fProducer->Disconnect(fromObject->fConsumer) == B_OK) { 209 fConnections->RemoveItem(fromObject); 210 } 211 } 212 213 214 bool 215 BMidi::IsConnected(BMidi* toObject) const 216 { 217 if (toObject != NULL) 218 return fProducer->IsConnected(toObject->fConsumer); 219 220 return false; 221 } 222 223 224 BList* 225 BMidi::Connections() const 226 { 227 return fConnections; 228 } 229 230 231 void 232 BMidi::SnoozeUntil(uint32 time) const 233 { 234 snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE); 235 } 236 237 238 bool 239 BMidi::KeepRunning() 240 { 241 return (fThreadId != -1); 242 } 243 244 245 void BMidi::_ReservedMidi1() {} 246 void BMidi::_ReservedMidi2() {} 247 void BMidi::_ReservedMidi3() {} 248 249 250 void 251 BMidi::Run() 252 { 253 // do nothing 254 } 255 256 257 void 258 BMidi::SprayNoteOff( 259 uchar channel, uchar note, uchar velocity, uint32 time) const 260 { 261 fProducer->SprayNoteOff( 262 channel - 1, note, velocity, MAKE_BIGTIME(time)); 263 } 264 265 266 void 267 BMidi::SprayNoteOn( 268 uchar channel, uchar note, uchar velocity, uint32 time) const 269 { 270 fProducer->SprayNoteOn( 271 channel - 1, note, velocity, MAKE_BIGTIME(time)); 272 } 273 274 275 void 276 BMidi::SprayKeyPressure( 277 uchar channel, uchar note, uchar pressure, uint32 time) const 278 { 279 fProducer->SprayKeyPressure( 280 channel - 1, note, pressure, MAKE_BIGTIME(time)); 281 } 282 283 284 void 285 BMidi::SprayControlChange( 286 uchar channel, uchar controlNumber, uchar controlValue, 287 uint32 time) const 288 { 289 fProducer->SprayControlChange( 290 channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time)); 291 } 292 293 294 void 295 BMidi::SprayProgramChange( 296 uchar channel, uchar programNumber, uint32 time) const 297 { 298 fProducer->SprayProgramChange( 299 channel - 1, programNumber, MAKE_BIGTIME(time)); 300 } 301 302 303 void 304 BMidi::SprayChannelPressure( 305 uchar channel, uchar pressure, uint32 time) const 306 { 307 fProducer->SprayChannelPressure( 308 channel - 1, pressure, MAKE_BIGTIME(time)); 309 } 310 311 312 void 313 BMidi::SprayPitchBend( 314 uchar channel, uchar lsb, uchar msb, uint32 time) const 315 { 316 fProducer->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time)); 317 } 318 319 320 void 321 BMidi::SpraySystemExclusive( 322 void* data, size_t length, uint32 time) const 323 { 324 fProducer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time)); 325 } 326 327 328 void 329 BMidi::SpraySystemCommon( 330 uchar status, uchar data1, uchar data2, uint32 time) const 331 { 332 fProducer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time)); 333 } 334 335 336 void 337 BMidi::SpraySystemRealTime(uchar status, uint32 time) const 338 { 339 fProducer->SpraySystemRealTime(status, MAKE_BIGTIME(time)); 340 } 341 342 343 void 344 BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const 345 { 346 fProducer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time)); 347 } 348 349