1 /* 2 * Copyright (c) 2002-2003 Matthijs Hollemans 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 23 #include "debug.h" 24 #include "MidiConsumer.h" 25 #include "MidiProducer.h" 26 #include "MidiRoster.h" 27 #include "MidiRosterLooper.h" 28 #include "protocol.h" 29 30 //------------------------------------------------------------------------------ 31 32 status_t BMidiProducer::Connect(BMidiConsumer* cons) 33 { 34 if (cons == NULL) 35 { 36 WARN("Connect() does not accept a NULL consumer") 37 return B_BAD_VALUE; 38 } 39 else if (!IsValid() || !cons->IsValid()) 40 { 41 return B_ERROR; 42 } 43 else 44 { 45 return SendConnectRequest(cons, true); 46 } 47 } 48 49 //------------------------------------------------------------------------------ 50 51 status_t BMidiProducer::Disconnect(BMidiConsumer* cons) 52 { 53 if (cons == NULL) 54 { 55 WARN("Disconnect() does not accept a NULL consumer") 56 return B_BAD_VALUE; 57 } 58 else if (!IsValid() || !cons->IsValid()) 59 { 60 return B_ERROR; 61 } 62 else 63 { 64 return SendConnectRequest(cons, false); 65 } 66 } 67 68 //------------------------------------------------------------------------------ 69 70 bool BMidiProducer::IsConnected(BMidiConsumer* cons) const 71 { 72 bool isConnected = false; 73 74 if (cons != NULL) 75 { 76 if (LockProducer()) 77 { 78 isConnected = connections->HasItem(cons); 79 UnlockProducer(); 80 } 81 } 82 83 return isConnected; 84 } 85 86 //------------------------------------------------------------------------------ 87 88 BList* BMidiProducer::Connections() const 89 { 90 BList* list = new BList(); 91 92 if (LockProducer()) 93 { 94 for (int32 t = 0; t < CountConsumers(); ++t) 95 { 96 BMidiConsumer* cons = ConsumerAt(t); 97 cons->Acquire(); 98 list->AddItem(cons); 99 } 100 101 UnlockProducer(); 102 } 103 104 return list; 105 } 106 107 //------------------------------------------------------------------------------ 108 109 BMidiProducer::BMidiProducer(const char* name) 110 : BMidiEndpoint(name) 111 { 112 isConsumer = false; 113 connections = new BList; 114 locker = new BLocker("MidiProducerLock"); 115 } 116 117 //------------------------------------------------------------------------------ 118 119 BMidiProducer::~BMidiProducer() 120 { 121 delete connections; 122 delete locker; 123 } 124 125 //------------------------------------------------------------------------------ 126 127 void BMidiProducer::_Reserved1() { } 128 void BMidiProducer::_Reserved2() { } 129 void BMidiProducer::_Reserved3() { } 130 void BMidiProducer::_Reserved4() { } 131 void BMidiProducer::_Reserved5() { } 132 void BMidiProducer::_Reserved6() { } 133 void BMidiProducer::_Reserved7() { } 134 void BMidiProducer::_Reserved8() { } 135 136 //------------------------------------------------------------------------------ 137 138 status_t BMidiProducer::SendConnectRequest( 139 BMidiConsumer* cons, bool mustConnect) 140 { 141 ASSERT(cons != NULL) 142 143 BMessage msg, reply; 144 145 if (mustConnect) 146 { 147 msg.what = MSG_CONNECT_ENDPOINTS; 148 } 149 else 150 { 151 msg.what = MSG_DISCONNECT_ENDPOINTS; 152 } 153 154 msg.AddInt32("midi:producer", ID()); 155 msg.AddInt32("midi:consumer", cons->ID()); 156 157 status_t err = BMidiRoster::MidiRoster()->SendRequest(&msg, &reply); 158 if (err != B_OK) { return err; } 159 160 status_t res; 161 if (reply.FindInt32("midi:result", &res) == B_OK) 162 { 163 if (res == B_OK) 164 { 165 if (mustConnect) 166 { 167 ConnectionMade(cons); 168 } 169 else 170 { 171 ConnectionBroken(cons); 172 } 173 174 #ifdef DEBUG 175 BMidiRoster::MidiRoster()->looper->DumpEndpoints(); 176 #endif 177 } 178 179 return res; 180 } 181 182 return B_ERROR; 183 } 184 185 //------------------------------------------------------------------------------ 186 187 void BMidiProducer::ConnectionMade(BMidiConsumer* cons) 188 { 189 ASSERT(cons != NULL) 190 191 if (LockProducer()) 192 { 193 ASSERT(!connections->HasItem(cons)) 194 195 connections->AddItem(cons); 196 UnlockProducer(); 197 } 198 199 if (IsLocal()) 200 { 201 ((BMidiLocalProducer*) this)->Connected(cons); 202 } 203 } 204 205 //------------------------------------------------------------------------------ 206 207 bool BMidiProducer::ConnectionBroken(BMidiConsumer* cons) 208 { 209 ASSERT(cons != NULL) 210 211 bool wasConnected = false; 212 213 if (LockProducer()) 214 { 215 wasConnected = connections->RemoveItem(cons); 216 UnlockProducer(); 217 } 218 219 if (wasConnected && IsLocal()) 220 { 221 ((BMidiLocalProducer*) this)->Disconnected(cons); 222 } 223 224 return wasConnected; 225 } 226 227 //------------------------------------------------------------------------------ 228 229 int32 BMidiProducer::CountConsumers() const 230 { 231 return connections->CountItems(); 232 } 233 234 //------------------------------------------------------------------------------ 235 236 BMidiConsumer* BMidiProducer::ConsumerAt(int32 index) const 237 { 238 ASSERT(connections != NULL) 239 ASSERT(index >= 0 && index < CountConsumers()) 240 241 return (BMidiConsumer*) connections->ItemAt(index); 242 } 243 244 //------------------------------------------------------------------------------ 245 246 bool BMidiProducer::LockProducer() const 247 { 248 return locker->Lock(); 249 } 250 251 //------------------------------------------------------------------------------ 252 253 void BMidiProducer::UnlockProducer() const 254 { 255 locker->Unlock(); 256 } 257 258 //------------------------------------------------------------------------------ 259