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';
202 *_buffer
= static_cast<const void *>(buffer
+ length
);
210 template<class Type
> Type
*
211 reserve_in_buffer(void **_buffer
)
213 Type
*typedBuffer
= static_cast<Type
*>(*_buffer
);
218 *_buffer
= static_cast<void *>(typedBuffer
);
222 template<class Type
> void
223 write_to_buffer(void **_buffer
, Type value
)
225 Type
*typedBuffer
= static_cast<Type
*>(*_buffer
);
227 *typedBuffer
= value
;
230 *_buffer
= static_cast<void *>(typedBuffer
);
235 write_string_to_buffer(void **_buffer
, const char *string
)
237 uint8
*buffer
= static_cast<uint8
*>(*_buffer
);
238 uint32 length
= string
? strlen(string
) : 0;
242 *buffer
++ = static_cast<uint8
>(length
);
244 memcpy(buffer
, string
, length
);
248 *_buffer
= static_cast<void *>(buffer
);
253 skip_in_buffer(const void **_buffer
, uint32 bytes
)
255 const uint8
*buffer
= static_cast<const uint8
*>(*_buffer
);
259 *_buffer
= static_cast<const void *>(buffer
);
264 skip_in_buffer(void **_buffer
, uint32 bytes
)
266 // This actually shouldn't be necessary, but I believe it's a
267 // bug in Be's gcc - it complains about "adds cv-quals without intervening `const'"
268 // when passing a "const void **" pointer as the first argument.
269 // Maybe I am just stupid, though -- axeld.
271 skip_in_buffer((const void **)_buffer
, bytes
);
275 template<class Type
> Type
276 swap32(Type value
, bool doSwap
)
278 STATIC_ASSERT(sizeof(Type
) == 4);
281 return (Type
)B_SWAP_INT32((int32
)value
);
287 template<class Type
> Type
288 swap64(Type value
, bool doSwap
)
290 STATIC_ASSERT(sizeof(Type
) == 8);
293 return (Type
)B_SWAP_INT64((int64
)value
);
299 template<class Type
> Type
300 read_from_buffer_swap32(const void **_buffer
, bool doSwap
)
302 return swap32
<Type
>(read_from_buffer
<Type
>(_buffer
), doSwap
);
306 template<class Type
> Type
307 read_pointer_from_buffer_swap(const void **_buffer
, bool doSwap
)
310 return swap32
<Type
>(read_from_buffer
<Type
>(_buffer
), doSwap
);
312 return swap64
<Type
>(read_from_buffer
<Type
>(_buffer
), doSwap
);
319 static inline ssize_t
320 size_left(ssize_t size
, const void *bufferStart
, const void *buffer
)
322 return size
- static_cast<ssize_t
>((const uint8
*)buffer
- (const uint8
*)bufferStart
);
326 // #pragma mark - BParameterWeb
329 BParameterWeb::BParameterWeb()
331 fNode(media_node::null
)
332 // fNode is set in BControllable::SetParameterWeb()
336 fGroups
= new BList();
337 fOldRefs
= new BList();
338 fNewRefs
= new BList();
342 BParameterWeb::~BParameterWeb()
346 for (int32 i
= fGroups
->CountItems(); i
-- > 0;) {
347 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
357 BParameterWeb::Node()
364 BParameterWeb::MakeGroup(const char* name
)
368 BParameterGroup
* group
= new(std::nothrow
) BParameterGroup(this, name
);
372 if (!fGroups
->AddItem(group
)) {
382 BParameterWeb::CountGroups()
384 return fGroups
->CountItems();
389 BParameterWeb::GroupAt(int32 index
)
391 return static_cast<BParameterGroup
*>(fGroups
->ItemAt(index
));
396 BParameterWeb::CountParameters()
400 // Counts over all groups (and sub-groups) in the web.
401 // The "groups" list is used as count stack
403 BList
groups(*fGroups
);
406 for (int32 i
= 0; i
< groups
.CountItems(); i
++) {
407 BParameterGroup
* group
408 = static_cast<BParameterGroup
*>(groups
.ItemAt(i
));
410 count
+= group
->CountParameters();
412 if (group
->fGroups
!= NULL
)
413 groups
.AddList(group
->fGroups
);
421 BParameterWeb::ParameterAt(int32 index
)
425 // Iterates over all groups (and sub-groups) in the web.
426 // The "groups" list is used as iteration stack (breadth search style)
427 // Maintains the same order as the Be implementation
429 BList
groups(*fGroups
);
431 for (int32 i
= 0; i
< groups
.CountItems(); i
++) {
432 BParameterGroup
* group
433 = static_cast<BParameterGroup
*>(groups
.ItemAt(i
));
434 int32 count
= group
->CountParameters();
436 return group
->ParameterAt(index
);
439 // the index is always relative to the start of the current group
441 if (group
->fGroups
!= NULL
)
442 groups
.AddList(group
->fGroups
);
445 TRACE("*** could not find parameter at %ld (count = %ld)\n", index
,
452 BParameterWeb::IsFixedSize() const
459 BParameterWeb::TypeCode() const
461 return B_MEDIA_PARAMETER_WEB_TYPE
;
466 BParameterWeb::FlattenedSize() const
471 //--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
472 ?? 0x01030506: 4 bytes
473 ??: 4 bytes (is always 1)
475 Node (as media_node): 0x18 bytes (decimal 24 bytes)
476 //for each Group BEGIN
477 Flattened Group Size: 4 bytes
478 Flattened Group: 'Flattened Group Size' bytes
480 //for each Group BEGIN
481 ??: 4 bytes (never get written to (holds uninitialized value))
483 //---------END-CORE-BPARAMETERWEB-STRUCT--------------
485 //36 guaranteed bytes, variable after that.
486 ssize_t size
= sizeof(int32
) + 2 * sizeof(int32
) + sizeof(media_node
);
488 for (int32 i
= fGroups
->CountItems(); i
-- > 0;) {
489 BParameterGroup
* group
490 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
492 size
+= sizeof(ssize_t
) + group
->FlattenedSize();
501 BParameterWeb::Flatten(void* buffer
, ssize_t size
) const
508 ssize_t actualSize
= BParameterWeb::FlattenedSize();
509 if (size
< actualSize
)
512 void* bufferStart
= buffer
;
514 write_to_buffer
<int32
>(&buffer
, kParameterWebMagic
);
515 write_to_buffer
<int32
>(&buffer
, kCurrentParameterWebVersion
);
517 // flatten all groups into this buffer
519 int32 count
= fGroups
->CountItems();
520 write_to_buffer
<int32
>(&buffer
, count
);
522 write_to_buffer
<media_node
>(&buffer
, fNode
);
524 for (int32 i
= 0; i
< count
; i
++) {
525 BParameterGroup
* group
526 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
528 ERROR("BParameterWeb::Flatten(): group is NULL\n");
532 ssize_t groupSize
= group
->FlattenedSize();
533 if (groupSize
> size_left(size
, bufferStart
, buffer
)) {
534 ERROR("BParameterWeb::Flatten(): buffer too small\n");
538 write_to_buffer
<ssize_t
>(&buffer
, groupSize
);
540 // write the flattened sub group
541 status_t status
= group
->Flatten(buffer
, groupSize
);
545 skip_in_buffer(&buffer
, groupSize
);
553 BParameterWeb::AllowsTypeCode(type_code code
) const
555 return code
== TypeCode();
560 BParameterWeb::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
564 if (!AllowsTypeCode(code
)) {
565 ERROR("BParameterWeb::Unflatten(): wrong type code\n");
569 if (buffer
== NULL
) {
570 ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n");
574 // if the buffer is smaller than the size needed to read the
575 // signature field, the mystery field, the group count, and the Node, then there is a problem
576 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(int32
)
577 + sizeof(ssize_t
) + sizeof(media_node
))) {
578 ERROR("BParameterWeb::Unflatten(): size to small\n");
582 const void* bufferStart
= buffer
;
584 uint32 magic
= read_from_buffer
<uint32
>(&buffer
);
585 bool isSwapped
= false;
587 if (magic
== B_SWAP_INT32(kParameterWebMagic
)) {
589 magic
= B_SWAP_INT32(magic
);
591 if (magic
!= kParameterWebMagic
)
594 // Note, it's not completely sure that this field is the version
595 // information - but it doesn't seem to have another purpose
596 int32 version
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
597 if (version
!= kCurrentParameterWebVersion
) {
598 ERROR("BParameterWeb::Unflatten(): wrong version %" B_PRId32
" (%"
599 B_PRIx32
")?!\n", version
, version
);
603 for (int32 i
= 0; i
< fGroups
->CountItems(); i
++) {
604 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
606 fGroups
->MakeEmpty();
608 int32 count
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
610 fNode
= read_from_buffer
<media_node
>(&buffer
);
612 swap_data(B_INT32_TYPE
, &fNode
, sizeof(media_node
), B_SWAP_ALWAYS
);
614 for (int32 i
= 0; i
< count
; i
++) {
616 = read_pointer_from_buffer_swap
<ssize_t
>(&buffer
, isSwapped
);
617 if (groupSize
> size_left(size
, bufferStart
, buffer
)) {
618 ERROR("BParameterWeb::Unflatten(): buffer too small\n");
622 BParameterGroup
* group
= new BParameterGroup(this, "unnamed");
623 status_t status
= group
->Unflatten(group
->TypeCode(), buffer
,
626 ERROR("BParameterWeb::Unflatten(): unflatten group failed\n");
631 skip_in_buffer(&buffer
, groupSize
);
633 fGroups
->AddItem(group
);
636 // fix all references (ParameterAt() style)
638 BList
groups(*fGroups
);
640 for (int32 i
= 0; i
< groups
.CountItems(); i
++) {
641 BParameterGroup
* group
642 = static_cast<BParameterGroup
*>(groups
.ItemAt(i
));
644 for (int32 index
= group
->CountParameters(); index
-- > 0;) {
645 BParameter
* parameter
646 = static_cast<BParameter
*>(group
->ParameterAt(index
));
648 parameter
->FixRefs(*fOldRefs
, *fNewRefs
);
651 if (group
->fGroups
!= NULL
)
652 groups
.AddList(group
->fGroups
);
655 fOldRefs
->MakeEmpty();
656 fNewRefs
->MakeEmpty();
663 BParameterWeb::AddRefFix(void* oldItem
, void* newItem
)
665 fOldRefs
->AddItem(oldItem
);
666 fNewRefs
->AddItem(newItem
);
670 // #pragma mark - BParameterGroup
673 BParameterGroup::BParameterGroup(BParameterWeb
* web
, const char* name
)
679 TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web
, name
);
681 fName
= strndup(name
, 255);
683 fControls
= new BList();
684 fGroups
= new BList();
688 BParameterGroup::~BParameterGroup()
692 for (int i
= fControls
->CountItems(); i
-- > 0;) {
693 delete static_cast<BParameter
*>(fControls
->ItemAt(i
));
697 for (int i
= fGroups
->CountItems(); i
-- > 0;) {
698 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
707 BParameterGroup::Web() const
714 BParameterGroup::Name() const
721 BParameterGroup::SetFlags(uint32 flags
)
728 BParameterGroup::Flags() const
735 BParameterGroup::MakeNullParameter(int32 id
, media_type mediaType
,
736 const char* name
, const char* kind
)
740 BNullParameter
* parameter
= new(std::nothrow
) BNullParameter(id
, mediaType
,
742 if (parameter
== NULL
)
745 parameter
->fGroup
= this;
746 fControls
->AddItem(parameter
);
752 BContinuousParameter
*
753 BParameterGroup::MakeContinuousParameter(int32 id
, media_type mediaType
,
754 const char* name
, const char* kind
, const char* unit
,
755 float minimum
, float maximum
, float stepping
)
759 BContinuousParameter
* parameter
760 = new(std::nothrow
) BContinuousParameter(id
, mediaType
, fWeb
, name
,
761 kind
, unit
, minimum
, maximum
, stepping
);
762 if (parameter
== NULL
)
765 parameter
->fGroup
= this;
766 fControls
->AddItem(parameter
);
773 BParameterGroup::MakeDiscreteParameter(int32 id
, media_type mediaType
,
774 const char* name
, const char* kind
)
778 BDiscreteParameter
* parameter
= new(std::nothrow
) BDiscreteParameter(id
,
779 mediaType
, fWeb
, name
, kind
);
780 if (parameter
== NULL
)
783 parameter
->fGroup
= this;
784 fControls
->AddItem(parameter
);
791 BParameterGroup::MakeTextParameter(int32 id
, media_type mediaType
,
792 const char* name
, const char* kind
, size_t maxBytes
)
796 BTextParameter
* parameter
= new(std::nothrow
) BTextParameter(id
, mediaType
,
797 fWeb
, name
, kind
, maxBytes
);
798 if (parameter
== NULL
)
801 parameter
->fGroup
= this;
802 fControls
->AddItem(parameter
);
809 BParameterGroup::MakeGroup(const char* name
)
813 BParameterGroup
* group
= new(std::nothrow
) BParameterGroup(fWeb
, name
);
815 fGroups
->AddItem(group
);
822 BParameterGroup::CountParameters()
824 return fControls
->CountItems();
829 BParameterGroup::ParameterAt(int32 index
)
831 return static_cast<BParameter
*>(fControls
->ItemAt(index
));
836 BParameterGroup::CountGroups()
838 return fGroups
->CountItems();
843 BParameterGroup::GroupAt(int32 index
)
845 return static_cast<BParameterGroup
*>(fGroups
->ItemAt(index
));
850 BParameterGroup::IsFixedSize() const
857 BParameterGroup::TypeCode() const
859 return B_MEDIA_PARAMETER_GROUP_TYPE
;
864 BParameterGroup::FlattenedSize() const
869 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
870 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
871 (possible) Flags: 4 bytes
872 Name String Length: 1 byte (??)
873 Name String: 'Name String Length' bytes
875 //for each Param BEGIN
877 Parameter Type: 4 bytes
878 Flattened Parameter Size: 4 bytes
879 Flattened Parameter: 'Flattened Parameter Size' bytes
881 Subgroup Count: 4 bytes
882 //for each SubGroup BEGIN
884 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
885 Flattened Group Size: 4 bytes
886 Flattened Group: 'Flattened Group Size' bytes
887 //for each SubGroup END
889 //---------END-CORE-BPARAMETERGROUP-STRUCT--------------
891 //13 guaranteed bytes, variable after that.
895 size
+= sizeof(uint32
);
898 size
+= min_c(strlen(fName
), 255);
900 int limit
= fControls
->CountItems();
901 for (int i
= 0; i
< limit
; i
++) {
902 BParameter
* parameter
= static_cast<BParameter
*>(fControls
->ItemAt(i
));
903 if (parameter
!= NULL
) {
904 // overhead for each parameter flattened
905 size
+= sizeof(BParameter
*) + sizeof(BParameter::media_parameter_type
)
906 + sizeof(ssize_t
) + parameter
->FlattenedSize();
910 limit
= fGroups
->CountItems();
911 for (int i
= 0; i
< limit
; i
++) {
912 BParameterGroup
* group
913 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
915 // overhead for each group flattened
916 size
+= sizeof(BParameterGroup
*) + sizeof(type_code
)
917 + sizeof(ssize_t
) + group
->FlattenedSize();
926 BParameterGroup::Flatten(void* buffer
, ssize_t size
) const
930 if (buffer
== NULL
) {
931 ERROR("BParameterGroup::Flatten buffer is NULL\n");
935 // NOTICE: It is important that this value is the size returned by
936 // BParameterGroup::FlattenedSize, not by a descendent's override of this method.
937 ssize_t actualSize
= BParameterGroup::FlattenedSize();
938 if (size
< actualSize
) {
939 ERROR("BParameterGroup::Flatten size to small\n");
944 write_to_buffer
<int32
>(&buffer
, kBufferGroupMagic
);
945 write_to_buffer
<uint32
>(&buffer
, fFlags
);
947 write_to_buffer
<int32
>(&buffer
, kBufferGroupMagicNoFlags
);
949 write_string_to_buffer(&buffer
, fName
);
951 int32 count
= fControls
->CountItems();
952 write_to_buffer
<int32
>(&buffer
, count
);
954 for (int32 i
= 0; i
< count
; i
++) {
955 BParameter
* parameter
= static_cast<BParameter
*>(fControls
->ItemAt(i
));
956 if (parameter
== NULL
) {
957 ERROR("BParameterGroup::Flatten(): NULL parameter\n");
961 write_to_buffer
<BParameter
*>(&buffer
, parameter
);
962 write_to_buffer
<BParameter::media_parameter_type
>(&buffer
,
965 // flatten parameter into this buffer
967 ssize_t parameterSize
= parameter
->FlattenedSize();
968 write_to_buffer
<ssize_t
>(&buffer
, parameterSize
);
970 status_t status
= parameter
->Flatten(buffer
, parameterSize
);
971 // we have only that much bytes left to write in this buffer
975 skip_in_buffer(&buffer
, parameterSize
);
978 count
= fGroups
->CountItems();
979 write_to_buffer
<int32
>(&buffer
, count
);
981 for (int32 i
= 0; i
< count
; i
++) {
982 BParameterGroup
* group
983 = static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
985 ERROR("BParameterGroup::Flatten(): NULL group\n");
989 write_to_buffer
<BParameterGroup
*>(&buffer
, group
);
990 write_to_buffer
<type_code
>(&buffer
, group
->TypeCode());
992 // flatten sub group into this buffer
994 ssize_t groupSize
= group
->FlattenedSize();
995 write_to_buffer
<ssize_t
>(&buffer
, groupSize
);
997 status_t status
= group
->Flatten(buffer
, groupSize
);
998 // we have only that much bytes left to write in this buffer
1002 skip_in_buffer(&buffer
, groupSize
);
1010 BParameterGroup::AllowsTypeCode(type_code code
) const
1012 return code
== TypeCode();
1017 BParameterGroup::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
1021 if (!AllowsTypeCode(code
)) {
1022 ERROR("BParameterGroup::Unflatten() wrong type code\n");
1026 if (buffer
== NULL
) {
1027 ERROR("BParameterGroup::Unflatten() buffer is NULL\n");
1031 // if the buffer is smaller than the size needed to read the
1032 // signature field, then there is a problem
1033 if (size
< static_cast<ssize_t
>(sizeof(int32
))) {
1034 ERROR("BParameterGroup::Unflatten() size to small\n");
1038 const void* bufferStart
= buffer
;
1039 // used to compute the rest length of the buffer when needed
1041 uint32 magic
= read_from_buffer
<uint32
>(&buffer
);
1042 bool isSwapped
= false;
1044 if (magic
== B_SWAP_INT32(kBufferGroupMagic
)
1045 || magic
== B_SWAP_INT32(kBufferGroupMagicNoFlags
)) {
1047 magic
= B_SWAP_INT32(magic
);
1050 if (magic
== kBufferGroupMagic
)
1051 fFlags
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
1052 else if (magic
== kBufferGroupMagicNoFlags
)
1057 if (read_string_from_buffer(&buffer
, &fName
,
1058 size
- (ssize_t
)((uint8
*)buffer
- (uint8
*)bufferStart
)) < B_OK
)
1061 // Clear all existing parameters/subgroups
1062 for (int32 i
= 0; i
< fControls
->CountItems(); i
++) {
1063 delete static_cast<BParameter
*>(fControls
->ItemAt(i
));
1065 fControls
->MakeEmpty();
1067 for (int32 i
= 0; i
< fGroups
->CountItems(); i
++) {
1068 delete static_cast<BParameterGroup
*>(fGroups
->ItemAt(i
));
1070 fGroups
->MakeEmpty();
1072 // unflatten parameter list
1074 int32 count
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
1075 if (count
< 0 || count
* kAdditionalParameterSize
1076 > size_left(size
, bufferStart
, buffer
))
1079 for (int32 i
= 0; i
< count
; i
++) {
1080 // make sure we can read as many bytes
1081 if (size_left(size
, bufferStart
, buffer
) < (ssize_t
)(
1082 sizeof(BParameter
*) + sizeof(BParameter::media_parameter_type
)
1083 + sizeof(ssize_t
))) {
1087 BParameter
* oldPointer
= read_pointer_from_buffer_swap
<BParameter
*>(
1088 &buffer
, isSwapped
);
1089 BParameter::media_parameter_type mediaType
1090 = read_from_buffer_swap32
<BParameter::media_parameter_type
>(&buffer
,
1093 ssize_t parameterSize
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
,
1095 if (parameterSize
> size_left(size
, bufferStart
, buffer
))
1098 BParameter
* parameter
= MakeControl(mediaType
);
1099 if (parameter
== NULL
) {
1100 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n");
1104 status_t status
= parameter
->Unflatten(parameter
->TypeCode(), buffer
,
1106 if (status
< B_OK
) {
1107 ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n");
1112 skip_in_buffer(&buffer
, parameterSize
);
1114 // add the item to the list
1115 parameter
->fGroup
= this;
1116 parameter
->fWeb
= fWeb
;
1117 fControls
->AddItem(parameter
);
1119 // add it's old pointer value to the RefFix list kept by the owner web
1121 fWeb
->AddRefFix(oldPointer
, parameter
);
1124 // unflatten sub groups
1126 count
= read_from_buffer_swap32
<int32
>(&buffer
, isSwapped
);
1127 if (count
< 0 || count
* kAdditionalParameterGroupSize
1128 > size_left(size
, bufferStart
, buffer
))
1131 for (int32 i
= 0; i
< count
; i
++) {
1132 // make sure we can read as many bytes
1133 if (size_left(size
, bufferStart
, buffer
) < (ssize_t
)(
1134 sizeof(BParameterGroup
*) + sizeof(type_code
)
1135 + sizeof(ssize_t
))) {
1139 BParameterGroup
* oldPointer
= read_pointer_from_buffer_swap
<
1140 BParameterGroup
*>(&buffer
, isSwapped
);
1141 type_code type
= read_from_buffer_swap32
<type_code
>(&buffer
, isSwapped
);
1144 = read_pointer_from_buffer_swap
<ssize_t
>(&buffer
, isSwapped
);
1145 if (groupSize
> size_left(size
, bufferStart
, buffer
))
1148 BParameterGroup
* group
= new BParameterGroup(fWeb
, "sub-unnamed");
1149 if (group
== NULL
) {
1150 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n");
1154 status_t status
= group
->Unflatten(type
, buffer
, groupSize
);
1155 if (status
!= B_OK
) {
1156 ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n");
1161 skip_in_buffer(&buffer
, groupSize
);
1163 fGroups
->AddItem(group
);
1165 // add it's old pointer value to the RefFix list kept by the owner web
1167 fWeb
->AddRefFix(oldPointer
, group
);
1174 /*! Creates an uninitialized parameter of the specified type.
1175 Unlike the BParameterGroup::MakeXXXParameter() type of methods, this
1176 method does not add the parameter to this group automatically.
1179 BParameterGroup::MakeControl(int32 type
)
1184 case BParameter::B_NULL_PARAMETER
:
1185 return new BNullParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
, NULL
);
1187 case BParameter::B_DISCRETE_PARAMETER
:
1188 return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
,
1191 case BParameter::B_CONTINUOUS_PARAMETER
:
1192 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
,
1193 NULL
, NULL
, 0, 0, 0);
1195 case BParameter::B_TEXT_PARAMETER
:
1196 return new BTextParameter(-1, B_MEDIA_NO_TYPE
, NULL
, NULL
, NULL
, 0);
1199 ERROR("BParameterGroup::MakeControl unknown type %" B_PRId32
"\n",
1206 // #pragma mark - BParameter
1209 BParameter::media_parameter_type
1210 BParameter::Type() const
1217 BParameter::Web() const
1224 BParameter::Group() const
1231 BParameter::Name() const
1238 BParameter::Kind() const
1245 BParameter::Unit() const
1252 BParameter::ID() const
1259 BParameter::SetFlags(uint32 flags
)
1266 BParameter::Flags() const
1273 BParameter::GetValue(void* buffer
, size_t* _size
, bigtime_t
* _when
)
1277 if (buffer
== NULL
|| _size
== NULL
)
1280 size_t size
= *_size
;
1285 ERROR("BParameter::GetValue: no parent BParameterWeb\n");
1289 media_node node
= fWeb
->Node();
1290 if (IS_INVALID_NODE(node
)) {
1291 ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n");
1295 controllable_get_parameter_data_request request
;
1296 controllable_get_parameter_data_reply reply
;
1300 if (size
> MAX_PARAMETER_DATA
) {
1301 // create an area if large data needs to be transfered
1302 area
= create_area("get parameter data", &data
, B_ANY_ADDRESS
,
1303 ROUND_UP_TO_PAGE(size
), B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
1305 ERROR("BParameter::GetValue can't create area of %ld bytes\n",
1311 data
= reply
.raw_data
;
1314 request
.parameter_id
= fID
;
1315 request
.request_size
= size
;
1316 request
.area
= area
;
1318 status_t status
= QueryPort(node
.port
, CONTROLLABLE_GET_PARAMETER_DATA
,
1319 &request
, sizeof(request
), &reply
, sizeof(reply
));
1320 if (status
== B_OK
) {
1321 // we don't want to copy more than the buffer provides
1322 if (reply
.size
< size
)
1325 memcpy(buffer
, data
, size
);
1327 // store reported values
1329 *_size
= reply
.size
;
1331 *_when
= reply
.last_change
;
1333 ERROR("BParameter::GetValue parameter '%s' querying node %d, "
1334 "port %d failed: %s\n", fName
, (int)node
.node
, (int)node
.port
,
1346 BParameter::SetValue(const void* buffer
, size_t size
, bigtime_t when
)
1356 ERROR("BParameter::SetValue: no parent BParameterWeb\n");
1360 media_node node
= fWeb
->Node();
1361 if (IS_INVALID_NODE(node
)) {
1362 ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned "
1363 "to a BMediaNode\n");
1367 controllable_set_parameter_data_request request
;
1368 controllable_set_parameter_data_reply reply
;
1372 if (size
> MAX_PARAMETER_DATA
) {
1373 // create an area if large data needs to be transfered
1374 area
= create_area("set parameter data", &data
, B_ANY_ADDRESS
,
1375 ROUND_UP_TO_PAGE(size
), B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
1377 ERROR("BParameter::SetValue can't create area of %ld bytes\n", size
);
1382 data
= request
.raw_data
;
1385 memcpy(data
, buffer
, size
);
1386 request
.parameter_id
= fID
;
1387 request
.when
= when
;
1388 request
.area
= area
;
1389 request
.size
= size
;
1391 status_t status
= QueryPort(node
.port
, CONTROLLABLE_SET_PARAMETER_DATA
,
1392 &request
, sizeof(request
), &reply
, sizeof(reply
));
1393 if (status
!= B_OK
) {
1394 ERROR("BParameter::SetValue querying node failed: %s\n",
1406 BParameter::CountChannels()
1413 BParameter::SetChannelCount(int32 count
)
1420 BParameter::MediaType()
1427 BParameter::SetMediaType(media_type type
)
1434 BParameter::CountInputs()
1436 return fInputs
->CountItems();
1441 BParameter::InputAt(int32 index
)
1443 return static_cast<BParameter
*>(fInputs
->ItemAt(index
));
1448 BParameter::AddInput(BParameter
* input
)
1452 // BeBook has this method returning a status value,
1453 // but it should be updated
1457 if (fInputs
->HasItem(input
)) {
1458 // if already in input list, don't duplicate.
1462 fInputs
->AddItem(input
);
1463 input
->AddOutput(this);
1468 BParameter::CountOutputs()
1470 return fOutputs
->CountItems();
1475 BParameter::OutputAt(int32 index
)
1477 return static_cast<BParameter
*>(fOutputs
->ItemAt(index
));
1482 BParameter::AddOutput(BParameter
* output
)
1486 // BeBook has this method returning a status value,
1487 // but it should be updated
1491 if (fOutputs
->HasItem(output
)) {
1492 // if already in output list, don't duplicate.
1496 fOutputs
->AddItem(output
);
1497 output
->AddInput(this);
1502 BParameter::IsFixedSize() const
1509 BParameter::TypeCode() const
1511 return B_MEDIA_PARAMETER_TYPE
;
1516 BParameter::FlattenedSize() const
1520 ?? (0x02040607): 4 bytes
1521 BParameter Struct Size (in bytes): 4 bytes
1523 Name String Length: 1 byte (??)
1524 Name String: 'Name String Length' bytes
1525 Kind String Length: 1 byte (??)
1526 Kind String: 'Kind String Length' bytes
1527 Unit String Length: 1 byte (??)
1528 Unit String: 'Unit String Length' bytes
1529 Inputs Count: 4 bytes
1530 Inputs (pointers): ('Inputs Count')*4 bytes
1531 Outputs Count: 4 bytes
1532 Outputs (pointers): ('Outputs Count')*4 bytes
1534 ChannelCount: 4 bytes
1537 //35 bytes are guaranteed, after that, add the variable length parts.
1538 ssize_t size
= kAdditionalParameterSize
;
1541 size
+= strlen(fName
);
1543 size
+= strlen(fKind
);
1545 size
+= strlen(fUnit
);
1547 size
+= fInputs
->CountItems() * sizeof(BParameter
*);
1548 size
+= fOutputs
->CountItems() * sizeof(BParameter
*);
1555 BParameter::Flatten(void* buffer
, ssize_t size
) const
1559 if (buffer
== NULL
) {
1560 ERROR("BParameter::Flatten buffer is NULL\n");
1564 // NOTICE: It is important that this value is the size returned by
1565 // BParameter::FlattenedSize(), not by a descendent's override of this method.
1566 ssize_t actualSize
= BParameter::FlattenedSize();
1567 if (size
< actualSize
) {
1568 ERROR("BParameter::Flatten(): size too small\n");
1572 write_to_buffer
<uint32
>(&buffer
, kParameterMagic
);
1573 write_to_buffer
<ssize_t
>(&buffer
, actualSize
);
1574 write_to_buffer
<int32
>(&buffer
, fID
);
1576 write_string_to_buffer(&buffer
, fName
);
1577 write_string_to_buffer(&buffer
, fKind
);
1578 write_string_to_buffer(&buffer
, fUnit
);
1580 // flatten and write the list of inputs
1581 ssize_t count
= fInputs
->CountItems();
1582 write_to_buffer
<ssize_t
>(&buffer
, count
);
1585 memcpy(buffer
, fInputs
->Items(), sizeof(BParameter
*) * count
);
1586 skip_in_buffer(&buffer
, sizeof(BParameter
*) * count
);
1589 // flatten and write the list of outputs
1590 count
= fOutputs
->CountItems();
1591 write_to_buffer
<ssize_t
>(&buffer
, count
);
1594 memcpy(buffer
, fOutputs
->Items(), sizeof(BParameter
*) * count
);
1595 skip_in_buffer(&buffer
, sizeof(BParameter
*) * count
);
1598 write_to_buffer
<media_type
>(&buffer
, fMediaType
);
1599 write_to_buffer
<int32
>(&buffer
, fChannels
);
1600 write_to_buffer
<uint32
>(&buffer
, fFlags
);
1607 BParameter::AllowsTypeCode(type_code code
) const
1609 return code
== TypeCode();
1614 BParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
1618 if (!AllowsTypeCode(code
)) {
1619 ERROR("BParameter::Unflatten(): wrong type code\n");
1623 if (buffer
== NULL
) {
1624 ERROR("BParameter::Unflatten(): buffer is NULL\n");
1628 // if the buffer is smaller than the size needed to read the
1629 // signature and struct size fields, then there is a problem
1630 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(ssize_t
))) {
1631 ERROR("BParameter::Unflatten() size too small\n");
1635 const void* bufferStart
= buffer
;
1639 uint32 magic
= read_from_buffer
<uint32
>(&buffer
);
1640 if (magic
== B_SWAP_INT32(kParameterMagic
))
1641 fSwapDetected
= true;
1642 else if (magic
== kParameterMagic
)
1643 fSwapDetected
= false;
1645 ERROR("BParameter::Unflatten(): bad magic\n");
1649 ssize_t parameterSize
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
,
1651 if (parameterSize
> size
) {
1652 ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n",
1653 parameterSize
, size
);
1657 // if the struct doesn't meet the minimum size for
1658 // a flattened BParameter, then return an error.
1659 // MinFlattenedParamSize =
1661 // Name String Length (1 byte)
1662 // Kind String Length (1 byte)
1663 // Unit String Length (1 byte)
1664 // Inputs Count (4 bytes)
1665 // Outputs Count (4 bytes)
1666 // Media Type (4 bytes)
1667 // Channel Count (4 bytes)
1670 const ssize_t kMinFlattenedParamSize
= 15 + 3 * sizeof(ssize_t
);
1671 if (parameterSize
< kMinFlattenedParamSize
) {
1672 ERROR("BParameter::Unflatten out of memory (2)\n");
1676 fID
= read_from_buffer_swap32
<int32
>(&buffer
, fSwapDetected
);
1678 if (read_string_from_buffer(&buffer
, &fName
,
1679 size_left(size
, bufferStart
, buffer
)) < B_OK
1680 || read_string_from_buffer(&buffer
, &fKind
,
1681 size_left(size
, bufferStart
, buffer
)) < B_OK
1682 || read_string_from_buffer(&buffer
, &fUnit
,
1683 size_left(size
, bufferStart
, buffer
)) < B_OK
)
1686 // read the list of inputs
1688 // it will directly add the pointers in the flattened message to the list;
1689 // these will be fixed to point to the real inputs/outputs later in FixRefs()
1691 ssize_t count
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
,
1694 fInputs
->MakeEmpty();
1695 for (ssize_t i
= 0; i
< count
; i
++) {
1696 fInputs
->AddItem(read_pointer_from_buffer_swap
<BParameter
* const>(
1697 &buffer
, fSwapDetected
));
1700 // read the list of outputs
1702 count
= read_pointer_from_buffer_swap
<ssize_t
>(&buffer
, fSwapDetected
);
1704 fOutputs
->MakeEmpty();
1705 for (ssize_t i
= 0; i
< count
; i
++) {
1706 fOutputs
->AddItem(read_pointer_from_buffer_swap
<BParameter
* const>(
1707 &buffer
, fSwapDetected
));
1710 fMediaType
= read_from_buffer_swap32
<media_type
>(&buffer
, fSwapDetected
);
1711 fChannels
= read_from_buffer_swap32
<int32
>(&buffer
, fSwapDetected
);
1712 fFlags
= read_from_buffer_swap32
<uint32
>(&buffer
, fSwapDetected
);
1718 BParameter::BParameter(int32 id
, media_type mediaType
,
1719 media_parameter_type type
, BParameterWeb
* web
, const char* name
,
1720 const char* kind
, const char* unit
)
1726 fSwapDetected(true),
1727 fMediaType(mediaType
),
1733 fName
= strndup(name
, 255);
1734 fKind
= strndup(kind
, 255);
1735 fUnit
= strndup(unit
, 255);
1737 // create empty input/output lists
1738 fInputs
= new BList();
1739 fOutputs
= new BList();
1743 BParameter::~BParameter()
1747 // don't worry about the fWeb/fGroup properties, you don't need
1748 // to remove yourself from a web/group since the only way in which
1749 // a parameter is destroyed is when the owner web/group destroys it
1760 /*! Replaces references to items in the old list with the corresponding
1761 items in the updated list. The references are replaced in the input
1763 This is called by BParameterWeb::Unflatten().
1766 BParameter::FixRefs(BList
& old
, BList
& updated
)
1772 void** items
= static_cast<void**>(fInputs
->Items());
1773 int32 count
= fInputs
->CountItems();
1775 for (int32 i
= 0; i
< count
; i
++) {
1776 int32 index
= old
.IndexOf(items
[i
]);
1778 items
[i
] = updated
.ItemAt(index
);
1780 ERROR("BParameter::FixRefs(): No mapping found for input");
1785 // remove all NULL inputs (those which couldn't be mapped)
1787 for (int32 i
= count
; i
-- > 0;) {
1788 if (items
[i
] == NULL
)
1789 fInputs
->RemoveItem(i
);
1794 items
= static_cast<void **>(fOutputs
->Items());
1795 count
= fOutputs
->CountItems();
1797 for (int32 i
= 0; i
< count
; i
++) {
1798 int32 index
= old
.IndexOf(items
[i
]);
1800 items
[i
] = updated
.ItemAt(index
);
1802 ERROR("BParameter::FixRefs(): No mapping found for output");
1807 // remove all NULL outputs (those which couldn't be mapped)
1809 for (int32 i
= count
; i
-- > 0;) {
1810 if (items
[i
] == NULL
)
1811 fOutputs
->RemoveItem(i
);
1816 // #pragma mark - public BContinuousParameter
1820 BContinuousParameter::ValueType()
1822 return B_FLOAT_TYPE
;
1827 BContinuousParameter::MinValue()
1834 BContinuousParameter::MaxValue()
1841 BContinuousParameter::ValueStep()
1848 BContinuousParameter::SetResponse(int resp
, float factor
, float offset
)
1850 fResponse
= static_cast<response
>(resp
);
1857 BContinuousParameter::GetResponse(int* _resp
, float* _factor
, float* _offset
)
1861 if (_factor
!= NULL
)
1863 if (_offset
!= NULL
)
1869 BContinuousParameter::FlattenedSize() const
1873 // only adds a fixed amount of bytes
1874 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize
;
1879 BContinuousParameter::Flatten(void* buffer
, ssize_t size
) const
1883 if (buffer
== NULL
) {
1884 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n");
1888 ssize_t parameterSize
= BParameter::FlattenedSize();
1889 if (size
< (parameterSize
+ kAdditionalContinuousParameterSize
)) {
1890 ERROR("BContinuousParameter::Flatten(): size to small\n");
1894 status_t status
= BParameter::Flatten(buffer
, size
);
1895 if (status
!= B_OK
) {
1896 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n");
1900 // add our data to the general flattened BParameter
1902 skip_in_buffer(&buffer
, parameterSize
);
1904 write_to_buffer
<float>(&buffer
, fMinimum
);
1905 write_to_buffer
<float>(&buffer
, fMaximum
);
1906 write_to_buffer
<float>(&buffer
, fStepping
);
1907 write_to_buffer
<response
>(&buffer
, fResponse
);
1908 write_to_buffer
<float>(&buffer
, fFactor
);
1909 write_to_buffer
<float>(&buffer
, fOffset
);
1916 BContinuousParameter::Unflatten(type_code code
, const void* buffer
,
1921 // we try to check if the buffer size is long enough to hold an object
1922 // as early as possible.
1924 if (!AllowsTypeCode(code
)) {
1925 ERROR("BContinuousParameter::Unflatten wrong type code\n");
1929 if (buffer
== NULL
) {
1930 ERROR("BContinuousParameter::Unflatten buffer is NULL\n");
1934 // if the buffer is smaller than the size needed to read the
1935 // signature and struct size fields, then there is a problem
1936 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(ssize_t
))) {
1937 ERROR("BContinuousParameter::Unflatten size too small\n");
1941 status_t status
= BParameter::Unflatten(code
, buffer
, size
);
1942 if (status
!= B_OK
) {
1943 ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten "
1944 "failed: %s\n", strerror(status
));
1948 ssize_t parameterSize
= BParameter::FlattenedSize();
1949 skip_in_buffer(&buffer
, parameterSize
);
1951 if (size
< (parameterSize
+ kAdditionalContinuousParameterSize
)) {
1952 ERROR("BContinuousParameter::Unflatten(): buffer too small\n");
1956 fMinimum
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1957 fMaximum
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1958 fStepping
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1959 fResponse
= read_from_buffer_swap32
<response
>(&buffer
, SwapOnUnflatten());
1960 fFactor
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1961 fOffset
= read_from_buffer_swap32
<float>(&buffer
, SwapOnUnflatten());
1967 BContinuousParameter::BContinuousParameter(int32 id
, media_type mediaType
,
1968 BParameterWeb
* web
, const char* name
, const char* kind
,
1969 const char* unit
, float minimum
, float maximum
, float stepping
)
1970 : BParameter(id
, mediaType
, B_CONTINUOUS_PARAMETER
, web
, name
, kind
, unit
),
1973 fStepping(stepping
),
1974 fResponse(B_LINEAR
),
1982 BContinuousParameter::~BContinuousParameter()
1988 // #pragma mark - public BDiscreteParameter
1992 BDiscreteParameter::ValueType()
1994 return B_INT32_TYPE
;
1999 BDiscreteParameter::CountItems()
2001 return fValues
->CountItems();
2006 BDiscreteParameter::ItemNameAt(int32 index
)
2008 return reinterpret_cast<const char*>(fSelections
->ItemAt(index
));
2013 BDiscreteParameter::ItemValueAt(int32 index
)
2015 int32
* item
= static_cast<int32
*>(fValues
->ItemAt(index
));
2024 BDiscreteParameter::AddItem(int32 value
, const char* name
)
2028 int32
* valueCopy
= new(std::nothrow
) int32(value
);
2029 if (valueCopy
== NULL
)
2031 char* nameCopy
= strndup(name
, 255);
2032 if (name
!= NULL
&& nameCopy
== NULL
) {
2037 if (!fValues
->AddItem(valueCopy
))
2039 if (!fSelections
->AddItem(nameCopy
)) {
2040 fValues
->RemoveItem(valueCopy
);
2053 BDiscreteParameter::MakeItemsFromInputs()
2057 int32 count
= fInputs
->CountItems();
2058 for (int32 i
= 0; i
< count
; i
++) {
2059 BParameter
* parameter
= static_cast<BParameter
*>(fInputs
->ItemAt(i
));
2060 AddItem(i
, parameter
->Name());
2068 BDiscreteParameter::MakeItemsFromOutputs()
2072 int32 count
= fOutputs
->CountItems();
2073 for (int32 i
= 0; i
< count
; i
++) {
2074 BParameter
* parameter
= static_cast<BParameter
*>(fOutputs
->ItemAt(i
));
2075 AddItem(i
, parameter
->Name());
2083 BDiscreteParameter::MakeEmpty()
2087 for (int32 i
= fValues
->CountItems(); i
-- > 0;) {
2088 delete static_cast<int32
*>(fValues
->ItemAt(i
));
2090 fValues
->MakeEmpty();
2092 for (int32 i
= fSelections
->CountItems(); i
-- > 0;) {
2093 free(static_cast<char*>(fSelections
->ItemAt(i
)));
2095 fSelections
->MakeEmpty();
2100 BDiscreteParameter::FlattenedSize() const
2104 ssize_t size
= BParameter::FlattenedSize()
2105 + kAdditionalDiscreteParameterSize
;
2107 int32 count
= fValues
->CountItems();
2108 for (int32 i
= 0; i
< count
; i
++) {
2109 char* selection
= static_cast<char*>(fSelections
->ItemAt(i
));
2111 if (selection
!= NULL
)
2112 size
+= min_c(strlen(selection
), 255);
2115 // string length + value
2123 BDiscreteParameter::Flatten(void* buffer
, ssize_t size
) const
2127 if (buffer
== NULL
) {
2128 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n");
2132 ssize_t parameterSize
= BParameter::FlattenedSize();
2134 if (size
< FlattenedSize()) {
2135 ERROR("BDiscreteParameter::Flatten(): size too small\n");
2139 status_t status
= BParameter::Flatten(buffer
, size
);
2140 if (status
!= B_OK
) {
2141 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n");
2145 skip_in_buffer(&buffer
, parameterSize
);
2147 int32 count
= fValues
->CountItems();
2148 write_to_buffer
<int32
>(&buffer
, count
);
2150 // write out all value/name pairs
2151 for (int32 i
= 0; i
< count
; i
++) {
2152 const char* selection
= static_cast<char*>(fSelections
->ItemAt(i
));
2153 const int32
* value
= static_cast<int32
*>(fValues
->ItemAt(i
));
2155 write_string_to_buffer(&buffer
, selection
);
2156 write_to_buffer
<int32
>(&buffer
, value
? *value
: 0);
2164 BDiscreteParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
2168 if (!AllowsTypeCode(code
)) {
2169 ERROR("BDiscreteParameter::Unflatten(): bad type code\n");
2173 if (buffer
== NULL
) {
2174 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n");
2178 // if the buffer is smaller than the size needed to read the
2179 // signature and struct size fields, then there is a problem
2180 if (size
< static_cast<ssize_t
>(sizeof(int32
) + sizeof(ssize_t
))) {
2181 ERROR("BDiscreteParameter::Unflatten(): size too small\n");
2185 const void* bufferStart
= buffer
;
2187 status_t status
= BParameter::Unflatten(code
, buffer
, size
);
2188 if (status
!= B_OK
) {
2189 ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n");
2193 ssize_t parameterSize
= BParameter::FlattenedSize();
2194 skip_in_buffer(&buffer
, parameterSize
);
2196 if (size
< (parameterSize
+ kAdditionalDiscreteParameterSize
)) {
2197 ERROR("BDiscreteParameter::Unflatten(): buffer too small\n");
2201 int32 count
= read_from_buffer_swap32
<int32
>(&buffer
, SwapOnUnflatten());
2203 // clear any existing name/value pairs
2206 for (int32 i
= 0; i
< count
; i
++) {
2208 if (read_string_from_buffer(&buffer
, &name
, size_left(size
, bufferStart
,
2212 if (size_left(size
, bufferStart
, buffer
) < (int)sizeof(int32
)) {
2217 int32 value
= read_from_buffer_swap32
<int32
>(&buffer
,
2220 AddItem(value
, name
);
2228 BDiscreteParameter::BDiscreteParameter(int32 id
, media_type mediaType
,
2229 BParameterWeb
* web
, const char* name
, const char* kind
)
2230 : BParameter(id
, mediaType
, B_DISCRETE_PARAMETER
, web
, name
, kind
, NULL
)
2234 fSelections
= new BList();
2235 fValues
= new BList();
2239 BDiscreteParameter::~BDiscreteParameter()
2250 // #pragma mark - public BTextParameter
2254 BTextParameter::MaxBytes() const
2261 BTextParameter::ValueType()
2263 return B_FLOAT_TYPE
;
2268 BTextParameter::FlattenedSize() const
2270 return BParameter::FlattenedSize() + sizeof(fMaxBytes
);
2275 BTextParameter::Flatten(void* buffer
, ssize_t size
) const
2277 if (buffer
== NULL
) {
2278 ERROR("BTextParameter::Flatten(): buffer is NULL\n");
2282 ssize_t parameterSize
= BParameter::FlattenedSize();
2283 if (size
< static_cast<ssize_t
>(parameterSize
+ sizeof(fMaxBytes
))) {
2284 ERROR("BContinuousParameter::Flatten(): size to small\n");
2288 status_t status
= BParameter::Flatten(buffer
, size
);
2289 if (status
!= B_OK
) {
2290 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n");
2294 // add our data to the general flattened BParameter
2296 skip_in_buffer(&buffer
, parameterSize
);
2298 write_to_buffer
<uint32
>(&buffer
, fMaxBytes
);
2305 BTextParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
2307 // we try to check if the buffer size is long enough to hold an object
2308 // as early as possible.
2310 if (!AllowsTypeCode(code
)) {
2311 ERROR("BTextParameter::Unflatten wrong type code\n");
2315 if (buffer
== NULL
) {
2316 ERROR("BTextParameter::Unflatten buffer is NULL\n");
2320 if (size
< static_cast<ssize_t
>(sizeof(fMaxBytes
))) {
2321 ERROR("BTextParameter::Unflatten size too small\n");
2325 status_t status
= BParameter::Unflatten(code
, buffer
, size
);
2326 if (status
!= B_OK
) {
2327 ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n");
2331 ssize_t parameterSize
= BParameter::FlattenedSize();
2332 skip_in_buffer(&buffer
, parameterSize
);
2334 if (size
< static_cast<ssize_t
>(parameterSize
+ sizeof(fMaxBytes
))) {
2335 ERROR("BTextParameter::Unflatten(): buffer too small\n");
2339 fMaxBytes
= read_from_buffer_swap32
<uint32
>(&buffer
, SwapOnUnflatten());
2345 BTextParameter::BTextParameter(int32 id
, media_type mediaType
,
2346 BParameterWeb
* web
, const char* name
, const char* kind
,
2348 : BParameter(id
, mediaType
, B_TEXT_PARAMETER
, web
, name
, kind
, NULL
)
2350 fMaxBytes
= maxBytes
;
2354 BTextParameter::~BTextParameter()
2359 // #pragma mark - public BNullParameter
2363 BNullParameter::ValueType()
2365 // NULL parameters have no value type
2371 BNullParameter::FlattenedSize() const
2373 return BParameter::FlattenedSize();
2378 BNullParameter::Flatten(void* buffer
, ssize_t size
) const
2380 return BParameter::Flatten(buffer
, size
);
2385 BNullParameter::Unflatten(type_code code
, const void* buffer
, ssize_t size
)
2387 return BParameter::Unflatten(code
, buffer
, size
);
2391 BNullParameter::BNullParameter(int32 id
, media_type mediaType
,
2392 BParameterWeb
* web
, const char* name
, const char* kind
)
2393 : BParameter(id
, mediaType
, B_NULL_PARAMETER
, web
, name
, kind
, NULL
)
2398 BNullParameter::~BNullParameter()
2403 // #pragma mark - reserved functions
2406 status_t
BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR
; }
2407 status_t
BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR
; }
2408 status_t
BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR
; }
2409 status_t
BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR
; }
2410 status_t
BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR
; }
2411 status_t
BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR
; }
2412 status_t
BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR
; }
2413 status_t
BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR
; }
2415 status_t
BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR
; }
2416 status_t
BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR
; }
2417 status_t
BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR
; }
2418 status_t
BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR
; }
2419 status_t
BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR
; }
2420 status_t
BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR
; }
2421 status_t
BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR
; }
2422 status_t
BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR
; }
2424 status_t
BParameter::_Reserved_Control_0(void *) { return B_ERROR
; }
2425 status_t
BParameter::_Reserved_Control_1(void *) { return B_ERROR
; }
2426 status_t
BParameter::_Reserved_Control_2(void *) { return B_ERROR
; }
2427 status_t
BParameter::_Reserved_Control_3(void *) { return B_ERROR
; }
2428 status_t
BParameter::_Reserved_Control_4(void *) { return B_ERROR
; }
2429 status_t
BParameter::_Reserved_Control_5(void *) { return B_ERROR
; }
2430 status_t
BParameter::_Reserved_Control_6(void *) { return B_ERROR
; }
2431 status_t
BParameter::_Reserved_Control_7(void *) { return B_ERROR
; }
2433 status_t
BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR
; }
2434 status_t
BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR
; }
2435 status_t
BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR
; }
2436 status_t
BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR
; }
2437 status_t
BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR
; }
2438 status_t
BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR
; }
2439 status_t
BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR
; }
2440 status_t
BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR
; }
2442 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR
; }
2443 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR
; }
2444 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR
; }
2445 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR
; }
2446 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR
; }
2447 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR
; }
2448 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR
; }
2449 status_t
BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR
; }
2451 status_t
BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR
; }
2452 status_t
BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR
; }
2453 status_t
BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR
; }
2454 status_t
BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR
; }
2455 status_t
BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR
; }
2456 status_t
BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR
; }
2457 status_t
BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR
; }
2458 status_t
BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR
; }
2460 status_t
BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR
; }
2461 status_t
BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR
; }
2462 status_t
BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR
; }
2463 status_t
BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR
; }
2464 status_t
BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR
; }
2465 status_t
BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR
; }
2466 status_t
BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR
; }
2467 status_t
BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR
; }