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 21using namespace BPrivate; 22 23 24BMidiPort::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 45BMidiPort::~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 59status_t 60BMidiPort::InitCheck() const 61{ 62 return fStatus; 63} 64 65 66status_t 67BMidiPort::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 104void 105BMidiPort::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 124const char* 125BMidiPort::PortName() const 126{ 127 return fPortName; 128} 129 130 131void 132BMidiPort::NoteOff( 133 uchar channel, uchar note, uchar velocity, uint32 time) 134{ 135 fLocalSource->SprayNoteOff(channel - 1, note, velocity, MAKE_BIGTIME(time)); 136} 137 138 139void 140BMidiPort::NoteOn( 141 uchar channel, uchar note, uchar velocity, uint32 time) 142{ 143 fLocalSource->SprayNoteOn(channel - 1, note, velocity, MAKE_BIGTIME(time)); 144} 145 146 147void 148BMidiPort::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 156void 157BMidiPort::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 165void 166BMidiPort::ProgramChange( 167 uchar channel, uchar programNumber, uint32 time) 168{ 169 fLocalSource->SprayProgramChange( 170 channel - 1, programNumber, MAKE_BIGTIME(time)); 171} 172 173 174void 175BMidiPort::ChannelPressure(uchar channel, uchar pressure, uint32 time) 176{ 177 fLocalSource->SprayChannelPressure( 178 channel - 1, pressure, MAKE_BIGTIME(time)); 179} 180 181 182void 183BMidiPort::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time) 184{ 185 fLocalSource->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time)); 186} 187 188 189void 190BMidiPort::SystemExclusive(void* data, size_t length, uint32 time) 191{ 192 fLocalSource->SpraySystemExclusive(data, length, MAKE_BIGTIME(time)); 193} 194 195 196void 197BMidiPort::SystemCommon( 198 uchar status, uchar data1, uchar data2, uint32 time) 199{ 200 fLocalSource->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time)); 201} 202 203 204void 205BMidiPort::SystemRealTime(uchar status, uint32 time) 206{ 207 fLocalSource->SpraySystemRealTime(status, MAKE_BIGTIME(time)); 208} 209 210 211status_t 212BMidiPort::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 224void 225BMidiPort::Stop() 226{ 227 if (fRemoteSource != NULL) { 228 fRemoteSource->Disconnect(fLocalSink); 229 } 230 231 super::Stop(); 232} 233 234 235int32 236BMidiPort::CountDevices() 237{ 238 return fDevices->CountItems(); 239} 240 241 242status_t 243BMidiPort::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 258void BMidiPort::_ReservedMidiPort1() { } 259void BMidiPort::_ReservedMidiPort2() { } 260void BMidiPort::_ReservedMidiPort3() { } 261 262 263void 264BMidiPort::Run() 265{ 266 while (KeepRunning()) 267 snooze(50000); 268} 269 270 271void 272BMidiPort::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 301void 302BMidiPort::EmptyDeviceList() 303{ 304 for (int32 t = 0; t < fDevices->CountItems(); ++t) 305 ((BMidiEndpoint*)fDevices->ItemAt(t))->Release(); 306 307 fDevices->MakeEmpty(); 308} 309 310