1 /* 2 * Copyright 2006, Haiku. 3 * 4 * Copyright (c) 2002-2003 Matthijs Hollemans 5 * Copyright (c) 2002 Jerome Leveque 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Matthijs Hollemans 10 * Jérôme Leveque 11 */ 12 13 #include <MidiPort.h> 14 #include <MidiProducer.h> 15 #include <MidiRoster.h> 16 #include <stdlib.h> 17 18 #include "debug.h" 19 #include "MidiGlue.h" 20 21 using namespace BPrivate; 22 23 24 BMidiPort::BMidiPort(const char* name) 25 { 26 fPortName = NULL; 27 fDevices = new BList; 28 fStatus = B_ERROR; 29 30 fLocalSource = new BMidiLocalProducer("MidiPortGlue(out)"); 31 fLocalSink = new BMidiPortGlue(this, "MidiPortGlue(in)"); 32 33 fRemoteSource = NULL; 34 fRemoteSink = NULL; 35 36 ScanDevices(); 37 38 if (name != NULL) 39 Open(name); 40 } 41 42 43 BMidiPort::~BMidiPort() 44 { 45 Close(); 46 47 EmptyDeviceList(); 48 delete fDevices; 49 50 fLocalSource->Release(); 51 fLocalSink->Release(); 52 } 53 54 55 status_t 56 BMidiPort::InitCheck() const 57 { 58 return fStatus; 59 } 60 61 62 status_t 63 BMidiPort::Open(const char* name) 64 { 65 fStatus = B_ERROR; 66 67 if (name != NULL) { 68 Close(); 69 70 for (int32 t = 0; t < fDevices->CountItems(); ++t) { 71 BMidiEndpoint* endp = (BMidiEndpoint*) fDevices->ItemAt(t); 72 if (strcmp(name, endp->Name()) != 0) 73 continue; 74 if (!endp->IsValid()) // still exists? 75 continue; 76 if (endp->IsProducer()) { 77 if (fRemoteSource == NULL) 78 fRemoteSource = (BMidiProducer*) endp; 79 } else { 80 if (fRemoteSink == NULL) { 81 fRemoteSink = (BMidiConsumer*) endp; 82 fLocalSource->Connect(fRemoteSink); 83 } 84 } 85 } 86 87 if (fRemoteSource != NULL) { 88 fPortName = strdup(fRemoteSource->Name()); 89 fStatus = B_OK; 90 } else if (fRemoteSink != NULL) { 91 fPortName = strdup(fRemoteSink->Name()); 92 fStatus = B_OK; 93 } 94 } 95 96 return fStatus; 97 } 98 99 100 void 101 BMidiPort::Close() 102 { 103 if (fRemoteSource != NULL) { 104 fRemoteSource->Disconnect(fLocalSink); 105 fRemoteSource = NULL; 106 } 107 108 if (fRemoteSink != NULL) { 109 fLocalSource->Disconnect(fRemoteSink); 110 fRemoteSink = NULL; 111 } 112 113 if (fPortName != NULL) { 114 free(fPortName); 115 fPortName = NULL; 116 } 117 } 118 119 120 const char* 121 BMidiPort::PortName() const 122 { 123 return fPortName; 124 } 125 126 127 void 128 BMidiPort::NoteOff( 129 uchar channel, uchar note, uchar velocity, uint32 time) 130 { 131 fLocalSource->SprayNoteOff(channel - 1, note, velocity, MAKE_BIGTIME(time)); 132 } 133 134 135 void 136 BMidiPort::NoteOn( 137 uchar channel, uchar note, uchar velocity, uint32 time) 138 { 139 fLocalSource->SprayNoteOn(channel - 1, note, velocity, MAKE_BIGTIME(time)); 140 } 141 142 143 void 144 BMidiPort::KeyPressure( 145 uchar channel, uchar note, uchar pressure, uint32 time) 146 { 147 fLocalSource->SprayKeyPressure( 148 channel - 1, note, pressure, MAKE_BIGTIME(time)); 149 } 150 151 152 void 153 BMidiPort::ControlChange( 154 uchar channel, uchar controlNumber, uchar controlValue, uint32 time) 155 { 156 fLocalSource->SprayControlChange( 157 channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time)); 158 } 159 160 161 void 162 BMidiPort::ProgramChange( 163 uchar channel, uchar programNumber, uint32 time) 164 { 165 fLocalSource->SprayProgramChange( 166 channel - 1, programNumber, MAKE_BIGTIME(time)); 167 } 168 169 170 void 171 BMidiPort::ChannelPressure(uchar channel, uchar pressure, uint32 time) 172 { 173 fLocalSource->SprayChannelPressure( 174 channel - 1, pressure, MAKE_BIGTIME(time)); 175 } 176 177 178 void 179 BMidiPort::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time) 180 { 181 fLocalSource->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time)); 182 } 183 184 185 void 186 BMidiPort::SystemExclusive(void* data, size_t length, uint32 time) 187 { 188 fLocalSource->SpraySystemExclusive(data, length, MAKE_BIGTIME(time)); 189 } 190 191 192 void 193 BMidiPort::SystemCommon( 194 uchar status, uchar data1, uchar data2, uint32 time) 195 { 196 fLocalSource->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time)); 197 } 198 199 200 void 201 BMidiPort::SystemRealTime(uchar status, uint32 time) 202 { 203 fLocalSource->SpraySystemRealTime(status, MAKE_BIGTIME(time)); 204 } 205 206 207 status_t 208 BMidiPort::Start() 209 { 210 status_t err = super::Start(); 211 212 if ((err == B_OK) && (fRemoteSource != NULL)) { 213 return fRemoteSource->Connect(fLocalSink); 214 } 215 216 return err; 217 } 218 219 220 void 221 BMidiPort::Stop() 222 { 223 if (fRemoteSource != NULL) { 224 fRemoteSource->Disconnect(fLocalSink); 225 } 226 227 super::Stop(); 228 } 229 230 231 int32 232 BMidiPort::CountDevices() 233 { 234 return fDevices->CountItems(); 235 } 236 237 238 status_t 239 BMidiPort::GetDeviceName(int32 n, char* name, size_t bufSize) 240 { 241 BMidiEndpoint* endp = (BMidiEndpoint*) fDevices->ItemAt(n); 242 if (endp == NULL) 243 return B_BAD_VALUE; 244 245 size_t size = strlen(endp->Name()); 246 if (size >= bufSize) 247 return B_NAME_TOO_LONG; 248 249 strcpy(name, endp->Name()); 250 return B_OK; 251 } 252 253 254 void BMidiPort::_ReservedMidiPort1() { } 255 void BMidiPort::_ReservedMidiPort2() { } 256 void BMidiPort::_ReservedMidiPort3() { } 257 258 259 void 260 BMidiPort::Run() 261 { 262 while (KeepRunning()) 263 snooze(50000); 264 } 265 266 267 void 268 BMidiPort::ScanDevices() 269 { 270 EmptyDeviceList(); 271 272 int32 id = 0; 273 BMidiEndpoint* endp; 274 275 while ((endp = BMidiRoster::NextEndpoint(&id)) != NULL) { 276 // Each hardware port has two endpoints associated with it, a consumer 277 // and a producer. Both have the same name, so we add only one of them. 278 279 bool addItem = true; 280 for (int32 t = 0; t < fDevices->CountItems(); ++t) { 281 BMidiEndpoint* other = (BMidiEndpoint*) fDevices->ItemAt(t); 282 if (strcmp(endp->Name(), other->Name()) == 0) { 283 addItem = false; 284 break; 285 } 286 } 287 288 if (addItem) { 289 fDevices->AddItem(endp); 290 } else { 291 endp->Release(); 292 } 293 } 294 } 295 296 297 void 298 BMidiPort::EmptyDeviceList() 299 { 300 for (int32 t = 0; t < fDevices->CountItems(); ++t) 301 ((BMidiEndpoint*) fDevices->ItemAt(t))->Release(); 302 303 fDevices->MakeEmpty(); 304 } 305 306