xref: /haiku/src/kits/media/Controllable.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
1 /*
2  * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files or portions
6  * thereof (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject
10  * to the following conditions:
11  *
12  *  * Redistributions of source code must retain the above copyright notice,
13  *    this list of conditions and the following disclaimer.
14  *
15  *  * Redistributions in binary form must reproduce the above copyright notice
16  *    in the  binary, as well as this list of conditions and the following
17  *    disclaimer in the documentation and/or other materials provided with
18  *    the distribution.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  * THE SOFTWARE.
27  *
28  */
29 
30 #include <OS.h>
31 #include <Controllable.h>
32 #include <ParameterWeb.h>
33 #include "debug.h"
34 #include "DataExchange.h"
35 #include "Notifications.h"
36 
37 /*************************************************************
38  * protected BControllable
39  *************************************************************/
40 
41 BControllable::~BControllable()
42 {
43 	CALLED();
44 	if (fSem > 0)
45 		delete_sem(fSem);
46 	if (fWeb)
47 		delete fWeb;
48 }
49 
50 /*************************************************************
51  * public BControllable
52  *************************************************************/
53 
54 BParameterWeb *
55 BControllable::Web()
56 {
57 	CALLED();
58 	BParameterWeb *temp;
59 	LockParameterWeb();
60 	temp = fWeb;
61 	UnlockParameterWeb();
62 	return temp;
63 }
64 
65 
66 bool
67 BControllable::LockParameterWeb()
68 {
69 	CALLED();
70 	status_t rv;
71 	if (fSem <= 0)
72 		return false;
73 	if (atomic_add(&fBen, 1) > 0) {
74 		while (B_INTERRUPTED == (rv = acquire_sem(fSem)))
75 			;
76 		return rv == B_OK;
77 	}
78 	return true;
79 }
80 
81 /*************************************************************
82  * protected BControllable
83  *************************************************************/
84 
85 void
86 BControllable::UnlockParameterWeb()
87 {
88 	CALLED();
89 	if (fSem <= 0)
90 		return;
91 	if (atomic_add(&fBen, -1) > 1)
92 		release_sem(fSem);
93 }
94 
95 
96 BControllable::BControllable() :
97 	BMediaNode("this one is never called"),
98 	fWeb(0),
99 	fSem(create_sem(0, "BControllable lock")),
100 	fBen(0)
101 {
102 	CALLED();
103 
104 	AddNodeKind(B_CONTROLLABLE);
105 }
106 
107 
108 status_t
109 BControllable::SetParameterWeb(BParameterWeb *web)
110 {
111 	CALLED();
112 	BParameterWeb *old;
113 	LockParameterWeb();
114 	old = fWeb;
115 	fWeb = web;
116 
117 	if (fWeb)
118 		fWeb->mNode = Node(); // initialize BParameterWeb member variable
119 
120 	UnlockParameterWeb();
121 	if (old != web && web != 0)
122 		BPrivate::media::notifications::WebChanged(Node());
123 	if (old)
124 		delete old;
125 	return B_OK;
126 }
127 
128 
129 status_t
130 BControllable::HandleMessage(int32 message, const void *data, size_t size)
131 {
132 	PRINT(4, "BControllable::HandleMessage %#lx, node %ld\n", message, ID());
133 
134 	status_t rv;
135 	switch (message) {
136 		case CONTROLLABLE_GET_PARAMETER_DATA:
137 		{
138 			const controllable_get_parameter_data_request *request = static_cast<const controllable_get_parameter_data_request *>(data);
139 			controllable_get_parameter_data_reply reply;
140 			area_id area;
141 			void *data;
142 
143 			if (request->area == -1) {
144 				// small data transfer uses buffer in reply
145 				area = -1;
146 				data = reply.rawdata;
147 			} else {
148 				// large data transfer, clone area
149 				area = clone_area("get parameter data clone", &data, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area);
150 				if (area < B_OK) {
151 					ERROR("CONTROLLABLE_GET_PARAMETER_DATA cloning area failed\n");
152 					request->SendReply(B_NO_MEMORY, &reply, sizeof(reply));
153 					return B_OK;
154 				}
155 			}
156 			reply.size = request->requestsize;
157 			rv = GetParameterValue(request->parameter_id, &reply.last_change, data, &reply.size);
158 			if (area != -1)
159 				delete_area(area);
160 			request->SendReply(rv, &reply, sizeof(reply));
161 			return B_OK;
162 		}
163 
164 		case CONTROLLABLE_SET_PARAMETER_DATA:
165 		{
166 			const controllable_set_parameter_data_request *request = static_cast<const controllable_set_parameter_data_request *>(data);
167 			controllable_set_parameter_data_reply reply;
168 			area_id area;
169 			const void *data;
170 
171 			if (request->area == -1) {
172 				// small data transfer uses buffer in request
173 				area = -1;
174 				data = request->rawdata;
175 			} else {
176 				// large data transfer, clone area
177 				area = clone_area("set parameter data clone", (void **)&data, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area);
178 				if (area < B_OK) {
179 					ERROR("CONTROLLABLE_SET_PARAMETER_DATA cloning area failed\n");
180 					request->SendReply(B_NO_MEMORY, &reply, sizeof(reply));
181 					return B_OK;
182 				}
183 			}
184 			SetParameterValue(request->parameter_id, request->when, data, request->size);
185 			if (area != -1)
186 				delete_area(area);
187 			request->SendReply(B_OK, &reply, sizeof(reply));
188 			return B_OK;
189 		}
190 
191 		case CONTROLLABLE_GET_PARAMETER_WEB:
192 		{
193 			const controllable_get_parameter_web_request *request = static_cast<const controllable_get_parameter_web_request *>(data);
194 			controllable_get_parameter_web_reply reply;
195 			bool waslocked = LockParameterWeb();
196 			if (fWeb != NULL && fWeb->FlattenedSize() > request->maxsize) {
197 				reply.code = 0;
198 				reply.size = -1; // parameter web too large
199 				rv = B_OK;
200 			} else if (fWeb != NULL && fWeb->FlattenedSize() <= request->maxsize) {
201 				void *buffer;
202 				area_id area;
203 				area = clone_area("cloned parameter web", &buffer, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area);
204 				if (area < B_OK) {
205 					ERROR("BControllable::HandleMessage CONTROLLABLE_GET_PARAMETER_WEB clone_area failed\n");
206 					rv = B_ERROR;
207 				} else {
208 					reply.code = fWeb->TypeCode();
209 					reply.size = fWeb->FlattenedSize();
210 					rv = fWeb->Flatten(buffer, reply.size);
211 					if (rv != B_OK) {
212 						ERROR("BControllable::HandleMessage CONTROLLABLE_GET_PARAMETER_WEB Flatten failed\n");
213 					} else {
214 						printf("BControllable::HandleMessage CONTROLLABLE_GET_PARAMETER_WEB %ld bytes, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx\n",
215 							reply.size, ((uint32*)buffer)[0], ((uint32*)buffer)[1], ((uint32*)buffer)[2], ((uint32*)buffer)[3]);
216 					}
217 					delete_area(area);
218 				}
219 			} else {
220 				reply.code = 0;
221 				reply.size = 0; // no parameter web
222 				rv = B_OK;
223 			}
224 			if (waslocked)
225 				UnlockParameterWeb();
226 			request->SendReply(rv, &reply, sizeof(reply));
227 			return B_OK;
228 		}
229 
230 	}
231 	return B_ERROR;
232 }
233 
234 
235 status_t
236 BControllable::BroadcastChangedParameter(int32 id)
237 {
238 	CALLED();
239 	return BPrivate::media::notifications::ParameterChanged(Node(), id);
240 }
241 
242 
243 status_t
244 BControllable::BroadcastNewParameterValue(bigtime_t when,
245 										  int32 id,
246 										  void *newValue,
247 										  size_t valueSize)
248 {
249 	CALLED();
250 	return BPrivate::media::notifications::NewParameterValue(Node(), id, when, newValue, valueSize);
251 }
252 
253 
254 status_t
255 BControllable::StartControlPanel(BMessenger *out_messenger)
256 {
257 	UNIMPLEMENTED();
258 
259 	return B_ERROR;
260 }
261 
262 
263 status_t
264 BControllable::ApplyParameterData(const void *value,
265 								  size_t size)
266 {
267 	UNIMPLEMENTED();
268 
269 	return B_ERROR;
270 }
271 
272 
273 status_t
274 BControllable::MakeParameterData(const int32 *controls,
275 								 int32 count,
276 								 void *buf,
277 								 size_t *ioSize)
278 {
279 	UNIMPLEMENTED();
280 
281 	return B_ERROR;
282 }
283 
284 /*************************************************************
285  * private BControllable
286  *************************************************************/
287 
288 /*
289 private unimplemented
290 BControllable::BControllable(const BControllable &clone)
291 BControllable & BControllable::operator=(const BControllable &clone)
292 */
293 
294 status_t BControllable::_Reserved_Controllable_0(void *) { return B_ERROR; }
295 status_t BControllable::_Reserved_Controllable_1(void *) { return B_ERROR; }
296 status_t BControllable::_Reserved_Controllable_2(void *) { return B_ERROR; }
297 status_t BControllable::_Reserved_Controllable_3(void *) { return B_ERROR; }
298 status_t BControllable::_Reserved_Controllable_4(void *) { return B_ERROR; }
299 status_t BControllable::_Reserved_Controllable_5(void *) { return B_ERROR; }
300 status_t BControllable::_Reserved_Controllable_6(void *) { return B_ERROR; }
301 status_t BControllable::_Reserved_Controllable_7(void *) { return B_ERROR; }
302 status_t BControllable::_Reserved_Controllable_8(void *) { return B_ERROR; }
303 status_t BControllable::_Reserved_Controllable_9(void *) { return B_ERROR; }
304 status_t BControllable::_Reserved_Controllable_10(void *) { return B_ERROR; }
305 status_t BControllable::_Reserved_Controllable_11(void *) { return B_ERROR; }
306 status_t BControllable::_Reserved_Controllable_12(void *) { return B_ERROR; }
307 status_t BControllable::_Reserved_Controllable_13(void *) { return B_ERROR; }
308 status_t BControllable::_Reserved_Controllable_14(void *) { return B_ERROR; }
309 status_t BControllable::_Reserved_Controllable_15(void *) { return B_ERROR; }
310 
311 
312