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
Connect(BMidiConsumer * cons)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
Disconnect(BMidiConsumer * cons)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
IsConnected(BMidiConsumer * cons) const48 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*
Connections() const64 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
BMidiProducer(const char * name)82 BMidiProducer::BMidiProducer(const char* name)
83 : BMidiEndpoint(name),
84 fLocker("MidiProducerLock")
85 {
86 fIsConsumer = false;
87 fConnections = new BList();
88 }
89
90
~BMidiProducer()91 BMidiProducer::~BMidiProducer()
92 {
93 delete fConnections;
94 }
95
96
_Reserved1()97 void BMidiProducer::_Reserved1() { }
_Reserved2()98 void BMidiProducer::_Reserved2() { }
_Reserved3()99 void BMidiProducer::_Reserved3() { }
_Reserved4()100 void BMidiProducer::_Reserved4() { }
_Reserved5()101 void BMidiProducer::_Reserved5() { }
_Reserved6()102 void BMidiProducer::_Reserved6() { }
_Reserved7()103 void BMidiProducer::_Reserved7() { }
_Reserved8()104 void BMidiProducer::_Reserved8() { }
105
106
107 status_t
SendConnectRequest(BMidiConsumer * cons,bool mustConnect)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
ConnectionMade(BMidiConsumer * consumer)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
ConnectionBroken(BMidiConsumer * consumer)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
CountConsumers() const190 BMidiProducer::CountConsumers() const
191 {
192 return fConnections->CountItems();
193 }
194
195
196 BMidiConsumer*
ConsumerAt(int32 index) const197 BMidiProducer::ConsumerAt(int32 index) const
198 {
199 ASSERT(index >= 0 && index < CountConsumers())
200
201 return (BMidiConsumer*) fConnections->ItemAt(index);
202 }
203
204
205 bool
LockProducer() const206 BMidiProducer::LockProducer() const
207 {
208 return fLocker.Lock();
209 }
210
211
212 void
UnlockProducer() const213 BMidiProducer::UnlockProducer() const
214 {
215 fLocker.Unlock();
216 }
217
218