2 * Copyright 2009-2012, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT license.
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
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
35 #include <Controllable.h>
40 #include <ParameterWeb.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
{
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
60 fData
= const_cast<void*>(smallBuffer
);
61 // The caller is actually responsible to enforce the const;
62 // we don't touch the data.
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
);
68 ERROR("BControllabe: cloning area failed: %s\n",
81 status_t
InitCheck() const
83 return fData
!= NULL
? B_OK
: fArea
;
97 } // namespace BPrivate
99 using BPrivate::media::ReceiveTransfer
;
102 // #pragma mark - protected
105 BControllable::~BControllable()
115 // #pragma mark - public
127 BControllable::LockParameterWeb()
133 if (atomic_add(&fBen
, 1) > 0) {
136 status
= acquire_sem(fSem
);
137 } while (status
== B_INTERRUPTED
);
139 return status
== B_OK
;
147 BControllable::UnlockParameterWeb()
153 if (atomic_add(&fBen
, -1) > 1)
158 // #pragma mark - protected
161 BControllable::BControllable()
162 : BMediaNode("this one is never called"),
164 fSem(create_sem(0, "BControllable lock")),
169 AddNodeKind(B_CONTROLLABLE
);
174 BControllable::SetParameterWeb(BParameterWeb
* web
)
179 BParameterWeb
* old
= fWeb
;
183 // initialize BParameterWeb member variable
184 fWeb
->fNode
= Node();
187 UnlockParameterWeb();
189 if (old
!= web
&& web
!= NULL
)
190 BPrivate::media::notifications::WebChanged(Node());
197 BControllable::HandleMessage(int32 message
, const void* data
, size_t size
)
199 PRINT(4, "BControllable::HandleMessage %#lx, node %ld\n", message
, ID());
202 case CONTROLLABLE_GET_PARAMETER_DATA
:
204 const controllable_get_parameter_data_request
& request
205 = *static_cast<const controllable_get_parameter_data_request
*>(
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
));
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
));
223 case CONTROLLABLE_SET_PARAMETER_DATA
:
225 const controllable_set_parameter_data_request
& request
226 = *static_cast<const controllable_set_parameter_data_request
*>(
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
));
236 SetParameterValue(request
.parameter_id
, request
.when
,
237 transfer
.Data(), request
.size
);
238 request
.SendReply(B_OK
, &reply
, sizeof(reply
));
242 case CONTROLLABLE_GET_PARAMETER_WEB
:
244 const controllable_get_parameter_web_request
& request
245 = *static_cast<const controllable_get_parameter_web_request
*>(
247 controllable_get_parameter_web_reply reply
;
249 status_t status
= B_OK
;
250 bool wasLocked
= true;
251 if (!LockParameterWeb()) {
256 if (status
== B_OK
&& fWeb
!= NULL
) {
257 if (fWeb
->FlattenedSize() > request
.max_size
) {
258 // parameter web too large
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");
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]);
286 UnlockParameterWeb();
288 request
.SendReply(status
, &reply
, sizeof(reply
));
292 case CONTROLLABLE_START_CONTROL_PANEL
:
294 const controllable_start_control_panel_request
* request
295 = static_cast<const controllable_start_control_panel_request
*>(
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
));
319 BControllable::BroadcastChangedParameter(int32 id
)
322 return BPrivate::media::notifications::ParameterChanged(Node(), id
);
327 BControllable::BroadcastNewParameterValue(bigtime_t when
, int32 id
,
328 void* newValue
, size_t valueSize
)
331 return BPrivate::media::notifications::NewParameterValue(Node(), id
, when
,
332 newValue
, valueSize
);
337 BControllable::StartControlPanel(BMessenger
* _messenger
)
342 BMediaAddOn
* addon
= AddOn(&internalId
);
344 ERROR("BControllable::StartControlPanel not instantiated per AddOn\n");
348 image_id imageID
= addon
->ImageID();
350 if (imageID
<= 0 || get_image_info(imageID
, &info
) != B_OK
) {
351 ERROR("BControllable::StartControlPanel Error accessing image\n");
356 if (get_ref_for_path(info
.name
, &ref
) != B_OK
) {
357 ERROR("BControllable::StartControlPanel Error getting ref\n");
361 // The first argument is "node=id" with id meaning the media_node_id
363 snprintf(arg
, sizeof(arg
), "node=%d", (int)ID());
366 if (be_roster
->Launch(&ref
, 1, (const char* const*)&arg
, &team
) != B_OK
) {
367 ERROR("BControllable::StartControlPanel Error launching application\n");
370 printf("BControllable::StartControlPanel done with id: %" B_PRId32
"\n",
374 *_messenger
= BMessenger(NULL
, team
);
381 BControllable::ApplyParameterData(const void* value
, size_t size
)
390 BControllable::MakeParameterData(const int32
* controls
, int32 count
,
391 void* buffer
, size_t* ioSize
)
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
; }