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