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