1 /* 2 * Copyright 2006, Haiku. 3 * 4 * Copyright (c) 2002-2003 Matthijs Hollemans 5 * Distributed under the terms of the MIT License. 6 * 7 * Authors: 8 * Matthijs Hollemans 9 */ 10 11 #include "debug.h" 12 #include <MidiConsumer.h> 13 #include <MidiProducer.h> 14 #include <MidiRoster.h> 15 #include "MidiRosterLooper.h" 16 #include "protocol.h" 17 18 19 status_t 20 BMidiProducer::Connect(BMidiConsumer* cons) 21 { 22 if (cons == NULL) { 23 WARN("Connect() does not accept a NULL consumer") 24 return B_BAD_VALUE; 25 } 26 if (!IsValid() || !cons->IsValid()) { 27 return B_ERROR; 28 } 29 return SendConnectRequest(cons, true); 30 } 31 32 33 status_t 34 BMidiProducer::Disconnect(BMidiConsumer* cons) 35 { 36 if (cons == NULL) { 37 WARN("Disconnect() does not accept a NULL consumer") 38 return B_BAD_VALUE; 39 } 40 if (!IsValid() || !cons->IsValid()) { 41 return B_ERROR; 42 } 43 return SendConnectRequest(cons, false); 44 } 45 46 47 bool 48 BMidiProducer::IsConnected(BMidiConsumer* cons) const 49 { 50 bool isConnected = false; 51 52 if (cons != NULL) { 53 if (LockProducer()) { 54 isConnected = fConnections->HasItem(cons); 55 UnlockProducer(); 56 } 57 } 58 59 return isConnected; 60 } 61 62 63 BList* 64 BMidiProducer::Connections() const 65 { 66 BList* list = new BList(); 67 68 if (LockProducer()) { 69 for (int32 t = 0; t < CountConsumers(); ++t) { 70 BMidiConsumer* cons = ConsumerAt(t); 71 cons->Acquire(); 72 list->AddItem(cons); 73 } 74 75 UnlockProducer(); 76 } 77 78 return list; 79 } 80 81 82 BMidiProducer::BMidiProducer(const char* name) 83 : BMidiEndpoint(name), 84 fLocker("MidiProducerLock") 85 { 86 fIsConsumer = false; 87 fConnections = new BList(); 88 } 89 90 91 BMidiProducer::~BMidiProducer() 92 { 93 delete fConnections; 94 } 95 96 97 void BMidiProducer::_Reserved1() { } 98 void BMidiProducer::_Reserved2() { } 99 void BMidiProducer::_Reserved3() { } 100 void BMidiProducer::_Reserved4() { } 101 void BMidiProducer::_Reserved5() { } 102 void BMidiProducer::_Reserved6() { } 103 void BMidiProducer::_Reserved7() { } 104 void BMidiProducer::_Reserved8() { } 105 106 107 status_t 108 BMidiProducer::SendConnectRequest( 109 BMidiConsumer* cons, bool mustConnect) 110 { 111 ASSERT(cons != NULL) 112 113 BMessage msg, reply; 114 115 if (mustConnect) { 116 msg.what = MSG_CONNECT_ENDPOINTS; 117 } else { 118 msg.what = MSG_DISCONNECT_ENDPOINTS; 119 } 120 121 msg.AddInt32("midi:producer", ID()); 122 msg.AddInt32("midi:consumer", cons->ID()); 123 124 status_t err = BMidiRoster::MidiRoster()->SendRequest(&msg, &reply); 125 if (err != B_OK) 126 return err; 127 128 status_t res; 129 if (reply.FindInt32("midi:result", &res) == B_OK) { 130 if (res == B_OK) { 131 if (mustConnect) { 132 ConnectionMade(cons); 133 } else { 134 ConnectionBroken(cons); 135 } 136 137 #ifdef DEBUG 138 BMidiRoster::MidiRoster()->fLooper->DumpEndpoints(); 139 #endif 140 } 141 142 return res; 143 } 144 145 return B_ERROR; 146 } 147 148 149 void 150 BMidiProducer::ConnectionMade(BMidiConsumer* consumer) 151 { 152 if (consumer == NULL) 153 return; 154 155 if (LockProducer()) { 156 ASSERT(!fConnections->HasItem(consumer)) 157 158 fConnections->AddItem(consumer); 159 UnlockProducer(); 160 } 161 162 if (IsLocal()) { 163 ((BMidiLocalProducer*) this)->Connected(consumer); 164 } 165 } 166 167 168 bool 169 BMidiProducer::ConnectionBroken(BMidiConsumer* consumer) 170 { 171 if (consumer == NULL) 172 return false; 173 174 bool wasConnected = false; 175 176 if (LockProducer()) { 177 wasConnected = fConnections->RemoveItem(consumer); 178 UnlockProducer(); 179 } 180 181 if (wasConnected && IsLocal()) { 182 ((BMidiLocalProducer*) this)->Disconnected(consumer); 183 } 184 185 return wasConnected; 186 } 187 188 189 int32 190 BMidiProducer::CountConsumers() const 191 { 192 return fConnections->CountItems(); 193 } 194 195 196 BMidiConsumer* 197 BMidiProducer::ConsumerAt(int32 index) const 198 { 199 ASSERT(index >= 0 && index < CountConsumers()) 200 201 return (BMidiConsumer*) fConnections->ItemAt(index); 202 } 203 204 205 bool 206 BMidiProducer::LockProducer() const 207 { 208 return fLocker.Lock(); 209 } 210 211 212 void 213 BMidiProducer::UnlockProducer() const 214 { 215 fLocker.Unlock(); 216 } 217 218