1 /* 2 * Copyright (c) 2002-2003 Matthijs Hollemans 3 * Copyright (c) 2002 Michael Pfeiffer 4 * Copyright (c) 2002 Jerome Leveque 5 * Copyright (c) 2002 Paul Stadler 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26 #include <List.h> 27 #include <MidiProducer.h> 28 29 #include "Midi.h" 30 #include "MidiGlue.h" 31 #include "debug.h" 32 33 //------------------------------------------------------------------------------ 34 35 status_t _run_thread(void* data) 36 { 37 BMidi* midi = (BMidi*) data; 38 midi->Run(); 39 midi->isRunning = false; 40 return 0; 41 } 42 43 //------------------------------------------------------------------------------ 44 45 BMidi::BMidi() 46 { 47 connections = new BList; 48 threadId = -1; 49 isRunning = false; 50 51 producer = new BMidiLocalProducer("MidiGlue(out)"); 52 consumer = new BMidiGlue(this, "MidiGlue(in)"); 53 } 54 55 //------------------------------------------------------------------------------ 56 57 BMidi::~BMidi() 58 { 59 Stop(); 60 61 status_t result; 62 wait_for_thread(threadId, &result); 63 64 producer->Release(); 65 consumer->Release(); 66 67 delete connections; 68 } 69 70 //------------------------------------------------------------------------------ 71 72 void BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time) 73 { 74 // do nothing 75 } 76 77 //------------------------------------------------------------------------------ 78 79 void BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time) 80 { 81 // do nothing 82 } 83 84 //------------------------------------------------------------------------------ 85 86 void BMidi::KeyPressure( 87 uchar channel, uchar note, uchar pressure, uint32 time) 88 { 89 // do nothing 90 } 91 92 //------------------------------------------------------------------------------ 93 94 void BMidi::ControlChange( 95 uchar channel, uchar controlNumber, uchar controlValue, uint32 time) 96 { 97 // do nothing 98 } 99 100 //------------------------------------------------------------------------------ 101 102 void BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time) 103 { 104 // do nothing 105 } 106 107 //------------------------------------------------------------------------------ 108 109 void BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time) 110 { 111 // do nothing 112 } 113 114 //------------------------------------------------------------------------------ 115 116 void BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time) 117 { 118 // do nothing 119 } 120 121 //------------------------------------------------------------------------------ 122 123 void BMidi::SystemExclusive(void* data, size_t length, uint32 time) 124 { 125 // do nothing 126 } 127 128 //------------------------------------------------------------------------------ 129 130 void BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time) 131 { 132 // do nothing 133 } 134 135 //------------------------------------------------------------------------------ 136 137 void BMidi::SystemRealTime(uchar status, uint32 time) 138 { 139 // do nothing 140 } 141 142 //------------------------------------------------------------------------------ 143 144 void BMidi::TempoChange(int32 beatsPerMinute, uint32 time) 145 { 146 // do nothing 147 } 148 149 //------------------------------------------------------------------------------ 150 151 void BMidi::AllNotesOff(bool justChannel, uint32 time) 152 { 153 for (uchar channel = 1; channel <= 16; ++channel) 154 { 155 SprayControlChange(channel, B_ALL_NOTES_OFF, 0, time); 156 157 if (!justChannel) 158 { 159 for (uchar note = 0; note <= 0x7F; ++note) 160 { 161 SprayNoteOff(channel, note, 0, time); 162 } 163 } 164 } 165 } 166 167 //------------------------------------------------------------------------------ 168 169 status_t BMidi::Start() 170 { 171 if (isRunning) { return B_OK; } 172 173 status_t err = spawn_thread( 174 _run_thread, "MidiRunThread", B_URGENT_PRIORITY, this); 175 176 if (err < B_OK) { return err; } 177 178 threadId = err; 179 isRunning = true; 180 181 err = resume_thread(threadId); 182 if (err != B_OK) 183 { 184 threadId = -1; 185 isRunning = false; 186 } 187 188 return err; 189 } 190 191 //------------------------------------------------------------------------------ 192 193 void BMidi::Stop() 194 { 195 threadId = -1; 196 } 197 198 //------------------------------------------------------------------------------ 199 200 bool BMidi::IsRunning() const 201 { 202 return isRunning; 203 } 204 205 //------------------------------------------------------------------------------ 206 207 void BMidi::Connect(BMidi* toObject) 208 { 209 if (toObject != NULL) 210 { 211 if (producer->Connect(toObject->consumer) == B_OK) 212 { 213 connections->AddItem(toObject); 214 } 215 } 216 } 217 218 //------------------------------------------------------------------------------ 219 220 void BMidi::Disconnect(BMidi* fromObject) 221 { 222 if (fromObject != NULL) 223 { 224 if (producer->Disconnect(fromObject->consumer) == B_OK) 225 { 226 connections->RemoveItem(fromObject); 227 } 228 } 229 } 230 231 //------------------------------------------------------------------------------ 232 233 bool BMidi::IsConnected(BMidi* toObject) const 234 { 235 if (toObject != NULL) 236 { 237 return producer->IsConnected(toObject->consumer); 238 } 239 240 return false; 241 } 242 243 //------------------------------------------------------------------------------ 244 245 BList* BMidi::Connections() const 246 { 247 return connections; 248 } 249 250 //------------------------------------------------------------------------------ 251 252 void BMidi::SnoozeUntil(uint32 time) const 253 { 254 snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE); 255 } 256 257 //------------------------------------------------------------------------------ 258 259 bool BMidi::KeepRunning() 260 { 261 return (threadId != -1); 262 } 263 264 //------------------------------------------------------------------------------ 265 266 void BMidi::_ReservedMidi1() {} 267 void BMidi::_ReservedMidi2() {} 268 void BMidi::_ReservedMidi3() {} 269 270 //------------------------------------------------------------------------------ 271 272 void BMidi::Run() 273 { 274 // do nothing 275 } 276 277 //------------------------------------------------------------------------------ 278 279 void BMidi::SprayNoteOff( 280 uchar channel, uchar note, uchar velocity, uint32 time) const 281 { 282 producer->SprayNoteOff( 283 channel - 1, note, velocity, MAKE_BIGTIME(time)); 284 } 285 286 //------------------------------------------------------------------------------ 287 288 void BMidi::SprayNoteOn( 289 uchar channel, uchar note, uchar velocity, uint32 time) const 290 { 291 producer->SprayNoteOn( 292 channel - 1, note, velocity, MAKE_BIGTIME(time)); 293 } 294 295 //------------------------------------------------------------------------------ 296 297 void BMidi::SprayKeyPressure( 298 uchar channel, uchar note, uchar pressure, uint32 time) const 299 { 300 producer->SprayKeyPressure( 301 channel - 1, note, pressure, MAKE_BIGTIME(time)); 302 } 303 304 //------------------------------------------------------------------------------ 305 306 void BMidi::SprayControlChange( 307 uchar channel, uchar controlNumber, uchar controlValue, 308 uint32 time) const 309 { 310 producer->SprayControlChange( 311 channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time)); 312 } 313 314 //------------------------------------------------------------------------------ 315 316 void BMidi::SprayProgramChange( 317 uchar channel, uchar programNumber, uint32 time) const 318 { 319 producer->SprayProgramChange( 320 channel - 1, programNumber, MAKE_BIGTIME(time)); 321 } 322 323 //------------------------------------------------------------------------------ 324 325 void BMidi::SprayChannelPressure( 326 uchar channel, uchar pressure, uint32 time) const 327 { 328 producer->SprayChannelPressure( 329 channel - 1, pressure, MAKE_BIGTIME(time)); 330 } 331 332 //------------------------------------------------------------------------------ 333 334 void BMidi::SprayPitchBend( 335 uchar channel, uchar lsb, uchar msb, uint32 time) const 336 { 337 producer->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time)); 338 } 339 340 //------------------------------------------------------------------------------ 341 342 void BMidi::SpraySystemExclusive( 343 void* data, size_t length, uint32 time) const 344 { 345 producer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time)); 346 } 347 348 //------------------------------------------------------------------------------ 349 350 void BMidi::SpraySystemCommon( 351 uchar status, uchar data1, uchar data2, uint32 time) const 352 { 353 producer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time)); 354 } 355 356 //------------------------------------------------------------------------------ 357 358 void BMidi::SpraySystemRealTime(uchar status, uint32 time) const 359 { 360 producer->SpraySystemRealTime(status, MAKE_BIGTIME(time)); 361 } 362 363 //------------------------------------------------------------------------------ 364 365 void BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const 366 { 367 producer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time)); 368 } 369 370 //------------------------------------------------------------------------------ 371