2 * Copyright 2002-2012, Haiku. All Rights Reserved.
3 * This file may be used under the terms of the MIT License.
5 * Author: Zousar Shaker
6 * Axel Dörfler, axeld@pinc-software.de
11 /*! Implements the following classes:
12 BParameterWeb, BParameterGroup, BParameter, BNullParameter,
13 BContinuousParameter, BDiscreteParameter
17 #include <ParameterWeb.h>
22 #include <MediaNode.h>
23 #include <MediaRoster.h>
25 #include "DataExchange.h"
27 #include "MediaMisc.h"
31 The following is documentation on the flattened format
32 of structures/classes in this module:
34 //--------BEGIN-CORE-BPARAMETER-STRUCT---------------------
35 ?? (0x02040607): 4 bytes
36 BParameter Struct Size (in bytes): 4 bytes
38 Name String Length: 1 byte (??)
39 Name String: 'Name String Length' bytes
40 Kind String Length: 1 byte (??)
41 Kind String: 'Kind String Length' bytes
42 Unit String Length: 1 byte (??)
43 Unit String: 'Unit String Length' bytes
45 Inputs (pointers): ('Inputs Count')*4 bytes
46 Outputs Count: 4 bytes
47 Outputs (pointers): ('Outputs Count')*4 bytes
51 //---------END-CORE-BPARAMETER-STRUCT-----------------------
52 //--------BEGIN-BCONTINUOUSPARAMETER-STRUCT---------
53 Min: 4 bytes (as float)
54 Max: 4 bytes (as float)
55 Stepping: 4 bytes (as float)
56 Response: 4 bytes (as int or enum)
57 Factor: 4 bytes (as float)
58 Offset: 4 bytes (as float)
59 //--------END-BCONTINUOUSPARAMETER-STRUCT-------------
60 //--------BEGIN-BDISCRETEPARAMETER-STRUCT----------------
61 NumItems: 4 bytes (as int)
63 Item Name String Length: 1 byte
64 Item Name String: 'Item Name String Length' bytes
65 Item Value: 4 bytes (as int)
67 //--------END-BDISCRETEPARAMETER-STRUCT-------------------
69 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
70 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
71 (possible) Flags: 4 bytes
72 Name String Length: 1 byte (??)
73 Name String: 'Name String Length' bytes
75 //for each Param BEGIN
77 Parameter Type: 4 bytes
78 Flattened Parameter Size: 4 bytes
79 Flattened Parameter: 'Flattened Parameter Size' bytes
81 Subgroup Count: 4 bytes
82 //for each SubGroup BEGIN
84 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
85 Flattened Group Size: 4 bytes
86 Flattened Group: 'Flattened Group Size' bytes
87 //for each SubGroup END
89 //---------END-CORE-BPARAMETERGROUP-STRUCT--------------
91 //--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
92 ?? 0x01030506: 4 bytes
93 ??: 4 bytes (is always 1)
95 Node (as media_node): 0x18 bytes (decimal 24 bytes)
96 //for each Group BEGIN
97 Flattened Group Size: 4 bytes
98 Flattened Group: 'Flattened Group Size' bytes
100 //for each Group BEGIN
101 ??: 4 bytes (never get written to (holds uninitialized value))
103 //---------END-CORE-BPARAMETERWEB-STRUCT--------------
108 const char * const B_GENERIC
= "";
109 const char * const B_MASTER_GAIN
= "Master";
110 const char * const B_GAIN
= "Gain";
111 const char * const B_BALANCE
= "Balance";
112 const char * const B_FREQUENCY
= "Frequency";
113 const char * const B_LEVEL
= "Level";
114 const char * const B_SHUTTLE_SPEED
= "Speed";
115 const char * const B_CROSSFADE
= "XFade";
116 const char * const B_EQUALIZATION
= "EQ";
117 const char * const B_COMPRESSION
= "Compression";
118 const char * const B_QUALITY
= "Quality";
119 const char * const B_BITRATE
= "Bitrate";
120 const char * const B_GOP_SIZE
= "GOPSize";
121 const char * const B_MUTE
= "Mute";
122 const char * const B_ENABLE
= "Enable";
123 const char * const B_INPUT_MUX
= "Input";
124 const char * const B_OUTPUT_MUX
= "Output";
125 const char * const B_TUNER_CHANNEL
= "Channel";
126 const char * const B_TRACK
= "Track";
127 const char * const B_RECSTATE
= "RecState";
128 const char * const B_SHUTTLE_MODE
= "Shuttle";
129 const char * const B_RESOLUTION
= "Resolution";
130 const char * const B_COLOR_SPACE
= "Colorspace";
131 const char * const B_FRAME_RATE
= "FrameRate";
132 const char * const B_VIDEO_FORMAT
= "VideoFormat";
133 const char * const B_WEB_PHYSICAL_INPUT
= "PhysInput";
134 const char * const B_WEB_PHYSICAL_OUTPUT
= "PhysOutput";
135 const char * const B_WEB_ADC_CONVERTER
= "ADC";
136 const char * const B_WEB_DAC_CONVERTER
= "DAC";
137 const char * const B_WEB_LOGICAL_INPUT
= "LogInput";
138 const char * const B_WEB_LOGICAL_OUTPUT
= "LogOutput";
139 const char * const B_WEB_LOGICAL_BUS
= "LogBus";
140 const char * const B_WEB_BUFFER_INPUT
= "DataInput";
141 const char * const B_WEB_BUFFER_OUTPUT
= "DataOutput";
142 const char * const B_SIMPLE_TRANSPORT
= "SimpleTransport";
146 static const int32 kCurrentParameterWebVersion
= 1;
147 static const uint32 kParameterWebMagic
= 0x01030506;
148 static const uint32 kBufferGroupMagic
= 0x03040509;
149 static const uint32 kBufferGroupMagicNoFlags
= 0x03040507;
150 static const uint32 kParameterMagic
= 0x02040607;
152 static const ssize_t kAdditionalParameterGroupSize
= 12;
153 static const ssize_t kAdditionalParameterSize
= 23 + 3 * sizeof(ssize_t
);
155 /* BContinuousParameter - FlattenedSize() fixed part
156 * Min: 4 bytes (as float)
157 * Max: 4 bytes (as float)
158 * Stepping: 4 bytes (as float)
159 * Response: 4 bytes (as int or enum)
160 * Factor: 4 bytes (as float)
161 * Offset: 4 bytes (as float)
163 static const ssize_t kAdditionalContinuousParameterSize
= 5 * sizeof(float)
164 + sizeof(BContinuousParameter::response
);
165 static const ssize_t kAdditionalDiscreteParameterSize
= sizeof(ssize_t
);
171 template<class Type
> Type
172 read_from_buffer(const void **_buffer
)
174 const Type
*typedBuffer
= static_cast<const Type
*>(*_buffer
);
175 Type value
= *typedBuffer
;
178 *_buffer
= static_cast<const void *>(typedBuffer
);
185 read_string_from_buffer(const void **_buffer
, char **_string
, ssize_t size
)
190 const uint8
*buffer
= static_cast<const uint8
*>(*_buffer
);
191 uint8 length
= *buffer
++;
192 if (length
> size
- 1)
195 char *string
= (char *)malloc(length
+ 1);
199 memcpy(string
, buffer
, length
);
200 string
[length
] = '\0';
204 *_buffer
= static_cast<const void *>(buffer
+ length
);
212 template<class Type
> Type
*
213 reserve_in_buffer(void **_buffer
)
215 Type
*typedBuffer
= static_cast<Type
*>(*_buffer
);
220 *_buffer
= static_cast<void *>(typedBuffer
);
224 template<class Type
> void
225 write_to_buffer(void **_buffer
, Type value
)
227 Type
*typedBuffer
= static_cast<Type
*>(*_buffer
);
229 *typedBuffer
= value
;
232 *_buffer
= static_cast<void *>(typedBuffer
);
237 write_string_to_buffer(void **_buffer
, const char *string
)
239 uint8
*buffer
= static_cast<uint8
*>(*_buffer
);
240 uint32 length
= string
? strlen(string
) : 0;
244 *buffer
++ = static_cast<uint8
>(length
);
246 memcpy(buffer
, string
, length
);
250 *_buffer
= static_cast<void *>(buffer
);
255 skip_in_buffer(const void **_buffer
, uint32 bytes
)
257 const uint8
*buffer
= static_cast<const uint8
*>(*_buffer
);
261 *_buffer
= static_cast<const void *>(buffer
);
266 skip_in_buffer(void **_buffer
, uint32 bytes
)
268 // This actually shouldn't be necessary, but I believe it's a
269 // bug in Be's gcc - it complains about "adds cv-quals without intervening `const'"
270 // when passing a "const void **" pointer as the first argument.
271 // Maybe I am just stupid, though -- axeld.
273 skip_in_buffer((const void **)_buffer
, bytes
);
277 template<class Type
> Type
278 swap32(Type value
, bool doSwap
)
280 STATIC_ASSERT(sizeof(Type
) == 4);
283 return (Type
)B_SWAP_INT32((int32
)value
);
289 template<class Type
> Type
290 swap64(Type value
, bool doSwap
)
292 STATIC_ASSERT(sizeof(Type
) == 8);
295 return (Type
)B_SWAP_INT64((int64
)value
);
301 template<class Type
> Type
302 read_from_buffer_swap32(const void **_buffer
, bool doSwap
)
304 return swap32
<Type
>(read_from_buffer
<Type
>(_buffer
), doSwap
);
308 template<class Type
> Type
309 read_pointer_from_buffer_swap(const void **_buffer
, bool doSwap
)
312 return swap32
<Type
>(read_from_buffer
<Type
>(_buffer
), doSwap
);
314 return swap64
<Type
>(read_from_buffer
<Type
>(_buffer
), doSwap
);
321 static inline ssize_t
322 size_left(ssize_t size
, const void *bufferStart
, const void *buffer
)
324 return size
- static_cast<ssize_t
>((const uint8
*)buffer
- (const uint8
*)bufferStart
);
328 // #pragma mark - BParameterWeb
331 BParameterWeb::BParameterWeb()
333 fNode(media_node::null
)
334 // fNode is set in BControllable::SetParameterWeb()
338 fGroups
= new BList();
339 fOldRefs
= new BList();
340 fNewRefs
= new BList();
344 BParameterWeb::~BParameterWeb()
348 for (int32 i
= fGroups
->CountItems(); i
-- > 0;) {
349 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
359 BParameterWeb::Node()
366 BParameterWeb::MakeGroup(const char* name
)
370 BParameterGroup
* group
= new(std::nothrow
) BParameterGroup(this, name
);
374 if (!fGroups
->AddItem(group
)) {
384 BParameterWeb::CountGroups()
386 return fGroups
->CountItems();
391 BParameterWeb::GroupAt(int32 index
)
393 return static_cast<BParameterGroup
*>(fGroups
->ItemAt(index
));
398 BParameterWeb::CountParameters()
402 // Counts over all groups (and sub-groups) in the web.
403 // The "groups" list is used as count stack
405 BList
groups(*fGroups
);
408 for (int32 i
= 0; i
< groups
.CountItems(); i
++) {
409 BParameterGroup
* group
410 = static_cast<BParameterGroup
*>(groups
.ItemAt(i
));
412 count
+= group
->CountParameters();
414 if (group
->fGroups
!= NULL
)
415 groups
.AddList(group
->fGroups
);
423 BParameterWeb::ParameterAt(int32 index
)
427 // Iterates over all groups (and sub-groups) in the web.
428 // The "groups" list is used as iteration stack (breadth search style)
429 // Maintains the same order as the Be implementation
431 BList
groups(*fGroups
);
433 for (int32 i
= 0; i
< groups
.CountItems(); i
++) {
434 BParameterGroup
* group
435 = static_cast<BParameterGroup
*>(groups
.ItemAt(i
));
436 int32 count
= group
->CountParameters();
438 return group
->ParameterAt(index
);
441 // the index is always relative to the start of the current group
443 if (group
->fGroups
!= NULL
)
444 groups
.AddList(group
->fGroups
);
447 TRACE("*** could not find parameter at %"
448 B_PRId32
" (count = %" B_PRId32
")\n", index
, CountParameters());
455 BParameterWeb::IsFixedSize() const
462 BParameterWeb::TypeCode() const
464 return B_MEDIA_PARAMETER_WEB_TYPE
;
469 BParameterWeb::FlattenedSize() const
474 //--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
475 ?? 0x01030506: 4 bytes
476 ??: 4 bytes (is always 1)
478 Node (as media_node): 0x18 bytes (decimal 24 bytes)
479 //for each Group BEGIN
480 Flattened Group Size: 4 bytes
481 Flattened Group: 'Flattened Group Size' bytes
483 //for each Group BEGIN
484 ??: 4 bytes (never get written to (holds uninitialized value))
486 //---------END-CORE-BPARAMETERWEB-STRUCT--------------
488 //36 guaranteed bytes, variable after that.
489 ssize_t size
= sizeof(int32
) + 2 * sizeof(int32
) + sizeof(media_node
);
491 for (int32 i
= fGroups
->CountItems(); i
-- > 0;) {
492 BParameterGroup
* group
493 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
495 size
+= sizeof(ssize_t
) + group
->FlattenedSize();
504 BParameterWeb::Flatten(void* buffer
, ssize_t size
) const
511 ssize_t actualSize
= BParameterWeb::FlattenedSize();
512 if (size
< actualSize
)
515 void* bufferStart
= buffer
;
517 write_to_buffer
<int32
>(&buffer
, kParameterWebMagic
);
518 write_to_buffer
<int32
>(&buffer
, kCurrentParameterWebVersion
);
520 // flatten all groups into this buffer
522 int32 count
= fGroups
->CountItems();
523 write_to_buffer
<int32
>(&buffer
, count
);
525 write_to_buffer
<media_node
>(&buffer
, fNode
);
527 for (int32 i
= 0; i
< count
; i
++) {
528 BParameterGroup
* group
529 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
531 ERROR("BParameterWeb::Flatten(): group is NULL\n");
535 ssize_t groupSize
= group
->FlattenedSize();
536 if (groupSize
> size_left(size
, bufferStart
, buffer
)) {
537 ERROR("BParameterWeb::Flatten(): buffer too small\n");
541 write_to_buffer
<ssize_t
>(&buffer
, groupSize
);
543 // write the flattened sub group
544 status_t status
= group
->Flatten(buffer
, groupSize
);
548 skip_in_buffer(&buffer
, groupSize
);
556 BParameterWeb::AllowsTypeCode(type_code code
) const
558 return code
== TypeCode();
563 BParameterWeb::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
567 if (!AllowsTypeCode(code
)) {
568 ERROR("BParameterWeb::Unflatten(): wrong type code\n");
572 if (buffer
== NULL
) {
573 ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n");
577 // if the buffer is smaller than the size needed to read the
578 // signature field, the mystery field, the group count, and the Node, then there is a problem
579 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(int32
)
580 + sizeof(ssize_t
) + sizeof(media_node
))) {
581 ERROR("BParameterWeb::Unflatten(): size to small\n");
585 const void* bufferStart
= buffer
;
587 uint32 magic
= read_from_buffer
<uint32
>(&buffer
);
588 bool isSwapped
= false;
590 if (magic
== B_SWAP_INT32(kParameterWebMagic
)) {
592 magic
= B_SWAP_INT32(magic
);
594 if (magic
!= kParameterWebMagic
)
597 // Note, it's not completely sure that this field is the version
598 // information - but it doesn't seem to have another purpose
599 int32 version
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
600 if (version
!= kCurrentParameterWebVersion
) {
601 ERROR("BParameterWeb::Unflatten(): wrong version %" B_PRId32
" (%"
602 B_PRIx32
")?!\n", version
, version
);
606 for (int32 i
= 0; i
< fGroups
->CountItems(); i
++) {
607 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
609 fGroups
->MakeEmpty();
611 int32 count
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
613 fNode
= read_from_buffer
<media_node
>(&buffer
);
615 swap_data(B_INT32_TYPE
, &fNode
, sizeof(media_node
), B_SWAP_ALWAYS
);
617 for (int32 i
= 0; i
< count
; i
++) {
619 = read_pointer_from_buffer_swap
<ssize_t
>(&buffer
, isSwapped
);
620 if (groupSize
> size_left(size
, bufferStart
, buffer
)) {
621 ERROR("BParameterWeb::Unflatten(): buffer too small\n");
625 BParameterGroup
* group
= new BParameterGroup(this, "unnamed");
626 status_t status
= group
->Unflatten(group
->TypeCode(), buffer
,
629 ERROR("BParameterWeb::Unflatten(): unflatten group failed\n");
634 skip_in_buffer(&buffer
, groupSize
);
636 fGroups
->AddItem(group
);
639 // fix all references (ParameterAt() style)
641 BList
groups(*fGroups
);
643 for (int32 i
= 0; i
< groups
.CountItems(); i
++) {
644 BParameterGroup
* group
645 = static_cast<BParameterGroup
*>(groups
.ItemAt(i
));
647 for (int32 index
= group
->CountParameters(); index
-- > 0;) {
648 BParameter
* parameter
649 = static_cast<BParameter
*>(group
->ParameterAt(index
));
651 parameter
->FixRefs(*fOldRefs
, *fNewRefs
);
654 if (group
->fGroups
!= NULL
)
655 groups
.AddList(group
->fGroups
);
658 fOldRefs
->MakeEmpty();
659 fNewRefs
->MakeEmpty();
666 BParameterWeb::AddRefFix(void* oldItem
, void* newItem
)
668 fOldRefs
->AddItem(oldItem
);
669 fNewRefs
->AddItem(newItem
);
673 // #pragma mark - BParameterGroup
676 BParameterGroup::BParameterGroup(BParameterWeb
* web
, const char* name
)
682 TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web
, name
);
684 fName
= strndup(name
, 255);
686 fControls
= new BList();
687 fGroups
= new BList();
691 BParameterGroup::~BParameterGroup()
695 for (int i
= fControls
->CountItems(); i
-- > 0;) {
696 delete static_cast<BParameter
*>(fControls
->ItemAt(i
));
700 for (int i
= fGroups
->CountItems(); i
-- > 0;) {
701 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
710 BParameterGroup::Web() const
717 BParameterGroup::Name() const
724 BParameterGroup::SetFlags(uint32 flags
)
731 BParameterGroup::Flags() const
738 BParameterGroup::MakeNullParameter(int32 id
, media_type mediaType
,
739 const char* name
, const char* kind
)
743 BNullParameter
* parameter
= new(std::nothrow
) BNullParameter(id
, mediaType
,
745 if (parameter
== NULL
)
748 parameter
->fGroup
= this;
749 fControls
->AddItem(parameter
);
755 BContinuousParameter
*
756 BParameterGroup::MakeContinuousParameter(int32 id
, media_type mediaType
,
757 const char* name
, const char* kind
, const char* unit
,
758 float minimum
, float maximum
, float stepping
)
762 BContinuousParameter
* parameter
763 = new(std::nothrow
) BContinuousParameter(id
, mediaType
, fWeb
, name
,
764 kind
, unit
, minimum
, maximum
, stepping
);
765 if (parameter
== NULL
)
768 parameter
->fGroup
= this;
769 fControls
->AddItem(parameter
);
776 BParameterGroup::MakeDiscreteParameter(int32 id
, media_type mediaType
,
777 const char* name
, const char* kind
)
781 BDiscreteParameter
* parameter
= new(std::nothrow
) BDiscreteParameter(id
,
782 mediaType
, fWeb
, name
, kind
);
783 if (parameter
== NULL
)
786 parameter
->fGroup
= this;
787 fControls
->AddItem(parameter
);
794 BParameterGroup::MakeTextParameter(int32 id
, media_type mediaType
,
795 const char* name
, const char* kind
, size_t maxBytes
)
799 BTextParameter
* parameter
= new(std::nothrow
) BTextParameter(id
, mediaType
,
800 fWeb
, name
, kind
, maxBytes
);
801 if (parameter
== NULL
)
804 parameter
->fGroup
= this;
805 fControls
->AddItem(parameter
);
812 BParameterGroup::MakeGroup(const char* name
)
816 BParameterGroup
* group
= new(std::nothrow
) BParameterGroup(fWeb
, name
);
818 fGroups
->AddItem(group
);
825 BParameterGroup::CountParameters()
827 return fControls
->CountItems();
832 BParameterGroup::ParameterAt(int32 index
)
834 return static_cast<BParameter
*>(fControls
->ItemAt(index
));
839 BParameterGroup::CountGroups()
841 return fGroups
->CountItems();
846 BParameterGroup::GroupAt(int32 index
)
848 return static_cast<BParameterGroup
*>(fGroups
->ItemAt(index
));
853 BParameterGroup::IsFixedSize() const
860 BParameterGroup::TypeCode() const
862 return B_MEDIA_PARAMETER_GROUP_TYPE
;
867 BParameterGroup::FlattenedSize() const
872 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
873 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
874 (possible) Flags: 4 bytes
875 Name String Length: 1 byte (??)
876 Name String: 'Name String Length' bytes
878 //for each Param BEGIN
880 Parameter Type: 4 bytes
881 Flattened Parameter Size: 4 bytes
882 Flattened Parameter: 'Flattened Parameter Size' bytes
884 Subgroup Count: 4 bytes
885 //for each SubGroup BEGIN
887 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
888 Flattened Group Size: 4 bytes
889 Flattened Group: 'Flattened Group Size' bytes
890 //for each SubGroup END
892 //---------END-CORE-BPARAMETERGROUP-STRUCT--------------
894 //13 guaranteed bytes, variable after that.
898 size
+= sizeof(uint32
);
901 size
+= min_c(strlen(fName
), 255);
903 int limit
= fControls
->CountItems();
904 for (int i
= 0; i
< limit
; i
++) {
905 BParameter
* parameter
= static_cast<BParameter
*>(fControls
->ItemAt(i
));
906 if (parameter
!= NULL
) {
907 // overhead for each parameter flattened
908 size
+= sizeof(BParameter
*) + sizeof(BParameter::media_parameter_type
)
909 + sizeof(ssize_t
) + parameter
->FlattenedSize();
913 limit
= fGroups
->CountItems();
914 for (int i
= 0; i
< limit
; i
++) {
915 BParameterGroup
* group
916 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
918 // overhead for each group flattened
919 size
+= sizeof(BParameterGroup
*) + sizeof(type_code
)
920 + sizeof(ssize_t
) + group
->FlattenedSize();
929 BParameterGroup::Flatten(void* buffer
, ssize_t size
) const
933 if (buffer
== NULL
) {
934 ERROR("BParameterGroup::Flatten buffer is NULL\n");
938 // NOTICE: It is important that this value is the size returned by
939 // BParameterGroup::FlattenedSize, not by a descendent's override of this method.
940 ssize_t actualSize
= BParameterGroup::FlattenedSize();
941 if (size
< actualSize
) {
942 ERROR("BParameterGroup::Flatten size to small\n");
947 write_to_buffer
<int32
>(&buffer
, kBufferGroupMagic
);
948 write_to_buffer
<uint32
>(&buffer
, fFlags
);
950 write_to_buffer
<int32
>(&buffer
, kBufferGroupMagicNoFlags
);
952 write_string_to_buffer(&buffer
, fName
);
954 int32 count
= fControls
->CountItems();
955 write_to_buffer
<int32
>(&buffer
, count
);
957 for (int32 i
= 0; i
< count
; i
++) {
958 BParameter
* parameter
= static_cast<BParameter
*>(fControls
->ItemAt(i
));
959 if (parameter
== NULL
) {
960 ERROR("BParameterGroup::Flatten(): NULL parameter\n");
964 write_to_buffer
<BParameter
*>(&buffer
, parameter
);
965 write_to_buffer
<BParameter::media_parameter_type
>(&buffer
,
968 // flatten parameter into this buffer
970 ssize_t parameterSize
= parameter
->FlattenedSize();
971 write_to_buffer
<ssize_t
>(&buffer
, parameterSize
);
973 status_t status
= parameter
->Flatten(buffer
, parameterSize
);
974 // we have only that much bytes left to write in this buffer
978 skip_in_buffer(&buffer
, parameterSize
);
981 count
= fGroups
->CountItems();
982 write_to_buffer
<int32
>(&buffer
, count
);
984 for (int32 i
= 0; i
< count
; i
++) {
985 BParameterGroup
* group
986 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
988 ERROR("BParameterGroup::Flatten(): NULL group\n");
992 write_to_buffer
<BParameterGroup
*>(&buffer
, group
);
993 write_to_buffer
<type_code
>(&buffer
, group
->TypeCode());
995 // flatten sub group into this buffer
997 ssize_t groupSize
= group
->FlattenedSize();
998 write_to_buffer
<ssize_t
>(&buffer
, groupSize
);
1000 status_t status
= group
->Flatten(buffer
, groupSize
);
1001 // we have only that much bytes left to write in this buffer
1005 skip_in_buffer(&buffer
, groupSize
);
1013 BParameterGroup::AllowsTypeCode(type_code code
) const
1015 return code
== TypeCode();
1020 BParameterGroup::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
1024 if (!AllowsTypeCode(code
)) {
1025 ERROR("BParameterGroup::Unflatten() wrong type code\n");
1029 if (buffer
== NULL
) {
1030 ERROR("BParameterGroup::Unflatten() buffer is NULL\n");
1034 // if the buffer is smaller than the size needed to read the
1035 // signature field, then there is a problem
1036 if (size
< static_cast<ssize_t
>(sizeof(int32
))) {
1037 ERROR("BParameterGroup::Unflatten() size to small\n");
1041 const void* bufferStart
= buffer
;
1042 // used to compute the rest length of the buffer when needed
1044 uint32 magic
= read_from_buffer
<uint32
>(&buffer
);
1045 bool isSwapped
= false;
1047 if (magic
== B_SWAP_INT32(kBufferGroupMagic
)
1048 || magic
== B_SWAP_INT32(kBufferGroupMagicNoFlags
)) {
1050 magic
= B_SWAP_INT32(magic
);
1053 if (magic
== kBufferGroupMagic
)
1054 fFlags
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
1055 else if (magic
== kBufferGroupMagicNoFlags
)
1060 if (read_string_from_buffer(&buffer
, &fName
,
1061 size
- (ssize_t
)((uint8
*)buffer
- (uint8
*)bufferStart
)) < B_OK
)
1064 // Clear all existing parameters/subgroups
1065 for (int32 i
= 0; i
< fControls
->CountItems(); i
++) {
1066 delete static_cast<BParameter
*>(fControls
->ItemAt(i
));
1068 fControls
->MakeEmpty();
1070 for (int32 i
= 0; i
< fGroups
->CountItems(); i
++) {
1071 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
1073 fGroups
->MakeEmpty();
1075 // unflatten parameter list
1077 int32 count
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
1078 if (count
< 0 || count
* kAdditionalParameterSize
1079 > size_left(size
, bufferStart
, buffer
))
1082 for (int32 i
= 0; i
< count
; i
++) {
1083 // make sure we can read as many bytes
1084 if (size_left(size
, bufferStart
, buffer
) < (ssize_t
)(
1085 sizeof(BParameter
*) + sizeof(BParameter::media_parameter_type
)
1086 + sizeof(ssize_t
))) {
1090 BParameter
* oldPointer
= read_pointer_from_buffer_swap
<BParameter
*>(
1091 &buffer
, isSwapped
);
1092 BParameter::media_parameter_type mediaType
1093 = read_from_buffer_swap32
<BParameter::media_parameter_type
>(&buffer
,
1096 ssize_t parameterSize
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
,
1098 if (parameterSize
> size_left(size
, bufferStart
, buffer
))
1101 BParameter
* parameter
= MakeControl(mediaType
);
1102 if (parameter
== NULL
) {
1103 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n");
1107 status_t status
= parameter
->Unflatten(parameter
->TypeCode(), buffer
,
1109 if (status
< B_OK
) {
1110 ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n");
1115 skip_in_buffer(&buffer
, parameterSize
);
1117 // add the item to the list
1118 parameter
->fGroup
= this;
1119 parameter
->fWeb
= fWeb
;
1120 fControls
->AddItem(parameter
);
1122 // add it's old pointer value to the RefFix list kept by the owner web
1124 fWeb
->AddRefFix(oldPointer
, parameter
);
1127 // unflatten sub groups
1129 count
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
1130 if (count
< 0 || count
* kAdditionalParameterGroupSize
1131 > size_left(size
, bufferStart
, buffer
))
1134 for (int32 i
= 0; i
< count
; i
++) {
1135 // make sure we can read as many bytes
1136 if (size_left(size
, bufferStart
, buffer
) < (ssize_t
)(
1137 sizeof(BParameterGroup
*) + sizeof(type_code
)
1138 + sizeof(ssize_t
))) {
1142 BParameterGroup
* oldPointer
= read_pointer_from_buffer_swap
<
1143 BParameterGroup
*>(&buffer
, isSwapped
);
1144 type_code type
= read_from_buffer_swap32
<type_code
>(&buffer
, isSwapped
);
1147 = read_pointer_from_buffer_swap
<ssize_t
>(&buffer
, isSwapped
);
1148 if (groupSize
> size_left(size
, bufferStart
, buffer
))
1151 BParameterGroup
* group
= new BParameterGroup(fWeb
, "sub-unnamed");
1152 if (group
== NULL
) {
1153 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n");
1157 status_t status
= group
->Unflatten(type
, buffer
, groupSize
);
1158 if (status
!= B_OK
) {
1159 ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n");
1164 skip_in_buffer(&buffer
, groupSize
);
1166 fGroups
->AddItem(group
);
1168 // add it's old pointer value to the RefFix list kept by the owner web
1170 fWeb
->AddRefFix(oldPointer
, group
);
1177 /*! Creates an uninitialized parameter of the specified type.
1178 Unlike the BParameterGroup::MakeXXXParameter() type of methods, this
1179 method does not add the parameter to this group automatically.
1182 BParameterGroup::MakeControl(int32 type
)
1187 case BParameter::B_NULL_PARAMETER
:
1188 return new BNullParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
, NULL
);
1190 case BParameter::B_DISCRETE_PARAMETER
:
1191 return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
,
1194 case BParameter::B_CONTINUOUS_PARAMETER
:
1195 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
,
1196 NULL
, NULL
, 0, 0, 0);
1198 case BParameter::B_TEXT_PARAMETER
:
1199 return new BTextParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
, NULL
, 0);
1202 ERROR("BParameterGroup::MakeControl unknown type %" B_PRId32
"\n",
1209 // #pragma mark - BParameter
1212 BParameter::media_parameter_type
1213 BParameter::Type() const
1220 BParameter::Web() const
1227 BParameter::Group() const
1234 BParameter::Name() const
1241 BParameter::Kind() const
1248 BParameter::Unit() const
1255 BParameter::ID() const
1262 BParameter::SetFlags(uint32 flags
)
1269 BParameter::Flags() const
1276 BParameter::GetValue(void* buffer
, size_t* _size
, bigtime_t
* _when
)
1280 if (buffer
== NULL
|| _size
== NULL
)
1283 size_t size
= *_size
;
1288 ERROR("BParameter::GetValue: no parent BParameterWeb\n");
1292 media_node node
= fWeb
->Node();
1293 if (IS_INVALID_NODE(node
)) {
1294 ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n");
1298 controllable_get_parameter_data_request request
;
1299 controllable_get_parameter_data_reply reply
;
1303 if (size
> MAX_PARAMETER_DATA
) {
1304 // create an area if large data needs to be transfered
1305 area
= create_area("get parameter data", &data
, B_ANY_ADDRESS
,
1306 ROUND_UP_TO_PAGE(size
), B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
1308 ERROR("BParameter::GetValue can't create area of %ld bytes\n",
1314 data
= reply
.raw_data
;
1317 request
.parameter_id
= fID
;
1318 request
.request_size
= size
;
1319 request
.area
= area
;
1321 status_t status
= QueryPort(node
.port
, CONTROLLABLE_GET_PARAMETER_DATA
,
1322 &request
, sizeof(request
), &reply
, sizeof(reply
));
1323 if (status
== B_OK
) {
1324 // we don't want to copy more than the buffer provides
1325 if (reply
.size
< size
)
1328 memcpy(buffer
, data
, size
);
1330 // store reported values
1332 *_size
= reply
.size
;
1334 *_when
= reply
.last_change
;
1336 ERROR("BParameter::GetValue parameter '%s' querying node %d, "
1337 "port %d failed: %s\n", fName
, (int)node
.node
, (int)node
.port
,
1349 BParameter::SetValue(const void* buffer
, size_t size
, bigtime_t when
)
1359 ERROR("BParameter::SetValue: no parent BParameterWeb\n");
1363 media_node node
= fWeb
->Node();
1364 if (IS_INVALID_NODE(node
)) {
1365 ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned "
1366 "to a BMediaNode\n");
1370 controllable_set_parameter_data_request request
;
1371 controllable_set_parameter_data_reply reply
;
1375 if (size
> MAX_PARAMETER_DATA
) {
1376 // create an area if large data needs to be transfered
1377 area
= create_area("set parameter data", &data
, B_ANY_ADDRESS
,
1378 ROUND_UP_TO_PAGE(size
), B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
1380 ERROR("BParameter::SetValue can't create area of %ld bytes\n", size
);
1385 data
= request
.raw_data
;
1388 memcpy(data
, buffer
, size
);
1389 request
.parameter_id
= fID
;
1390 request
.when
= when
;
1391 request
.area
= area
;
1392 request
.size
= size
;
1394 status_t status
= QueryPort(node
.port
, CONTROLLABLE_SET_PARAMETER_DATA
,
1395 &request
, sizeof(request
), &reply
, sizeof(reply
));
1396 if (status
!= B_OK
) {
1397 ERROR("BParameter::SetValue querying node failed: %s\n",
1409 BParameter::CountChannels()
1416 BParameter::SetChannelCount(int32 count
)
1423 BParameter::MediaType()
1430 BParameter::SetMediaType(media_type type
)
1437 BParameter::CountInputs()
1439 return fInputs
->CountItems();
1444 BParameter::InputAt(int32 index
)
1446 return static_cast<BParameter
*>(fInputs
->ItemAt(index
));
1451 BParameter::AddInput(BParameter
* input
)
1455 // BeBook has this method returning a status value,
1456 // but it should be updated
1460 if (fInputs
->HasItem(input
)) {
1461 // if already in input list, don't duplicate.
1465 fInputs
->AddItem(input
);
1466 input
->AddOutput(this);
1471 BParameter::CountOutputs()
1473 return fOutputs
->CountItems();
1478 BParameter::OutputAt(int32 index
)
1480 return static_cast<BParameter
*>(fOutputs
->ItemAt(index
));
1485 BParameter::AddOutput(BParameter
* output
)
1489 // BeBook has this method returning a status value,
1490 // but it should be updated
1494 if (fOutputs
->HasItem(output
)) {
1495 // if already in output list, don't duplicate.
1499 fOutputs
->AddItem(output
);
1500 output
->AddInput(this);
1505 BParameter::IsFixedSize() const
1512 BParameter::TypeCode() const
1514 return B_MEDIA_PARAMETER_TYPE
;
1519 BParameter::FlattenedSize() const
1523 ?? (0x02040607): 4 bytes
1524 BParameter Struct Size (in bytes): 4 bytes
1526 Name String Length: 1 byte (??)
1527 Name String: 'Name String Length' bytes
1528 Kind String Length: 1 byte (??)
1529 Kind String: 'Kind String Length' bytes
1530 Unit String Length: 1 byte (??)
1531 Unit String: 'Unit String Length' bytes
1532 Inputs Count: 4 bytes
1533 Inputs (pointers): ('Inputs Count')*4 bytes
1534 Outputs Count: 4 bytes
1535 Outputs (pointers): ('Outputs Count')*4 bytes
1537 ChannelCount: 4 bytes
1540 //35 bytes are guaranteed, after that, add the variable length parts.
1541 ssize_t size
= kAdditionalParameterSize
;
1544 size
+= strlen(fName
);
1546 size
+= strlen(fKind
);
1548 size
+= strlen(fUnit
);
1550 size
+= fInputs
->CountItems() * sizeof(BParameter
*);
1551 size
+= fOutputs
->CountItems() * sizeof(BParameter
*);
1558 BParameter::Flatten(void* buffer
, ssize_t size
) const
1562 if (buffer
== NULL
) {
1563 ERROR("BParameter::Flatten buffer is NULL\n");
1567 // NOTICE: It is important that this value is the size returned by
1568 // BParameter::FlattenedSize(), not by a descendent's override of this method.
1569 ssize_t actualSize
= BParameter::FlattenedSize();
1570 if (size
< actualSize
) {
1571 ERROR("BParameter::Flatten(): size too small\n");
1575 write_to_buffer
<uint32
>(&buffer
, kParameterMagic
);
1576 write_to_buffer
<ssize_t
>(&buffer
, actualSize
);
1577 write_to_buffer
<int32
>(&buffer
, fID
);
1579 write_string_to_buffer(&buffer
, fName
);
1580 write_string_to_buffer(&buffer
, fKind
);
1581 write_string_to_buffer(&buffer
, fUnit
);
1583 // flatten and write the list of inputs
1584 ssize_t count
= fInputs
->CountItems();
1585 write_to_buffer
<ssize_t
>(&buffer
, count
);
1588 memcpy(buffer
, fInputs
->Items(), sizeof(BParameter
*) * count
);
1589 skip_in_buffer(&buffer
, sizeof(BParameter
*) * count
);
1592 // flatten and write the list of outputs
1593 count
= fOutputs
->CountItems();
1594 write_to_buffer
<ssize_t
>(&buffer
, count
);
1597 memcpy(buffer
, fOutputs
->Items(), sizeof(BParameter
*) * count
);
1598 skip_in_buffer(&buffer
, sizeof(BParameter
*) * count
);
1601 write_to_buffer
<media_type
>(&buffer
, fMediaType
);
1602 write_to_buffer
<int32
>(&buffer
, fChannels
);
1603 write_to_buffer
<uint32
>(&buffer
, fFlags
);
1610 BParameter::AllowsTypeCode(type_code code
) const
1612 return code
== TypeCode();
1617 BParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
1621 if (!AllowsTypeCode(code
)) {
1622 ERROR("BParameter::Unflatten(): wrong type code\n");
1626 if (buffer
== NULL
) {
1627 ERROR("BParameter::Unflatten(): buffer is NULL\n");
1631 // if the buffer is smaller than the size needed to read the
1632 // signature and struct size fields, then there is a problem
1633 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(ssize_t
))) {
1634 ERROR("BParameter::Unflatten() size too small\n");
1638 const void* bufferStart
= buffer
;
1642 uint32 magic
= read_from_buffer
<uint32
>(&buffer
);
1643 if (magic
== B_SWAP_INT32(kParameterMagic
))
1644 fSwapDetected
= true;
1645 else if (magic
== kParameterMagic
)
1646 fSwapDetected
= false;
1648 ERROR("BParameter::Unflatten(): bad magic\n");
1652 ssize_t parameterSize
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
,
1654 if (parameterSize
> size
) {
1655 ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n",
1656 parameterSize
, size
);
1660 // if the struct doesn't meet the minimum size for
1661 // a flattened BParameter, then return an error.
1662 // MinFlattenedParamSize =
1664 // Name String Length (1 byte)
1665 // Kind String Length (1 byte)
1666 // Unit String Length (1 byte)
1667 // Inputs Count (4 bytes)
1668 // Outputs Count (4 bytes)
1669 // Media Type (4 bytes)
1670 // Channel Count (4 bytes)
1673 const ssize_t kMinFlattenedParamSize
= 15 + 3 * sizeof(ssize_t
);
1674 if (parameterSize
< kMinFlattenedParamSize
) {
1675 ERROR("BParameter::Unflatten out of memory (2)\n");
1679 fID
= read_from_buffer_swap32
<int32
>(&buffer
, fSwapDetected
);
1681 if (read_string_from_buffer(&buffer
, &fName
,
1682 size_left(size
, bufferStart
, buffer
)) < B_OK
1683 || read_string_from_buffer(&buffer
, &fKind
,
1684 size_left(size
, bufferStart
, buffer
)) < B_OK
1685 || read_string_from_buffer(&buffer
, &fUnit
,
1686 size_left(size
, bufferStart
, buffer
)) < B_OK
)
1689 // read the list of inputs
1691 // it will directly add the pointers in the flattened message to the list;
1692 // these will be fixed to point to the real inputs/outputs later in FixRefs()
1694 ssize_t count
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
,
1697 fInputs
->MakeEmpty();
1698 for (ssize_t i
= 0; i
< count
; i
++) {
1699 fInputs
->AddItem(read_pointer_from_buffer_swap
<BParameter
* const>(
1700 &buffer
, fSwapDetected
));
1703 // read the list of outputs
1705 count
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
, fSwapDetected
);
1707 fOutputs
->MakeEmpty();
1708 for (ssize_t i
= 0; i
< count
; i
++) {
1709 fOutputs
->AddItem(read_pointer_from_buffer_swap
<BParameter
* const>(
1710 &buffer
, fSwapDetected
));
1713 fMediaType
= read_from_buffer_swap32
<media_type
>(&buffer
, fSwapDetected
);
1714 fChannels
= read_from_buffer_swap32
<int32
>(&buffer
, fSwapDetected
);
1715 fFlags
= read_from_buffer_swap32
<uint32
>(&buffer
, fSwapDetected
);
1721 BParameter::BParameter(int32 id
, media_type mediaType
,
1722 media_parameter_type type
, BParameterWeb
* web
, const char* name
,
1723 const char* kind
, const char* unit
)
1729 fSwapDetected(true),
1730 fMediaType(mediaType
),
1736 fName
= strndup(name
, 255);
1737 fKind
= strndup(kind
, 255);
1738 fUnit
= strndup(unit
, 255);
1740 // create empty input/output lists
1741 fInputs
= new BList();
1742 fOutputs
= new BList();
1746 BParameter::~BParameter()
1750 // don't worry about the fWeb/fGroup properties, you don't need
1751 // to remove yourself from a web/group since the only way in which
1752 // a parameter is destroyed is when the owner web/group destroys it
1763 /*! Replaces references to items in the old list with the corresponding
1764 items in the updated list. The references are replaced in the input
1766 This is called by BParameterWeb::Unflatten().
1769 BParameter::FixRefs(BList
& old
, BList
& updated
)
1775 void** items
= static_cast<void**>(fInputs
->Items());
1776 int32 count
= fInputs
->CountItems();
1778 for (int32 i
= 0; i
< count
; i
++) {
1779 int32 index
= old
.IndexOf(items
[i
]);
1781 items
[i
] = updated
.ItemAt(index
);
1783 ERROR("BParameter::FixRefs(): No mapping found for input");
1788 // remove all NULL inputs (those which couldn't be mapped)
1790 for (int32 i
= count
; i
-- > 0;) {
1791 if (items
[i
] == NULL
)
1792 fInputs
->RemoveItem(i
);
1797 items
= static_cast<void **>(fOutputs
->Items());
1798 count
= fOutputs
->CountItems();
1800 for (int32 i
= 0; i
< count
; i
++) {
1801 int32 index
= old
.IndexOf(items
[i
]);
1803 items
[i
] = updated
.ItemAt(index
);
1805 ERROR("BParameter::FixRefs(): No mapping found for output");
1810 // remove all NULL outputs (those which couldn't be mapped)
1812 for (int32 i
= count
; i
-- > 0;) {
1813 if (items
[i
] == NULL
)
1814 fOutputs
->RemoveItem(i
);
1819 // #pragma mark - public BContinuousParameter
1823 BContinuousParameter::ValueType()
1825 return B_FLOAT_TYPE
;
1830 BContinuousParameter::MinValue()
1837 BContinuousParameter::MaxValue()
1844 BContinuousParameter::ValueStep()
1851 BContinuousParameter::SetResponse(int resp
, float factor
, float offset
)
1853 fResponse
= static_cast<response
>(resp
);
1860 BContinuousParameter::GetResponse(int* _resp
, float* _factor
, float* _offset
)
1864 if (_factor
!= NULL
)
1866 if (_offset
!= NULL
)
1872 BContinuousParameter::FlattenedSize() const
1876 // only adds a fixed amount of bytes
1877 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize
;
1882 BContinuousParameter::Flatten(void* buffer
, ssize_t size
) const
1886 if (buffer
== NULL
) {
1887 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n");
1891 ssize_t parameterSize
= BParameter::FlattenedSize();
1892 if (size
< (parameterSize
+ kAdditionalContinuousParameterSize
)) {
1893 ERROR("BContinuousParameter::Flatten(): size to small\n");
1897 status_t status
= BParameter::Flatten(buffer
, size
);
1898 if (status
!= B_OK
) {
1899 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n");
1903 // add our data to the general flattened BParameter
1905 skip_in_buffer(&buffer
, parameterSize
);
1907 write_to_buffer
<float>(&buffer
, fMinimum
);
1908 write_to_buffer
<float>(&buffer
, fMaximum
);
1909 write_to_buffer
<float>(&buffer
, fStepping
);
1910 write_to_buffer
<response
>(&buffer
, fResponse
);
1911 write_to_buffer
<float>(&buffer
, fFactor
);
1912 write_to_buffer
<float>(&buffer
, fOffset
);
1919 BContinuousParameter::Unflatten(type_code code
, const void* buffer
,
1924 // we try to check if the buffer size is long enough to hold an object
1925 // as early as possible.
1927 if (!AllowsTypeCode(code
)) {
1928 ERROR("BContinuousParameter::Unflatten wrong type code\n");
1932 if (buffer
== NULL
) {
1933 ERROR("BContinuousParameter::Unflatten buffer is NULL\n");
1937 // if the buffer is smaller than the size needed to read the
1938 // signature and struct size fields, then there is a problem
1939 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(ssize_t
))) {
1940 ERROR("BContinuousParameter::Unflatten size too small\n");
1944 status_t status
= BParameter::Unflatten(code
, buffer
, size
);
1945 if (status
!= B_OK
) {
1946 ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten "
1947 "failed: %s\n", strerror(status
));
1951 ssize_t parameterSize
= BParameter::FlattenedSize();
1952 skip_in_buffer(&buffer
, parameterSize
);
1954 if (size
< (parameterSize
+ kAdditionalContinuousParameterSize
)) {
1955 ERROR("BContinuousParameter::Unflatten(): buffer too small\n");
1959 fMinimum
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1960 fMaximum
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1961 fStepping
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1962 fResponse
= read_from_buffer_swap32
<response
>(&buffer
, SwapOnUnflatten());
1963 fFactor
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1964 fOffset
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1970 BContinuousParameter::BContinuousParameter(int32 id
, media_type mediaType
,
1971 BParameterWeb
* web
, const char* name
, const char* kind
,
1972 const char* unit
, float minimum
, float maximum
, float stepping
)
1973 : BParameter(id
, mediaType
, B_CONTINUOUS_PARAMETER
, web
, name
, kind
, unit
),
1976 fStepping(stepping
),
1977 fResponse(B_LINEAR
),
1985 BContinuousParameter::~BContinuousParameter()
1991 // #pragma mark - public BDiscreteParameter
1995 BDiscreteParameter::ValueType()
1997 return B_INT32_TYPE
;
2002 BDiscreteParameter::CountItems()
2004 return fValues
->CountItems();
2009 BDiscreteParameter::ItemNameAt(int32 index
)
2011 return reinterpret_cast<const char*>(fSelections
->ItemAt(index
));
2016 BDiscreteParameter::ItemValueAt(int32 index
)
2018 int32
* item
= static_cast<int32
*>(fValues
->ItemAt(index
));
2027 BDiscreteParameter::AddItem(int32 value
, const char* name
)
2031 int32
* valueCopy
= new(std::nothrow
) int32(value
);
2032 if (valueCopy
== NULL
)
2034 char* nameCopy
= strndup(name
, 255);
2035 if (name
!= NULL
&& nameCopy
== NULL
) {
2040 if (!fValues
->AddItem(valueCopy
))
2042 if (!fSelections
->AddItem(nameCopy
)) {
2043 fValues
->RemoveItem(valueCopy
);
2056 BDiscreteParameter::MakeItemsFromInputs()
2060 int32 count
= fInputs
->CountItems();
2061 for (int32 i
= 0; i
< count
; i
++) {
2062 BParameter
* parameter
= static_cast<BParameter
*>(fInputs
->ItemAt(i
));
2063 AddItem(i
, parameter
->Name());
2071 BDiscreteParameter::MakeItemsFromOutputs()
2075 int32 count
= fOutputs
->CountItems();
2076 for (int32 i
= 0; i
< count
; i
++) {
2077 BParameter
* parameter
= static_cast<BParameter
*>(fOutputs
->ItemAt(i
));
2078 AddItem(i
, parameter
->Name());
2086 BDiscreteParameter::MakeEmpty()
2090 for (int32 i
= fValues
->CountItems(); i
-- > 0;) {
2091 delete static_cast<int32
*>(fValues
->ItemAt(i
));
2093 fValues
->MakeEmpty();
2095 for (int32 i
= fSelections
->CountItems(); i
-- > 0;) {
2096 free(static_cast<char*>(fSelections
->ItemAt(i
)));
2098 fSelections
->MakeEmpty();
2103 BDiscreteParameter::FlattenedSize() const
2107 ssize_t size
= BParameter::FlattenedSize()
2108 + kAdditionalDiscreteParameterSize
;
2110 int32 count
= fValues
->CountItems();
2111 for (int32 i
= 0; i
< count
; i
++) {
2112 char* selection
= static_cast<char*>(fSelections
->ItemAt(i
));
2114 if (selection
!= NULL
)
2115 size
+= min_c(strlen(selection
), 255);
2118 // string length + value
2126 BDiscreteParameter::Flatten(void* buffer
, ssize_t size
) const
2130 if (buffer
== NULL
) {
2131 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n");
2135 ssize_t parameterSize
= BParameter::FlattenedSize();
2137 if (size
< FlattenedSize()) {
2138 ERROR("BDiscreteParameter::Flatten(): size too small\n");
2142 status_t status
= BParameter::Flatten(buffer
, size
);
2143 if (status
!= B_OK
) {
2144 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n");
2148 skip_in_buffer(&buffer
, parameterSize
);
2150 int32 count
= fValues
->CountItems();
2151 write_to_buffer
<int32
>(&buffer
, count
);
2153 // write out all value/name pairs
2154 for (int32 i
= 0; i
< count
; i
++) {
2155 const char* selection
= static_cast<char*>(fSelections
->ItemAt(i
));
2156 const int32
* value
= static_cast<int32
*>(fValues
->ItemAt(i
));
2158 write_string_to_buffer(&buffer
, selection
);
2159 write_to_buffer
<int32
>(&buffer
, value
? *value
: 0);
2167 BDiscreteParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
2171 if (!AllowsTypeCode(code
)) {
2172 ERROR("BDiscreteParameter::Unflatten(): bad type code\n");
2176 if (buffer
== NULL
) {
2177 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n");
2181 // if the buffer is smaller than the size needed to read the
2182 // signature and struct size fields, then there is a problem
2183 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(ssize_t
))) {
2184 ERROR("BDiscreteParameter::Unflatten(): size too small\n");
2188 const void* bufferStart
= buffer
;
2190 status_t status
= BParameter::Unflatten(code
, buffer
, size
);
2191 if (status
!= B_OK
) {
2192 ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n");
2196 ssize_t parameterSize
= BParameter::FlattenedSize();
2197 skip_in_buffer(&buffer
, parameterSize
);
2199 if (size
< (parameterSize
+ kAdditionalDiscreteParameterSize
)) {
2200 ERROR("BDiscreteParameter::Unflatten(): buffer too small\n");
2204 int32 count
= read_from_buffer_swap32
<int32
>(&buffer
, SwapOnUnflatten());
2206 // clear any existing name/value pairs
2209 for (int32 i
= 0; i
< count
; i
++) {
2211 if (read_string_from_buffer(&buffer
, &name
, size_left(size
, bufferStart
,
2215 if (size_left(size
, bufferStart
, buffer
) < (int)sizeof(int32
)) {
2220 int32 value
= read_from_buffer_swap32
<int32
>(&buffer
,
2223 AddItem(value
, name
);
2231 BDiscreteParameter::BDiscreteParameter(int32 id
, media_type mediaType
,
2232 BParameterWeb
* web
, const char* name
, const char* kind
)
2233 : BParameter(id
, mediaType
, B_DISCRETE_PARAMETER
, web
, name
, kind
, NULL
)
2237 fSelections
= new BList();
2238 fValues
= new BList();
2242 BDiscreteParameter::~BDiscreteParameter()
2253 // #pragma mark - public BTextParameter
2257 BTextParameter::MaxBytes() const
2264 BTextParameter::ValueType()
2266 return B_FLOAT_TYPE
;
2271 BTextParameter::FlattenedSize() const
2273 return BParameter::FlattenedSize() + sizeof(fMaxBytes
);
2278 BTextParameter::Flatten(void* buffer
, ssize_t size
) const
2280 if (buffer
== NULL
) {
2281 ERROR("BTextParameter::Flatten(): buffer is NULL\n");
2285 ssize_t parameterSize
= BParameter::FlattenedSize();
2286 if (size
< static_cast<ssize_t
>(parameterSize
+ sizeof(fMaxBytes
))) {
2287 ERROR("BContinuousParameter::Flatten(): size to small\n");
2291 status_t status
= BParameter::Flatten(buffer
, size
);
2292 if (status
!= B_OK
) {
2293 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n");
2297 // add our data to the general flattened BParameter
2299 skip_in_buffer(&buffer
, parameterSize
);
2301 write_to_buffer
<uint32
>(&buffer
, fMaxBytes
);
2308 BTextParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
2310 // we try to check if the buffer size is long enough to hold an object
2311 // as early as possible.
2313 if (!AllowsTypeCode(code
)) {
2314 ERROR("BTextParameter::Unflatten wrong type code\n");
2318 if (buffer
== NULL
) {
2319 ERROR("BTextParameter::Unflatten buffer is NULL\n");
2323 if (size
< static_cast<ssize_t
>(sizeof(fMaxBytes
))) {
2324 ERROR("BTextParameter::Unflatten size too small\n");
2328 status_t status
= BParameter::Unflatten(code
, buffer
, size
);
2329 if (status
!= B_OK
) {
2330 ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n");
2334 ssize_t parameterSize
= BParameter::FlattenedSize();
2335 skip_in_buffer(&buffer
, parameterSize
);
2337 if (size
< static_cast<ssize_t
>(parameterSize
+ sizeof(fMaxBytes
))) {
2338 ERROR("BTextParameter::Unflatten(): buffer too small\n");
2342 fMaxBytes
= read_from_buffer_swap32
<uint32
>(&buffer
, SwapOnUnflatten());
2348 BTextParameter::BTextParameter(int32 id
, media_type mediaType
,
2349 BParameterWeb
* web
, const char* name
, const char* kind
,
2351 : BParameter(id
, mediaType
, B_TEXT_PARAMETER
, web
, name
, kind
, NULL
)
2353 fMaxBytes
= maxBytes
;
2357 BTextParameter::~BTextParameter()
2362 // #pragma mark - public BNullParameter
2366 BNullParameter::ValueType()
2368 // NULL parameters have no value type
2374 BNullParameter::FlattenedSize() const
2376 return BParameter::FlattenedSize();
2381 BNullParameter::Flatten(void* buffer
, ssize_t size
) const
2383 return BParameter::Flatten(buffer
, size
);
2388 BNullParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
2390 return BParameter::Unflatten(code
, buffer
, size
);
2394 BNullParameter::BNullParameter(int32 id
, media_type mediaType
,
2395 BParameterWeb
* web
, const char* name
, const char* kind
)
2396 : BParameter(id
, mediaType
, B_NULL_PARAMETER
, web
, name
, kind
, NULL
)
2401 BNullParameter::~BNullParameter()
2406 // #pragma mark - reserved functions
2409 status_t
BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR
; }
2410 status_t
BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR
; }
2411 status_t
BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR
; }
2412 status_t
BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR
; }
2413 status_t
BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR
; }
2414 status_t
BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR
; }
2415 status_t
BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR
; }
2416 status_t
BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR
; }
2418 status_t
BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR
; }
2419 status_t
BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR
; }
2420 status_t
BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR
; }
2421 status_t
BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR
; }
2422 status_t
BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR
; }
2423 status_t
BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR
; }
2424 status_t
BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR
; }
2425 status_t
BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR
; }
2427 status_t
BParameter::_Reserved_Control_0(void *) { return B_ERROR
; }
2428 status_t
BParameter::_Reserved_Control_1(void *) { return B_ERROR
; }
2429 status_t
BParameter::_Reserved_Control_2(void *) { return B_ERROR
; }
2430 status_t
BParameter::_Reserved_Control_3(void *) { return B_ERROR
; }
2431 status_t
BParameter::_Reserved_Control_4(void *) { return B_ERROR
; }
2432 status_t
BParameter::_Reserved_Control_5(void *) { return B_ERROR
; }
2433 status_t
BParameter::_Reserved_Control_6(void *) { return B_ERROR
; }
2434 status_t
BParameter::_Reserved_Control_7(void *) { return B_ERROR
; }
2436 status_t
BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR
; }
2437 status_t
BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR
; }
2438 status_t
BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR
; }
2439 status_t
BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR
; }
2440 status_t
BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR
; }
2441 status_t
BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR
; }
2442 status_t
BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR
; }
2443 status_t
BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR
; }
2445 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR
; }
2446 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR
; }
2447 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR
; }
2448 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR
; }
2449 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR
; }
2450 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR
; }
2451 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR
; }
2452 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR
; }
2454 status_t
BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR
; }
2455 status_t
BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR
; }
2456 status_t
BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR
; }
2457 status_t
BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR
; }
2458 status_t
BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR
; }
2459 status_t
BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR
; }
2460 status_t
BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR
; }
2461 status_t
BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR
; }
2463 status_t
BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR
; }
2464 status_t
BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR
; }
2465 status_t
BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR
; }
2466 status_t
BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR
; }
2467 status_t
BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR
; }
2468 status_t
BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR
; }
2469 status_t
BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR
; }
2470 status_t
BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR
; }