headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / midi2 / MidiEndpoint.cpp
blob6bb9acfc7d5add9dd65c33cda4d052c4d7581433
1 /*
2 * Copyright 2006, Haiku.
4 * Copyright (c) 2002-2003 Matthijs Hollemans
5 * Distributed under the terms of the MIT License.
7 * Authors:
8 * Matthijs Hollemans
9 */
11 #include "debug.h"
12 #include <MidiEndpoint.h>
13 #include <MidiRoster.h>
14 #include "MidiRosterLooper.h"
15 #include "protocol.h"
18 const char*
19 BMidiEndpoint::Name() const
21 const char* str = NULL;
23 // It seems reasonable to assume that the pointer returned by
24 // BString::String() can change when the string is modified,
25 // e.g. to allocate more space. That's why we lock here too.
27 if (LockLooper()) {
28 str = fName.String();
29 UnlockLooper();
32 return str;
36 void
37 BMidiEndpoint::SetName(const char* newName)
39 if (newName == NULL) {
40 WARN("SetName() does not accept a NULL name");
41 return;
43 if (IsRemote()) {
44 WARN("SetName() is not allowed on remote endpoints");
45 return;
47 if (!IsValid())
48 return;
50 if (fName != newName) {
51 BMessage msg;
52 msg.AddString("midi:name", newName);
54 if (SendChangeRequest(&msg) == B_OK) {
55 if (LockLooper()) {
56 fName.SetTo(newName);
57 UnlockLooper();
64 int32
65 BMidiEndpoint::ID() const
67 return fId;
71 bool
72 BMidiEndpoint::IsProducer() const
74 return !fIsConsumer;
78 bool
79 BMidiEndpoint::IsConsumer() const
81 return fIsConsumer;
85 bool
86 BMidiEndpoint::IsRemote() const
88 return !fIsLocal;
92 bool
93 BMidiEndpoint::IsLocal() const
95 return fIsLocal;
99 bool
100 BMidiEndpoint::IsPersistent() const
102 return false;
106 bool
107 BMidiEndpoint::IsValid() const
109 if (IsLocal())
110 return (ID() > 0);
112 // remote endpoint
113 return IsRegistered();
117 status_t
118 BMidiEndpoint::Release()
120 int32 old = atomic_add(&fRefCount, -1);
122 TRACE(("BMidiEndpoint::Release refCount is now %" B_PRId32, old - 1))
124 if (old == 1) {
125 // If the reference count of a local endpoint drops to zero,
126 // we must delete it. The destructor of BMidiLocalXXX calls
127 // BMidiRoster::DeleteLocal(), which does all the hard work.
128 // If we are a proxy for a remote endpoint, we must only be
129 // deleted if that remote endpoint no longer exists.
131 if (IsLocal() || !fIsAlive)
132 delete this;
133 } else if (old <= 0) {
134 debugger("too many calls to Release()");
137 return B_OK;
141 status_t
142 BMidiEndpoint::Acquire()
144 #ifdef DEBUG
145 int32 old =
146 #endif
147 atomic_add(&fRefCount, 1);
149 TRACE(("BMidiEndpoint::Acquire refCount is now %" B_PRId32, old + 1))
151 return B_OK;
155 status_t
156 BMidiEndpoint::SetProperties(const BMessage* properties_)
158 if (properties_ == NULL) {
159 WARN("SetProperties() does not accept a NULL message")
160 return B_BAD_VALUE;
161 } else if (IsRemote()) {
162 WARN("SetProperties() is not allowed on remote endpoints");
163 return B_ERROR;
164 } else if (!IsValid()) {
165 return B_ERROR;
166 } else {
167 BMessage msg;
168 msg.AddMessage("midi:properties", properties_);
170 status_t err = SendChangeRequest(&msg);
171 if (err == B_OK) {
172 if (LockLooper()) {
173 *fProperties = *properties_;
174 UnlockLooper();
178 return err;
183 status_t
184 BMidiEndpoint::GetProperties(BMessage* _properties) const
186 if (_properties == NULL) {
187 WARN("GetProperties() does not accept NULL properties")
188 return B_BAD_VALUE;
191 if (LockLooper()) {
192 *_properties = *fProperties;
193 UnlockLooper();
196 return B_OK;
200 status_t
201 BMidiEndpoint::Register()
203 if (IsRemote()) {
204 WARN("You cannot Register() remote endpoints");
205 return B_ERROR;
207 if (IsRegistered()) {
208 WARN("This endpoint is already registered");
209 return B_OK;
211 if (!IsValid())
212 return B_ERROR;
214 return SendRegisterRequest(true);
218 status_t
219 BMidiEndpoint::Unregister()
221 if (IsRemote()) {
222 WARN("You cannot Unregister() remote endpoints");
223 return B_ERROR;
225 if (!IsRegistered()) {
226 WARN("This endpoint is already unregistered");
227 return B_OK;
229 if (!IsValid())
230 return B_ERROR;
232 return SendRegisterRequest(false);
236 BMidiEndpoint::BMidiEndpoint(const char* name_)
238 TRACE(("BMidiEndpoint::BMidiEndpoint"))
240 if (name_ != NULL)
241 fName.SetTo(name_);
243 fId = 0;
244 fRefCount = 0;
245 fIsLocal = false;
246 fIsRegistered = false;
247 fIsAlive = true;
249 fProperties = new BMessage();
253 BMidiEndpoint::~BMidiEndpoint()
255 TRACE(("BMidiEndpoint::~BMidiEndpoint (%p)", this))
257 if (fRefCount > 0) {
258 debugger(
259 "you should use Release() to dispose of endpoints; "
260 "do not \"delete\" them or allocate them on the stack!");
262 delete fProperties;
265 //------------------------------------------------------------------------------
267 void BMidiEndpoint::_Reserved1() { }
268 void BMidiEndpoint::_Reserved2() { }
269 void BMidiEndpoint::_Reserved3() { }
270 void BMidiEndpoint::_Reserved4() { }
271 void BMidiEndpoint::_Reserved5() { }
272 void BMidiEndpoint::_Reserved6() { }
273 void BMidiEndpoint::_Reserved7() { }
274 void BMidiEndpoint::_Reserved8() { }
276 //------------------------------------------------------------------------------
278 status_t
279 BMidiEndpoint::SendRegisterRequest(bool registered)
281 BMessage msg;
282 msg.AddBool("midi:registered", registered);
284 status_t err = SendChangeRequest(&msg);
285 if (err == B_OK) {
286 if (LockLooper()) {
287 fIsRegistered = registered;
288 UnlockLooper();
292 return err;
296 status_t
297 BMidiEndpoint::SendChangeRequest(BMessage* msg)
299 ASSERT(msg != NULL)
301 msg->what = MSG_CHANGE_ENDPOINT;
302 msg->AddInt32("midi:id", ID());
304 BMessage reply;
305 status_t err = BMidiRoster::MidiRoster()->SendRequest(msg, &reply);
306 if (err != B_OK)
307 return err;
309 status_t res;
310 if (reply.FindInt32("midi:result", &res) == B_OK)
311 return res;
313 return B_ERROR;
317 bool
318 BMidiEndpoint::IsRegistered() const
320 // No need to protect this with a lock, because reading
321 // and writing a bool is always an atomic operation.
323 return fIsRegistered;
327 bool
328 BMidiEndpoint::LockLooper() const
330 return BMidiRoster::MidiRoster()->fLooper->Lock();
334 void
335 BMidiEndpoint::UnlockLooper() const
337 BMidiRoster::MidiRoster()->fLooper->Unlock();