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