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