xref: /haiku/src/kits/midi2/MidiProducer.cpp (revision 77f879871f89bfcd40965f6d4f2b2a529e2f9743)
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