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