* Copyright 2002-2012, Haiku. All Rights Reserved.
* This file may be used under the terms of the MIT License.
*
* Author: Zousar Shaker
* Axel Dörfler, axeld@pinc-software.de
* Marcus Overhagen
*/
BParameterWeb, BParameterGroup, BParameter, BNullParameter,
BContinuousParameter, BDiscreteParameter
*/
#include <ParameterWeb.h>
#include <new>
#include <string.h>
#include <MediaNode.h>
#include <MediaRoster.h>
#include "DataExchange.h"
#include "MediaDebug.h"
#include "MediaMisc.h"
The following is documentation on the flattened format
of structures/classes in this module:
//--------BEGIN-CORE-BPARAMETER-STRUCT---------------------
?? (0x02040607): 4 bytes
BParameter Struct Size (in bytes): 4 bytes
ID: 4 bytes
Name String Length: 1 byte (??)
Name String: 'Name String Length' bytes
Kind String Length: 1 byte (??)
Kind String: 'Kind String Length' bytes
Unit String Length: 1 byte (??)
Unit String: 'Unit String Length' bytes
Inputs Count: 4 bytes
Inputs (pointers): ('Inputs Count')*4 bytes
Outputs Count: 4 bytes
Outputs (pointers): ('Outputs Count')*4 bytes
Media Type: 4 bytes
ChannelCount: 4 bytes
Flags: 4 bytes
//---------END-CORE-BPARAMETER-STRUCT-----------------------
//--------BEGIN-BCONTINUOUSPARAMETER-STRUCT---------
Min: 4 bytes (as float)
Max: 4 bytes (as float)
Stepping: 4 bytes (as float)
Response: 4 bytes (as int or enum)
Factor: 4 bytes (as float)
Offset: 4 bytes (as float)
//--------END-BCONTINUOUSPARAMETER-STRUCT-------------
//--------BEGIN-BDISCRETEPARAMETER-STRUCT----------------
NumItems: 4 bytes (as int)
//for each item BEGIN
Item Name String Length: 1 byte
Item Name String: 'Item Name String Length' bytes
Item Value: 4 bytes (as int)
//for each item END
//--------END-BDISCRETEPARAMETER-STRUCT-------------------
//--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
(possible) Flags: 4 bytes
Name String Length: 1 byte (??)
Name String: 'Name String Length' bytes
Param Count: 4 bytes
//for each Param BEGIN
Pointer: 4 bytes
Parameter Type: 4 bytes
Flattened Parameter Size: 4 bytes
Flattened Parameter: 'Flattened Parameter Size' bytes
//for each Param END
Subgroup Count: 4 bytes
//for each SubGroup BEGIN
Pointer: 4 bytes
MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
Flattened Group Size: 4 bytes
Flattened Group: 'Flattened Group Size' bytes
//for each SubGroup END
//---------END-CORE-BPARAMETERGROUP-STRUCT--------------
//--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
?? 0x01030506: 4 bytes
??: 4 bytes (is always 1)
Group Count: 4 bytes
Node (as media_node): 0x18 bytes (decimal 24 bytes)
//for each Group BEGIN
Flattened Group Size: 4 bytes
Flattened Group: 'Flattened Group Size' bytes
//for each Group END
//for each Group BEGIN
??: 4 bytes (never get written to (holds uninitialized value))
//for each Group END
//---------END-CORE-BPARAMETERWEB-STRUCT--------------
*/
const char * const B_GENERIC = "";
const char * const B_MASTER_GAIN = "Master";
const char * const B_GAIN = "Gain";
const char * const B_BALANCE = "Balance";
const char * const B_FREQUENCY = "Frequency";
const char * const B_LEVEL = "Level";
const char * const B_SHUTTLE_SPEED = "Speed";
const char * const B_CROSSFADE = "XFade";
const char * const B_EQUALIZATION = "EQ";
const char * const B_COMPRESSION = "Compression";
const char * const B_QUALITY = "Quality";
const char * const B_BITRATE = "Bitrate";
const char * const B_GOP_SIZE = "GOPSize";
const char * const B_MUTE = "Mute";
const char * const B_ENABLE = "Enable";
const char * const B_INPUT_MUX = "Input";
const char * const B_OUTPUT_MUX = "Output";
const char * const B_TUNER_CHANNEL = "Channel";
const char * const B_TRACK = "Track";
const char * const B_RECSTATE = "RecState";
const char * const B_SHUTTLE_MODE = "Shuttle";
const char * const B_RESOLUTION = "Resolution";
const char * const B_COLOR_SPACE = "Colorspace";
const char * const B_FRAME_RATE = "FrameRate";
const char * const B_VIDEO_FORMAT = "VideoFormat";
const char * const B_WEB_PHYSICAL_INPUT = "PhysInput";
const char * const B_WEB_PHYSICAL_OUTPUT = "PhysOutput";
const char * const B_WEB_ADC_CONVERTER = "ADC";
const char * const B_WEB_DAC_CONVERTER = "DAC";
const char * const B_WEB_LOGICAL_INPUT = "LogInput";
const char * const B_WEB_LOGICAL_OUTPUT = "LogOutput";
const char * const B_WEB_LOGICAL_BUS = "LogBus";
const char * const B_WEB_BUFFER_INPUT = "DataInput";
const char * const B_WEB_BUFFER_OUTPUT = "DataOutput";
const char * const B_SIMPLE_TRANSPORT = "SimpleTransport";
static const int32 kCurrentParameterWebVersion = 1;
static const uint32 kParameterWebMagic = 0x01030506;
static const uint32 kBufferGroupMagic = 0x03040509;
static const uint32 kBufferGroupMagicNoFlags = 0x03040507;
static const uint32 kParameterMagic = 0x02040607;
static const ssize_t kAdditionalParameterGroupSize = 12;
static const ssize_t kAdditionalParameterSize = 23 + 3 * sizeof(ssize_t);
* Min: 4 bytes (as float)
* Max: 4 bytes (as float)
* Stepping: 4 bytes (as float)
* Response: 4 bytes (as int or enum)
* Factor: 4 bytes (as float)
* Offset: 4 bytes (as float)
*/
static const ssize_t kAdditionalContinuousParameterSize = 5 * sizeof(float)
+ sizeof(BContinuousParameter::response);
static const ssize_t kAdditionalDiscreteParameterSize = sizeof(ssize_t);
template<class Type> Type
read_from_buffer(const void **_buffer)
{
const Type *typedBuffer = static_cast<const Type *>(*_buffer);
Type value = *typedBuffer;
typedBuffer++;
*_buffer = static_cast<const void *>(typedBuffer);
return value;
}
static status_t
read_string_from_buffer(const void **_buffer, char **_string, ssize_t size)
{
if (size < 1)
return B_BAD_VALUE;
const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
uint8 length = *buffer++;
if (length > size - 1)
return B_BAD_VALUE;
char *string = (char *)malloc(length + 1);
if (string == NULL)
return B_NO_MEMORY;
memcpy(string, buffer, length);
string[length] = '\0';
free(*_string);
*_buffer = static_cast<const void *>(buffer + length);
*_string = string;
return B_OK;
}
#if 0
template<class Type> Type *
reserve_in_buffer(void **_buffer)
{
Type *typedBuffer = static_cast<Type *>(*_buffer);
*typedBuffer = 0;
typedBuffer++;
*_buffer = static_cast<void *>(typedBuffer);
}
#endif
template<class Type> void
write_to_buffer(void **_buffer, Type value)
{
Type *typedBuffer = static_cast<Type *>(*_buffer);
*typedBuffer = value;
typedBuffer++;
*_buffer = static_cast<void *>(typedBuffer);
}
void
write_string_to_buffer(void **_buffer, const char *string)
{
uint8 *buffer = static_cast<uint8 *>(*_buffer);
uint32 length = string ? strlen(string) : 0;
if (length > 255)
length = 255;
*buffer++ = static_cast<uint8>(length);
if (length) {
memcpy(buffer, string, length);
buffer += length;
}
*_buffer = static_cast<void *>(buffer);
}
static void
skip_in_buffer(const void **_buffer, uint32 bytes)
{
const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
buffer += bytes;
*_buffer = static_cast<const void *>(buffer);
}
static void inline
skip_in_buffer(void **_buffer, uint32 bytes)
{
skip_in_buffer((const void **)_buffer, bytes);
}
template<class Type> Type
swap32(Type value, bool doSwap)
{
STATIC_ASSERT(sizeof(Type) == 4);
if (doSwap)
return (Type)B_SWAP_INT32((int32)value);
return value;
}
template<class Type> Type
swap64(Type value, bool doSwap)
{
STATIC_ASSERT(sizeof(Type) == 8);
if (doSwap)
return (Type)B_SWAP_INT64((int64)value);
return value;
}
template<class Type> Type
read_from_buffer_swap32(const void **_buffer, bool doSwap)
{
return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
}
template<class Type> Type
read_pointer_from_buffer_swap(const void **_buffer, bool doSwap)
{
#if B_HAIKU_32_BIT
return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
#elif B_HAIKU_64_BIT
return swap64<Type>(read_from_buffer<Type>(_buffer), doSwap);
#else
# error Interesting
#endif
}
static inline ssize_t
size_left(ssize_t size, const void *bufferStart, const void *buffer)
{
return size - static_cast<ssize_t>((const uint8 *)buffer - (const uint8 *)bufferStart);
}
BParameterWeb::BParameterWeb()
:
fNode(media_node::null)
{
CALLED();
fGroups = new BList();
fOldRefs = new BList();
fNewRefs = new BList();
}
BParameterWeb::~BParameterWeb()
{
CALLED();
for (int32 i = fGroups->CountItems(); i-- > 0;) {
delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
}
delete fGroups;
delete fOldRefs;
delete fNewRefs;
}
media_node
BParameterWeb::Node()
{
return fNode;
}
BParameterGroup*
BParameterWeb::MakeGroup(const char* name)
{
CALLED();
BParameterGroup* group = new(std::nothrow) BParameterGroup(this, name);
if (group == NULL)
return NULL;
if (!fGroups->AddItem(group)) {
delete group;
return NULL;
}
return group;
}
int32
BParameterWeb::CountGroups()
{
return fGroups->CountItems();
}
BParameterGroup*
BParameterWeb::GroupAt(int32 index)
{
return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
}
int32
BParameterWeb::CountParameters()
{
CALLED();
BList groups(*fGroups);
int32 count = 0;
for (int32 i = 0; i < groups.CountItems(); i++) {
BParameterGroup* group
= static_cast<BParameterGroup*>(groups.ItemAt(i));
count += group->CountParameters();
if (group->fGroups != NULL)
groups.AddList(group->fGroups);
}
return count;
}
BParameter*
BParameterWeb::ParameterAt(int32 index)
{
CALLED();
BList groups(*fGroups);
for (int32 i = 0; i < groups.CountItems(); i++) {
BParameterGroup* group
= static_cast<BParameterGroup*>(groups.ItemAt(i));
int32 count = group->CountParameters();
if (index < count)
return group->ParameterAt(index);
index -= count;
if (group->fGroups != NULL)
groups.AddList(group->fGroups);
}
TRACE("*** could not find parameter at %"
B_PRId32 " (count = %" B_PRId32 ")\n", index, CountParameters());
return NULL;
}
bool
BParameterWeb::IsFixedSize() const
{
return false;
}
type_code
BParameterWeb::TypeCode() const
{
return B_MEDIA_PARAMETER_WEB_TYPE;
}
ssize_t
BParameterWeb::FlattenedSize() const
{
CALLED();
//--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
?? 0x01030506: 4 bytes
??: 4 bytes (is always 1)
Group Count: 4 bytes
Node (as media_node): 0x18 bytes (decimal 24 bytes)
//for each Group BEGIN
Flattened Group Size: 4 bytes
Flattened Group: 'Flattened Group Size' bytes
//for each Group END
//for each Group BEGIN
??: 4 bytes (never get written to (holds uninitialized value))
//for each Group END
//---------END-CORE-BPARAMETERWEB-STRUCT--------------
*/
ssize_t size = sizeof(int32) + 2 * sizeof(int32) + sizeof(media_node);
for (int32 i = fGroups->CountItems(); i-- > 0;) {
BParameterGroup* group
= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
if (group != NULL) {
size += sizeof(ssize_t) + group->FlattenedSize();
}
}
return size;
}
status_t
BParameterWeb::Flatten(void* buffer, ssize_t size) const
{
CALLED();
if (buffer == NULL)
return B_NO_INIT;
ssize_t actualSize = BParameterWeb::FlattenedSize();
if (size < actualSize)
return B_NO_MEMORY;
void* bufferStart = buffer;
write_to_buffer<int32>(&buffer, kParameterWebMagic);
write_to_buffer<int32>(&buffer, kCurrentParameterWebVersion);
int32 count = fGroups->CountItems();
write_to_buffer<int32>(&buffer, count);
write_to_buffer<media_node>(&buffer, fNode);
for (int32 i = 0; i < count; i++) {
BParameterGroup* group
= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
if (group == NULL) {
ERROR("BParameterWeb::Flatten(): group is NULL\n");
continue;
}
ssize_t groupSize = group->FlattenedSize();
if (groupSize > size_left(size, bufferStart, buffer)) {
ERROR("BParameterWeb::Flatten(): buffer too small\n");
return B_BAD_VALUE;
}
write_to_buffer<ssize_t>(&buffer, groupSize);
status_t status = group->Flatten(buffer, groupSize);
if (status < B_OK)
return status;
skip_in_buffer(&buffer, groupSize);
}
return B_OK;
}
bool
BParameterWeb::AllowsTypeCode(type_code code) const
{
return code == TypeCode();
}
status_t
BParameterWeb::Unflatten(type_code code, const void* buffer, ssize_t size)
{
CALLED();
if (!AllowsTypeCode(code)) {
ERROR("BParameterWeb::Unflatten(): wrong type code\n");
return B_BAD_TYPE;
}
if (buffer == NULL) {
ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n");
return B_NO_INIT;
}
if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(int32)
+ sizeof(ssize_t) + sizeof(media_node))) {
ERROR("BParameterWeb::Unflatten(): size to small\n");
return B_ERROR;
}
const void* bufferStart = buffer;
uint32 magic = read_from_buffer<uint32>(&buffer);
bool isSwapped = false;
if (magic == B_SWAP_INT32(kParameterWebMagic)) {
isSwapped = true;
magic = B_SWAP_INT32(magic);
}
if (magic != kParameterWebMagic)
return B_BAD_DATA;
int32 version = read_from_buffer_swap32<int32>(&buffer, isSwapped);
if (version != kCurrentParameterWebVersion) {
ERROR("BParameterWeb::Unflatten(): wrong version %" B_PRId32 " (%"
B_PRIx32 ")?!\n", version, version);
return B_ERROR;
}
for (int32 i = 0; i < fGroups->CountItems(); i++) {
delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
}
fGroups->MakeEmpty();
int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
fNode = read_from_buffer<media_node>(&buffer);
if (isSwapped)
swap_data(B_INT32_TYPE, &fNode, sizeof(media_node), B_SWAP_ALWAYS);
for (int32 i = 0; i < count; i++) {
ssize_t groupSize
= read_pointer_from_buffer_swap<ssize_t>(&buffer, isSwapped);
if (groupSize > size_left(size, bufferStart, buffer)) {
ERROR("BParameterWeb::Unflatten(): buffer too small\n");
return B_BAD_DATA;
}
BParameterGroup* group = new BParameterGroup(this, "unnamed");
status_t status = group->Unflatten(group->TypeCode(), buffer,
groupSize);
if (status < B_OK) {
ERROR("BParameterWeb::Unflatten(): unflatten group failed\n");
delete group;
return status;
}
skip_in_buffer(&buffer, groupSize);
fGroups->AddItem(group);
}
BList groups(*fGroups);
for (int32 i = 0; i < groups.CountItems(); i++) {
BParameterGroup* group
= static_cast<BParameterGroup*>(groups.ItemAt(i));
for (int32 index = group->CountParameters(); index-- > 0;) {
BParameter* parameter
= static_cast<BParameter*>(group->ParameterAt(index));
parameter->FixRefs(*fOldRefs, *fNewRefs);
}
if (group->fGroups != NULL)
groups.AddList(group->fGroups);
}
fOldRefs->MakeEmpty();
fNewRefs->MakeEmpty();
return B_OK;
}
void
BParameterWeb::AddRefFix(void* oldItem, void* newItem)
{
fOldRefs->AddItem(oldItem);
fNewRefs->AddItem(newItem);
}
BParameterGroup::BParameterGroup(BParameterWeb* web, const char* name)
:
fWeb(web),
fFlags(0)
{
CALLED();
TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web, name);
fName = strndup(name, 255);
fControls = new BList();
fGroups = new BList();
}
BParameterGroup::~BParameterGroup()
{
CALLED();
for (int i = fControls->CountItems(); i-- > 0;) {
delete static_cast<BParameter*>(fControls->ItemAt(i));
}
delete fControls;
for (int i = fGroups->CountItems(); i-- > 0;) {
delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
}
delete fGroups;
free(fName);
}
BParameterWeb*
BParameterGroup::Web() const
{
return fWeb;
}
const char*
BParameterGroup::Name() const
{
return fName;
}
void
BParameterGroup::SetFlags(uint32 flags)
{
fFlags = flags;
}
uint32
BParameterGroup::Flags() const
{
return fFlags;
}
BNullParameter*
BParameterGroup::MakeNullParameter(int32 id, media_type mediaType,
const char* name, const char* kind)
{
CALLED();
BNullParameter* parameter = new(std::nothrow) BNullParameter(id, mediaType,
fWeb, name, kind);
if (parameter == NULL)
return NULL;
parameter->fGroup = this;
fControls->AddItem(parameter);
return parameter;
}
BContinuousParameter*
BParameterGroup::MakeContinuousParameter(int32 id, media_type mediaType,
const char* name, const char* kind, const char* unit,
float minimum, float maximum, float stepping)
{
CALLED();
BContinuousParameter* parameter
= new(std::nothrow) BContinuousParameter(id, mediaType, fWeb, name,
kind, unit, minimum, maximum, stepping);
if (parameter == NULL)
return NULL;
parameter->fGroup = this;
fControls->AddItem(parameter);
return parameter;
}
BDiscreteParameter*
BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType,
const char* name, const char* kind)
{
CALLED();
BDiscreteParameter* parameter = new(std::nothrow) BDiscreteParameter(id,
mediaType, fWeb, name, kind);
if (parameter == NULL)
return NULL;
parameter->fGroup = this;
fControls->AddItem(parameter);
return parameter;
}
BTextParameter*
BParameterGroup::MakeTextParameter(int32 id, media_type mediaType,
const char* name, const char* kind, size_t maxBytes)
{
CALLED();
BTextParameter* parameter = new(std::nothrow) BTextParameter(id, mediaType,
fWeb, name, kind, maxBytes);
if (parameter == NULL)
return NULL;
parameter->fGroup = this;
fControls->AddItem(parameter);
return parameter;
}
BParameterGroup*
BParameterGroup::MakeGroup(const char* name)
{
CALLED();
BParameterGroup* group = new(std::nothrow) BParameterGroup(fWeb, name);
if (group != NULL)
fGroups->AddItem(group);
return group;
}
int32
BParameterGroup::CountParameters()
{
return fControls->CountItems();
}
BParameter*
BParameterGroup::ParameterAt(int32 index)
{
return static_cast<BParameter*>(fControls->ItemAt(index));
}
int32
BParameterGroup::CountGroups()
{
return fGroups->CountItems();
}
BParameterGroup*
BParameterGroup::GroupAt(int32 index)
{
return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
}
bool
BParameterGroup::IsFixedSize() const
{
return false;
}
type_code
BParameterGroup::TypeCode() const
{
return B_MEDIA_PARAMETER_GROUP_TYPE;
}
ssize_t
BParameterGroup::FlattenedSize() const
{
CALLED();
//--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
(possible) Flags: 4 bytes
Name String Length: 1 byte (??)
Name String: 'Name String Length' bytes
Param Count: 4 bytes
//for each Param BEGIN
Pointer: 4 bytes
Parameter Type: 4 bytes
Flattened Parameter Size: 4 bytes
Flattened Parameter: 'Flattened Parameter Size' bytes
//for each Param END
Subgroup Count: 4 bytes
//for each SubGroup BEGIN
Pointer: 4 bytes
MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
Flattened Group Size: 4 bytes
Flattened Group: 'Flattened Group Size' bytes
//for each SubGroup END
//---------END-CORE-BPARAMETERGROUP-STRUCT--------------
*/
ssize_t size = 13;
if (fFlags != 0)
size += sizeof(uint32);
if (fName != NULL)
size += min_c(strlen(fName), 255);
int limit = fControls->CountItems();
for (int i = 0; i < limit; i++) {
BParameter* parameter = static_cast<BParameter*>(fControls->ItemAt(i));
if (parameter != NULL) {
size += sizeof(BParameter*) + sizeof(BParameter::media_parameter_type)
+ sizeof(ssize_t) + parameter->FlattenedSize();
}
}
limit = fGroups->CountItems();
for (int i = 0; i < limit; i++) {
BParameterGroup* group
= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
if (group != NULL) {
size += sizeof(BParameterGroup*) + sizeof(type_code)
+ sizeof(ssize_t) + group->FlattenedSize();
}
}
return size;
}
status_t
BParameterGroup::Flatten(void* buffer, ssize_t size) const
{
CALLED();
if (buffer == NULL) {
ERROR("BParameterGroup::Flatten buffer is NULL\n");
return B_NO_INIT;
}
ssize_t actualSize = BParameterGroup::FlattenedSize();
if (size < actualSize) {
ERROR("BParameterGroup::Flatten size to small\n");
return B_NO_MEMORY;
}
if (fFlags != 0) {
write_to_buffer<int32>(&buffer, kBufferGroupMagic);
write_to_buffer<uint32>(&buffer, fFlags);
} else
write_to_buffer<int32>(&buffer, kBufferGroupMagicNoFlags);
write_string_to_buffer(&buffer, fName);
int32 count = fControls->CountItems();
write_to_buffer<int32>(&buffer, count);
for (int32 i = 0; i < count; i++) {
BParameter* parameter = static_cast<BParameter*>(fControls->ItemAt(i));
if (parameter == NULL) {
ERROR("BParameterGroup::Flatten(): NULL parameter\n");
continue;
}
write_to_buffer<BParameter*>(&buffer, parameter);
write_to_buffer<BParameter::media_parameter_type>(&buffer,
parameter->Type());
ssize_t parameterSize = parameter->FlattenedSize();
write_to_buffer<ssize_t>(&buffer, parameterSize);
status_t status = parameter->Flatten(buffer, parameterSize);
if (status < B_OK)
return status;
skip_in_buffer(&buffer, parameterSize);
}
count = fGroups->CountItems();
write_to_buffer<int32>(&buffer, count);
for (int32 i = 0; i < count; i++) {
BParameterGroup* group
= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
if (group == NULL) {
ERROR("BParameterGroup::Flatten(): NULL group\n");
continue;
}
write_to_buffer<BParameterGroup*>(&buffer, group);
write_to_buffer<type_code>(&buffer, group->TypeCode());
ssize_t groupSize = group->FlattenedSize();
write_to_buffer<ssize_t>(&buffer, groupSize);
status_t status = group->Flatten(buffer, groupSize);
if (status < B_OK)
return status;
skip_in_buffer(&buffer, groupSize);
}
return B_OK;
}
bool
BParameterGroup::AllowsTypeCode(type_code code) const
{
return code == TypeCode();
}
status_t
BParameterGroup::Unflatten(type_code code, const void* buffer, ssize_t size)
{
CALLED();
if (!AllowsTypeCode(code)) {
ERROR("BParameterGroup::Unflatten() wrong type code\n");
return B_BAD_TYPE;
}
if (buffer == NULL) {
ERROR("BParameterGroup::Unflatten() buffer is NULL\n");
return B_NO_INIT;
}
if (size < static_cast<ssize_t>(sizeof(int32))) {
ERROR("BParameterGroup::Unflatten() size to small\n");
return B_ERROR;
}
const void* bufferStart = buffer;
uint32 magic = read_from_buffer<uint32>(&buffer);
bool isSwapped = false;
if (magic == B_SWAP_INT32(kBufferGroupMagic)
|| magic == B_SWAP_INT32(kBufferGroupMagicNoFlags)) {
isSwapped = true;
magic = B_SWAP_INT32(magic);
}
if (magic == kBufferGroupMagic)
fFlags = read_from_buffer_swap32<int32>(&buffer, isSwapped);
else if (magic == kBufferGroupMagicNoFlags)
fFlags = 0;
else
return B_BAD_TYPE;
if (read_string_from_buffer(&buffer, &fName,
size - (ssize_t)((uint8*)buffer - (uint8*)bufferStart)) < B_OK)
return B_BAD_VALUE;
for (int32 i = 0; i < fControls->CountItems(); i++) {
delete static_cast<BParameter*>(fControls->ItemAt(i));
}
fControls->MakeEmpty();
for (int32 i = 0; i < fGroups->CountItems(); i++) {
delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
}
fGroups->MakeEmpty();
int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
if (count < 0 || count * kAdditionalParameterSize
> size_left(size, bufferStart, buffer))
return B_BAD_VALUE;
for (int32 i = 0; i < count; i++) {
if (size_left(size, bufferStart, buffer) < (ssize_t)(
sizeof(BParameter*) + sizeof(BParameter::media_parameter_type)
+ sizeof(ssize_t))) {
return B_BAD_VALUE;
}
BParameter* oldPointer = read_pointer_from_buffer_swap<BParameter*>(
&buffer, isSwapped);
BParameter::media_parameter_type mediaType
= read_from_buffer_swap32<BParameter::media_parameter_type>(&buffer,
isSwapped);
ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
isSwapped);
if (parameterSize > size_left(size, bufferStart, buffer))
return B_BAD_VALUE;
BParameter* parameter = MakeControl(mediaType);
if (parameter == NULL) {
ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n");
return B_ERROR;
}
status_t status = parameter->Unflatten(parameter->TypeCode(), buffer,
parameterSize);
if (status < B_OK) {
ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n");
delete parameter;
return status;
}
skip_in_buffer(&buffer, parameterSize);
parameter->fGroup = this;
parameter->fWeb = fWeb;
fControls->AddItem(parameter);
if (fWeb != NULL)
fWeb->AddRefFix(oldPointer, parameter);
}
count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
if (count < 0 || count * kAdditionalParameterGroupSize
> size_left(size, bufferStart, buffer))
return B_BAD_VALUE;
for (int32 i = 0; i < count; i++) {
if (size_left(size, bufferStart, buffer) < (ssize_t)(
sizeof(BParameterGroup*) + sizeof(type_code)
+ sizeof(ssize_t))) {
return B_BAD_VALUE;
}
BParameterGroup* oldPointer = read_pointer_from_buffer_swap<
BParameterGroup*>(&buffer, isSwapped);
type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped);
ssize_t groupSize
= read_pointer_from_buffer_swap<ssize_t>(&buffer, isSwapped);
if (groupSize > size_left(size, bufferStart, buffer))
return B_BAD_VALUE;
BParameterGroup* group = new BParameterGroup(fWeb, "sub-unnamed");
if (group == NULL) {
ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n");
return B_ERROR;
}
status_t status = group->Unflatten(type, buffer, groupSize);
if (status != B_OK) {
ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n");
delete group;
return status;
}
skip_in_buffer(&buffer, groupSize);
fGroups->AddItem(group);
if (fWeb != NULL)
fWeb->AddRefFix(oldPointer, group);
}
return B_OK;
}
Unlike the BParameterGroup::MakeXXXParameter() type of methods, this
method does not add the parameter to this group automatically.
*/
BParameter*
BParameterGroup::MakeControl(int32 type)
{
CALLED();
switch (type) {
case BParameter::B_NULL_PARAMETER:
return new BNullParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL);
case BParameter::B_DISCRETE_PARAMETER:
return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
NULL);
case BParameter::B_CONTINUOUS_PARAMETER:
return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
NULL, NULL, 0, 0, 0);
case BParameter::B_TEXT_PARAMETER:
return new BTextParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, 0);
default:
ERROR("BParameterGroup::MakeControl unknown type %" B_PRId32 "\n",
type);
return NULL;
}
}
BParameter::media_parameter_type
BParameter::Type() const
{
return fType;
}
BParameterWeb*
BParameter::Web() const
{
return fWeb;
}
BParameterGroup*
BParameter::Group() const
{
return fGroup;
}
const char*
BParameter::Name() const
{
return fName;
}
const char*
BParameter::Kind() const
{
return fKind;
}
const char*
BParameter::Unit() const
{
return fUnit;
}
int32
BParameter::ID() const
{
return fID;
}
void
BParameter::SetFlags(uint32 flags)
{
fFlags = flags;
}
uint32
BParameter::Flags() const
{
return fFlags;
}
status_t
BParameter::GetValue(void* buffer, size_t* _size, bigtime_t* _when)
{
CALLED();
if (buffer == NULL || _size == NULL)
return B_BAD_VALUE;
size_t size = *_size;
if (size <= 0)
return B_NO_MEMORY;
if (fWeb == NULL) {
ERROR("BParameter::GetValue: no parent BParameterWeb\n");
return B_NO_INIT;
}
media_node node = fWeb->Node();
if (IS_INVALID_NODE(node)) {
ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n");
return B_NO_INIT;
}
controllable_get_parameter_data_request request;
controllable_get_parameter_data_reply reply;
area_id area;
void* data;
if (size > MAX_PARAMETER_DATA) {
area = create_area("get parameter data", &data, B_ANY_ADDRESS,
ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (area < B_OK) {
ERROR("BParameter::GetValue can't create area of %ld bytes\n",
size);
return B_NO_MEMORY;
}
} else {
area = -1;
data = reply.raw_data;
}
request.parameter_id = fID;
request.request_size = size;
request.area = area;
status_t status = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_DATA,
&request, sizeof(request), &reply, sizeof(reply));
if (status == B_OK) {
if (reply.size < size)
size = reply.size;
memcpy(buffer, data, size);
*_size = reply.size;
if (_when != NULL)
*_when = reply.last_change;
} else {
ERROR("BParameter::GetValue parameter '%s' querying node %d, "
"port %d failed: %s\n", fName, (int)node.node, (int)node.port,
strerror(status));
}
if (area >= B_OK)
delete_area(area);
return status;
}
status_t
BParameter::SetValue(const void* buffer, size_t size, bigtime_t when)
{
CALLED();
if (buffer == 0)
return B_BAD_VALUE;
if (size <= 0)
return B_NO_MEMORY;
if (fWeb == 0) {
ERROR("BParameter::SetValue: no parent BParameterWeb\n");
return B_NO_INIT;
}
media_node node = fWeb->Node();
if (IS_INVALID_NODE(node)) {
ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned "
"to a BMediaNode\n");
return B_NO_INIT;
}
controllable_set_parameter_data_request request;
controllable_set_parameter_data_reply reply;
area_id area;
void* data;
if (size > MAX_PARAMETER_DATA) {
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) {
ERROR("BParameter::SetValue can't create area of %ld bytes\n", size);
return B_NO_MEMORY;
}
} else {
area = -1;
data = request.raw_data;
}
memcpy(data, buffer, size);
request.parameter_id = fID;
request.when = when;
request.area = area;
request.size = size;
status_t status = QueryPort(node.port, CONTROLLABLE_SET_PARAMETER_DATA,
&request, sizeof(request), &reply, sizeof(reply));
if (status != B_OK) {
ERROR("BParameter::SetValue querying node failed: %s\n",
strerror(status));
}
if (area != -1)
delete_area(area);
return status;
}
int32
BParameter::CountChannels()
{
return fChannels;
}
void
BParameter::SetChannelCount(int32 count)
{
fChannels = count;
}
media_type
BParameter::MediaType()
{
return fMediaType;
}
void
BParameter::SetMediaType(media_type type)
{
fMediaType = type;
}
int32
BParameter::CountInputs()
{
return fInputs->CountItems();
}
BParameter*
BParameter::InputAt(int32 index)
{
return static_cast<BParameter*>(fInputs->ItemAt(index));
}
void
BParameter::AddInput(BParameter* input)
{
CALLED();
if (input == NULL)
return;
if (fInputs->HasItem(input)) {
return;
}
fInputs->AddItem(input);
input->AddOutput(this);
}
int32
BParameter::CountOutputs()
{
return fOutputs->CountItems();
}
BParameter*
BParameter::OutputAt(int32 index)
{
return static_cast<BParameter*>(fOutputs->ItemAt(index));
}
void
BParameter::AddOutput(BParameter* output)
{
CALLED();
if (output == NULL)
return;
if (fOutputs->HasItem(output)) {
return;
}
fOutputs->AddItem(output);
output->AddInput(this);
}
bool
BParameter::IsFixedSize() const
{
return false;
}
type_code
BParameter::TypeCode() const
{
return B_MEDIA_PARAMETER_TYPE;
}
ssize_t
BParameter::FlattenedSize() const
{
CALLED();
?? (0x02040607): 4 bytes
BParameter Struct Size (in bytes): 4 bytes
ID: 4 bytes
Name String Length: 1 byte (??)
Name String: 'Name String Length' bytes
Kind String Length: 1 byte (??)
Kind String: 'Kind String Length' bytes
Unit String Length: 1 byte (??)
Unit String: 'Unit String Length' bytes
Inputs Count: 4 bytes
Inputs (pointers): ('Inputs Count')*4 bytes
Outputs Count: 4 bytes
Outputs (pointers): ('Outputs Count')*4 bytes
Media Type: 4 bytes
ChannelCount: 4 bytes
Flags: 4 bytes
*/
ssize_t size = kAdditionalParameterSize;
if (fName != NULL)
size += strlen(fName);
if (fKind != NULL)
size += strlen(fKind);
if (fUnit != NULL)
size += strlen(fUnit);
size += fInputs->CountItems() * sizeof(BParameter*);
size += fOutputs->CountItems() * sizeof(BParameter*);
return size;
}
status_t
BParameter::Flatten(void* buffer, ssize_t size) const
{
CALLED();
if (buffer == NULL) {
ERROR("BParameter::Flatten buffer is NULL\n");
return B_NO_INIT;
}
ssize_t actualSize = BParameter::FlattenedSize();
if (size < actualSize) {
ERROR("BParameter::Flatten(): size too small\n");
return B_NO_MEMORY;
}
write_to_buffer<uint32>(&buffer, kParameterMagic);
write_to_buffer<ssize_t>(&buffer, actualSize);
write_to_buffer<int32>(&buffer, fID);
write_string_to_buffer(&buffer, fName);
write_string_to_buffer(&buffer, fKind);
write_string_to_buffer(&buffer, fUnit);
ssize_t count = fInputs->CountItems();
write_to_buffer<ssize_t>(&buffer, count);
if (count > 0) {
memcpy(buffer, fInputs->Items(), sizeof(BParameter*) * count);
skip_in_buffer(&buffer, sizeof(BParameter*) * count);
}
count = fOutputs->CountItems();
write_to_buffer<ssize_t>(&buffer, count);
if (count > 0) {
memcpy(buffer, fOutputs->Items(), sizeof(BParameter*) * count);
skip_in_buffer(&buffer, sizeof(BParameter*) * count);
}
write_to_buffer<media_type>(&buffer, fMediaType);
write_to_buffer<int32>(&buffer, fChannels);
write_to_buffer<uint32>(&buffer, fFlags);
return B_OK;
}
bool
BParameter::AllowsTypeCode(type_code code) const
{
return code == TypeCode();
}
status_t
BParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
{
CALLED();
if (!AllowsTypeCode(code)) {
ERROR("BParameter::Unflatten(): wrong type code\n");
return B_BAD_TYPE;
}
if (buffer == NULL) {
ERROR("BParameter::Unflatten(): buffer is NULL\n");
return B_NO_INIT;
}
if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
ERROR("BParameter::Unflatten() size too small\n");
return B_BAD_VALUE;
}
const void* bufferStart = buffer;
uint32 magic = read_from_buffer<uint32>(&buffer);
if (magic == B_SWAP_INT32(kParameterMagic))
fSwapDetected = true;
else if (magic == kParameterMagic)
fSwapDetected = false;
else {
ERROR("BParameter::Unflatten(): bad magic\n");
return B_BAD_TYPE;
}
ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
fSwapDetected);
if (parameterSize > size) {
ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n",
parameterSize, size);
return B_BAD_VALUE;
}
const ssize_t kMinFlattenedParamSize = 15 + 3 * sizeof(ssize_t);
if (parameterSize < kMinFlattenedParamSize) {
ERROR("BParameter::Unflatten out of memory (2)\n");
return B_ERROR;
}
fID = read_from_buffer_swap32<int32>(&buffer, fSwapDetected);
if (read_string_from_buffer(&buffer, &fName,
size_left(size, bufferStart, buffer)) < B_OK
|| read_string_from_buffer(&buffer, &fKind,
size_left(size, bufferStart, buffer)) < B_OK
|| read_string_from_buffer(&buffer, &fUnit,
size_left(size, bufferStart, buffer)) < B_OK)
return B_NO_MEMORY;
ssize_t count = read_pointer_from_buffer_swap<ssize_t>(&buffer,
fSwapDetected);
fInputs->MakeEmpty();
for (ssize_t i = 0; i < count; i++) {
fInputs->AddItem(read_pointer_from_buffer_swap<BParameter * const>(
&buffer, fSwapDetected));
}
count = read_pointer_from_buffer_swap<ssize_t>(&buffer, fSwapDetected);
fOutputs->MakeEmpty();
for (ssize_t i = 0; i < count; i++) {
fOutputs->AddItem(read_pointer_from_buffer_swap<BParameter * const>(
&buffer, fSwapDetected));
}
fMediaType = read_from_buffer_swap32<media_type>(&buffer, fSwapDetected);
fChannels = read_from_buffer_swap32<int32>(&buffer, fSwapDetected);
fFlags = read_from_buffer_swap32<uint32>(&buffer, fSwapDetected);
return B_OK;
}
BParameter::BParameter(int32 id, media_type mediaType,
media_parameter_type type, BParameterWeb* web, const char* name,
const char* kind, const char* unit)
:
fID(id),
fType(type),
fWeb(web),
fGroup(NULL),
fSwapDetected(true),
fMediaType(mediaType),
fChannels(1),
fFlags(0)
{
CALLED();
fName = strndup(name, 255);
fKind = strndup(kind, 255);
fUnit = strndup(unit, 255);
fInputs = new BList();
fOutputs = new BList();
}
BParameter::~BParameter()
{
CALLED();
free(fName);
free(fKind);
free(fUnit);
delete fInputs;
delete fOutputs;
}
items in the updated list. The references are replaced in the input
and output lists.
This is called by BParameterWeb::Unflatten().
*/
void
BParameter::FixRefs(BList& old, BList& updated)
{
CALLED();
void** items = static_cast<void**>(fInputs->Items());
int32 count = fInputs->CountItems();
for (int32 i = 0; i < count; i++) {
int32 index = old.IndexOf(items[i]);
if (index >= 0)
items[i] = updated.ItemAt(index);
else {
ERROR("BParameter::FixRefs(): No mapping found for input");
items[i] = NULL;
}
}
for (int32 i = count; i-- > 0;) {
if (items[i] == NULL)
fInputs->RemoveItem(i);
}
items = static_cast<void **>(fOutputs->Items());
count = fOutputs->CountItems();
for (int32 i = 0; i < count; i++) {
int32 index = old.IndexOf(items[i]);
if (index >= 0)
items[i] = updated.ItemAt(index);
else {
ERROR("BParameter::FixRefs(): No mapping found for output");
items[i] = NULL;
}
}
for (int32 i = count; i-- > 0;) {
if (items[i] == NULL)
fOutputs->RemoveItem(i);
}
}
type_code
BContinuousParameter::ValueType()
{
return B_FLOAT_TYPE;
}
float
BContinuousParameter::MinValue()
{
return fMinimum;
}
float
BContinuousParameter::MaxValue()
{
return fMaximum;
}
float
BContinuousParameter::ValueStep()
{
return fStepping;
}
void
BContinuousParameter::SetResponse(int resp, float factor, float offset)
{
fResponse = static_cast<response>(resp);
fFactor = factor;
fOffset = offset;
}
void
BContinuousParameter::GetResponse(int* _resp, float* _factor, float* _offset)
{
if (_resp != NULL)
*_resp = fResponse;
if (_factor != NULL)
*_factor = fFactor;
if (_offset != NULL)
*_offset = fOffset;
}
ssize_t
BContinuousParameter::FlattenedSize() const
{
CALLED();
return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize;
}
status_t
BContinuousParameter::Flatten(void* buffer, ssize_t size) const
{
CALLED();
if (buffer == NULL) {
ERROR("BContinuousParameter::Flatten(): buffer is NULL\n");
return B_NO_INIT;
}
ssize_t parameterSize = BParameter::FlattenedSize();
if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
ERROR("BContinuousParameter::Flatten(): size to small\n");
return B_NO_MEMORY;
}
status_t status = BParameter::Flatten(buffer, size);
if (status != B_OK) {
ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n");
return status;
}
skip_in_buffer(&buffer, parameterSize);
write_to_buffer<float>(&buffer, fMinimum);
write_to_buffer<float>(&buffer, fMaximum);
write_to_buffer<float>(&buffer, fStepping);
write_to_buffer<response>(&buffer, fResponse);
write_to_buffer<float>(&buffer, fFactor);
write_to_buffer<float>(&buffer, fOffset);
return B_OK;
}
status_t
BContinuousParameter::Unflatten(type_code code, const void* buffer,
ssize_t size)
{
CALLED();
if (!AllowsTypeCode(code)) {
ERROR("BContinuousParameter::Unflatten wrong type code\n");
return B_BAD_TYPE;
}
if (buffer == NULL) {
ERROR("BContinuousParameter::Unflatten buffer is NULL\n");
return B_NO_INIT;
}
if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
ERROR("BContinuousParameter::Unflatten size too small\n");
return B_ERROR;
}
status_t status = BParameter::Unflatten(code, buffer, size);
if (status != B_OK) {
ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten "
"failed: %s\n", strerror(status));
return status;
}
ssize_t parameterSize = BParameter::FlattenedSize();
skip_in_buffer(&buffer, parameterSize);
if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
ERROR("BContinuousParameter::Unflatten(): buffer too small\n");
return B_BAD_VALUE;
}
fMinimum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
fMaximum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
fStepping = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
fResponse = read_from_buffer_swap32<response>(&buffer, SwapOnUnflatten());
fFactor = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
fOffset = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
return B_OK;
}
BContinuousParameter::BContinuousParameter(int32 id, media_type mediaType,
BParameterWeb* web, const char* name, const char* kind,
const char* unit, float minimum, float maximum, float stepping)
: BParameter(id, mediaType, B_CONTINUOUS_PARAMETER, web, name, kind, unit),
fMinimum(minimum),
fMaximum(maximum),
fStepping(stepping),
fResponse(B_LINEAR),
fFactor(1.0),
fOffset(0.0)
{
CALLED();
}
BContinuousParameter::~BContinuousParameter()
{
CALLED();
}
type_code
BDiscreteParameter::ValueType()
{
return B_INT32_TYPE;
}
int32
BDiscreteParameter::CountItems()
{
return fValues->CountItems();
}
const char*
BDiscreteParameter::ItemNameAt(int32 index)
{
return reinterpret_cast<const char*>(fSelections->ItemAt(index));
}
int32
BDiscreteParameter::ItemValueAt(int32 index)
{
int32* item = static_cast<int32*>(fValues->ItemAt(index));
if (item == NULL)
return 0;
return *item;
}
status_t
BDiscreteParameter::AddItem(int32 value, const char* name)
{
CALLED();
int32* valueCopy = new(std::nothrow) int32(value);
if (valueCopy == NULL)
return B_NO_MEMORY;
char* nameCopy = strndup(name, 255);
if (name != NULL && nameCopy == NULL) {
delete valueCopy;
return B_NO_MEMORY;
}
if (!fValues->AddItem(valueCopy))
goto err;
if (!fSelections->AddItem(nameCopy)) {
fValues->RemoveItem(valueCopy);
goto err;
}
return B_OK;
err:
free(nameCopy);
delete valueCopy;
return B_NO_MEMORY;
}
status_t
BDiscreteParameter::MakeItemsFromInputs()
{
CALLED();
int32 count = fInputs->CountItems();
for (int32 i = 0; i < count; i++) {
BParameter* parameter = static_cast<BParameter*>(fInputs->ItemAt(i));
AddItem(i, parameter->Name());
}
return B_OK;
}
status_t
BDiscreteParameter::MakeItemsFromOutputs()
{
CALLED();
int32 count = fOutputs->CountItems();
for (int32 i = 0; i < count; i++) {
BParameter* parameter = static_cast<BParameter*>(fOutputs->ItemAt(i));
AddItem(i, parameter->Name());
}
return B_OK;
}
void
BDiscreteParameter::MakeEmpty()
{
CALLED();
for (int32 i = fValues->CountItems(); i-- > 0;) {
delete static_cast<int32*>(fValues->ItemAt(i));
}
fValues->MakeEmpty();
for (int32 i = fSelections->CountItems(); i-- > 0;) {
free(static_cast<char*>(fSelections->ItemAt(i)));
}
fSelections->MakeEmpty();
}
ssize_t
BDiscreteParameter::FlattenedSize() const
{
CALLED();
ssize_t size = BParameter::FlattenedSize()
+ kAdditionalDiscreteParameterSize;
int32 count = fValues->CountItems();
for (int32 i = 0; i < count; i++) {
char* selection = static_cast<char*>(fSelections->ItemAt(i));
if (selection != NULL)
size += min_c(strlen(selection), 255);
size += 5;
}
return size;
}
status_t
BDiscreteParameter::Flatten(void* buffer, ssize_t size) const
{
CALLED();
if (buffer == NULL) {
ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n");
return B_NO_INIT;
}
ssize_t parameterSize = BParameter::FlattenedSize();
if (size < FlattenedSize()) {
ERROR("BDiscreteParameter::Flatten(): size too small\n");
return B_NO_MEMORY;
}
status_t status = BParameter::Flatten(buffer, size);
if (status != B_OK) {
ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n");
return status;
}
skip_in_buffer(&buffer, parameterSize);
int32 count = fValues->CountItems();
write_to_buffer<int32>(&buffer, count);
for (int32 i = 0; i < count; i++) {
const char* selection = static_cast<char*>(fSelections->ItemAt(i));
const int32* value = static_cast<int32*>(fValues->ItemAt(i));
write_string_to_buffer(&buffer, selection);
write_to_buffer<int32>(&buffer, value ? *value : 0);
}
return B_OK;
}
status_t
BDiscreteParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
{
CALLED();
if (!AllowsTypeCode(code)) {
ERROR("BDiscreteParameter::Unflatten(): bad type code\n");
return B_BAD_TYPE;
}
if (buffer == NULL) {
ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n");
return B_NO_INIT;
}
if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
ERROR("BDiscreteParameter::Unflatten(): size too small\n");
return B_ERROR;
}
const void* bufferStart = buffer;
status_t status = BParameter::Unflatten(code, buffer, size);
if (status != B_OK) {
ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n");
return status;
}
ssize_t parameterSize = BParameter::FlattenedSize();
skip_in_buffer(&buffer, parameterSize);
if (size < (parameterSize + kAdditionalDiscreteParameterSize)) {
ERROR("BDiscreteParameter::Unflatten(): buffer too small\n");
return B_BAD_VALUE;
}
int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten());
MakeEmpty();
for (int32 i = 0; i < count; i++) {
char* name = NULL;
if (read_string_from_buffer(&buffer, &name, size_left(size, bufferStart,
buffer)) < B_OK)
return B_BAD_DATA;
if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) {
free(name);
return B_BAD_DATA;
}
int32 value = read_from_buffer_swap32<int32>(&buffer,
SwapOnUnflatten());
AddItem(value, name);
free(name);
}
return B_OK;
}
BDiscreteParameter::BDiscreteParameter(int32 id, media_type mediaType,
BParameterWeb* web, const char* name, const char* kind)
: BParameter(id, mediaType, B_DISCRETE_PARAMETER, web, name, kind, NULL)
{
CALLED();
fSelections = new BList();
fValues = new BList();
}
BDiscreteParameter::~BDiscreteParameter()
{
CALLED();
MakeEmpty();
delete fSelections;
delete fValues;
}
size_t
BTextParameter::MaxBytes() const
{
return fMaxBytes;
}
type_code
BTextParameter::ValueType()
{
return B_FLOAT_TYPE;
}
ssize_t
BTextParameter::FlattenedSize() const
{
return BParameter::FlattenedSize() + sizeof(fMaxBytes);
}
status_t
BTextParameter::Flatten(void* buffer, ssize_t size) const
{
if (buffer == NULL) {
ERROR("BTextParameter::Flatten(): buffer is NULL\n");
return B_NO_INIT;
}
ssize_t parameterSize = BParameter::FlattenedSize();
if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
ERROR("BContinuousParameter::Flatten(): size to small\n");
return B_NO_MEMORY;
}
status_t status = BParameter::Flatten(buffer, size);
if (status != B_OK) {
ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n");
return status;
}
skip_in_buffer(&buffer, parameterSize);
write_to_buffer<uint32>(&buffer, fMaxBytes);
return B_OK;
}
status_t
BTextParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
{
if (!AllowsTypeCode(code)) {
ERROR("BTextParameter::Unflatten wrong type code\n");
return B_BAD_TYPE;
}
if (buffer == NULL) {
ERROR("BTextParameter::Unflatten buffer is NULL\n");
return B_NO_INIT;
}
if (size < static_cast<ssize_t>(sizeof(fMaxBytes))) {
ERROR("BTextParameter::Unflatten size too small\n");
return B_ERROR;
}
status_t status = BParameter::Unflatten(code, buffer, size);
if (status != B_OK) {
ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n");
return status;
}
ssize_t parameterSize = BParameter::FlattenedSize();
skip_in_buffer(&buffer, parameterSize);
if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
ERROR("BTextParameter::Unflatten(): buffer too small\n");
return B_BAD_VALUE;
}
fMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten());
return B_OK;
}
BTextParameter::BTextParameter(int32 id, media_type mediaType,
BParameterWeb* web, const char* name, const char* kind,
size_t maxBytes)
: BParameter(id, mediaType, B_TEXT_PARAMETER, web, name, kind, NULL)
{
fMaxBytes = maxBytes;
}
BTextParameter::~BTextParameter()
{
}
type_code
BNullParameter::ValueType()
{
return 0;
}
ssize_t
BNullParameter::FlattenedSize() const
{
return BParameter::FlattenedSize();
}
status_t
BNullParameter::Flatten(void* buffer, ssize_t size) const
{
return BParameter::Flatten(buffer, size);
}
status_t
BNullParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
{
return BParameter::Unflatten(code, buffer, size);
}
BNullParameter::BNullParameter(int32 id, media_type mediaType,
BParameterWeb* web, const char* name, const char* kind)
: BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL)
{
}
BNullParameter::~BNullParameter()
{
}
status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; }
status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; }
status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; }
status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; }
status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; }
status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; }
status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; }
status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; }
status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; }
status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; }
status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; }
status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; }
status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR; }
status_t BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR; }