tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / media / ParameterWeb.cpp
blob35ef993d4a6f7ca4461ca2dd8ddbedb28083f159
1 /*
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
7 * Marcus Overhagen
8 */
11 /*! Implements the following classes:
12 BParameterWeb, BParameterGroup, BParameter, BNullParameter,
13 BContinuousParameter, BDiscreteParameter
17 #include <ParameterWeb.h>
19 #include <new>
20 #include <string.h>
22 #include <MediaNode.h>
23 #include <MediaRoster.h>
25 #include "DataExchange.h"
26 #include "debug.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
37 ID: 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
44 Inputs Count: 4 bytes
45 Inputs (pointers): ('Inputs Count')*4 bytes
46 Outputs Count: 4 bytes
47 Outputs (pointers): ('Outputs Count')*4 bytes
48 Media Type: 4 bytes
49 ChannelCount: 4 bytes
50 Flags: 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)
62 //for each item BEGIN
63 Item Name String Length: 1 byte
64 Item Name String: 'Item Name String Length' bytes
65 Item Value: 4 bytes (as int)
66 //for each item END
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
74 Param Count: 4 bytes
75 //for each Param BEGIN
76 Pointer: 4 bytes
77 Parameter Type: 4 bytes
78 Flattened Parameter Size: 4 bytes
79 Flattened Parameter: 'Flattened Parameter Size' bytes
80 //for each Param END
81 Subgroup Count: 4 bytes
82 //for each SubGroup BEGIN
83 Pointer: 4 bytes
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)
94 Group Count: 4 bytes
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
99 //for each Group END
100 //for each Group BEGIN
101 ??: 4 bytes (never get written to (holds uninitialized value))
102 //for each Group END
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";
144 // Flattened data
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);
168 // helper functions
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;
177 typedBuffer++;
178 *_buffer = static_cast<const void *>(typedBuffer);
180 return value;
184 static status_t
185 read_string_from_buffer(const void **_buffer, char **_string, ssize_t size)
187 if (size < 1)
188 return B_BAD_VALUE;
190 const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
191 uint8 length = *buffer++;
192 if (length > size - 1)
193 return B_BAD_VALUE;
195 char *string = (char *)malloc(length + 1);
196 if (string == NULL)
197 return B_NO_MEMORY;
199 memcpy(string, buffer, length);
200 string[length] = '\0';
202 *_buffer = static_cast<const void *>(buffer + length);
203 *_string = string;
204 return B_OK;
208 // currently unused
209 #if 0
210 template<class Type> Type *
211 reserve_in_buffer(void **_buffer)
213 Type *typedBuffer = static_cast<Type *>(*_buffer);
215 *typedBuffer = 0;
216 typedBuffer++;
218 *_buffer = static_cast<void *>(typedBuffer);
220 #endif
222 template<class Type> void
223 write_to_buffer(void **_buffer, Type value)
225 Type *typedBuffer = static_cast<Type *>(*_buffer);
227 *typedBuffer = value;
228 typedBuffer++;
230 *_buffer = static_cast<void *>(typedBuffer);
234 void
235 write_string_to_buffer(void **_buffer, const char *string)
237 uint8 *buffer = static_cast<uint8 *>(*_buffer);
238 uint32 length = string ? strlen(string) : 0;
239 if (length > 255)
240 length = 255;
242 *buffer++ = static_cast<uint8>(length);
243 if (length) {
244 memcpy(buffer, string, length);
245 buffer += length;
248 *_buffer = static_cast<void *>(buffer);
252 static void
253 skip_in_buffer(const void **_buffer, uint32 bytes)
255 const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
257 buffer += bytes;
259 *_buffer = static_cast<const void *>(buffer);
263 static void inline
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);
280 if (doSwap)
281 return (Type)B_SWAP_INT32((int32)value);
283 return value;
287 template<class Type> Type
288 swap64(Type value, bool doSwap)
290 STATIC_ASSERT(sizeof(Type) == 8);
292 if (doSwap)
293 return (Type)B_SWAP_INT64((int64)value);
295 return 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)
309 #if B_HAIKU_32_BIT
310 return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
311 #elif B_HAIKU_64_BIT
312 return swap64<Type>(read_from_buffer<Type>(_buffer), doSwap);
313 #else
314 # error Interesting
315 #endif
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()
334 CALLED();
336 fGroups = new BList();
337 fOldRefs = new BList();
338 fNewRefs = new BList();
342 BParameterWeb::~BParameterWeb()
344 CALLED();
346 for (int32 i = fGroups->CountItems(); i-- > 0;) {
347 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
350 delete fGroups;
351 delete fOldRefs;
352 delete fNewRefs;
356 media_node
357 BParameterWeb::Node()
359 return fNode;
363 BParameterGroup*
364 BParameterWeb::MakeGroup(const char* name)
366 CALLED();
368 BParameterGroup* group = new(std::nothrow) BParameterGroup(this, name);
369 if (group == NULL)
370 return NULL;
372 if (!fGroups->AddItem(group)) {
373 delete group;
374 return NULL;
377 return group;
381 int32
382 BParameterWeb::CountGroups()
384 return fGroups->CountItems();
388 BParameterGroup*
389 BParameterWeb::GroupAt(int32 index)
391 return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
395 int32
396 BParameterWeb::CountParameters()
398 CALLED();
400 // Counts over all groups (and sub-groups) in the web.
401 // The "groups" list is used as count stack
403 BList groups(*fGroups);
404 int32 count = 0;
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);
416 return count;
420 BParameter*
421 BParameterWeb::ParameterAt(int32 index)
423 CALLED();
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();
435 if (index < count)
436 return group->ParameterAt(index);
438 index -= count;
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,
446 CountParameters());
447 return NULL;
451 bool
452 BParameterWeb::IsFixedSize() const
454 return false;
458 type_code
459 BParameterWeb::TypeCode() const
461 return B_MEDIA_PARAMETER_WEB_TYPE;
465 ssize_t
466 BParameterWeb::FlattenedSize() const
468 CALLED();
471 //--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
472 ?? 0x01030506: 4 bytes
473 ??: 4 bytes (is always 1)
474 Group Count: 4 bytes
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
479 //for each Group END
480 //for each Group BEGIN
481 ??: 4 bytes (never get written to (holds uninitialized value))
482 //for each Group END
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));
491 if (group != NULL) {
492 size += sizeof(ssize_t) + group->FlattenedSize();
496 return size;
500 status_t
501 BParameterWeb::Flatten(void* buffer, ssize_t size) const
503 CALLED();
505 if (buffer == NULL)
506 return B_NO_INIT;
508 ssize_t actualSize = BParameterWeb::FlattenedSize();
509 if (size < actualSize)
510 return B_NO_MEMORY;
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));
527 if (group == NULL) {
528 ERROR("BParameterWeb::Flatten(): group is NULL\n");
529 continue;
532 ssize_t groupSize = group->FlattenedSize();
533 if (groupSize > size_left(size, bufferStart, buffer)) {
534 ERROR("BParameterWeb::Flatten(): buffer too small\n");
535 return B_BAD_VALUE;
538 write_to_buffer<ssize_t>(&buffer, groupSize);
540 // write the flattened sub group
541 status_t status = group->Flatten(buffer, groupSize);
542 if (status < B_OK)
543 return status;
545 skip_in_buffer(&buffer, groupSize);
548 return B_OK;
552 bool
553 BParameterWeb::AllowsTypeCode(type_code code) const
555 return code == TypeCode();
559 status_t
560 BParameterWeb::Unflatten(type_code code, const void* buffer, ssize_t size)
562 CALLED();
564 if (!AllowsTypeCode(code)) {
565 ERROR("BParameterWeb::Unflatten(): wrong type code\n");
566 return B_BAD_TYPE;
569 if (buffer == NULL) {
570 ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n");
571 return B_NO_INIT;
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");
579 return B_ERROR;
582 const void* bufferStart = buffer;
584 uint32 magic = read_from_buffer<uint32>(&buffer);
585 bool isSwapped = false;
587 if (magic == B_SWAP_INT32(kParameterWebMagic)) {
588 isSwapped = true;
589 magic = B_SWAP_INT32(magic);
591 if (magic != kParameterWebMagic)
592 return B_BAD_DATA;
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);
600 return B_ERROR;
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);
611 if (isSwapped)
612 swap_data(B_INT32_TYPE, &fNode, sizeof(media_node), B_SWAP_ALWAYS);
614 for (int32 i = 0; i < count; i++) {
615 ssize_t groupSize
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");
619 return B_BAD_DATA;
622 BParameterGroup* group = new BParameterGroup(this, "unnamed");
623 status_t status = group->Unflatten(group->TypeCode(), buffer,
624 groupSize);
625 if (status < B_OK) {
626 ERROR("BParameterWeb::Unflatten(): unflatten group failed\n");
627 delete group;
628 return status;
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();
658 return B_OK;
662 void
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)
675 fWeb(web),
676 fFlags(0)
678 CALLED();
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()
690 CALLED();
692 for (int i = fControls->CountItems(); i-- > 0;) {
693 delete static_cast<BParameter*>(fControls->ItemAt(i));
695 delete fControls;
697 for (int i = fGroups->CountItems(); i-- > 0;) {
698 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
700 delete fGroups;
702 free(fName);
706 BParameterWeb*
707 BParameterGroup::Web() const
709 return fWeb;
713 const char*
714 BParameterGroup::Name() const
716 return fName;
720 void
721 BParameterGroup::SetFlags(uint32 flags)
723 fFlags = flags;
727 uint32
728 BParameterGroup::Flags() const
730 return fFlags;
734 BNullParameter*
735 BParameterGroup::MakeNullParameter(int32 id, media_type mediaType,
736 const char* name, const char* kind)
738 CALLED();
740 BNullParameter* parameter = new(std::nothrow) BNullParameter(id, mediaType,
741 fWeb, name, kind);
742 if (parameter == NULL)
743 return NULL;
745 parameter->fGroup = this;
746 fControls->AddItem(parameter);
748 return 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)
757 CALLED();
759 BContinuousParameter* parameter
760 = new(std::nothrow) BContinuousParameter(id, mediaType, fWeb, name,
761 kind, unit, minimum, maximum, stepping);
762 if (parameter == NULL)
763 return NULL;
765 parameter->fGroup = this;
766 fControls->AddItem(parameter);
768 return parameter;
772 BDiscreteParameter*
773 BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType,
774 const char* name, const char* kind)
776 CALLED();
778 BDiscreteParameter* parameter = new(std::nothrow) BDiscreteParameter(id,
779 mediaType, fWeb, name, kind);
780 if (parameter == NULL)
781 return NULL;
783 parameter->fGroup = this;
784 fControls->AddItem(parameter);
786 return parameter;
790 BTextParameter*
791 BParameterGroup::MakeTextParameter(int32 id, media_type mediaType,
792 const char* name, const char* kind, size_t maxBytes)
794 CALLED();
796 BTextParameter* parameter = new(std::nothrow) BTextParameter(id, mediaType,
797 fWeb, name, kind, maxBytes);
798 if (parameter == NULL)
799 return NULL;
801 parameter->fGroup = this;
802 fControls->AddItem(parameter);
804 return parameter;
808 BParameterGroup*
809 BParameterGroup::MakeGroup(const char* name)
811 CALLED();
813 BParameterGroup* group = new(std::nothrow) BParameterGroup(fWeb, name);
814 if (group != NULL)
815 fGroups->AddItem(group);
817 return group;
821 int32
822 BParameterGroup::CountParameters()
824 return fControls->CountItems();
828 BParameter*
829 BParameterGroup::ParameterAt(int32 index)
831 return static_cast<BParameter*>(fControls->ItemAt(index));
835 int32
836 BParameterGroup::CountGroups()
838 return fGroups->CountItems();
842 BParameterGroup*
843 BParameterGroup::GroupAt(int32 index)
845 return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
849 bool
850 BParameterGroup::IsFixedSize() const
852 return false;
856 type_code
857 BParameterGroup::TypeCode() const
859 return B_MEDIA_PARAMETER_GROUP_TYPE;
863 ssize_t
864 BParameterGroup::FlattenedSize() const
866 CALLED();
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
874 Param Count: 4 bytes
875 //for each Param BEGIN
876 Pointer: 4 bytes
877 Parameter Type: 4 bytes
878 Flattened Parameter Size: 4 bytes
879 Flattened Parameter: 'Flattened Parameter Size' bytes
880 //for each Param END
881 Subgroup Count: 4 bytes
882 //for each SubGroup BEGIN
883 Pointer: 4 bytes
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.
892 ssize_t size = 13;
894 if (fFlags != 0)
895 size += sizeof(uint32);
897 if (fName != NULL)
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));
914 if (group != NULL) {
915 // overhead for each group flattened
916 size += sizeof(BParameterGroup*) + sizeof(type_code)
917 + sizeof(ssize_t) + group->FlattenedSize();
921 return size;
925 status_t
926 BParameterGroup::Flatten(void* buffer, ssize_t size) const
928 CALLED();
930 if (buffer == NULL) {
931 ERROR("BParameterGroup::Flatten buffer is NULL\n");
932 return B_NO_INIT;
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");
940 return B_NO_MEMORY;
943 if (fFlags != 0) {
944 write_to_buffer<int32>(&buffer, kBufferGroupMagic);
945 write_to_buffer<uint32>(&buffer, fFlags);
946 } else
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");
958 continue;
961 write_to_buffer<BParameter*>(&buffer, parameter);
962 write_to_buffer<BParameter::media_parameter_type>(&buffer,
963 parameter->Type());
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
972 if (status < B_OK)
973 return status;
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));
984 if (group == NULL) {
985 ERROR("BParameterGroup::Flatten(): NULL group\n");
986 continue;
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
999 if (status < B_OK)
1000 return status;
1002 skip_in_buffer(&buffer, groupSize);
1005 return B_OK;
1009 bool
1010 BParameterGroup::AllowsTypeCode(type_code code) const
1012 return code == TypeCode();
1016 status_t
1017 BParameterGroup::Unflatten(type_code code, const void* buffer, ssize_t size)
1019 CALLED();
1021 if (!AllowsTypeCode(code)) {
1022 ERROR("BParameterGroup::Unflatten() wrong type code\n");
1023 return B_BAD_TYPE;
1026 if (buffer == NULL) {
1027 ERROR("BParameterGroup::Unflatten() buffer is NULL\n");
1028 return B_NO_INIT;
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");
1035 return B_ERROR;
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)) {
1046 isSwapped = true;
1047 magic = B_SWAP_INT32(magic);
1050 if (magic == kBufferGroupMagic)
1051 fFlags = read_from_buffer_swap32<int32>(&buffer, isSwapped);
1052 else if (magic == kBufferGroupMagicNoFlags)
1053 fFlags = 0;
1054 else
1055 return B_BAD_TYPE;
1057 if (read_string_from_buffer(&buffer, &fName,
1058 size - (ssize_t)((uint8*)buffer - (uint8*)bufferStart)) < B_OK)
1059 return B_BAD_VALUE;
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))
1077 return B_BAD_VALUE;
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))) {
1084 return B_BAD_VALUE;
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,
1091 isSwapped);
1093 ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1094 isSwapped);
1095 if (parameterSize > size_left(size, bufferStart, buffer))
1096 return B_BAD_VALUE;
1098 BParameter* parameter = MakeControl(mediaType);
1099 if (parameter == NULL) {
1100 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n");
1101 return B_ERROR;
1104 status_t status = parameter->Unflatten(parameter->TypeCode(), buffer,
1105 parameterSize);
1106 if (status < B_OK) {
1107 ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n");
1108 delete parameter;
1109 return status;
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
1120 if (fWeb != NULL)
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))
1129 return B_BAD_VALUE;
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))) {
1136 return B_BAD_VALUE;
1139 BParameterGroup* oldPointer = read_pointer_from_buffer_swap<
1140 BParameterGroup*>(&buffer, isSwapped);
1141 type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped);
1143 ssize_t groupSize
1144 = read_pointer_from_buffer_swap<ssize_t>(&buffer, isSwapped);
1145 if (groupSize > size_left(size, bufferStart, buffer))
1146 return B_BAD_VALUE;
1148 BParameterGroup* group = new BParameterGroup(fWeb, "sub-unnamed");
1149 if (group == NULL) {
1150 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n");
1151 return B_ERROR;
1154 status_t status = group->Unflatten(type, buffer, groupSize);
1155 if (status != B_OK) {
1156 ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n");
1157 delete group;
1158 return status;
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
1166 if (fWeb != NULL)
1167 fWeb->AddRefFix(oldPointer, group);
1170 return B_OK;
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.
1178 BParameter*
1179 BParameterGroup::MakeControl(int32 type)
1181 CALLED();
1183 switch (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,
1189 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);
1198 default:
1199 ERROR("BParameterGroup::MakeControl unknown type %" B_PRId32 "\n",
1200 type);
1201 return NULL;
1206 // #pragma mark - BParameter
1209 BParameter::media_parameter_type
1210 BParameter::Type() const
1212 return fType;
1216 BParameterWeb*
1217 BParameter::Web() const
1219 return fWeb;
1223 BParameterGroup*
1224 BParameter::Group() const
1226 return fGroup;
1230 const char*
1231 BParameter::Name() const
1233 return fName;
1237 const char*
1238 BParameter::Kind() const
1240 return fKind;
1244 const char*
1245 BParameter::Unit() const
1247 return fUnit;
1251 int32
1252 BParameter::ID() const
1254 return fID;
1258 void
1259 BParameter::SetFlags(uint32 flags)
1261 fFlags = flags;
1265 uint32
1266 BParameter::Flags() const
1268 return fFlags;
1272 status_t
1273 BParameter::GetValue(void* buffer, size_t* _size, bigtime_t* _when)
1275 CALLED();
1277 if (buffer == NULL || _size == NULL)
1278 return B_BAD_VALUE;
1280 size_t size = *_size;
1281 if (size <= 0)
1282 return B_NO_MEMORY;
1284 if (fWeb == NULL) {
1285 ERROR("BParameter::GetValue: no parent BParameterWeb\n");
1286 return B_NO_INIT;
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");
1292 return B_NO_INIT;
1295 controllable_get_parameter_data_request request;
1296 controllable_get_parameter_data_reply reply;
1298 area_id area;
1299 void* data;
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);
1304 if (area < B_OK) {
1305 ERROR("BParameter::GetValue can't create area of %ld bytes\n",
1306 size);
1307 return B_NO_MEMORY;
1309 } else {
1310 area = -1;
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)
1323 size = reply.size;
1325 memcpy(buffer, data, size);
1327 // store reported values
1329 *_size = reply.size;
1330 if (_when != NULL)
1331 *_when = reply.last_change;
1332 } else {
1333 ERROR("BParameter::GetValue parameter '%s' querying node %d, "
1334 "port %d failed: %s\n", fName, (int)node.node, (int)node.port,
1335 strerror(status));
1338 if (area >= B_OK)
1339 delete_area(area);
1341 return status;
1345 status_t
1346 BParameter::SetValue(const void* buffer, size_t size, bigtime_t when)
1348 CALLED();
1350 if (buffer == 0)
1351 return B_BAD_VALUE;
1352 if (size <= 0)
1353 return B_NO_MEMORY;
1355 if (fWeb == 0) {
1356 ERROR("BParameter::SetValue: no parent BParameterWeb\n");
1357 return B_NO_INIT;
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");
1364 return B_NO_INIT;
1367 controllable_set_parameter_data_request request;
1368 controllable_set_parameter_data_reply reply;
1369 area_id area;
1370 void* data;
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);
1376 if (area < B_OK) {
1377 ERROR("BParameter::SetValue can't create area of %ld bytes\n", size);
1378 return B_NO_MEMORY;
1380 } else {
1381 area = -1;
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",
1395 strerror(status));
1398 if (area != -1)
1399 delete_area(area);
1401 return status;
1405 int32
1406 BParameter::CountChannels()
1408 return fChannels;
1412 void
1413 BParameter::SetChannelCount(int32 count)
1415 fChannels = count;
1419 media_type
1420 BParameter::MediaType()
1422 return fMediaType;
1426 void
1427 BParameter::SetMediaType(media_type type)
1429 fMediaType = type;
1433 int32
1434 BParameter::CountInputs()
1436 return fInputs->CountItems();
1440 BParameter*
1441 BParameter::InputAt(int32 index)
1443 return static_cast<BParameter*>(fInputs->ItemAt(index));
1447 void
1448 BParameter::AddInput(BParameter* input)
1450 CALLED();
1452 // BeBook has this method returning a status value,
1453 // but it should be updated
1454 if (input == NULL)
1455 return;
1457 if (fInputs->HasItem(input)) {
1458 // if already in input list, don't duplicate.
1459 return;
1462 fInputs->AddItem(input);
1463 input->AddOutput(this);
1467 int32
1468 BParameter::CountOutputs()
1470 return fOutputs->CountItems();
1474 BParameter*
1475 BParameter::OutputAt(int32 index)
1477 return static_cast<BParameter*>(fOutputs->ItemAt(index));
1481 void
1482 BParameter::AddOutput(BParameter* output)
1484 CALLED();
1486 // BeBook has this method returning a status value,
1487 // but it should be updated
1488 if (output == NULL)
1489 return;
1491 if (fOutputs->HasItem(output)) {
1492 // if already in output list, don't duplicate.
1493 return;
1496 fOutputs->AddItem(output);
1497 output->AddInput(this);
1501 bool
1502 BParameter::IsFixedSize() const
1504 return false;
1508 type_code
1509 BParameter::TypeCode() const
1511 return B_MEDIA_PARAMETER_TYPE;
1515 ssize_t
1516 BParameter::FlattenedSize() const
1518 CALLED();
1520 ?? (0x02040607): 4 bytes
1521 BParameter Struct Size (in bytes): 4 bytes
1522 ID: 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
1533 Media Type: 4 bytes
1534 ChannelCount: 4 bytes
1535 Flags: 4 bytes
1537 //35 bytes are guaranteed, after that, add the variable length parts.
1538 ssize_t size = kAdditionalParameterSize;
1540 if (fName != NULL)
1541 size += strlen(fName);
1542 if (fKind != NULL)
1543 size += strlen(fKind);
1544 if (fUnit != NULL)
1545 size += strlen(fUnit);
1547 size += fInputs->CountItems() * sizeof(BParameter*);
1548 size += fOutputs->CountItems() * sizeof(BParameter*);
1550 return size;
1554 status_t
1555 BParameter::Flatten(void* buffer, ssize_t size) const
1557 CALLED();
1559 if (buffer == NULL) {
1560 ERROR("BParameter::Flatten buffer is NULL\n");
1561 return B_NO_INIT;
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");
1569 return B_NO_MEMORY;
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);
1584 if (count > 0) {
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);
1593 if (count > 0) {
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);
1602 return B_OK;
1606 bool
1607 BParameter::AllowsTypeCode(type_code code) const
1609 return code == TypeCode();
1613 status_t
1614 BParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
1616 CALLED();
1618 if (!AllowsTypeCode(code)) {
1619 ERROR("BParameter::Unflatten(): wrong type code\n");
1620 return B_BAD_TYPE;
1623 if (buffer == NULL) {
1624 ERROR("BParameter::Unflatten(): buffer is NULL\n");
1625 return B_NO_INIT;
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");
1632 return B_BAD_VALUE;
1635 const void* bufferStart = buffer;
1637 // check magic
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;
1644 else {
1645 ERROR("BParameter::Unflatten(): bad magic\n");
1646 return B_BAD_TYPE;
1649 ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1650 fSwapDetected);
1651 if (parameterSize > size) {
1652 ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n",
1653 parameterSize, size);
1654 return B_BAD_VALUE;
1657 // if the struct doesn't meet the minimum size for
1658 // a flattened BParameter, then return an error.
1659 // MinFlattenedParamSize =
1660 // ID (4 bytes)
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)
1668 // Flags (4 bytes)
1669 // TOTAL: 27 bytes
1670 const ssize_t kMinFlattenedParamSize = 15 + 3 * sizeof(ssize_t);
1671 if (parameterSize < kMinFlattenedParamSize) {
1672 ERROR("BParameter::Unflatten out of memory (2)\n");
1673 return B_ERROR;
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)
1684 return B_NO_MEMORY;
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,
1692 fSwapDetected);
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);
1714 return B_OK;
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)
1722 fID(id),
1723 fType(type),
1724 fWeb(web),
1725 fGroup(NULL),
1726 fSwapDetected(true),
1727 fMediaType(mediaType),
1728 fChannels(1),
1729 fFlags(0)
1731 CALLED();
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()
1745 CALLED();
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
1751 free(fName);
1752 free(fKind);
1753 free(fUnit);
1755 delete fInputs;
1756 delete fOutputs;
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
1762 and output lists.
1763 This is called by BParameterWeb::Unflatten().
1765 void
1766 BParameter::FixRefs(BList& old, BList& updated)
1768 CALLED();
1770 // update inputs
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]);
1777 if (index >= 0)
1778 items[i] = updated.ItemAt(index);
1779 else {
1780 ERROR("BParameter::FixRefs(): No mapping found for input");
1781 items[i] = NULL;
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);
1792 // update outputs
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]);
1799 if (index >= 0)
1800 items[i] = updated.ItemAt(index);
1801 else {
1802 ERROR("BParameter::FixRefs(): No mapping found for output");
1803 items[i] = NULL;
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
1819 type_code
1820 BContinuousParameter::ValueType()
1822 return B_FLOAT_TYPE;
1826 float
1827 BContinuousParameter::MinValue()
1829 return fMinimum;
1833 float
1834 BContinuousParameter::MaxValue()
1836 return fMaximum;
1840 float
1841 BContinuousParameter::ValueStep()
1843 return fStepping;
1847 void
1848 BContinuousParameter::SetResponse(int resp, float factor, float offset)
1850 fResponse = static_cast<response>(resp);
1851 fFactor = factor;
1852 fOffset = offset;
1856 void
1857 BContinuousParameter::GetResponse(int* _resp, float* _factor, float* _offset)
1859 if (_resp != NULL)
1860 *_resp = fResponse;
1861 if (_factor != NULL)
1862 *_factor = fFactor;
1863 if (_offset != NULL)
1864 *_offset = fOffset;
1868 ssize_t
1869 BContinuousParameter::FlattenedSize() const
1871 CALLED();
1873 // only adds a fixed amount of bytes
1874 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize;
1878 status_t
1879 BContinuousParameter::Flatten(void* buffer, ssize_t size) const
1881 CALLED();
1883 if (buffer == NULL) {
1884 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n");
1885 return B_NO_INIT;
1888 ssize_t parameterSize = BParameter::FlattenedSize();
1889 if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
1890 ERROR("BContinuousParameter::Flatten(): size to small\n");
1891 return B_NO_MEMORY;
1894 status_t status = BParameter::Flatten(buffer, size);
1895 if (status != B_OK) {
1896 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n");
1897 return status;
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);
1911 return B_OK;
1915 status_t
1916 BContinuousParameter::Unflatten(type_code code, const void* buffer,
1917 ssize_t size)
1919 CALLED();
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");
1926 return B_BAD_TYPE;
1929 if (buffer == NULL) {
1930 ERROR("BContinuousParameter::Unflatten buffer is NULL\n");
1931 return B_NO_INIT;
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");
1938 return B_ERROR;
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));
1945 return 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");
1953 return B_BAD_VALUE;
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());
1963 return B_OK;
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),
1971 fMinimum(minimum),
1972 fMaximum(maximum),
1973 fStepping(stepping),
1974 fResponse(B_LINEAR),
1975 fFactor(1.0),
1976 fOffset(0.0)
1978 CALLED();
1982 BContinuousParameter::~BContinuousParameter()
1984 CALLED();
1988 // #pragma mark - public BDiscreteParameter
1991 type_code
1992 BDiscreteParameter::ValueType()
1994 return B_INT32_TYPE;
1998 int32
1999 BDiscreteParameter::CountItems()
2001 return fValues->CountItems();
2005 const char*
2006 BDiscreteParameter::ItemNameAt(int32 index)
2008 return reinterpret_cast<const char*>(fSelections->ItemAt(index));
2012 int32
2013 BDiscreteParameter::ItemValueAt(int32 index)
2015 int32* item = static_cast<int32*>(fValues->ItemAt(index));
2016 if (item == NULL)
2017 return 0;
2019 return *item;
2023 status_t
2024 BDiscreteParameter::AddItem(int32 value, const char* name)
2026 CALLED();
2028 int32* valueCopy = new(std::nothrow) int32(value);
2029 if (valueCopy == NULL)
2030 return B_NO_MEMORY;
2031 char* nameCopy = strndup(name, 255);
2032 if (name != NULL && nameCopy == NULL) {
2033 delete valueCopy;
2034 return B_NO_MEMORY;
2037 if (!fValues->AddItem(valueCopy))
2038 goto err;
2039 if (!fSelections->AddItem(nameCopy)) {
2040 fValues->RemoveItem(valueCopy);
2041 goto err;
2043 return B_OK;
2045 err:
2046 free(nameCopy);
2047 delete valueCopy;
2048 return B_NO_MEMORY;
2052 status_t
2053 BDiscreteParameter::MakeItemsFromInputs()
2055 CALLED();
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());
2063 return B_OK;
2067 status_t
2068 BDiscreteParameter::MakeItemsFromOutputs()
2070 CALLED();
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());
2078 return B_OK;
2082 void
2083 BDiscreteParameter::MakeEmpty()
2085 CALLED();
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();
2099 ssize_t
2100 BDiscreteParameter::FlattenedSize() const
2102 CALLED();
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);
2114 size += 5;
2115 // string length + value
2118 return size;
2122 status_t
2123 BDiscreteParameter::Flatten(void* buffer, ssize_t size) const
2125 CALLED();
2127 if (buffer == NULL) {
2128 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n");
2129 return B_NO_INIT;
2132 ssize_t parameterSize = BParameter::FlattenedSize();
2134 if (size < FlattenedSize()) {
2135 ERROR("BDiscreteParameter::Flatten(): size too small\n");
2136 return B_NO_MEMORY;
2139 status_t status = BParameter::Flatten(buffer, size);
2140 if (status != B_OK) {
2141 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n");
2142 return status;
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);
2159 return B_OK;
2163 status_t
2164 BDiscreteParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2166 CALLED();
2168 if (!AllowsTypeCode(code)) {
2169 ERROR("BDiscreteParameter::Unflatten(): bad type code\n");
2170 return B_BAD_TYPE;
2173 if (buffer == NULL) {
2174 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n");
2175 return B_NO_INIT;
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");
2182 return B_ERROR;
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");
2190 return status;
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");
2198 return B_BAD_VALUE;
2201 int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten());
2203 // clear any existing name/value pairs
2204 MakeEmpty();
2206 for (int32 i = 0; i < count; i++) {
2207 char* name;
2208 if (read_string_from_buffer(&buffer, &name, size_left(size, bufferStart,
2209 buffer)) < B_OK)
2210 return B_BAD_DATA;
2212 if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) {
2213 free(name);
2214 return B_BAD_DATA;
2217 int32 value = read_from_buffer_swap32<int32>(&buffer,
2218 SwapOnUnflatten());
2220 AddItem(value, name);
2221 free(name);
2224 return B_OK;
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)
2232 CALLED();
2234 fSelections = new BList();
2235 fValues = new BList();
2239 BDiscreteParameter::~BDiscreteParameter()
2241 CALLED();
2243 MakeEmpty();
2245 delete fSelections;
2246 delete fValues;
2250 // #pragma mark - public BTextParameter
2253 size_t
2254 BTextParameter::MaxBytes() const
2256 return fMaxBytes;
2260 type_code
2261 BTextParameter::ValueType()
2263 return B_FLOAT_TYPE;
2267 ssize_t
2268 BTextParameter::FlattenedSize() const
2270 return BParameter::FlattenedSize() + sizeof(fMaxBytes);
2274 status_t
2275 BTextParameter::Flatten(void* buffer, ssize_t size) const
2277 if (buffer == NULL) {
2278 ERROR("BTextParameter::Flatten(): buffer is NULL\n");
2279 return B_NO_INIT;
2282 ssize_t parameterSize = BParameter::FlattenedSize();
2283 if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
2284 ERROR("BContinuousParameter::Flatten(): size to small\n");
2285 return B_NO_MEMORY;
2288 status_t status = BParameter::Flatten(buffer, size);
2289 if (status != B_OK) {
2290 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n");
2291 return status;
2294 // add our data to the general flattened BParameter
2296 skip_in_buffer(&buffer, parameterSize);
2298 write_to_buffer<uint32>(&buffer, fMaxBytes);
2300 return B_OK;
2304 status_t
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");
2312 return B_BAD_TYPE;
2315 if (buffer == NULL) {
2316 ERROR("BTextParameter::Unflatten buffer is NULL\n");
2317 return B_NO_INIT;
2320 if (size < static_cast<ssize_t>(sizeof(fMaxBytes))) {
2321 ERROR("BTextParameter::Unflatten size too small\n");
2322 return B_ERROR;
2325 status_t status = BParameter::Unflatten(code, buffer, size);
2326 if (status != B_OK) {
2327 ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n");
2328 return status;
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");
2336 return B_BAD_VALUE;
2339 fMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten());
2341 return B_OK;
2345 BTextParameter::BTextParameter(int32 id, media_type mediaType,
2346 BParameterWeb* web, const char* name, const char* kind,
2347 size_t maxBytes)
2348 : BParameter(id, mediaType, B_TEXT_PARAMETER, web, name, kind, NULL)
2350 fMaxBytes = maxBytes;
2354 BTextParameter::~BTextParameter()
2359 // #pragma mark - public BNullParameter
2362 type_code
2363 BNullParameter::ValueType()
2365 // NULL parameters have no value type
2366 return 0;
2370 ssize_t
2371 BNullParameter::FlattenedSize() const
2373 return BParameter::FlattenedSize();
2377 status_t
2378 BNullParameter::Flatten(void* buffer, ssize_t size) const
2380 return BParameter::Flatten(buffer, size);
2384 status_t
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; }