tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / media / Controllable.cpp
blobd2e505a21e58c2956b7517752804f751bc46ada2
1 /*
2 * Copyright 2009-2012, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT license.
4 */
6 /*
7 * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files or portions
11 * thereof (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so, subject
15 * to the following conditions:
17 * * Redistributions of source code must retain the above copyright notice,
18 * this list of conditions and the following disclaimer.
20 * * Redistributions in binary form must reproduce the above copyright notice
21 * in the binary, as well as this list of conditions and the following
22 * disclaimer in the documentation and/or other materials provided with
23 * the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 * THE SOFTWARE.
35 #include <Controllable.h>
37 #include <string.h>
39 #include <OS.h>
40 #include <ParameterWeb.h>
41 #include <Roster.h>
43 #include <debug.h>
44 #include <DataExchange.h>
45 #include <Notifications.h>
48 namespace BPrivate { namespace media {
50 /*! A helper class for the communication with the media server that
51 takes care of large buffers that need an area.
53 class ReceiveTransfer {
54 public:
55 ReceiveTransfer(const area_request_data& request, const void* smallBuffer)
57 if (request.area == -1 && smallBuffer != NULL) {
58 // small data transfer uses buffer in reply
59 fArea = -1;
60 fData = const_cast<void*>(smallBuffer);
61 // The caller is actually responsible to enforce the const;
62 // we don't touch the data.
63 } else {
64 // large data transfer, clone area
65 fArea = clone_area("get parameter data clone", &fData,
66 B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request.area);
67 if (fArea < B_OK) {
68 ERROR("BControllabe: cloning area failed: %s\n",
69 strerror(fArea));
70 fData = NULL;
75 ~ReceiveTransfer()
77 if (fArea >= B_OK)
78 delete_area(fArea);
81 status_t InitCheck() const
83 return fData != NULL ? B_OK : fArea;
86 void* Data() const
88 return fData;
91 private:
92 area_id fArea;
93 void* fData;
96 } // namespace media
97 } // namespace BPrivate
99 using BPrivate::media::ReceiveTransfer;
102 // #pragma mark - protected
105 BControllable::~BControllable()
107 CALLED();
108 if (fSem > 0)
109 delete_sem(fSem);
111 delete fWeb;
115 // #pragma mark - public
118 BParameterWeb*
119 BControllable::Web()
121 CALLED();
122 return fWeb;
126 bool
127 BControllable::LockParameterWeb()
129 CALLED();
130 if (fSem <= 0)
131 return false;
133 if (atomic_add(&fBen, 1) > 0) {
134 status_t status;
135 do {
136 status = acquire_sem(fSem);
137 } while (status == B_INTERRUPTED);
139 return status == B_OK;
142 return true;
146 void
147 BControllable::UnlockParameterWeb()
149 CALLED();
150 if (fSem <= 0)
151 return;
153 if (atomic_add(&fBen, -1) > 1)
154 release_sem(fSem);
158 // #pragma mark - protected
161 BControllable::BControllable()
162 : BMediaNode("this one is never called"),
163 fWeb(NULL),
164 fSem(create_sem(0, "BControllable lock")),
165 fBen(0)
167 CALLED();
169 AddNodeKind(B_CONTROLLABLE);
173 status_t
174 BControllable::SetParameterWeb(BParameterWeb* web)
176 CALLED();
178 LockParameterWeb();
179 BParameterWeb* old = fWeb;
180 fWeb = web;
182 if (fWeb != NULL) {
183 // initialize BParameterWeb member variable
184 fWeb->fNode = Node();
187 UnlockParameterWeb();
189 if (old != web && web != NULL)
190 BPrivate::media::notifications::WebChanged(Node());
191 delete old;
192 return B_OK;
196 status_t
197 BControllable::HandleMessage(int32 message, const void* data, size_t size)
199 PRINT(4, "BControllable::HandleMessage %#lx, node %ld\n", message, ID());
201 switch (message) {
202 case CONTROLLABLE_GET_PARAMETER_DATA:
204 const controllable_get_parameter_data_request& request
205 = *static_cast<const controllable_get_parameter_data_request*>(
206 data);
207 controllable_get_parameter_data_reply reply;
209 ReceiveTransfer transfer(request, reply.raw_data);
210 if (transfer.InitCheck() != B_OK) {
211 request.SendReply(transfer.InitCheck(), &reply, sizeof(reply));
212 return B_OK;
215 reply.size = request.request_size;
216 status_t status = GetParameterValue(request.parameter_id,
217 &reply.last_change, transfer.Data(), &reply.size);
219 request.SendReply(status, &reply, sizeof(reply));
220 return B_OK;
223 case CONTROLLABLE_SET_PARAMETER_DATA:
225 const controllable_set_parameter_data_request& request
226 = *static_cast<const controllable_set_parameter_data_request*>(
227 data);
228 controllable_set_parameter_data_reply reply;
230 ReceiveTransfer transfer(request, request.raw_data);
231 if (transfer.InitCheck() != B_OK) {
232 request.SendReply(transfer.InitCheck(), &reply, sizeof(reply));
233 return B_OK;
236 SetParameterValue(request.parameter_id, request.when,
237 transfer.Data(), request.size);
238 request.SendReply(B_OK, &reply, sizeof(reply));
239 return B_OK;
242 case CONTROLLABLE_GET_PARAMETER_WEB:
244 const controllable_get_parameter_web_request& request
245 = *static_cast<const controllable_get_parameter_web_request*>(
246 data);
247 controllable_get_parameter_web_reply reply;
249 status_t status = B_OK;
250 bool wasLocked = true;
251 if (!LockParameterWeb()) {
252 status = B_ERROR;
253 wasLocked = false;
256 if (status == B_OK && fWeb != NULL) {
257 if (fWeb->FlattenedSize() > request.max_size) {
258 // parameter web too large
259 reply.code = 0;
260 reply.size = -1;
261 status = B_OK;
262 } else {
263 ReceiveTransfer transfer(request, NULL);
264 status = transfer.InitCheck();
265 if (status == B_OK) {
266 reply.code = fWeb->TypeCode();
267 reply.size = fWeb->FlattenedSize();
268 status = fWeb->Flatten(transfer.Data(), reply.size);
269 if (status != B_OK) {
270 ERROR("BControllable::HandleMessage "
271 "CONTROLLABLE_GET_PARAMETER_WEB Flatten failed\n");
272 #if 0
273 } else {
274 printf("BControllable::HandleMessage CONTROLLABLE_GET_PARAMETER_WEB %ld bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
275 reply.size, ((uint32*)buffer)[0], ((uint32*)buffer)[1], ((uint32*)buffer)[2], ((uint32*)buffer)[3]);
276 #endif
280 } else {
281 // no parameter web
282 reply.code = 0;
283 reply.size = 0;
285 if (wasLocked)
286 UnlockParameterWeb();
288 request.SendReply(status, &reply, sizeof(reply));
289 return B_OK;
292 case CONTROLLABLE_START_CONTROL_PANEL:
294 const controllable_start_control_panel_request* request
295 = static_cast<const controllable_start_control_panel_request*>(
296 data);
297 controllable_start_control_panel_reply reply;
298 BMessenger targetMessenger;
299 status_t status = StartControlPanel(&targetMessenger);
300 if (status != B_OK) {
301 ERROR("BControllable::HandleMessage "
302 "CONTROLLABLE_START_CONTROL_PANEL failed\n");
304 reply.result = status;
305 reply.team = targetMessenger.Team();
306 request->SendReply(status, &reply, sizeof(reply));
307 return B_OK;
310 default:
311 return B_ERROR;
314 return B_OK;
318 status_t
319 BControllable::BroadcastChangedParameter(int32 id)
321 CALLED();
322 return BPrivate::media::notifications::ParameterChanged(Node(), id);
326 status_t
327 BControllable::BroadcastNewParameterValue(bigtime_t when, int32 id,
328 void* newValue, size_t valueSize)
330 CALLED();
331 return BPrivate::media::notifications::NewParameterValue(Node(), id, when,
332 newValue, valueSize);
336 status_t
337 BControllable::StartControlPanel(BMessenger* _messenger)
339 CALLED();
341 int32 internalId;
342 BMediaAddOn* addon = AddOn(&internalId);
343 if (!addon) {
344 ERROR("BControllable::StartControlPanel not instantiated per AddOn\n");
345 return B_ERROR;
348 image_id imageID = addon->ImageID();
349 image_info info;
350 if (imageID <= 0 || get_image_info(imageID, &info) != B_OK) {
351 ERROR("BControllable::StartControlPanel Error accessing image\n");
352 return B_BAD_VALUE;
355 entry_ref ref;
356 if (get_ref_for_path(info.name, &ref) != B_OK) {
357 ERROR("BControllable::StartControlPanel Error getting ref\n");
358 return B_BAD_VALUE;
361 // The first argument is "node=id" with id meaning the media_node_id
362 char arg[32];
363 snprintf(arg, sizeof(arg), "node=%d", (int)ID());
365 team_id team;
366 if (be_roster->Launch(&ref, 1, (const char* const*)&arg, &team) != B_OK) {
367 ERROR("BControllable::StartControlPanel Error launching application\n");
368 return B_BAD_VALUE;
370 printf("BControllable::StartControlPanel done with id: %" B_PRId32 "\n",
371 team);
373 if (_messenger)
374 *_messenger = BMessenger(NULL, team);
376 return B_OK;
380 status_t
381 BControllable::ApplyParameterData(const void* value, size_t size)
383 UNIMPLEMENTED();
385 return B_ERROR;
389 status_t
390 BControllable::MakeParameterData(const int32* controls, int32 count,
391 void* buffer, size_t* ioSize)
393 UNIMPLEMENTED();
395 return B_ERROR;
399 // #pragma mark - private
402 status_t BControllable::_Reserved_Controllable_0(void *) { return B_ERROR; }
403 status_t BControllable::_Reserved_Controllable_1(void *) { return B_ERROR; }
404 status_t BControllable::_Reserved_Controllable_2(void *) { return B_ERROR; }
405 status_t BControllable::_Reserved_Controllable_3(void *) { return B_ERROR; }
406 status_t BControllable::_Reserved_Controllable_4(void *) { return B_ERROR; }
407 status_t BControllable::_Reserved_Controllable_5(void *) { return B_ERROR; }
408 status_t BControllable::_Reserved_Controllable_6(void *) { return B_ERROR; }
409 status_t BControllable::_Reserved_Controllable_7(void *) { return B_ERROR; }
410 status_t BControllable::_Reserved_Controllable_8(void *) { return B_ERROR; }
411 status_t BControllable::_Reserved_Controllable_9(void *) { return B_ERROR; }
412 status_t BControllable::_Reserved_Controllable_10(void *) { return B_ERROR; }
413 status_t BControllable::_Reserved_Controllable_11(void *) { return B_ERROR; }
414 status_t BControllable::_Reserved_Controllable_12(void *) { return B_ERROR; }
415 status_t BControllable::_Reserved_Controllable_13(void *) { return B_ERROR; }
416 status_t BControllable::_Reserved_Controllable_14(void *) { return B_ERROR; }
417 status_t BControllable::_Reserved_Controllable_15(void *) { return B_ERROR; }