headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / media / ParameterWeb.cpp
blobc7fb13c519a02ea178b848af13131f65bd6c7fb4
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 free(*_string);
204 *_buffer = static_cast<const void *>(buffer + length);
205 *_string = string;
206 return B_OK;
210 // currently unused
211 #if 0
212 template<class Type> Type *
213 reserve_in_buffer(void **_buffer)
215 Type *typedBuffer = static_cast<Type *>(*_buffer);
217 *typedBuffer = 0;
218 typedBuffer++;
220 *_buffer = static_cast<void *>(typedBuffer);
222 #endif
224 template<class Type> void
225 write_to_buffer(void **_buffer, Type value)
227 Type *typedBuffer = static_cast<Type *>(*_buffer);
229 *typedBuffer = value;
230 typedBuffer++;
232 *_buffer = static_cast<void *>(typedBuffer);
236 void
237 write_string_to_buffer(void **_buffer, const char *string)
239 uint8 *buffer = static_cast<uint8 *>(*_buffer);
240 uint32 length = string ? strlen(string) : 0;
241 if (length > 255)
242 length = 255;
244 *buffer++ = static_cast<uint8>(length);
245 if (length) {
246 memcpy(buffer, string, length);
247 buffer += length;
250 *_buffer = static_cast<void *>(buffer);
254 static void
255 skip_in_buffer(const void **_buffer, uint32 bytes)
257 const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
259 buffer += bytes;
261 *_buffer = static_cast<const void *>(buffer);
265 static void inline
266 skip_in_buffer(void **_buffer, uint32 bytes)
268 // This actually shouldn't be necessary, but I believe it's a
269 // bug in Be's gcc - it complains about "adds cv-quals without intervening `const'"
270 // when passing a "const void **" pointer as the first argument.
271 // Maybe I am just stupid, though -- axeld.
273 skip_in_buffer((const void **)_buffer, bytes);
277 template<class Type> Type
278 swap32(Type value, bool doSwap)
280 STATIC_ASSERT(sizeof(Type) == 4);
282 if (doSwap)
283 return (Type)B_SWAP_INT32((int32)value);
285 return value;
289 template<class Type> Type
290 swap64(Type value, bool doSwap)
292 STATIC_ASSERT(sizeof(Type) == 8);
294 if (doSwap)
295 return (Type)B_SWAP_INT64((int64)value);
297 return value;
301 template<class Type> Type
302 read_from_buffer_swap32(const void **_buffer, bool doSwap)
304 return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
308 template<class Type> Type
309 read_pointer_from_buffer_swap(const void **_buffer, bool doSwap)
311 #if B_HAIKU_32_BIT
312 return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
313 #elif B_HAIKU_64_BIT
314 return swap64<Type>(read_from_buffer<Type>(_buffer), doSwap);
315 #else
316 # error Interesting
317 #endif
321 static inline ssize_t
322 size_left(ssize_t size, const void *bufferStart, const void *buffer)
324 return size - static_cast<ssize_t>((const uint8 *)buffer - (const uint8 *)bufferStart);
328 // #pragma mark - BParameterWeb
331 BParameterWeb::BParameterWeb()
333 fNode(media_node::null)
334 // fNode is set in BControllable::SetParameterWeb()
336 CALLED();
338 fGroups = new BList();
339 fOldRefs = new BList();
340 fNewRefs = new BList();
344 BParameterWeb::~BParameterWeb()
346 CALLED();
348 for (int32 i = fGroups->CountItems(); i-- > 0;) {
349 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
352 delete fGroups;
353 delete fOldRefs;
354 delete fNewRefs;
358 media_node
359 BParameterWeb::Node()
361 return fNode;
365 BParameterGroup*
366 BParameterWeb::MakeGroup(const char* name)
368 CALLED();
370 BParameterGroup* group = new(std::nothrow) BParameterGroup(this, name);
371 if (group == NULL)
372 return NULL;
374 if (!fGroups->AddItem(group)) {
375 delete group;
376 return NULL;
379 return group;
383 int32
384 BParameterWeb::CountGroups()
386 return fGroups->CountItems();
390 BParameterGroup*
391 BParameterWeb::GroupAt(int32 index)
393 return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
397 int32
398 BParameterWeb::CountParameters()
400 CALLED();
402 // Counts over all groups (and sub-groups) in the web.
403 // The "groups" list is used as count stack
405 BList groups(*fGroups);
406 int32 count = 0;
408 for (int32 i = 0; i < groups.CountItems(); i++) {
409 BParameterGroup* group
410 = static_cast<BParameterGroup*>(groups.ItemAt(i));
412 count += group->CountParameters();
414 if (group->fGroups != NULL)
415 groups.AddList(group->fGroups);
418 return count;
422 BParameter*
423 BParameterWeb::ParameterAt(int32 index)
425 CALLED();
427 // Iterates over all groups (and sub-groups) in the web.
428 // The "groups" list is used as iteration stack (breadth search style)
429 // Maintains the same order as the Be implementation
431 BList groups(*fGroups);
433 for (int32 i = 0; i < groups.CountItems(); i++) {
434 BParameterGroup* group
435 = static_cast<BParameterGroup*>(groups.ItemAt(i));
436 int32 count = group->CountParameters();
437 if (index < count)
438 return group->ParameterAt(index);
440 index -= count;
441 // the index is always relative to the start of the current group
443 if (group->fGroups != NULL)
444 groups.AddList(group->fGroups);
447 TRACE("*** could not find parameter at %"
448 B_PRId32 " (count = %" B_PRId32 ")\n", index, CountParameters());
450 return NULL;
454 bool
455 BParameterWeb::IsFixedSize() const
457 return false;
461 type_code
462 BParameterWeb::TypeCode() const
464 return B_MEDIA_PARAMETER_WEB_TYPE;
468 ssize_t
469 BParameterWeb::FlattenedSize() const
471 CALLED();
474 //--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
475 ?? 0x01030506: 4 bytes
476 ??: 4 bytes (is always 1)
477 Group Count: 4 bytes
478 Node (as media_node): 0x18 bytes (decimal 24 bytes)
479 //for each Group BEGIN
480 Flattened Group Size: 4 bytes
481 Flattened Group: 'Flattened Group Size' bytes
482 //for each Group END
483 //for each Group BEGIN
484 ??: 4 bytes (never get written to (holds uninitialized value))
485 //for each Group END
486 //---------END-CORE-BPARAMETERWEB-STRUCT--------------
488 //36 guaranteed bytes, variable after that.
489 ssize_t size = sizeof(int32) + 2 * sizeof(int32) + sizeof(media_node);
491 for (int32 i = fGroups->CountItems(); i-- > 0;) {
492 BParameterGroup* group
493 = static_cast<BParameterGroup*>(fGroups->ItemAt(i));
494 if (group != NULL) {
495 size += sizeof(ssize_t) + group->FlattenedSize();
499 return size;
503 status_t
504 BParameterWeb::Flatten(void* buffer, ssize_t size) const
506 CALLED();
508 if (buffer == NULL)
509 return B_NO_INIT;
511 ssize_t actualSize = BParameterWeb::FlattenedSize();
512 if (size < actualSize)
513 return B_NO_MEMORY;
515 void* bufferStart = buffer;
517 write_to_buffer<int32>(&buffer, kParameterWebMagic);
518 write_to_buffer<int32>(&buffer, kCurrentParameterWebVersion);
520 // flatten all groups into this buffer
522 int32 count = fGroups->CountItems();
523 write_to_buffer<int32>(&buffer, count);
525 write_to_buffer<media_node>(&buffer, fNode);
527 for (int32 i = 0; i < count; i++) {
528 BParameterGroup* group
529 = static_cast<BParameterGroup*>(fGroups->ItemAt(i));
530 if (group == NULL) {
531 ERROR("BParameterWeb::Flatten(): group is NULL\n");
532 continue;
535 ssize_t groupSize = group->FlattenedSize();
536 if (groupSize > size_left(size, bufferStart, buffer)) {
537 ERROR("BParameterWeb::Flatten(): buffer too small\n");
538 return B_BAD_VALUE;
541 write_to_buffer<ssize_t>(&buffer, groupSize);
543 // write the flattened sub group
544 status_t status = group->Flatten(buffer, groupSize);
545 if (status < B_OK)
546 return status;
548 skip_in_buffer(&buffer, groupSize);
551 return B_OK;
555 bool
556 BParameterWeb::AllowsTypeCode(type_code code) const
558 return code == TypeCode();
562 status_t
563 BParameterWeb::Unflatten(type_code code, const void* buffer, ssize_t size)
565 CALLED();
567 if (!AllowsTypeCode(code)) {
568 ERROR("BParameterWeb::Unflatten(): wrong type code\n");
569 return B_BAD_TYPE;
572 if (buffer == NULL) {
573 ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n");
574 return B_NO_INIT;
577 // if the buffer is smaller than the size needed to read the
578 // signature field, the mystery field, the group count, and the Node, then there is a problem
579 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(int32)
580 + sizeof(ssize_t) + sizeof(media_node))) {
581 ERROR("BParameterWeb::Unflatten(): size to small\n");
582 return B_ERROR;
585 const void* bufferStart = buffer;
587 uint32 magic = read_from_buffer<uint32>(&buffer);
588 bool isSwapped = false;
590 if (magic == B_SWAP_INT32(kParameterWebMagic)) {
591 isSwapped = true;
592 magic = B_SWAP_INT32(magic);
594 if (magic != kParameterWebMagic)
595 return B_BAD_DATA;
597 // Note, it's not completely sure that this field is the version
598 // information - but it doesn't seem to have another purpose
599 int32 version = read_from_buffer_swap32<int32>(&buffer, isSwapped);
600 if (version != kCurrentParameterWebVersion) {
601 ERROR("BParameterWeb::Unflatten(): wrong version %" B_PRId32 " (%"
602 B_PRIx32 ")?!\n", version, version);
603 return B_ERROR;
606 for (int32 i = 0; i < fGroups->CountItems(); i++) {
607 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
609 fGroups->MakeEmpty();
611 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
613 fNode = read_from_buffer<media_node>(&buffer);
614 if (isSwapped)
615 swap_data(B_INT32_TYPE, &fNode, sizeof(media_node), B_SWAP_ALWAYS);
617 for (int32 i = 0; i < count; i++) {
618 ssize_t groupSize
619 = read_pointer_from_buffer_swap<ssize_t>(&buffer, isSwapped);
620 if (groupSize > size_left(size, bufferStart, buffer)) {
621 ERROR("BParameterWeb::Unflatten(): buffer too small\n");
622 return B_BAD_DATA;
625 BParameterGroup* group = new BParameterGroup(this, "unnamed");
626 status_t status = group->Unflatten(group->TypeCode(), buffer,
627 groupSize);
628 if (status < B_OK) {
629 ERROR("BParameterWeb::Unflatten(): unflatten group failed\n");
630 delete group;
631 return status;
634 skip_in_buffer(&buffer, groupSize);
636 fGroups->AddItem(group);
639 // fix all references (ParameterAt() style)
641 BList groups(*fGroups);
643 for (int32 i = 0; i < groups.CountItems(); i++) {
644 BParameterGroup* group
645 = static_cast<BParameterGroup*>(groups.ItemAt(i));
647 for (int32 index = group->CountParameters(); index-- > 0;) {
648 BParameter* parameter
649 = static_cast<BParameter*>(group->ParameterAt(index));
651 parameter->FixRefs(*fOldRefs, *fNewRefs);
654 if (group->fGroups != NULL)
655 groups.AddList(group->fGroups);
658 fOldRefs->MakeEmpty();
659 fNewRefs->MakeEmpty();
661 return B_OK;
665 void
666 BParameterWeb::AddRefFix(void* oldItem, void* newItem)
668 fOldRefs->AddItem(oldItem);
669 fNewRefs->AddItem(newItem);
673 // #pragma mark - BParameterGroup
676 BParameterGroup::BParameterGroup(BParameterWeb* web, const char* name)
678 fWeb(web),
679 fFlags(0)
681 CALLED();
682 TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web, name);
684 fName = strndup(name, 255);
686 fControls = new BList();
687 fGroups = new BList();
691 BParameterGroup::~BParameterGroup()
693 CALLED();
695 for (int i = fControls->CountItems(); i-- > 0;) {
696 delete static_cast<BParameter*>(fControls->ItemAt(i));
698 delete fControls;
700 for (int i = fGroups->CountItems(); i-- > 0;) {
701 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
703 delete fGroups;
705 free(fName);
709 BParameterWeb*
710 BParameterGroup::Web() const
712 return fWeb;
716 const char*
717 BParameterGroup::Name() const
719 return fName;
723 void
724 BParameterGroup::SetFlags(uint32 flags)
726 fFlags = flags;
730 uint32
731 BParameterGroup::Flags() const
733 return fFlags;
737 BNullParameter*
738 BParameterGroup::MakeNullParameter(int32 id, media_type mediaType,
739 const char* name, const char* kind)
741 CALLED();
743 BNullParameter* parameter = new(std::nothrow) BNullParameter(id, mediaType,
744 fWeb, name, kind);
745 if (parameter == NULL)
746 return NULL;
748 parameter->fGroup = this;
749 fControls->AddItem(parameter);
751 return parameter;
755 BContinuousParameter*
756 BParameterGroup::MakeContinuousParameter(int32 id, media_type mediaType,
757 const char* name, const char* kind, const char* unit,
758 float minimum, float maximum, float stepping)
760 CALLED();
762 BContinuousParameter* parameter
763 = new(std::nothrow) BContinuousParameter(id, mediaType, fWeb, name,
764 kind, unit, minimum, maximum, stepping);
765 if (parameter == NULL)
766 return NULL;
768 parameter->fGroup = this;
769 fControls->AddItem(parameter);
771 return parameter;
775 BDiscreteParameter*
776 BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType,
777 const char* name, const char* kind)
779 CALLED();
781 BDiscreteParameter* parameter = new(std::nothrow) BDiscreteParameter(id,
782 mediaType, fWeb, name, kind);
783 if (parameter == NULL)
784 return NULL;
786 parameter->fGroup = this;
787 fControls->AddItem(parameter);
789 return parameter;
793 BTextParameter*
794 BParameterGroup::MakeTextParameter(int32 id, media_type mediaType,
795 const char* name, const char* kind, size_t maxBytes)
797 CALLED();
799 BTextParameter* parameter = new(std::nothrow) BTextParameter(id, mediaType,
800 fWeb, name, kind, maxBytes);
801 if (parameter == NULL)
802 return NULL;
804 parameter->fGroup = this;
805 fControls->AddItem(parameter);
807 return parameter;
811 BParameterGroup*
812 BParameterGroup::MakeGroup(const char* name)
814 CALLED();
816 BParameterGroup* group = new(std::nothrow) BParameterGroup(fWeb, name);
817 if (group != NULL)
818 fGroups->AddItem(group);
820 return group;
824 int32
825 BParameterGroup::CountParameters()
827 return fControls->CountItems();
831 BParameter*
832 BParameterGroup::ParameterAt(int32 index)
834 return static_cast<BParameter*>(fControls->ItemAt(index));
838 int32
839 BParameterGroup::CountGroups()
841 return fGroups->CountItems();
845 BParameterGroup*
846 BParameterGroup::GroupAt(int32 index)
848 return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
852 bool
853 BParameterGroup::IsFixedSize() const
855 return false;
859 type_code
860 BParameterGroup::TypeCode() const
862 return B_MEDIA_PARAMETER_GROUP_TYPE;
866 ssize_t
867 BParameterGroup::FlattenedSize() const
869 CALLED();
872 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
873 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
874 (possible) Flags: 4 bytes
875 Name String Length: 1 byte (??)
876 Name String: 'Name String Length' bytes
877 Param Count: 4 bytes
878 //for each Param BEGIN
879 Pointer: 4 bytes
880 Parameter Type: 4 bytes
881 Flattened Parameter Size: 4 bytes
882 Flattened Parameter: 'Flattened Parameter Size' bytes
883 //for each Param END
884 Subgroup Count: 4 bytes
885 //for each SubGroup BEGIN
886 Pointer: 4 bytes
887 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
888 Flattened Group Size: 4 bytes
889 Flattened Group: 'Flattened Group Size' bytes
890 //for each SubGroup END
892 //---------END-CORE-BPARAMETERGROUP-STRUCT--------------
894 //13 guaranteed bytes, variable after that.
895 ssize_t size = 13;
897 if (fFlags != 0)
898 size += sizeof(uint32);
900 if (fName != NULL)
901 size += min_c(strlen(fName), 255);
903 int limit = fControls->CountItems();
904 for (int i = 0; i < limit; i++) {
905 BParameter* parameter = static_cast<BParameter*>(fControls->ItemAt(i));
906 if (parameter != NULL) {
907 // overhead for each parameter flattened
908 size += sizeof(BParameter*) + sizeof(BParameter::media_parameter_type)
909 + sizeof(ssize_t) + parameter->FlattenedSize();
913 limit = fGroups->CountItems();
914 for (int i = 0; i < limit; i++) {
915 BParameterGroup* group
916 = static_cast<BParameterGroup*>(fGroups->ItemAt(i));
917 if (group != NULL) {
918 // overhead for each group flattened
919 size += sizeof(BParameterGroup*) + sizeof(type_code)
920 + sizeof(ssize_t) + group->FlattenedSize();
924 return size;
928 status_t
929 BParameterGroup::Flatten(void* buffer, ssize_t size) const
931 CALLED();
933 if (buffer == NULL) {
934 ERROR("BParameterGroup::Flatten buffer is NULL\n");
935 return B_NO_INIT;
938 // NOTICE: It is important that this value is the size returned by
939 // BParameterGroup::FlattenedSize, not by a descendent's override of this method.
940 ssize_t actualSize = BParameterGroup::FlattenedSize();
941 if (size < actualSize) {
942 ERROR("BParameterGroup::Flatten size to small\n");
943 return B_NO_MEMORY;
946 if (fFlags != 0) {
947 write_to_buffer<int32>(&buffer, kBufferGroupMagic);
948 write_to_buffer<uint32>(&buffer, fFlags);
949 } else
950 write_to_buffer<int32>(&buffer, kBufferGroupMagicNoFlags);
952 write_string_to_buffer(&buffer, fName);
954 int32 count = fControls->CountItems();
955 write_to_buffer<int32>(&buffer, count);
957 for (int32 i = 0; i < count; i++) {
958 BParameter* parameter = static_cast<BParameter*>(fControls->ItemAt(i));
959 if (parameter == NULL) {
960 ERROR("BParameterGroup::Flatten(): NULL parameter\n");
961 continue;
964 write_to_buffer<BParameter*>(&buffer, parameter);
965 write_to_buffer<BParameter::media_parameter_type>(&buffer,
966 parameter->Type());
968 // flatten parameter into this buffer
970 ssize_t parameterSize = parameter->FlattenedSize();
971 write_to_buffer<ssize_t>(&buffer, parameterSize);
973 status_t status = parameter->Flatten(buffer, parameterSize);
974 // we have only that much bytes left to write in this buffer
975 if (status < B_OK)
976 return status;
978 skip_in_buffer(&buffer, parameterSize);
981 count = fGroups->CountItems();
982 write_to_buffer<int32>(&buffer, count);
984 for (int32 i = 0; i < count; i++) {
985 BParameterGroup* group
986 = static_cast<BParameterGroup*>(fGroups->ItemAt(i));
987 if (group == NULL) {
988 ERROR("BParameterGroup::Flatten(): NULL group\n");
989 continue;
992 write_to_buffer<BParameterGroup*>(&buffer, group);
993 write_to_buffer<type_code>(&buffer, group->TypeCode());
995 // flatten sub group into this buffer
997 ssize_t groupSize = group->FlattenedSize();
998 write_to_buffer<ssize_t>(&buffer, groupSize);
1000 status_t status = group->Flatten(buffer, groupSize);
1001 // we have only that much bytes left to write in this buffer
1002 if (status < B_OK)
1003 return status;
1005 skip_in_buffer(&buffer, groupSize);
1008 return B_OK;
1012 bool
1013 BParameterGroup::AllowsTypeCode(type_code code) const
1015 return code == TypeCode();
1019 status_t
1020 BParameterGroup::Unflatten(type_code code, const void* buffer, ssize_t size)
1022 CALLED();
1024 if (!AllowsTypeCode(code)) {
1025 ERROR("BParameterGroup::Unflatten() wrong type code\n");
1026 return B_BAD_TYPE;
1029 if (buffer == NULL) {
1030 ERROR("BParameterGroup::Unflatten() buffer is NULL\n");
1031 return B_NO_INIT;
1034 // if the buffer is smaller than the size needed to read the
1035 // signature field, then there is a problem
1036 if (size < static_cast<ssize_t>(sizeof(int32))) {
1037 ERROR("BParameterGroup::Unflatten() size to small\n");
1038 return B_ERROR;
1041 const void* bufferStart = buffer;
1042 // used to compute the rest length of the buffer when needed
1044 uint32 magic = read_from_buffer<uint32>(&buffer);
1045 bool isSwapped = false;
1047 if (magic == B_SWAP_INT32(kBufferGroupMagic)
1048 || magic == B_SWAP_INT32(kBufferGroupMagicNoFlags)) {
1049 isSwapped = true;
1050 magic = B_SWAP_INT32(magic);
1053 if (magic == kBufferGroupMagic)
1054 fFlags = read_from_buffer_swap32<int32>(&buffer, isSwapped);
1055 else if (magic == kBufferGroupMagicNoFlags)
1056 fFlags = 0;
1057 else
1058 return B_BAD_TYPE;
1060 if (read_string_from_buffer(&buffer, &fName,
1061 size - (ssize_t)((uint8*)buffer - (uint8*)bufferStart)) < B_OK)
1062 return B_BAD_VALUE;
1064 // Clear all existing parameters/subgroups
1065 for (int32 i = 0; i < fControls->CountItems(); i++) {
1066 delete static_cast<BParameter*>(fControls->ItemAt(i));
1068 fControls->MakeEmpty();
1070 for (int32 i = 0; i < fGroups->CountItems(); i++) {
1071 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
1073 fGroups->MakeEmpty();
1075 // unflatten parameter list
1077 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
1078 if (count < 0 || count * kAdditionalParameterSize
1079 > size_left(size, bufferStart, buffer))
1080 return B_BAD_VALUE;
1082 for (int32 i = 0; i < count; i++) {
1083 // make sure we can read as many bytes
1084 if (size_left(size, bufferStart, buffer) < (ssize_t)(
1085 sizeof(BParameter*) + sizeof(BParameter::media_parameter_type)
1086 + sizeof(ssize_t))) {
1087 return B_BAD_VALUE;
1090 BParameter* oldPointer = read_pointer_from_buffer_swap<BParameter*>(
1091 &buffer, isSwapped);
1092 BParameter::media_parameter_type mediaType
1093 = read_from_buffer_swap32<BParameter::media_parameter_type>(&buffer,
1094 isSwapped);
1096 ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1097 isSwapped);
1098 if (parameterSize > size_left(size, bufferStart, buffer))
1099 return B_BAD_VALUE;
1101 BParameter* parameter = MakeControl(mediaType);
1102 if (parameter == NULL) {
1103 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n");
1104 return B_ERROR;
1107 status_t status = parameter->Unflatten(parameter->TypeCode(), buffer,
1108 parameterSize);
1109 if (status < B_OK) {
1110 ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n");
1111 delete parameter;
1112 return status;
1115 skip_in_buffer(&buffer, parameterSize);
1117 // add the item to the list
1118 parameter->fGroup = this;
1119 parameter->fWeb = fWeb;
1120 fControls->AddItem(parameter);
1122 // add it's old pointer value to the RefFix list kept by the owner web
1123 if (fWeb != NULL)
1124 fWeb->AddRefFix(oldPointer, parameter);
1127 // unflatten sub groups
1129 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
1130 if (count < 0 || count * kAdditionalParameterGroupSize
1131 > size_left(size, bufferStart, buffer))
1132 return B_BAD_VALUE;
1134 for (int32 i = 0; i < count; i++) {
1135 // make sure we can read as many bytes
1136 if (size_left(size, bufferStart, buffer) < (ssize_t)(
1137 sizeof(BParameterGroup*) + sizeof(type_code)
1138 + sizeof(ssize_t))) {
1139 return B_BAD_VALUE;
1142 BParameterGroup* oldPointer = read_pointer_from_buffer_swap<
1143 BParameterGroup*>(&buffer, isSwapped);
1144 type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped);
1146 ssize_t groupSize
1147 = read_pointer_from_buffer_swap<ssize_t>(&buffer, isSwapped);
1148 if (groupSize > size_left(size, bufferStart, buffer))
1149 return B_BAD_VALUE;
1151 BParameterGroup* group = new BParameterGroup(fWeb, "sub-unnamed");
1152 if (group == NULL) {
1153 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n");
1154 return B_ERROR;
1157 status_t status = group->Unflatten(type, buffer, groupSize);
1158 if (status != B_OK) {
1159 ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n");
1160 delete group;
1161 return status;
1164 skip_in_buffer(&buffer, groupSize);
1166 fGroups->AddItem(group);
1168 // add it's old pointer value to the RefFix list kept by the owner web
1169 if (fWeb != NULL)
1170 fWeb->AddRefFix(oldPointer, group);
1173 return B_OK;
1177 /*! Creates an uninitialized parameter of the specified type.
1178 Unlike the BParameterGroup::MakeXXXParameter() type of methods, this
1179 method does not add the parameter to this group automatically.
1181 BParameter*
1182 BParameterGroup::MakeControl(int32 type)
1184 CALLED();
1186 switch (type) {
1187 case BParameter::B_NULL_PARAMETER:
1188 return new BNullParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL);
1190 case BParameter::B_DISCRETE_PARAMETER:
1191 return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
1192 NULL);
1194 case BParameter::B_CONTINUOUS_PARAMETER:
1195 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
1196 NULL, NULL, 0, 0, 0);
1198 case BParameter::B_TEXT_PARAMETER:
1199 return new BTextParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, 0);
1201 default:
1202 ERROR("BParameterGroup::MakeControl unknown type %" B_PRId32 "\n",
1203 type);
1204 return NULL;
1209 // #pragma mark - BParameter
1212 BParameter::media_parameter_type
1213 BParameter::Type() const
1215 return fType;
1219 BParameterWeb*
1220 BParameter::Web() const
1222 return fWeb;
1226 BParameterGroup*
1227 BParameter::Group() const
1229 return fGroup;
1233 const char*
1234 BParameter::Name() const
1236 return fName;
1240 const char*
1241 BParameter::Kind() const
1243 return fKind;
1247 const char*
1248 BParameter::Unit() const
1250 return fUnit;
1254 int32
1255 BParameter::ID() const
1257 return fID;
1261 void
1262 BParameter::SetFlags(uint32 flags)
1264 fFlags = flags;
1268 uint32
1269 BParameter::Flags() const
1271 return fFlags;
1275 status_t
1276 BParameter::GetValue(void* buffer, size_t* _size, bigtime_t* _when)
1278 CALLED();
1280 if (buffer == NULL || _size == NULL)
1281 return B_BAD_VALUE;
1283 size_t size = *_size;
1284 if (size <= 0)
1285 return B_NO_MEMORY;
1287 if (fWeb == NULL) {
1288 ERROR("BParameter::GetValue: no parent BParameterWeb\n");
1289 return B_NO_INIT;
1292 media_node node = fWeb->Node();
1293 if (IS_INVALID_NODE(node)) {
1294 ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n");
1295 return B_NO_INIT;
1298 controllable_get_parameter_data_request request;
1299 controllable_get_parameter_data_reply reply;
1301 area_id area;
1302 void* data;
1303 if (size > MAX_PARAMETER_DATA) {
1304 // create an area if large data needs to be transfered
1305 area = create_area("get parameter data", &data, B_ANY_ADDRESS,
1306 ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1307 if (area < B_OK) {
1308 ERROR("BParameter::GetValue can't create area of %ld bytes\n",
1309 size);
1310 return B_NO_MEMORY;
1312 } else {
1313 area = -1;
1314 data = reply.raw_data;
1317 request.parameter_id = fID;
1318 request.request_size = size;
1319 request.area = area;
1321 status_t status = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_DATA,
1322 &request, sizeof(request), &reply, sizeof(reply));
1323 if (status == B_OK) {
1324 // we don't want to copy more than the buffer provides
1325 if (reply.size < size)
1326 size = reply.size;
1328 memcpy(buffer, data, size);
1330 // store reported values
1332 *_size = reply.size;
1333 if (_when != NULL)
1334 *_when = reply.last_change;
1335 } else {
1336 ERROR("BParameter::GetValue parameter '%s' querying node %d, "
1337 "port %d failed: %s\n", fName, (int)node.node, (int)node.port,
1338 strerror(status));
1341 if (area >= B_OK)
1342 delete_area(area);
1344 return status;
1348 status_t
1349 BParameter::SetValue(const void* buffer, size_t size, bigtime_t when)
1351 CALLED();
1353 if (buffer == 0)
1354 return B_BAD_VALUE;
1355 if (size <= 0)
1356 return B_NO_MEMORY;
1358 if (fWeb == 0) {
1359 ERROR("BParameter::SetValue: no parent BParameterWeb\n");
1360 return B_NO_INIT;
1363 media_node node = fWeb->Node();
1364 if (IS_INVALID_NODE(node)) {
1365 ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned "
1366 "to a BMediaNode\n");
1367 return B_NO_INIT;
1370 controllable_set_parameter_data_request request;
1371 controllable_set_parameter_data_reply reply;
1372 area_id area;
1373 void* data;
1375 if (size > MAX_PARAMETER_DATA) {
1376 // create an area if large data needs to be transfered
1377 area = create_area("set parameter data", &data, B_ANY_ADDRESS,
1378 ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1379 if (area < B_OK) {
1380 ERROR("BParameter::SetValue can't create area of %ld bytes\n", size);
1381 return B_NO_MEMORY;
1383 } else {
1384 area = -1;
1385 data = request.raw_data;
1388 memcpy(data, buffer, size);
1389 request.parameter_id = fID;
1390 request.when = when;
1391 request.area = area;
1392 request.size = size;
1394 status_t status = QueryPort(node.port, CONTROLLABLE_SET_PARAMETER_DATA,
1395 &request, sizeof(request), &reply, sizeof(reply));
1396 if (status != B_OK) {
1397 ERROR("BParameter::SetValue querying node failed: %s\n",
1398 strerror(status));
1401 if (area != -1)
1402 delete_area(area);
1404 return status;
1408 int32
1409 BParameter::CountChannels()
1411 return fChannels;
1415 void
1416 BParameter::SetChannelCount(int32 count)
1418 fChannels = count;
1422 media_type
1423 BParameter::MediaType()
1425 return fMediaType;
1429 void
1430 BParameter::SetMediaType(media_type type)
1432 fMediaType = type;
1436 int32
1437 BParameter::CountInputs()
1439 return fInputs->CountItems();
1443 BParameter*
1444 BParameter::InputAt(int32 index)
1446 return static_cast<BParameter*>(fInputs->ItemAt(index));
1450 void
1451 BParameter::AddInput(BParameter* input)
1453 CALLED();
1455 // BeBook has this method returning a status value,
1456 // but it should be updated
1457 if (input == NULL)
1458 return;
1460 if (fInputs->HasItem(input)) {
1461 // if already in input list, don't duplicate.
1462 return;
1465 fInputs->AddItem(input);
1466 input->AddOutput(this);
1470 int32
1471 BParameter::CountOutputs()
1473 return fOutputs->CountItems();
1477 BParameter*
1478 BParameter::OutputAt(int32 index)
1480 return static_cast<BParameter*>(fOutputs->ItemAt(index));
1484 void
1485 BParameter::AddOutput(BParameter* output)
1487 CALLED();
1489 // BeBook has this method returning a status value,
1490 // but it should be updated
1491 if (output == NULL)
1492 return;
1494 if (fOutputs->HasItem(output)) {
1495 // if already in output list, don't duplicate.
1496 return;
1499 fOutputs->AddItem(output);
1500 output->AddInput(this);
1504 bool
1505 BParameter::IsFixedSize() const
1507 return false;
1511 type_code
1512 BParameter::TypeCode() const
1514 return B_MEDIA_PARAMETER_TYPE;
1518 ssize_t
1519 BParameter::FlattenedSize() const
1521 CALLED();
1523 ?? (0x02040607): 4 bytes
1524 BParameter Struct Size (in bytes): 4 bytes
1525 ID: 4 bytes
1526 Name String Length: 1 byte (??)
1527 Name String: 'Name String Length' bytes
1528 Kind String Length: 1 byte (??)
1529 Kind String: 'Kind String Length' bytes
1530 Unit String Length: 1 byte (??)
1531 Unit String: 'Unit String Length' bytes
1532 Inputs Count: 4 bytes
1533 Inputs (pointers): ('Inputs Count')*4 bytes
1534 Outputs Count: 4 bytes
1535 Outputs (pointers): ('Outputs Count')*4 bytes
1536 Media Type: 4 bytes
1537 ChannelCount: 4 bytes
1538 Flags: 4 bytes
1540 //35 bytes are guaranteed, after that, add the variable length parts.
1541 ssize_t size = kAdditionalParameterSize;
1543 if (fName != NULL)
1544 size += strlen(fName);
1545 if (fKind != NULL)
1546 size += strlen(fKind);
1547 if (fUnit != NULL)
1548 size += strlen(fUnit);
1550 size += fInputs->CountItems() * sizeof(BParameter*);
1551 size += fOutputs->CountItems() * sizeof(BParameter*);
1553 return size;
1557 status_t
1558 BParameter::Flatten(void* buffer, ssize_t size) const
1560 CALLED();
1562 if (buffer == NULL) {
1563 ERROR("BParameter::Flatten buffer is NULL\n");
1564 return B_NO_INIT;
1567 // NOTICE: It is important that this value is the size returned by
1568 // BParameter::FlattenedSize(), not by a descendent's override of this method.
1569 ssize_t actualSize = BParameter::FlattenedSize();
1570 if (size < actualSize) {
1571 ERROR("BParameter::Flatten(): size too small\n");
1572 return B_NO_MEMORY;
1575 write_to_buffer<uint32>(&buffer, kParameterMagic);
1576 write_to_buffer<ssize_t>(&buffer, actualSize);
1577 write_to_buffer<int32>(&buffer, fID);
1579 write_string_to_buffer(&buffer, fName);
1580 write_string_to_buffer(&buffer, fKind);
1581 write_string_to_buffer(&buffer, fUnit);
1583 // flatten and write the list of inputs
1584 ssize_t count = fInputs->CountItems();
1585 write_to_buffer<ssize_t>(&buffer, count);
1587 if (count > 0) {
1588 memcpy(buffer, fInputs->Items(), sizeof(BParameter*) * count);
1589 skip_in_buffer(&buffer, sizeof(BParameter*) * count);
1592 // flatten and write the list of outputs
1593 count = fOutputs->CountItems();
1594 write_to_buffer<ssize_t>(&buffer, count);
1596 if (count > 0) {
1597 memcpy(buffer, fOutputs->Items(), sizeof(BParameter*) * count);
1598 skip_in_buffer(&buffer, sizeof(BParameter*) * count);
1601 write_to_buffer<media_type>(&buffer, fMediaType);
1602 write_to_buffer<int32>(&buffer, fChannels);
1603 write_to_buffer<uint32>(&buffer, fFlags);
1605 return B_OK;
1609 bool
1610 BParameter::AllowsTypeCode(type_code code) const
1612 return code == TypeCode();
1616 status_t
1617 BParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
1619 CALLED();
1621 if (!AllowsTypeCode(code)) {
1622 ERROR("BParameter::Unflatten(): wrong type code\n");
1623 return B_BAD_TYPE;
1626 if (buffer == NULL) {
1627 ERROR("BParameter::Unflatten(): buffer is NULL\n");
1628 return B_NO_INIT;
1631 // if the buffer is smaller than the size needed to read the
1632 // signature and struct size fields, then there is a problem
1633 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
1634 ERROR("BParameter::Unflatten() size too small\n");
1635 return B_BAD_VALUE;
1638 const void* bufferStart = buffer;
1640 // check magic
1642 uint32 magic = read_from_buffer<uint32>(&buffer);
1643 if (magic == B_SWAP_INT32(kParameterMagic))
1644 fSwapDetected = true;
1645 else if (magic == kParameterMagic)
1646 fSwapDetected = false;
1647 else {
1648 ERROR("BParameter::Unflatten(): bad magic\n");
1649 return B_BAD_TYPE;
1652 ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1653 fSwapDetected);
1654 if (parameterSize > size) {
1655 ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n",
1656 parameterSize, size);
1657 return B_BAD_VALUE;
1660 // if the struct doesn't meet the minimum size for
1661 // a flattened BParameter, then return an error.
1662 // MinFlattenedParamSize =
1663 // ID (4 bytes)
1664 // Name String Length (1 byte)
1665 // Kind String Length (1 byte)
1666 // Unit String Length (1 byte)
1667 // Inputs Count (4 bytes)
1668 // Outputs Count (4 bytes)
1669 // Media Type (4 bytes)
1670 // Channel Count (4 bytes)
1671 // Flags (4 bytes)
1672 // TOTAL: 27 bytes
1673 const ssize_t kMinFlattenedParamSize = 15 + 3 * sizeof(ssize_t);
1674 if (parameterSize < kMinFlattenedParamSize) {
1675 ERROR("BParameter::Unflatten out of memory (2)\n");
1676 return B_ERROR;
1679 fID = read_from_buffer_swap32<int32>(&buffer, fSwapDetected);
1681 if (read_string_from_buffer(&buffer, &fName,
1682 size_left(size, bufferStart, buffer)) < B_OK
1683 || read_string_from_buffer(&buffer, &fKind,
1684 size_left(size, bufferStart, buffer)) < B_OK
1685 || read_string_from_buffer(&buffer, &fUnit,
1686 size_left(size, bufferStart, buffer)) < B_OK)
1687 return B_NO_MEMORY;
1689 // read the list of inputs
1691 // it will directly add the pointers in the flattened message to the list;
1692 // these will be fixed to point to the real inputs/outputs later in FixRefs()
1694 ssize_t count = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1695 fSwapDetected);
1697 fInputs->MakeEmpty();
1698 for (ssize_t i = 0; i < count; i++) {
1699 fInputs->AddItem(read_pointer_from_buffer_swap<BParameter * const>(
1700 &buffer, fSwapDetected));
1703 // read the list of outputs
1705 count = read_pointer_from_buffer_swap<ssize_t>(&buffer, fSwapDetected);
1707 fOutputs->MakeEmpty();
1708 for (ssize_t i = 0; i < count; i++) {
1709 fOutputs->AddItem(read_pointer_from_buffer_swap<BParameter * const>(
1710 &buffer, fSwapDetected));
1713 fMediaType = read_from_buffer_swap32<media_type>(&buffer, fSwapDetected);
1714 fChannels = read_from_buffer_swap32<int32>(&buffer, fSwapDetected);
1715 fFlags = read_from_buffer_swap32<uint32>(&buffer, fSwapDetected);
1717 return B_OK;
1721 BParameter::BParameter(int32 id, media_type mediaType,
1722 media_parameter_type type, BParameterWeb* web, const char* name,
1723 const char* kind, const char* unit)
1725 fID(id),
1726 fType(type),
1727 fWeb(web),
1728 fGroup(NULL),
1729 fSwapDetected(true),
1730 fMediaType(mediaType),
1731 fChannels(1),
1732 fFlags(0)
1734 CALLED();
1736 fName = strndup(name, 255);
1737 fKind = strndup(kind, 255);
1738 fUnit = strndup(unit, 255);
1740 // create empty input/output lists
1741 fInputs = new BList();
1742 fOutputs = new BList();
1746 BParameter::~BParameter()
1748 CALLED();
1750 // don't worry about the fWeb/fGroup properties, you don't need
1751 // to remove yourself from a web/group since the only way in which
1752 // a parameter is destroyed is when the owner web/group destroys it
1754 free(fName);
1755 free(fKind);
1756 free(fUnit);
1758 delete fInputs;
1759 delete fOutputs;
1763 /*! Replaces references to items in the old list with the corresponding
1764 items in the updated list. The references are replaced in the input
1765 and output lists.
1766 This is called by BParameterWeb::Unflatten().
1768 void
1769 BParameter::FixRefs(BList& old, BList& updated)
1771 CALLED();
1773 // update inputs
1775 void** items = static_cast<void**>(fInputs->Items());
1776 int32 count = fInputs->CountItems();
1778 for (int32 i = 0; i < count; i++) {
1779 int32 index = old.IndexOf(items[i]);
1780 if (index >= 0)
1781 items[i] = updated.ItemAt(index);
1782 else {
1783 ERROR("BParameter::FixRefs(): No mapping found for input");
1784 items[i] = NULL;
1788 // remove all NULL inputs (those which couldn't be mapped)
1790 for (int32 i = count; i-- > 0;) {
1791 if (items[i] == NULL)
1792 fInputs->RemoveItem(i);
1795 // update outputs
1797 items = static_cast<void **>(fOutputs->Items());
1798 count = fOutputs->CountItems();
1800 for (int32 i = 0; i < count; i++) {
1801 int32 index = old.IndexOf(items[i]);
1802 if (index >= 0)
1803 items[i] = updated.ItemAt(index);
1804 else {
1805 ERROR("BParameter::FixRefs(): No mapping found for output");
1806 items[i] = NULL;
1810 // remove all NULL outputs (those which couldn't be mapped)
1812 for (int32 i = count; i-- > 0;) {
1813 if (items[i] == NULL)
1814 fOutputs->RemoveItem(i);
1819 // #pragma mark - public BContinuousParameter
1822 type_code
1823 BContinuousParameter::ValueType()
1825 return B_FLOAT_TYPE;
1829 float
1830 BContinuousParameter::MinValue()
1832 return fMinimum;
1836 float
1837 BContinuousParameter::MaxValue()
1839 return fMaximum;
1843 float
1844 BContinuousParameter::ValueStep()
1846 return fStepping;
1850 void
1851 BContinuousParameter::SetResponse(int resp, float factor, float offset)
1853 fResponse = static_cast<response>(resp);
1854 fFactor = factor;
1855 fOffset = offset;
1859 void
1860 BContinuousParameter::GetResponse(int* _resp, float* _factor, float* _offset)
1862 if (_resp != NULL)
1863 *_resp = fResponse;
1864 if (_factor != NULL)
1865 *_factor = fFactor;
1866 if (_offset != NULL)
1867 *_offset = fOffset;
1871 ssize_t
1872 BContinuousParameter::FlattenedSize() const
1874 CALLED();
1876 // only adds a fixed amount of bytes
1877 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize;
1881 status_t
1882 BContinuousParameter::Flatten(void* buffer, ssize_t size) const
1884 CALLED();
1886 if (buffer == NULL) {
1887 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n");
1888 return B_NO_INIT;
1891 ssize_t parameterSize = BParameter::FlattenedSize();
1892 if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
1893 ERROR("BContinuousParameter::Flatten(): size to small\n");
1894 return B_NO_MEMORY;
1897 status_t status = BParameter::Flatten(buffer, size);
1898 if (status != B_OK) {
1899 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n");
1900 return status;
1903 // add our data to the general flattened BParameter
1905 skip_in_buffer(&buffer, parameterSize);
1907 write_to_buffer<float>(&buffer, fMinimum);
1908 write_to_buffer<float>(&buffer, fMaximum);
1909 write_to_buffer<float>(&buffer, fStepping);
1910 write_to_buffer<response>(&buffer, fResponse);
1911 write_to_buffer<float>(&buffer, fFactor);
1912 write_to_buffer<float>(&buffer, fOffset);
1914 return B_OK;
1918 status_t
1919 BContinuousParameter::Unflatten(type_code code, const void* buffer,
1920 ssize_t size)
1922 CALLED();
1924 // we try to check if the buffer size is long enough to hold an object
1925 // as early as possible.
1927 if (!AllowsTypeCode(code)) {
1928 ERROR("BContinuousParameter::Unflatten wrong type code\n");
1929 return B_BAD_TYPE;
1932 if (buffer == NULL) {
1933 ERROR("BContinuousParameter::Unflatten buffer is NULL\n");
1934 return B_NO_INIT;
1937 // if the buffer is smaller than the size needed to read the
1938 // signature and struct size fields, then there is a problem
1939 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
1940 ERROR("BContinuousParameter::Unflatten size too small\n");
1941 return B_ERROR;
1944 status_t status = BParameter::Unflatten(code, buffer, size);
1945 if (status != B_OK) {
1946 ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten "
1947 "failed: %s\n", strerror(status));
1948 return status;
1951 ssize_t parameterSize = BParameter::FlattenedSize();
1952 skip_in_buffer(&buffer, parameterSize);
1954 if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
1955 ERROR("BContinuousParameter::Unflatten(): buffer too small\n");
1956 return B_BAD_VALUE;
1959 fMinimum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1960 fMaximum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1961 fStepping = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1962 fResponse = read_from_buffer_swap32<response>(&buffer, SwapOnUnflatten());
1963 fFactor = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1964 fOffset = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1966 return B_OK;
1970 BContinuousParameter::BContinuousParameter(int32 id, media_type mediaType,
1971 BParameterWeb* web, const char* name, const char* kind,
1972 const char* unit, float minimum, float maximum, float stepping)
1973 : BParameter(id, mediaType, B_CONTINUOUS_PARAMETER, web, name, kind, unit),
1974 fMinimum(minimum),
1975 fMaximum(maximum),
1976 fStepping(stepping),
1977 fResponse(B_LINEAR),
1978 fFactor(1.0),
1979 fOffset(0.0)
1981 CALLED();
1985 BContinuousParameter::~BContinuousParameter()
1987 CALLED();
1991 // #pragma mark - public BDiscreteParameter
1994 type_code
1995 BDiscreteParameter::ValueType()
1997 return B_INT32_TYPE;
2001 int32
2002 BDiscreteParameter::CountItems()
2004 return fValues->CountItems();
2008 const char*
2009 BDiscreteParameter::ItemNameAt(int32 index)
2011 return reinterpret_cast<const char*>(fSelections->ItemAt(index));
2015 int32
2016 BDiscreteParameter::ItemValueAt(int32 index)
2018 int32* item = static_cast<int32*>(fValues->ItemAt(index));
2019 if (item == NULL)
2020 return 0;
2022 return *item;
2026 status_t
2027 BDiscreteParameter::AddItem(int32 value, const char* name)
2029 CALLED();
2031 int32* valueCopy = new(std::nothrow) int32(value);
2032 if (valueCopy == NULL)
2033 return B_NO_MEMORY;
2034 char* nameCopy = strndup(name, 255);
2035 if (name != NULL && nameCopy == NULL) {
2036 delete valueCopy;
2037 return B_NO_MEMORY;
2040 if (!fValues->AddItem(valueCopy))
2041 goto err;
2042 if (!fSelections->AddItem(nameCopy)) {
2043 fValues->RemoveItem(valueCopy);
2044 goto err;
2046 return B_OK;
2048 err:
2049 free(nameCopy);
2050 delete valueCopy;
2051 return B_NO_MEMORY;
2055 status_t
2056 BDiscreteParameter::MakeItemsFromInputs()
2058 CALLED();
2060 int32 count = fInputs->CountItems();
2061 for (int32 i = 0; i < count; i++) {
2062 BParameter* parameter = static_cast<BParameter*>(fInputs->ItemAt(i));
2063 AddItem(i, parameter->Name());
2066 return B_OK;
2070 status_t
2071 BDiscreteParameter::MakeItemsFromOutputs()
2073 CALLED();
2075 int32 count = fOutputs->CountItems();
2076 for (int32 i = 0; i < count; i++) {
2077 BParameter* parameter = static_cast<BParameter*>(fOutputs->ItemAt(i));
2078 AddItem(i, parameter->Name());
2081 return B_OK;
2085 void
2086 BDiscreteParameter::MakeEmpty()
2088 CALLED();
2090 for (int32 i = fValues->CountItems(); i-- > 0;) {
2091 delete static_cast<int32*>(fValues->ItemAt(i));
2093 fValues->MakeEmpty();
2095 for (int32 i = fSelections->CountItems(); i-- > 0;) {
2096 free(static_cast<char*>(fSelections->ItemAt(i)));
2098 fSelections->MakeEmpty();
2102 ssize_t
2103 BDiscreteParameter::FlattenedSize() const
2105 CALLED();
2107 ssize_t size = BParameter::FlattenedSize()
2108 + kAdditionalDiscreteParameterSize;
2110 int32 count = fValues->CountItems();
2111 for (int32 i = 0; i < count; i++) {
2112 char* selection = static_cast<char*>(fSelections->ItemAt(i));
2114 if (selection != NULL)
2115 size += min_c(strlen(selection), 255);
2117 size += 5;
2118 // string length + value
2121 return size;
2125 status_t
2126 BDiscreteParameter::Flatten(void* buffer, ssize_t size) const
2128 CALLED();
2130 if (buffer == NULL) {
2131 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n");
2132 return B_NO_INIT;
2135 ssize_t parameterSize = BParameter::FlattenedSize();
2137 if (size < FlattenedSize()) {
2138 ERROR("BDiscreteParameter::Flatten(): size too small\n");
2139 return B_NO_MEMORY;
2142 status_t status = BParameter::Flatten(buffer, size);
2143 if (status != B_OK) {
2144 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n");
2145 return status;
2148 skip_in_buffer(&buffer, parameterSize);
2150 int32 count = fValues->CountItems();
2151 write_to_buffer<int32>(&buffer, count);
2153 // write out all value/name pairs
2154 for (int32 i = 0; i < count; i++) {
2155 const char* selection = static_cast<char*>(fSelections->ItemAt(i));
2156 const int32* value = static_cast<int32*>(fValues->ItemAt(i));
2158 write_string_to_buffer(&buffer, selection);
2159 write_to_buffer<int32>(&buffer, value ? *value : 0);
2162 return B_OK;
2166 status_t
2167 BDiscreteParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2169 CALLED();
2171 if (!AllowsTypeCode(code)) {
2172 ERROR("BDiscreteParameter::Unflatten(): bad type code\n");
2173 return B_BAD_TYPE;
2176 if (buffer == NULL) {
2177 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n");
2178 return B_NO_INIT;
2181 // if the buffer is smaller than the size needed to read the
2182 // signature and struct size fields, then there is a problem
2183 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
2184 ERROR("BDiscreteParameter::Unflatten(): size too small\n");
2185 return B_ERROR;
2188 const void* bufferStart = buffer;
2190 status_t status = BParameter::Unflatten(code, buffer, size);
2191 if (status != B_OK) {
2192 ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n");
2193 return status;
2196 ssize_t parameterSize = BParameter::FlattenedSize();
2197 skip_in_buffer(&buffer, parameterSize);
2199 if (size < (parameterSize + kAdditionalDiscreteParameterSize)) {
2200 ERROR("BDiscreteParameter::Unflatten(): buffer too small\n");
2201 return B_BAD_VALUE;
2204 int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten());
2206 // clear any existing name/value pairs
2207 MakeEmpty();
2209 for (int32 i = 0; i < count; i++) {
2210 char* name = NULL;
2211 if (read_string_from_buffer(&buffer, &name, size_left(size, bufferStart,
2212 buffer)) < B_OK)
2213 return B_BAD_DATA;
2215 if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) {
2216 free(name);
2217 return B_BAD_DATA;
2220 int32 value = read_from_buffer_swap32<int32>(&buffer,
2221 SwapOnUnflatten());
2223 AddItem(value, name);
2224 free(name);
2227 return B_OK;
2231 BDiscreteParameter::BDiscreteParameter(int32 id, media_type mediaType,
2232 BParameterWeb* web, const char* name, const char* kind)
2233 : BParameter(id, mediaType, B_DISCRETE_PARAMETER, web, name, kind, NULL)
2235 CALLED();
2237 fSelections = new BList();
2238 fValues = new BList();
2242 BDiscreteParameter::~BDiscreteParameter()
2244 CALLED();
2246 MakeEmpty();
2248 delete fSelections;
2249 delete fValues;
2253 // #pragma mark - public BTextParameter
2256 size_t
2257 BTextParameter::MaxBytes() const
2259 return fMaxBytes;
2263 type_code
2264 BTextParameter::ValueType()
2266 return B_FLOAT_TYPE;
2270 ssize_t
2271 BTextParameter::FlattenedSize() const
2273 return BParameter::FlattenedSize() + sizeof(fMaxBytes);
2277 status_t
2278 BTextParameter::Flatten(void* buffer, ssize_t size) const
2280 if (buffer == NULL) {
2281 ERROR("BTextParameter::Flatten(): buffer is NULL\n");
2282 return B_NO_INIT;
2285 ssize_t parameterSize = BParameter::FlattenedSize();
2286 if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
2287 ERROR("BContinuousParameter::Flatten(): size to small\n");
2288 return B_NO_MEMORY;
2291 status_t status = BParameter::Flatten(buffer, size);
2292 if (status != B_OK) {
2293 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n");
2294 return status;
2297 // add our data to the general flattened BParameter
2299 skip_in_buffer(&buffer, parameterSize);
2301 write_to_buffer<uint32>(&buffer, fMaxBytes);
2303 return B_OK;
2307 status_t
2308 BTextParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2310 // we try to check if the buffer size is long enough to hold an object
2311 // as early as possible.
2313 if (!AllowsTypeCode(code)) {
2314 ERROR("BTextParameter::Unflatten wrong type code\n");
2315 return B_BAD_TYPE;
2318 if (buffer == NULL) {
2319 ERROR("BTextParameter::Unflatten buffer is NULL\n");
2320 return B_NO_INIT;
2323 if (size < static_cast<ssize_t>(sizeof(fMaxBytes))) {
2324 ERROR("BTextParameter::Unflatten size too small\n");
2325 return B_ERROR;
2328 status_t status = BParameter::Unflatten(code, buffer, size);
2329 if (status != B_OK) {
2330 ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n");
2331 return status;
2334 ssize_t parameterSize = BParameter::FlattenedSize();
2335 skip_in_buffer(&buffer, parameterSize);
2337 if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
2338 ERROR("BTextParameter::Unflatten(): buffer too small\n");
2339 return B_BAD_VALUE;
2342 fMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten());
2344 return B_OK;
2348 BTextParameter::BTextParameter(int32 id, media_type mediaType,
2349 BParameterWeb* web, const char* name, const char* kind,
2350 size_t maxBytes)
2351 : BParameter(id, mediaType, B_TEXT_PARAMETER, web, name, kind, NULL)
2353 fMaxBytes = maxBytes;
2357 BTextParameter::~BTextParameter()
2362 // #pragma mark - public BNullParameter
2365 type_code
2366 BNullParameter::ValueType()
2368 // NULL parameters have no value type
2369 return 0;
2373 ssize_t
2374 BNullParameter::FlattenedSize() const
2376 return BParameter::FlattenedSize();
2380 status_t
2381 BNullParameter::Flatten(void* buffer, ssize_t size) const
2383 return BParameter::Flatten(buffer, size);
2387 status_t
2388 BNullParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2390 return BParameter::Unflatten(code, buffer, size);
2394 BNullParameter::BNullParameter(int32 id, media_type mediaType,
2395 BParameterWeb* web, const char* name, const char* kind)
2396 : BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL)
2401 BNullParameter::~BNullParameter()
2406 // #pragma mark - reserved functions
2409 status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; }
2410 status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; }
2411 status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; }
2412 status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; }
2413 status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; }
2414 status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; }
2415 status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; }
2416 status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; }
2418 status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; }
2419 status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; }
2420 status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; }
2421 status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; }
2422 status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; }
2423 status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; }
2424 status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; }
2425 status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; }
2427 status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; }
2428 status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; }
2429 status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; }
2430 status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; }
2431 status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; }
2432 status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; }
2433 status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; }
2434 status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; }
2436 status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; }
2437 status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; }
2438 status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; }
2439 status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; }
2440 status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; }
2441 status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; }
2442 status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; }
2443 status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; }
2445 status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; }
2446 status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; }
2447 status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; }
2448 status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; }
2449 status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; }
2450 status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; }
2451 status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; }
2452 status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; }
2454 status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; }
2455 status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; }
2456 status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; }
2457 status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; }
2458 status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; }
2459 status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; }
2460 status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; }
2461 status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; }
2463 status_t BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR; }
2464 status_t BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR; }
2465 status_t BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR; }
2466 status_t BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR; }
2467 status_t BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR; }
2468 status_t BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR; }
2469 status_t BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR; }
2470 status_t BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR; }