diff --git a/headers/private/media/DataExchange.h b/headers/private/media/DataExchange.h index 6762001592..8727398c9a 100644 --- a/headers/private/media/DataExchange.h +++ b/headers/private/media/DataExchange.h @@ -882,7 +882,7 @@ struct controllable_get_parameter_data_request : public request_data { int32 parameter_id; size_t requestsize; - area_id area; //if area != -1, data is to large and must be passed in area + area_id area; //if area != -1, data is too large and must be passed in the area }; struct controllable_get_parameter_data_reply : public reply_data @@ -892,5 +892,17 @@ struct controllable_get_parameter_data_reply : public reply_data size_t size; }; +struct controllable_set_parameter_data_request : public request_data +{ + int32 parameter_id; + bigtime_t when; + area_id area; //if area != -1, data is too large and is passed in the area + size_t size; + char rawdata[MAX_PARAMETER_DATA]; +}; + +struct controllable_set_parameter_data_reply : public reply_data +{ +}; #endif // _DATA_EXCHANGE_H diff --git a/src/kits/media/Controllable.cpp b/src/kits/media/Controllable.cpp index 253a92f43e..45bc4f423e 100644 --- a/src/kits/media/Controllable.cpp +++ b/src/kits/media/Controllable.cpp @@ -163,6 +163,33 @@ BControllable::HandleMessage(int32 message, const void *data, size_t size) request->SendReply(rv, &reply, sizeof(reply)); return B_OK; } + + case CONTROLLABLE_SET_PARAMETER_DATA: + { + const controllable_set_parameter_data_request *request = static_cast(data); + controllable_set_parameter_data_reply reply; + area_id area; + const void *data; + + if (request->area == -1) { + // small data transfer uses buffer in reply + area = -1; + data = request->rawdata; + } else { + // large data transfer, clone area + area = clone_area("set parameter data clone", (void **)&data, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area); + if (area < B_OK) { + FATAL("CONTROLLABLE_SET_PARAMETER_DATA cloning area failed\n"); + request->SendReply(B_NO_MEMORY, &reply, sizeof(reply)); + return B_OK; + } + } + SetParameterValue(request->parameter_id, request->when, data, request->size); + if (area != -1) + delete_area(area); + request->SendReply(B_OK, &reply, sizeof(reply)); + return B_OK; + } case CONTROLLABLE_GET_PARAMETER_WEB: { diff --git a/src/kits/media/ParameterWeb.cpp b/src/kits/media/ParameterWeb.cpp index 8c804c9b18..9b5c333d6b 100644 --- a/src/kits/media/ParameterWeb.cpp +++ b/src/kits/media/ParameterWeb.cpp @@ -1396,11 +1396,57 @@ BParameter::GetValue(void *buffer, size_t *ioSize, bigtime_t *when) status_t BParameter::SetValue(const void *buffer, size_t size, bigtime_t when) { - UNIMPLEMENTED(); - /* - * XXX ToDo! call BControllable::SetControlValue() here. - */ - return B_BAD_VALUE; + CALLED(); + + controllable_set_parameter_data_request request; + controllable_set_parameter_data_reply reply; + media_node node; + area_id area; + status_t rv; + void *data; + + if (buffer == 0) + return B_BAD_VALUE; + if (size <= 0) + return B_NO_MEMORY; + + if (mWeb == 0) { + FATAL("BParameter::SetValue: no parent BParameterWeb\n"); + return B_NO_INIT; + } + + node = mWeb->Node(); + if (IS_INVALID_NODE(node)) { + FATAL("BParameter::SetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); + return B_NO_INIT; + } + + if (size > MAX_PARAMETER_DATA) { + // create an area if large data needs to be transfered + area = create_area("set parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + if (area < B_OK) { + FATAL("BParameter::SetValue can't create area of %ld bytes\n", size); + return B_NO_MEMORY; + } + } else { + area = -1; + data = request.rawdata; + } + + memcpy(data, buffer, size); + request.parameter_id = mID; + request.when = when; + request.area = area; + request.size = size; + + rv = QueryPort(node.port, CONTROLLABLE_SET_PARAMETER_DATA, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) + FATAL("BParameter::SetValue querying node failed\n"); + + if (area != -1) + delete_area(area); + + return rv; }