diff --git a/src/kits/media/Controllable.cpp b/src/kits/media/Controllable.cpp index 256e74236a..fdb2e0bea0 100644 --- a/src/kits/media/Controllable.cpp +++ b/src/kits/media/Controllable.cpp @@ -5,7 +5,9 @@ ***********************************************************************/ #include #include +#include #include "debug.h" +#include "DataExchange.h" #include "Notifications.h" /************************************************************* @@ -17,6 +19,8 @@ BControllable::~BControllable() CALLED(); if (fSem > 0) delete_sem(fSem); + if (fWeb) + delete fWeb; } /************************************************************* @@ -66,7 +70,7 @@ BControllable::UnlockParameterWeb() BControllable::BControllable() : - BMediaNode("XXX fixme"), + BMediaNode("this one is never called"), fWeb(0), fSem(create_sem(0, "BControllable lock")), fBen(0) @@ -88,18 +92,59 @@ BControllable::SetParameterWeb(BParameterWeb *web) UnlockParameterWeb(); if (old != web && web != 0) BPrivate::media::notifications::WebChanged(Node()); - + if (old) + delete old; return B_OK; } status_t -BControllable::HandleMessage(int32 message, - const void *data, - size_t size) +BControllable::HandleMessage(int32 message, const void *data, size_t size) { INFO("BControllable::HandleMessage %#lx, node %ld\n", message, ID()); + status_t rv; + switch (message) { + case CONTROLLABLE_GET_PARAMETER_WEB: + { + const controllable_get_parameter_web_request *request = static_cast(data); + controllable_get_parameter_web_reply reply; + bool waslocked = LockParameterWeb(); + if (fWeb != NULL && fWeb->FlattenedSize() > request->maxsize) { + reply.code = 0; + reply.size = -1; // parameter web too large + rv = B_OK; + } else if (fWeb != NULL && fWeb->FlattenedSize() <= request->maxsize) { + void *buffer; + area_id area; + area = clone_area("cloned parameter web", &buffer, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, request->area); + if (area < B_OK) { + FATAL("BControllable::HandleMessage CONTROLLABLE_GET_PARAMETER_WEB clone_area failed\n"); + rv = B_ERROR; + } else { + reply.code = fWeb->TypeCode(); + reply.size = fWeb->FlattenedSize(); + rv = fWeb->Flatten(buffer, reply.size); + if (rv != B_OK) { + FATAL("BControllable::HandleMessage CONTROLLABLE_GET_PARAMETER_WEB Flatten failed\n"); + } else { + printf("BControllable::HandleMessage CONTROLLABLE_GET_PARAMETER_WEB %ld bytes, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + reply.size, ((uint32*)buffer)[0], ((uint32*)buffer)[1], ((uint32*)buffer)[2], ((uint32*)buffer)[3]); + } + delete_area(area); + } + } else { + reply.code = 0; + reply.size = 0; // no parameter web + rv = B_OK; + } + if (waslocked) + UnlockParameterWeb(); + request->SendReply(rv, &reply, sizeof(reply)); + return B_OK; + } + + } return B_ERROR; } diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 3b2e7f9799..dd4a62f209 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -1692,10 +1692,69 @@ status_t BMediaRoster::GetParameterWebFor(const media_node & node, BParameterWeb ** out_web) { - UNIMPLEMENTED(); -// return B_ERROR; - *out_web = new BParameterWeb; - return B_OK; + CALLED(); + if (out_web == NULL) + return B_BAD_VALUE; + if (IS_INVALID_NODE(node)) + return B_MEDIA_BAD_NODE; + if ((node.kind & B_CONTROLLABLE) == 0) + return B_MEDIA_BAD_NODE; + + controllable_get_parameter_web_request request; + controllable_get_parameter_web_reply reply; + int32 requestsize[] = {B_PAGE_SIZE, 4*B_PAGE_SIZE, 16*B_PAGE_SIZE, 64*B_PAGE_SIZE, 128*B_PAGE_SIZE, 256*B_PAGE_SIZE, 0}; + int32 size; + + // XXX it might be better to query the node for the (current) parameter size first + for (int i = 0; (size = requestsize[i]) != 0; i++) { + status_t rv; + area_id area; + void *data; + area = create_area("parameter web data", &data, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + if (area < B_OK) { + FATAL("BMediaRoster::GetParameterWebFor couldn't create area of size %ld\n", size); + return B_ERROR; + } + request.maxsize = size; + request.area = area; + rv = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_WEB, &request, sizeof(request), &reply, sizeof(reply)); + if (rv != B_OK) { + FATAL("BMediaRoster::GetParameterWebFor CONTROLLABLE_GET_PARAMETER_WEB failed\n"); + delete_area(area); + return B_ERROR; + } + if (reply.size == 0) { + // no parameter web available + // XXX should we return an error? + FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web\n", node.node); + *out_web = new BParameterWeb(); + delete_area(area); + return B_OK; + } + if (reply.size > 0) { + // we got a flattened parameter web! + *out_web = new BParameterWeb(); + + printf("BMediaRoster::GetParameterWebFor Unflattening %ld bytes, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + reply.size, ((uint32*)data)[0], ((uint32*)data)[1], ((uint32*)data)[2], ((uint32*)data)[3]); + + rv = (*out_web)->Unflatten(reply.code, data, reply.size); + if (rv != B_OK) { + FATAL("BMediaRoster::GetParameterWebFor Unflatten failed, %s\n", strerror(rv)); + delete_area(area); + delete *out_web; + return B_ERROR; + } + delete_area(area); + return B_OK; + } + delete_area(area); + ASSERT(reply.size == -1); + // parameter web data was too large + // loop and try a larger size + } + FATAL("BMediaRoster::GetParameterWebFor node %ld has no parameter web larger than %ld\n", node.node, size); + return B_ERROR; } diff --git a/src/kits/media/ParameterWeb.cpp b/src/kits/media/ParameterWeb.cpp index 402cb44a79..9136ab69c9 100644 --- a/src/kits/media/ParameterWeb.cpp +++ b/src/kits/media/ParameterWeb.cpp @@ -599,16 +599,20 @@ BParameterWeb::Unflatten(type_code c, const void *buf, ssize_t size) { - if(!this->AllowsTypeCode(c)) + if(!this->AllowsTypeCode(c)) { + FATAL("BParameterWeb::Unflatten wrong type code\n"); return B_BAD_TYPE; - - if(buf == NULL) + } + if(buf == NULL) { + FATAL("BParameterWeb::Unflatten NULL buffer pointer\n"); return B_NO_INIT; + } //if the buffer is smaller than the size needed to read the //signature field, the mystery field, the group count, and the Node, then there is a problem if(size < static_cast(sizeof(int32) + sizeof(int32) + sizeof(ssize_t) + sizeof(media_node)) ) { + FATAL("BParameterWeb::Unflatten size to small\n"); return B_ERROR; } @@ -618,6 +622,7 @@ BParameterWeb::Unflatten(type_code c, //being read in the correct byte order. if( *(reinterpret_cast(CurrentPos)) != 0x010300506) { + FATAL("BParameterWeb::Unflatten magic 1 wrong\n"); return B_BAD_TYPE; } CurrentPos += sizeof(int32); @@ -626,6 +631,7 @@ BParameterWeb::Unflatten(type_code c, //being read in the correct byte order. THIS SURELY HAS SOME MEANING I'M NOT AWARE OF. if( *(reinterpret_cast(CurrentPos)) != 1) { + FATAL("BParameterWeb::Unflatten magic 2 wrong\n"); return B_ERROR; } CurrentPos += sizeof(int32); @@ -702,6 +708,7 @@ BParameterWeb::Unflatten(type_code c, if(RetVal != B_OK) { + FATAL("BParameterWeb::Unflatten sub.grup Unflatten failed\n"); delete NewSubGroup; //don't return, because we should still fix references... break;