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 using namespace BPrivate; 33 34 //------------------------------------------------------------------------------ 35 36 BMidiPort::BMidiPort(const char* name) 37 { 38 portName = NULL; 39 devices = new BList; 40 status = B_ERROR; 41 42 localSource = new BMidiLocalProducer("MidiPortGlue(out)"); 43 localSink = new BMidiPortGlue(this, "MidiPortGlue(in)"); 44 45 remoteSource = NULL; 46 remoteSink = NULL; 47 48 ScanDevices(); 49 50 if (name != NULL) 51 { 52 Open(name); 53 } 54 } 55 56 //------------------------------------------------------------------------------ 57 58 BMidiPort::~BMidiPort() 59 { 60 Close(); 61 62 EmptyDeviceList(); 63 delete devices; 64 65 localSource->Release(); 66 localSink->Release(); 67 } 68 69 //------------------------------------------------------------------------------ 70 71 status_t BMidiPort::InitCheck() const 72 { 73 return status; 74 } 75 76 //------------------------------------------------------------------------------ 77 78 status_t BMidiPort::Open(const char* name) 79 { 80 status = B_ERROR; 81 82 if (name != NULL) 83 { 84 Close(); 85 86 for (int32 t = 0; t < devices->CountItems(); ++t) 87 { 88 BMidiEndpoint* endp = (BMidiEndpoint*) devices->ItemAt(t); 89 if (strcmp(name, endp->Name()) == 0) 90 { 91 if (endp->IsValid()) // still exists? 92 { 93 if (endp->IsProducer()) 94 { 95 if (remoteSource == NULL) 96 { 97 remoteSource = (BMidiProducer*) endp; 98 } 99 } 100 else if (endp->IsConsumer()) 101 { 102 if (remoteSink == NULL) 103 { 104 remoteSink = (BMidiConsumer*) endp; 105 localSource->Connect(remoteSink); 106 } 107 } 108 } 109 } 110 } 111 112 if (remoteSource != NULL) 113 { 114 portName = strdup(remoteSource->Name()); 115 status = B_OK; 116 } 117 else if (remoteSink != NULL) 118 { 119 portName = strdup(remoteSink->Name()); 120 status = B_OK; 121 } 122 } 123 124 return status; 125 } 126 127 //------------------------------------------------------------------------------ 128 129 void BMidiPort::Close() 130 { 131 if (remoteSource != NULL) 132 { 133 remoteSource->Disconnect(localSink); 134 remoteSource = NULL; 135 } 136 137 if (remoteSink != NULL) 138 { 139 localSource->Disconnect(remoteSink); 140 remoteSink = NULL; 141 } 142 143 if (portName != NULL) 144 { 145 free(portName); 146 portName = NULL; 147 } 148 } 149 150 //------------------------------------------------------------------------------ 151 152 const char* BMidiPort::PortName() const 153 { 154 return portName; 155 } 156 157 //------------------------------------------------------------------------------ 158 159 void BMidiPort::NoteOff( 160 uchar channel, uchar note, uchar velocity, uint32 time) 161 { 162 localSource->SprayNoteOff(channel - 1, note, velocity, MAKE_BIGTIME(time)); 163 } 164 165 //------------------------------------------------------------------------------ 166 167 void BMidiPort::NoteOn( 168 uchar channel, uchar note, uchar velocity, uint32 time) 169 { 170 localSource->SprayNoteOn(channel - 1, note, velocity, MAKE_BIGTIME(time)); 171 } 172 173 //------------------------------------------------------------------------------ 174 175 void BMidiPort::KeyPressure( 176 uchar channel, uchar note, uchar pressure, uint32 time) 177 { 178 localSource->SprayKeyPressure( 179 channel - 1, note, pressure, MAKE_BIGTIME(time)); 180 } 181 182 //------------------------------------------------------------------------------ 183 184 void BMidiPort::ControlChange( 185 uchar channel, uchar controlNumber, uchar controlValue, uint32 time) 186 { 187 localSource->SprayControlChange( 188 channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time)); 189 } 190 191 //------------------------------------------------------------------------------ 192 193 void BMidiPort::ProgramChange( 194 uchar channel, uchar programNumber, uint32 time) 195 { 196 localSource->SprayProgramChange( 197 channel - 1, programNumber, MAKE_BIGTIME(time)); 198 } 199 200 //------------------------------------------------------------------------------ 201 202 void BMidiPort::ChannelPressure(uchar channel, uchar pressure, uint32 time) 203 { 204 localSource->SprayChannelPressure( 205 channel - 1, pressure, MAKE_BIGTIME(time)); 206 } 207 208 //------------------------------------------------------------------------------ 209 210 void BMidiPort::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time) 211 { 212 localSource->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time)); 213 } 214 215 //------------------------------------------------------------------------------ 216 217 void BMidiPort::SystemExclusive(void* data, size_t length, uint32 time) 218 { 219 localSource->SpraySystemExclusive(data, length, MAKE_BIGTIME(time)); 220 } 221 222 //------------------------------------------------------------------------------ 223 224 void BMidiPort::SystemCommon( 225 uchar status, uchar data1, uchar data2, uint32 time) 226 { 227 localSource->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time)); 228 } 229 230 //------------------------------------------------------------------------------ 231 232 void BMidiPort::SystemRealTime(uchar status, uint32 time) 233 { 234 localSource->SpraySystemRealTime(status, MAKE_BIGTIME(time)); 235 } 236 237 //------------------------------------------------------------------------------ 238 239 status_t BMidiPort::Start() 240 { 241 status_t err = super::Start(); 242 243 if ((err == B_OK) && (remoteSource != NULL)) 244 { 245 return remoteSource->Connect(localSink); 246 } 247 248 return err; 249 } 250 251 //------------------------------------------------------------------------------ 252 253 void BMidiPort::Stop() 254 { 255 if (remoteSource != NULL) 256 { 257 remoteSource->Disconnect(localSink); 258 } 259 260 super::Stop(); 261 } 262 263 //------------------------------------------------------------------------------ 264 265 int32 BMidiPort::CountDevices() 266 { 267 return devices->CountItems(); 268 } 269 270 //------------------------------------------------------------------------------ 271 272 status_t BMidiPort::GetDeviceName(int32 n, char* name, size_t bufSize) 273 { 274 BMidiEndpoint* endp = (BMidiEndpoint*) devices->ItemAt(n); 275 if (endp == NULL) 276 { 277 return B_BAD_VALUE; 278 } 279 280 size_t size = strlen(endp->Name()); 281 if (size >= bufSize) 282 { 283 return B_NAME_TOO_LONG; 284 } 285 286 strcpy(name, endp->Name()); 287 return B_OK; 288 } 289 290 //------------------------------------------------------------------------------ 291 292 void BMidiPort::_ReservedMidiPort1() { } 293 void BMidiPort::_ReservedMidiPort2() { } 294 void BMidiPort::_ReservedMidiPort3() { } 295 296 //------------------------------------------------------------------------------ 297 298 void BMidiPort::Run() 299 { 300 while (KeepRunning()) 301 { 302 snooze(50000); 303 } 304 } 305 306 //------------------------------------------------------------------------------ 307 308 void BMidiPort::ScanDevices() 309 { 310 EmptyDeviceList(); 311 312 int32 id = 0; 313 BMidiEndpoint* endp; 314 315 while ((endp = BMidiRoster::NextEndpoint(&id)) != NULL) 316 { 317 // Each hardware port has two endpoints associated with it, a consumer 318 // and a producer. Both have the same name, so we add only one of them. 319 320 bool addItem = true; 321 for (int32 t = 0; t < devices->CountItems(); ++t) 322 { 323 BMidiEndpoint* other = (BMidiEndpoint*) devices->ItemAt(t); 324 if (strcmp(endp->Name(), other->Name()) == 0) 325 { 326 addItem = false; 327 break; 328 } 329 } 330 331 if (addItem) 332 { 333 devices->AddItem(endp); 334 } 335 else 336 { 337 endp->Release(); 338 } 339 } 340 } 341 342 //------------------------------------------------------------------------------ 343 344 void BMidiPort::EmptyDeviceList() 345 { 346 for (int32 t = 0; t < devices->CountItems(); ++t) 347 { 348 ((BMidiEndpoint*) devices->ItemAt(t))->Release(); 349 } 350 351 devices->MakeEmpty(); 352 } 353 354 //------------------------------------------------------------------------------ 355