1 /*
2 * Copyright 2002-2012, Haiku. All Rights Reserved.
3 * This file may be used under the terms of the MIT License.
4 *
5 * Author: Zousar Shaker
6 * Axel Dörfler, axeld@pinc-software.de
7 * Marcus Overhagen
8 */
9
10
11 /*! Implements the following classes:
12 BParameterWeb, BParameterGroup, BParameter, BNullParameter,
13 BContinuousParameter, BDiscreteParameter
14 */
15
16
17 #include <ParameterWeb.h>
18
19 #include <new>
20 #include <string.h>
21
22 #include <MediaNode.h>
23 #include <MediaRoster.h>
24
25 #include "DataExchange.h"
26 #include "MediaDebug.h"
27 #include "MediaMisc.h"
28
29
30 /*
31 The following is documentation on the flattened format
32 of structures/classes in this module:
33
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-------------------
68
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
88
89 //---------END-CORE-BPARAMETERGROUP-STRUCT--------------
90
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--------------
104
105 */
106
107
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";
143
144 // Flattened data
145
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;
151
152 static const ssize_t kAdditionalParameterGroupSize = 12;
153 static const ssize_t kAdditionalParameterSize = 23 + 3 * sizeof(ssize_t);
154
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)
162 */
163 static const ssize_t kAdditionalContinuousParameterSize = 5 * sizeof(float)
164 + sizeof(BContinuousParameter::response);
165 static const ssize_t kAdditionalDiscreteParameterSize = sizeof(ssize_t);
166
167
168 // helper functions
169
170
171 template<class Type> Type
read_from_buffer(const void ** _buffer)172 read_from_buffer(const void **_buffer)
173 {
174 const Type *typedBuffer = static_cast<const Type *>(*_buffer);
175 Type value = *typedBuffer;
176
177 typedBuffer++;
178 *_buffer = static_cast<const void *>(typedBuffer);
179
180 return value;
181 }
182
183
184 static status_t
read_string_from_buffer(const void ** _buffer,char ** _string,ssize_t size)185 read_string_from_buffer(const void **_buffer, char **_string, ssize_t size)
186 {
187 if (size < 1)
188 return B_BAD_VALUE;
189
190 const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
191 uint8 length = *buffer++;
192 if (length > size - 1)
193 return B_BAD_VALUE;
194
195 char *string = (char *)malloc(length + 1);
196 if (string == NULL)
197 return B_NO_MEMORY;
198
199 memcpy(string, buffer, length);
200 string[length] = '\0';
201
202 free(*_string);
203
204 *_buffer = static_cast<const void *>(buffer + length);
205 *_string = string;
206 return B_OK;
207 }
208
209
210 // currently unused
211 #if 0
212 template<class Type> Type *
213 reserve_in_buffer(void **_buffer)
214 {
215 Type *typedBuffer = static_cast<Type *>(*_buffer);
216
217 *typedBuffer = 0;
218 typedBuffer++;
219
220 *_buffer = static_cast<void *>(typedBuffer);
221 }
222 #endif
223
224 template<class Type> void
write_to_buffer(void ** _buffer,Type value)225 write_to_buffer(void **_buffer, Type value)
226 {
227 Type *typedBuffer = static_cast<Type *>(*_buffer);
228
229 *typedBuffer = value;
230 typedBuffer++;
231
232 *_buffer = static_cast<void *>(typedBuffer);
233 }
234
235
236 void
write_string_to_buffer(void ** _buffer,const char * string)237 write_string_to_buffer(void **_buffer, const char *string)
238 {
239 uint8 *buffer = static_cast<uint8 *>(*_buffer);
240 uint32 length = string ? strlen(string) : 0;
241 if (length > 255)
242 length = 255;
243
244 *buffer++ = static_cast<uint8>(length);
245 if (length) {
246 memcpy(buffer, string, length);
247 buffer += length;
248 }
249
250 *_buffer = static_cast<void *>(buffer);
251 }
252
253
254 static void
skip_in_buffer(const void ** _buffer,uint32 bytes)255 skip_in_buffer(const void **_buffer, uint32 bytes)
256 {
257 const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
258
259 buffer += bytes;
260
261 *_buffer = static_cast<const void *>(buffer);
262 }
263
264
265 static void inline
skip_in_buffer(void ** _buffer,uint32 bytes)266 skip_in_buffer(void **_buffer, uint32 bytes)
267 {
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.
272
273 skip_in_buffer((const void **)_buffer, bytes);
274 }
275
276
277 template<class Type> Type
swap32(Type value,bool doSwap)278 swap32(Type value, bool doSwap)
279 {
280 STATIC_ASSERT(sizeof(Type) == 4);
281
282 if (doSwap)
283 return (Type)B_SWAP_INT32((int32)value);
284
285 return value;
286 }
287
288
289 template<class Type> Type
swap64(Type value,bool doSwap)290 swap64(Type value, bool doSwap)
291 {
292 STATIC_ASSERT(sizeof(Type) == 8);
293
294 if (doSwap)
295 return (Type)B_SWAP_INT64((int64)value);
296
297 return value;
298 }
299
300
301 template<class Type> Type
read_from_buffer_swap32(const void ** _buffer,bool doSwap)302 read_from_buffer_swap32(const void **_buffer, bool doSwap)
303 {
304 return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
305 }
306
307
308 template<class Type> Type
read_pointer_from_buffer_swap(const void ** _buffer,bool doSwap)309 read_pointer_from_buffer_swap(const void **_buffer, bool doSwap)
310 {
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
318 }
319
320
321 static inline ssize_t
size_left(ssize_t size,const void * bufferStart,const void * buffer)322 size_left(ssize_t size, const void *bufferStart, const void *buffer)
323 {
324 return size - static_cast<ssize_t>((const uint8 *)buffer - (const uint8 *)bufferStart);
325 }
326
327
328 // #pragma mark - BParameterWeb
329
330
BParameterWeb()331 BParameterWeb::BParameterWeb()
332 :
333 fNode(media_node::null)
334 // fNode is set in BControllable::SetParameterWeb()
335 {
336 CALLED();
337
338 fGroups = new BList();
339 fOldRefs = new BList();
340 fNewRefs = new BList();
341 }
342
343
~BParameterWeb()344 BParameterWeb::~BParameterWeb()
345 {
346 CALLED();
347
348 for (int32 i = fGroups->CountItems(); i-- > 0;) {
349 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
350 }
351
352 delete fGroups;
353 delete fOldRefs;
354 delete fNewRefs;
355 }
356
357
358 media_node
Node()359 BParameterWeb::Node()
360 {
361 return fNode;
362 }
363
364
365 BParameterGroup*
MakeGroup(const char * name)366 BParameterWeb::MakeGroup(const char* name)
367 {
368 CALLED();
369
370 BParameterGroup* group = new(std::nothrow) BParameterGroup(this, name);
371 if (group == NULL)
372 return NULL;
373
374 if (!fGroups->AddItem(group)) {
375 delete group;
376 return NULL;
377 }
378
379 return group;
380 }
381
382
383 int32
CountGroups()384 BParameterWeb::CountGroups()
385 {
386 return fGroups->CountItems();
387 }
388
389
390 BParameterGroup*
GroupAt(int32 index)391 BParameterWeb::GroupAt(int32 index)
392 {
393 return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
394 }
395
396
397 int32
CountParameters()398 BParameterWeb::CountParameters()
399 {
400 CALLED();
401
402 // Counts over all groups (and sub-groups) in the web.
403 // The "groups" list is used as count stack
404
405 BList groups(*fGroups);
406 int32 count = 0;
407
408 for (int32 i = 0; i < groups.CountItems(); i++) {
409 BParameterGroup* group
410 = static_cast<BParameterGroup*>(groups.ItemAt(i));
411
412 count += group->CountParameters();
413
414 if (group->fGroups != NULL)
415 groups.AddList(group->fGroups);
416 }
417
418 return count;
419 }
420
421
422 BParameter*
ParameterAt(int32 index)423 BParameterWeb::ParameterAt(int32 index)
424 {
425 CALLED();
426
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
430
431 BList groups(*fGroups);
432
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);
439
440 index -= count;
441 // the index is always relative to the start of the current group
442
443 if (group->fGroups != NULL)
444 groups.AddList(group->fGroups);
445 }
446
447 TRACE("*** could not find parameter at %"
448 B_PRId32 " (count = %" B_PRId32 ")\n", index, CountParameters());
449
450 return NULL;
451 }
452
453
454 bool
IsFixedSize() const455 BParameterWeb::IsFixedSize() const
456 {
457 return false;
458 }
459
460
461 type_code
TypeCode() const462 BParameterWeb::TypeCode() const
463 {
464 return B_MEDIA_PARAMETER_WEB_TYPE;
465 }
466
467
468 ssize_t
FlattenedSize() const469 BParameterWeb::FlattenedSize() const
470 {
471 CALLED();
472
473 /*
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--------------
487 */
488 //36 guaranteed bytes, variable after that.
489 ssize_t size = sizeof(int32) + 2 * sizeof(int32) + sizeof(media_node);
490
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();
496 }
497 }
498
499 return size;
500 }
501
502
503 status_t
Flatten(void * buffer,ssize_t size) const504 BParameterWeb::Flatten(void* buffer, ssize_t size) const
505 {
506 CALLED();
507
508 if (buffer == NULL)
509 return B_NO_INIT;
510
511 ssize_t actualSize = BParameterWeb::FlattenedSize();
512 if (size < actualSize)
513 return B_NO_MEMORY;
514
515 void* bufferStart = buffer;
516
517 write_to_buffer<int32>(&buffer, kParameterWebMagic);
518 write_to_buffer<int32>(&buffer, kCurrentParameterWebVersion);
519
520 // flatten all groups into this buffer
521
522 int32 count = fGroups->CountItems();
523 write_to_buffer<int32>(&buffer, count);
524
525 write_to_buffer<media_node>(&buffer, fNode);
526
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;
533 }
534
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;
539 }
540
541 write_to_buffer<ssize_t>(&buffer, groupSize);
542
543 // write the flattened sub group
544 status_t status = group->Flatten(buffer, groupSize);
545 if (status < B_OK)
546 return status;
547
548 skip_in_buffer(&buffer, groupSize);
549 }
550
551 return B_OK;
552 }
553
554
555 bool
AllowsTypeCode(type_code code) const556 BParameterWeb::AllowsTypeCode(type_code code) const
557 {
558 return code == TypeCode();
559 }
560
561
562 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)563 BParameterWeb::Unflatten(type_code code, const void* buffer, ssize_t size)
564 {
565 CALLED();
566
567 if (!AllowsTypeCode(code)) {
568 ERROR("BParameterWeb::Unflatten(): wrong type code\n");
569 return B_BAD_TYPE;
570 }
571
572 if (buffer == NULL) {
573 ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n");
574 return B_NO_INIT;
575 }
576
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;
583 }
584
585 const void* bufferStart = buffer;
586
587 uint32 magic = read_from_buffer<uint32>(&buffer);
588 bool isSwapped = false;
589
590 if (magic == B_SWAP_INT32(kParameterWebMagic)) {
591 isSwapped = true;
592 magic = B_SWAP_INT32(magic);
593 }
594 if (magic != kParameterWebMagic)
595 return B_BAD_DATA;
596
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;
604 }
605
606 for (int32 i = 0; i < fGroups->CountItems(); i++) {
607 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
608 }
609 fGroups->MakeEmpty();
610
611 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
612
613 fNode = read_from_buffer<media_node>(&buffer);
614 if (isSwapped)
615 swap_data(B_INT32_TYPE, &fNode, sizeof(media_node), B_SWAP_ALWAYS);
616
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;
623 }
624
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;
632 }
633
634 skip_in_buffer(&buffer, groupSize);
635
636 fGroups->AddItem(group);
637 }
638
639 // fix all references (ParameterAt() style)
640
641 BList groups(*fGroups);
642
643 for (int32 i = 0; i < groups.CountItems(); i++) {
644 BParameterGroup* group
645 = static_cast<BParameterGroup*>(groups.ItemAt(i));
646
647 for (int32 index = group->CountParameters(); index-- > 0;) {
648 BParameter* parameter
649 = static_cast<BParameter*>(group->ParameterAt(index));
650
651 parameter->FixRefs(*fOldRefs, *fNewRefs);
652 }
653
654 if (group->fGroups != NULL)
655 groups.AddList(group->fGroups);
656 }
657
658 fOldRefs->MakeEmpty();
659 fNewRefs->MakeEmpty();
660
661 return B_OK;
662 }
663
664
665 void
AddRefFix(void * oldItem,void * newItem)666 BParameterWeb::AddRefFix(void* oldItem, void* newItem)
667 {
668 fOldRefs->AddItem(oldItem);
669 fNewRefs->AddItem(newItem);
670 }
671
672
673 // #pragma mark - BParameterGroup
674
675
BParameterGroup(BParameterWeb * web,const char * name)676 BParameterGroup::BParameterGroup(BParameterWeb* web, const char* name)
677 :
678 fWeb(web),
679 fFlags(0)
680 {
681 CALLED();
682 TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web, name);
683
684 fName = strndup(name, 255);
685
686 fControls = new BList();
687 fGroups = new BList();
688 }
689
690
~BParameterGroup()691 BParameterGroup::~BParameterGroup()
692 {
693 CALLED();
694
695 for (int i = fControls->CountItems(); i-- > 0;) {
696 delete static_cast<BParameter*>(fControls->ItemAt(i));
697 }
698 delete fControls;
699
700 for (int i = fGroups->CountItems(); i-- > 0;) {
701 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
702 }
703 delete fGroups;
704
705 free(fName);
706 }
707
708
709 BParameterWeb*
Web() const710 BParameterGroup::Web() const
711 {
712 return fWeb;
713 }
714
715
716 const char*
Name() const717 BParameterGroup::Name() const
718 {
719 return fName;
720 }
721
722
723 void
SetFlags(uint32 flags)724 BParameterGroup::SetFlags(uint32 flags)
725 {
726 fFlags = flags;
727 }
728
729
730 uint32
Flags() const731 BParameterGroup::Flags() const
732 {
733 return fFlags;
734 }
735
736
737 BNullParameter*
MakeNullParameter(int32 id,media_type mediaType,const char * name,const char * kind)738 BParameterGroup::MakeNullParameter(int32 id, media_type mediaType,
739 const char* name, const char* kind)
740 {
741 CALLED();
742
743 BNullParameter* parameter = new(std::nothrow) BNullParameter(id, mediaType,
744 fWeb, name, kind);
745 if (parameter == NULL)
746 return NULL;
747
748 parameter->fGroup = this;
749 fControls->AddItem(parameter);
750
751 return parameter;
752 }
753
754
755 BContinuousParameter*
MakeContinuousParameter(int32 id,media_type mediaType,const char * name,const char * kind,const char * unit,float minimum,float maximum,float stepping)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)
759 {
760 CALLED();
761
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;
767
768 parameter->fGroup = this;
769 fControls->AddItem(parameter);
770
771 return parameter;
772 }
773
774
775 BDiscreteParameter*
MakeDiscreteParameter(int32 id,media_type mediaType,const char * name,const char * kind)776 BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType,
777 const char* name, const char* kind)
778 {
779 CALLED();
780
781 BDiscreteParameter* parameter = new(std::nothrow) BDiscreteParameter(id,
782 mediaType, fWeb, name, kind);
783 if (parameter == NULL)
784 return NULL;
785
786 parameter->fGroup = this;
787 fControls->AddItem(parameter);
788
789 return parameter;
790 }
791
792
793 BTextParameter*
MakeTextParameter(int32 id,media_type mediaType,const char * name,const char * kind,size_t maxBytes)794 BParameterGroup::MakeTextParameter(int32 id, media_type mediaType,
795 const char* name, const char* kind, size_t maxBytes)
796 {
797 CALLED();
798
799 BTextParameter* parameter = new(std::nothrow) BTextParameter(id, mediaType,
800 fWeb, name, kind, maxBytes);
801 if (parameter == NULL)
802 return NULL;
803
804 parameter->fGroup = this;
805 fControls->AddItem(parameter);
806
807 return parameter;
808 }
809
810
811 BParameterGroup*
MakeGroup(const char * name)812 BParameterGroup::MakeGroup(const char* name)
813 {
814 CALLED();
815
816 BParameterGroup* group = new(std::nothrow) BParameterGroup(fWeb, name);
817 if (group != NULL)
818 fGroups->AddItem(group);
819
820 return group;
821 }
822
823
824 int32
CountParameters()825 BParameterGroup::CountParameters()
826 {
827 return fControls->CountItems();
828 }
829
830
831 BParameter*
ParameterAt(int32 index)832 BParameterGroup::ParameterAt(int32 index)
833 {
834 return static_cast<BParameter*>(fControls->ItemAt(index));
835 }
836
837
838 int32
CountGroups()839 BParameterGroup::CountGroups()
840 {
841 return fGroups->CountItems();
842 }
843
844
845 BParameterGroup*
GroupAt(int32 index)846 BParameterGroup::GroupAt(int32 index)
847 {
848 return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
849 }
850
851
852 bool
IsFixedSize() const853 BParameterGroup::IsFixedSize() const
854 {
855 return false;
856 }
857
858
859 type_code
TypeCode() const860 BParameterGroup::TypeCode() const
861 {
862 return B_MEDIA_PARAMETER_GROUP_TYPE;
863 }
864
865
866 ssize_t
FlattenedSize() const867 BParameterGroup::FlattenedSize() const
868 {
869 CALLED();
870
871 /*
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
891
892 //---------END-CORE-BPARAMETERGROUP-STRUCT--------------
893 */
894 //13 guaranteed bytes, variable after that.
895 ssize_t size = 13;
896
897 if (fFlags != 0)
898 size += sizeof(uint32);
899
900 if (fName != NULL)
901 size += min_c(strlen(fName), 255);
902
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();
910 }
911 }
912
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();
921 }
922 }
923
924 return size;
925 }
926
927
928 status_t
Flatten(void * buffer,ssize_t size) const929 BParameterGroup::Flatten(void* buffer, ssize_t size) const
930 {
931 CALLED();
932
933 if (buffer == NULL) {
934 ERROR("BParameterGroup::Flatten buffer is NULL\n");
935 return B_NO_INIT;
936 }
937
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;
944 }
945
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);
951
952 write_string_to_buffer(&buffer, fName);
953
954 int32 count = fControls->CountItems();
955 write_to_buffer<int32>(&buffer, count);
956
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;
962 }
963
964 write_to_buffer<BParameter*>(&buffer, parameter);
965 write_to_buffer<BParameter::media_parameter_type>(&buffer,
966 parameter->Type());
967
968 // flatten parameter into this buffer
969
970 ssize_t parameterSize = parameter->FlattenedSize();
971 write_to_buffer<ssize_t>(&buffer, parameterSize);
972
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;
977
978 skip_in_buffer(&buffer, parameterSize);
979 }
980
981 count = fGroups->CountItems();
982 write_to_buffer<int32>(&buffer, count);
983
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;
990 }
991
992 write_to_buffer<BParameterGroup*>(&buffer, group);
993 write_to_buffer<type_code>(&buffer, group->TypeCode());
994
995 // flatten sub group into this buffer
996
997 ssize_t groupSize = group->FlattenedSize();
998 write_to_buffer<ssize_t>(&buffer, groupSize);
999
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;
1004
1005 skip_in_buffer(&buffer, groupSize);
1006 }
1007
1008 return B_OK;
1009 }
1010
1011
1012 bool
AllowsTypeCode(type_code code) const1013 BParameterGroup::AllowsTypeCode(type_code code) const
1014 {
1015 return code == TypeCode();
1016 }
1017
1018
1019 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)1020 BParameterGroup::Unflatten(type_code code, const void* buffer, ssize_t size)
1021 {
1022 CALLED();
1023
1024 if (!AllowsTypeCode(code)) {
1025 ERROR("BParameterGroup::Unflatten() wrong type code\n");
1026 return B_BAD_TYPE;
1027 }
1028
1029 if (buffer == NULL) {
1030 ERROR("BParameterGroup::Unflatten() buffer is NULL\n");
1031 return B_NO_INIT;
1032 }
1033
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;
1039 }
1040
1041 const void* bufferStart = buffer;
1042 // used to compute the rest length of the buffer when needed
1043
1044 uint32 magic = read_from_buffer<uint32>(&buffer);
1045 bool isSwapped = false;
1046
1047 if (magic == B_SWAP_INT32(kBufferGroupMagic)
1048 || magic == B_SWAP_INT32(kBufferGroupMagicNoFlags)) {
1049 isSwapped = true;
1050 magic = B_SWAP_INT32(magic);
1051 }
1052
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;
1059
1060 if (read_string_from_buffer(&buffer, &fName,
1061 size - (ssize_t)((uint8*)buffer - (uint8*)bufferStart)) < B_OK)
1062 return B_BAD_VALUE;
1063
1064 // Clear all existing parameters/subgroups
1065 for (int32 i = 0; i < fControls->CountItems(); i++) {
1066 delete static_cast<BParameter*>(fControls->ItemAt(i));
1067 }
1068 fControls->MakeEmpty();
1069
1070 for (int32 i = 0; i < fGroups->CountItems(); i++) {
1071 delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
1072 }
1073 fGroups->MakeEmpty();
1074
1075 // unflatten parameter list
1076
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;
1081
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;
1088 }
1089
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);
1095
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;
1100
1101 BParameter* parameter = MakeControl(mediaType);
1102 if (parameter == NULL) {
1103 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n");
1104 return B_ERROR;
1105 }
1106
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;
1113 }
1114
1115 skip_in_buffer(&buffer, parameterSize);
1116
1117 // add the item to the list
1118 parameter->fGroup = this;
1119 parameter->fWeb = fWeb;
1120 fControls->AddItem(parameter);
1121
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);
1125 }
1126
1127 // unflatten sub groups
1128
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;
1133
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;
1140 }
1141
1142 BParameterGroup* oldPointer = read_pointer_from_buffer_swap<
1143 BParameterGroup*>(&buffer, isSwapped);
1144 type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped);
1145
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;
1150
1151 BParameterGroup* group = new BParameterGroup(fWeb, "sub-unnamed");
1152 if (group == NULL) {
1153 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n");
1154 return B_ERROR;
1155 }
1156
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;
1162 }
1163
1164 skip_in_buffer(&buffer, groupSize);
1165
1166 fGroups->AddItem(group);
1167
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);
1171 }
1172
1173 return B_OK;
1174 }
1175
1176
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.
1180 */
1181 BParameter*
MakeControl(int32 type)1182 BParameterGroup::MakeControl(int32 type)
1183 {
1184 CALLED();
1185
1186 switch (type) {
1187 case BParameter::B_NULL_PARAMETER:
1188 return new BNullParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL);
1189
1190 case BParameter::B_DISCRETE_PARAMETER:
1191 return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
1192 NULL);
1193
1194 case BParameter::B_CONTINUOUS_PARAMETER:
1195 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
1196 NULL, NULL, 0, 0, 0);
1197
1198 case BParameter::B_TEXT_PARAMETER:
1199 return new BTextParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, 0);
1200
1201 default:
1202 ERROR("BParameterGroup::MakeControl unknown type %" B_PRId32 "\n",
1203 type);
1204 return NULL;
1205 }
1206 }
1207
1208
1209 // #pragma mark - BParameter
1210
1211
1212 BParameter::media_parameter_type
Type() const1213 BParameter::Type() const
1214 {
1215 return fType;
1216 }
1217
1218
1219 BParameterWeb*
Web() const1220 BParameter::Web() const
1221 {
1222 return fWeb;
1223 }
1224
1225
1226 BParameterGroup*
Group() const1227 BParameter::Group() const
1228 {
1229 return fGroup;
1230 }
1231
1232
1233 const char*
Name() const1234 BParameter::Name() const
1235 {
1236 return fName;
1237 }
1238
1239
1240 const char*
Kind() const1241 BParameter::Kind() const
1242 {
1243 return fKind;
1244 }
1245
1246
1247 const char*
Unit() const1248 BParameter::Unit() const
1249 {
1250 return fUnit;
1251 }
1252
1253
1254 int32
ID() const1255 BParameter::ID() const
1256 {
1257 return fID;
1258 }
1259
1260
1261 void
SetFlags(uint32 flags)1262 BParameter::SetFlags(uint32 flags)
1263 {
1264 fFlags = flags;
1265 }
1266
1267
1268 uint32
Flags() const1269 BParameter::Flags() const
1270 {
1271 return fFlags;
1272 }
1273
1274
1275 status_t
GetValue(void * buffer,size_t * _size,bigtime_t * _when)1276 BParameter::GetValue(void* buffer, size_t* _size, bigtime_t* _when)
1277 {
1278 CALLED();
1279
1280 if (buffer == NULL || _size == NULL)
1281 return B_BAD_VALUE;
1282
1283 size_t size = *_size;
1284 if (size <= 0)
1285 return B_NO_MEMORY;
1286
1287 if (fWeb == NULL) {
1288 ERROR("BParameter::GetValue: no parent BParameterWeb\n");
1289 return B_NO_INIT;
1290 }
1291
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;
1296 }
1297
1298 controllable_get_parameter_data_request request;
1299 controllable_get_parameter_data_reply reply;
1300
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;
1311 }
1312 } else {
1313 area = -1;
1314 data = reply.raw_data;
1315 }
1316
1317 request.parameter_id = fID;
1318 request.request_size = size;
1319 request.area = area;
1320
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;
1327
1328 memcpy(buffer, data, size);
1329
1330 // store reported values
1331
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));
1339 }
1340
1341 if (area >= B_OK)
1342 delete_area(area);
1343
1344 return status;
1345 }
1346
1347
1348 status_t
SetValue(const void * buffer,size_t size,bigtime_t when)1349 BParameter::SetValue(const void* buffer, size_t size, bigtime_t when)
1350 {
1351 CALLED();
1352
1353 if (buffer == 0)
1354 return B_BAD_VALUE;
1355 if (size <= 0)
1356 return B_NO_MEMORY;
1357
1358 if (fWeb == 0) {
1359 ERROR("BParameter::SetValue: no parent BParameterWeb\n");
1360 return B_NO_INIT;
1361 }
1362
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;
1368 }
1369
1370 controllable_set_parameter_data_request request;
1371 controllable_set_parameter_data_reply reply;
1372 area_id area;
1373 void* data;
1374
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;
1382 }
1383 } else {
1384 area = -1;
1385 data = request.raw_data;
1386 }
1387
1388 memcpy(data, buffer, size);
1389 request.parameter_id = fID;
1390 request.when = when;
1391 request.area = area;
1392 request.size = size;
1393
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));
1399 }
1400
1401 if (area != -1)
1402 delete_area(area);
1403
1404 return status;
1405 }
1406
1407
1408 int32
CountChannels()1409 BParameter::CountChannels()
1410 {
1411 return fChannels;
1412 }
1413
1414
1415 void
SetChannelCount(int32 count)1416 BParameter::SetChannelCount(int32 count)
1417 {
1418 fChannels = count;
1419 }
1420
1421
1422 media_type
MediaType()1423 BParameter::MediaType()
1424 {
1425 return fMediaType;
1426 }
1427
1428
1429 void
SetMediaType(media_type type)1430 BParameter::SetMediaType(media_type type)
1431 {
1432 fMediaType = type;
1433 }
1434
1435
1436 int32
CountInputs()1437 BParameter::CountInputs()
1438 {
1439 return fInputs->CountItems();
1440 }
1441
1442
1443 BParameter*
InputAt(int32 index)1444 BParameter::InputAt(int32 index)
1445 {
1446 return static_cast<BParameter*>(fInputs->ItemAt(index));
1447 }
1448
1449
1450 void
AddInput(BParameter * input)1451 BParameter::AddInput(BParameter* input)
1452 {
1453 CALLED();
1454
1455 // BeBook has this method returning a status value,
1456 // but it should be updated
1457 if (input == NULL)
1458 return;
1459
1460 if (fInputs->HasItem(input)) {
1461 // if already in input list, don't duplicate.
1462 return;
1463 }
1464
1465 fInputs->AddItem(input);
1466 input->AddOutput(this);
1467 }
1468
1469
1470 int32
CountOutputs()1471 BParameter::CountOutputs()
1472 {
1473 return fOutputs->CountItems();
1474 }
1475
1476
1477 BParameter*
OutputAt(int32 index)1478 BParameter::OutputAt(int32 index)
1479 {
1480 return static_cast<BParameter*>(fOutputs->ItemAt(index));
1481 }
1482
1483
1484 void
AddOutput(BParameter * output)1485 BParameter::AddOutput(BParameter* output)
1486 {
1487 CALLED();
1488
1489 // BeBook has this method returning a status value,
1490 // but it should be updated
1491 if (output == NULL)
1492 return;
1493
1494 if (fOutputs->HasItem(output)) {
1495 // if already in output list, don't duplicate.
1496 return;
1497 }
1498
1499 fOutputs->AddItem(output);
1500 output->AddInput(this);
1501 }
1502
1503
1504 bool
IsFixedSize() const1505 BParameter::IsFixedSize() const
1506 {
1507 return false;
1508 }
1509
1510
1511 type_code
TypeCode() const1512 BParameter::TypeCode() const
1513 {
1514 return B_MEDIA_PARAMETER_TYPE;
1515 }
1516
1517
1518 ssize_t
FlattenedSize() const1519 BParameter::FlattenedSize() const
1520 {
1521 CALLED();
1522 /*
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
1539 */
1540 //35 bytes are guaranteed, after that, add the variable length parts.
1541 ssize_t size = kAdditionalParameterSize;
1542
1543 if (fName != NULL)
1544 size += strlen(fName);
1545 if (fKind != NULL)
1546 size += strlen(fKind);
1547 if (fUnit != NULL)
1548 size += strlen(fUnit);
1549
1550 size += fInputs->CountItems() * sizeof(BParameter*);
1551 size += fOutputs->CountItems() * sizeof(BParameter*);
1552
1553 return size;
1554 }
1555
1556
1557 status_t
Flatten(void * buffer,ssize_t size) const1558 BParameter::Flatten(void* buffer, ssize_t size) const
1559 {
1560 CALLED();
1561
1562 if (buffer == NULL) {
1563 ERROR("BParameter::Flatten buffer is NULL\n");
1564 return B_NO_INIT;
1565 }
1566
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;
1573 }
1574
1575 write_to_buffer<uint32>(&buffer, kParameterMagic);
1576 write_to_buffer<ssize_t>(&buffer, actualSize);
1577 write_to_buffer<int32>(&buffer, fID);
1578
1579 write_string_to_buffer(&buffer, fName);
1580 write_string_to_buffer(&buffer, fKind);
1581 write_string_to_buffer(&buffer, fUnit);
1582
1583 // flatten and write the list of inputs
1584 ssize_t count = fInputs->CountItems();
1585 write_to_buffer<ssize_t>(&buffer, count);
1586
1587 if (count > 0) {
1588 memcpy(buffer, fInputs->Items(), sizeof(BParameter*) * count);
1589 skip_in_buffer(&buffer, sizeof(BParameter*) * count);
1590 }
1591
1592 // flatten and write the list of outputs
1593 count = fOutputs->CountItems();
1594 write_to_buffer<ssize_t>(&buffer, count);
1595
1596 if (count > 0) {
1597 memcpy(buffer, fOutputs->Items(), sizeof(BParameter*) * count);
1598 skip_in_buffer(&buffer, sizeof(BParameter*) * count);
1599 }
1600
1601 write_to_buffer<media_type>(&buffer, fMediaType);
1602 write_to_buffer<int32>(&buffer, fChannels);
1603 write_to_buffer<uint32>(&buffer, fFlags);
1604
1605 return B_OK;
1606 }
1607
1608
1609 bool
AllowsTypeCode(type_code code) const1610 BParameter::AllowsTypeCode(type_code code) const
1611 {
1612 return code == TypeCode();
1613 }
1614
1615
1616 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)1617 BParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
1618 {
1619 CALLED();
1620
1621 if (!AllowsTypeCode(code)) {
1622 ERROR("BParameter::Unflatten(): wrong type code\n");
1623 return B_BAD_TYPE;
1624 }
1625
1626 if (buffer == NULL) {
1627 ERROR("BParameter::Unflatten(): buffer is NULL\n");
1628 return B_NO_INIT;
1629 }
1630
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;
1636 }
1637
1638 const void* bufferStart = buffer;
1639
1640 // check magic
1641
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;
1650 }
1651
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;
1658 }
1659
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;
1677 }
1678
1679 fID = read_from_buffer_swap32<int32>(&buffer, fSwapDetected);
1680
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;
1688
1689 // read the list of inputs
1690
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()
1693
1694 ssize_t count = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1695 fSwapDetected);
1696
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));
1701 }
1702
1703 // read the list of outputs
1704
1705 count = read_pointer_from_buffer_swap<ssize_t>(&buffer, fSwapDetected);
1706
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));
1711 }
1712
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);
1716
1717 return B_OK;
1718 }
1719
1720
BParameter(int32 id,media_type mediaType,media_parameter_type type,BParameterWeb * web,const char * name,const char * kind,const char * unit)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)
1724 :
1725 fID(id),
1726 fType(type),
1727 fWeb(web),
1728 fGroup(NULL),
1729 fSwapDetected(true),
1730 fMediaType(mediaType),
1731 fChannels(1),
1732 fFlags(0)
1733 {
1734 CALLED();
1735
1736 fName = strndup(name, 255);
1737 fKind = strndup(kind, 255);
1738 fUnit = strndup(unit, 255);
1739
1740 // create empty input/output lists
1741 fInputs = new BList();
1742 fOutputs = new BList();
1743 }
1744
1745
~BParameter()1746 BParameter::~BParameter()
1747 {
1748 CALLED();
1749
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
1753
1754 free(fName);
1755 free(fKind);
1756 free(fUnit);
1757
1758 delete fInputs;
1759 delete fOutputs;
1760 }
1761
1762
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().
1767 */
1768 void
FixRefs(BList & old,BList & updated)1769 BParameter::FixRefs(BList& old, BList& updated)
1770 {
1771 CALLED();
1772
1773 // update inputs
1774
1775 void** items = static_cast<void**>(fInputs->Items());
1776 int32 count = fInputs->CountItems();
1777
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;
1785 }
1786 }
1787
1788 // remove all NULL inputs (those which couldn't be mapped)
1789
1790 for (int32 i = count; i-- > 0;) {
1791 if (items[i] == NULL)
1792 fInputs->RemoveItem(i);
1793 }
1794
1795 // update outputs
1796
1797 items = static_cast<void **>(fOutputs->Items());
1798 count = fOutputs->CountItems();
1799
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;
1807 }
1808 }
1809
1810 // remove all NULL outputs (those which couldn't be mapped)
1811
1812 for (int32 i = count; i-- > 0;) {
1813 if (items[i] == NULL)
1814 fOutputs->RemoveItem(i);
1815 }
1816 }
1817
1818
1819 // #pragma mark - public BContinuousParameter
1820
1821
1822 type_code
ValueType()1823 BContinuousParameter::ValueType()
1824 {
1825 return B_FLOAT_TYPE;
1826 }
1827
1828
1829 float
MinValue()1830 BContinuousParameter::MinValue()
1831 {
1832 return fMinimum;
1833 }
1834
1835
1836 float
MaxValue()1837 BContinuousParameter::MaxValue()
1838 {
1839 return fMaximum;
1840 }
1841
1842
1843 float
ValueStep()1844 BContinuousParameter::ValueStep()
1845 {
1846 return fStepping;
1847 }
1848
1849
1850 void
SetResponse(int resp,float factor,float offset)1851 BContinuousParameter::SetResponse(int resp, float factor, float offset)
1852 {
1853 fResponse = static_cast<response>(resp);
1854 fFactor = factor;
1855 fOffset = offset;
1856 }
1857
1858
1859 void
GetResponse(int * _resp,float * _factor,float * _offset)1860 BContinuousParameter::GetResponse(int* _resp, float* _factor, float* _offset)
1861 {
1862 if (_resp != NULL)
1863 *_resp = fResponse;
1864 if (_factor != NULL)
1865 *_factor = fFactor;
1866 if (_offset != NULL)
1867 *_offset = fOffset;
1868 }
1869
1870
1871 ssize_t
FlattenedSize() const1872 BContinuousParameter::FlattenedSize() const
1873 {
1874 CALLED();
1875
1876 // only adds a fixed amount of bytes
1877 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize;
1878 }
1879
1880
1881 status_t
Flatten(void * buffer,ssize_t size) const1882 BContinuousParameter::Flatten(void* buffer, ssize_t size) const
1883 {
1884 CALLED();
1885
1886 if (buffer == NULL) {
1887 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n");
1888 return B_NO_INIT;
1889 }
1890
1891 ssize_t parameterSize = BParameter::FlattenedSize();
1892 if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
1893 ERROR("BContinuousParameter::Flatten(): size to small\n");
1894 return B_NO_MEMORY;
1895 }
1896
1897 status_t status = BParameter::Flatten(buffer, size);
1898 if (status != B_OK) {
1899 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n");
1900 return status;
1901 }
1902
1903 // add our data to the general flattened BParameter
1904
1905 skip_in_buffer(&buffer, parameterSize);
1906
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);
1913
1914 return B_OK;
1915 }
1916
1917
1918 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)1919 BContinuousParameter::Unflatten(type_code code, const void* buffer,
1920 ssize_t size)
1921 {
1922 CALLED();
1923
1924 // we try to check if the buffer size is long enough to hold an object
1925 // as early as possible.
1926
1927 if (!AllowsTypeCode(code)) {
1928 ERROR("BContinuousParameter::Unflatten wrong type code\n");
1929 return B_BAD_TYPE;
1930 }
1931
1932 if (buffer == NULL) {
1933 ERROR("BContinuousParameter::Unflatten buffer is NULL\n");
1934 return B_NO_INIT;
1935 }
1936
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;
1942 }
1943
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;
1949 }
1950
1951 ssize_t parameterSize = BParameter::FlattenedSize();
1952 skip_in_buffer(&buffer, parameterSize);
1953
1954 if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
1955 ERROR("BContinuousParameter::Unflatten(): buffer too small\n");
1956 return B_BAD_VALUE;
1957 }
1958
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());
1965
1966 return B_OK;
1967 }
1968
1969
BContinuousParameter(int32 id,media_type mediaType,BParameterWeb * web,const char * name,const char * kind,const char * unit,float minimum,float maximum,float stepping)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)
1980 {
1981 CALLED();
1982 }
1983
1984
~BContinuousParameter()1985 BContinuousParameter::~BContinuousParameter()
1986 {
1987 CALLED();
1988 }
1989
1990
1991 // #pragma mark - public BDiscreteParameter
1992
1993
1994 type_code
ValueType()1995 BDiscreteParameter::ValueType()
1996 {
1997 return B_INT32_TYPE;
1998 }
1999
2000
2001 int32
CountItems()2002 BDiscreteParameter::CountItems()
2003 {
2004 return fValues->CountItems();
2005 }
2006
2007
2008 const char*
ItemNameAt(int32 index)2009 BDiscreteParameter::ItemNameAt(int32 index)
2010 {
2011 return reinterpret_cast<const char*>(fSelections->ItemAt(index));
2012 }
2013
2014
2015 int32
ItemValueAt(int32 index)2016 BDiscreteParameter::ItemValueAt(int32 index)
2017 {
2018 int32* item = static_cast<int32*>(fValues->ItemAt(index));
2019 if (item == NULL)
2020 return 0;
2021
2022 return *item;
2023 }
2024
2025
2026 status_t
AddItem(int32 value,const char * name)2027 BDiscreteParameter::AddItem(int32 value, const char* name)
2028 {
2029 CALLED();
2030
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;
2038 }
2039
2040 if (!fValues->AddItem(valueCopy))
2041 goto err;
2042 if (!fSelections->AddItem(nameCopy)) {
2043 fValues->RemoveItem(valueCopy);
2044 goto err;
2045 }
2046 return B_OK;
2047
2048 err:
2049 free(nameCopy);
2050 delete valueCopy;
2051 return B_NO_MEMORY;
2052 }
2053
2054
2055 status_t
MakeItemsFromInputs()2056 BDiscreteParameter::MakeItemsFromInputs()
2057 {
2058 CALLED();
2059
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());
2064 }
2065
2066 return B_OK;
2067 }
2068
2069
2070 status_t
MakeItemsFromOutputs()2071 BDiscreteParameter::MakeItemsFromOutputs()
2072 {
2073 CALLED();
2074
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());
2079 }
2080
2081 return B_OK;
2082 }
2083
2084
2085 void
MakeEmpty()2086 BDiscreteParameter::MakeEmpty()
2087 {
2088 CALLED();
2089
2090 for (int32 i = fValues->CountItems(); i-- > 0;) {
2091 delete static_cast<int32*>(fValues->ItemAt(i));
2092 }
2093 fValues->MakeEmpty();
2094
2095 for (int32 i = fSelections->CountItems(); i-- > 0;) {
2096 free(static_cast<char*>(fSelections->ItemAt(i)));
2097 }
2098 fSelections->MakeEmpty();
2099 }
2100
2101
2102 ssize_t
FlattenedSize() const2103 BDiscreteParameter::FlattenedSize() const
2104 {
2105 CALLED();
2106
2107 ssize_t size = BParameter::FlattenedSize()
2108 + kAdditionalDiscreteParameterSize;
2109
2110 int32 count = fValues->CountItems();
2111 for (int32 i = 0; i < count; i++) {
2112 char* selection = static_cast<char*>(fSelections->ItemAt(i));
2113
2114 if (selection != NULL)
2115 size += min_c(strlen(selection), 255);
2116
2117 size += 5;
2118 // string length + value
2119 }
2120
2121 return size;
2122 }
2123
2124
2125 status_t
Flatten(void * buffer,ssize_t size) const2126 BDiscreteParameter::Flatten(void* buffer, ssize_t size) const
2127 {
2128 CALLED();
2129
2130 if (buffer == NULL) {
2131 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n");
2132 return B_NO_INIT;
2133 }
2134
2135 ssize_t parameterSize = BParameter::FlattenedSize();
2136
2137 if (size < FlattenedSize()) {
2138 ERROR("BDiscreteParameter::Flatten(): size too small\n");
2139 return B_NO_MEMORY;
2140 }
2141
2142 status_t status = BParameter::Flatten(buffer, size);
2143 if (status != B_OK) {
2144 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n");
2145 return status;
2146 }
2147
2148 skip_in_buffer(&buffer, parameterSize);
2149
2150 int32 count = fValues->CountItems();
2151 write_to_buffer<int32>(&buffer, count);
2152
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));
2157
2158 write_string_to_buffer(&buffer, selection);
2159 write_to_buffer<int32>(&buffer, value ? *value : 0);
2160 }
2161
2162 return B_OK;
2163 }
2164
2165
2166 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)2167 BDiscreteParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2168 {
2169 CALLED();
2170
2171 if (!AllowsTypeCode(code)) {
2172 ERROR("BDiscreteParameter::Unflatten(): bad type code\n");
2173 return B_BAD_TYPE;
2174 }
2175
2176 if (buffer == NULL) {
2177 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n");
2178 return B_NO_INIT;
2179 }
2180
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;
2186 }
2187
2188 const void* bufferStart = buffer;
2189
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;
2194 }
2195
2196 ssize_t parameterSize = BParameter::FlattenedSize();
2197 skip_in_buffer(&buffer, parameterSize);
2198
2199 if (size < (parameterSize + kAdditionalDiscreteParameterSize)) {
2200 ERROR("BDiscreteParameter::Unflatten(): buffer too small\n");
2201 return B_BAD_VALUE;
2202 }
2203
2204 int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten());
2205
2206 // clear any existing name/value pairs
2207 MakeEmpty();
2208
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;
2214
2215 if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) {
2216 free(name);
2217 return B_BAD_DATA;
2218 }
2219
2220 int32 value = read_from_buffer_swap32<int32>(&buffer,
2221 SwapOnUnflatten());
2222
2223 AddItem(value, name);
2224 free(name);
2225 }
2226
2227 return B_OK;
2228 }
2229
2230
BDiscreteParameter(int32 id,media_type mediaType,BParameterWeb * web,const char * name,const char * kind)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)
2234 {
2235 CALLED();
2236
2237 fSelections = new BList();
2238 fValues = new BList();
2239 }
2240
2241
~BDiscreteParameter()2242 BDiscreteParameter::~BDiscreteParameter()
2243 {
2244 CALLED();
2245
2246 MakeEmpty();
2247
2248 delete fSelections;
2249 delete fValues;
2250 }
2251
2252
2253 // #pragma mark - public BTextParameter
2254
2255
2256 size_t
MaxBytes() const2257 BTextParameter::MaxBytes() const
2258 {
2259 return fMaxBytes;
2260 }
2261
2262
2263 type_code
ValueType()2264 BTextParameter::ValueType()
2265 {
2266 return B_FLOAT_TYPE;
2267 }
2268
2269
2270 ssize_t
FlattenedSize() const2271 BTextParameter::FlattenedSize() const
2272 {
2273 return BParameter::FlattenedSize() + sizeof(fMaxBytes);
2274 }
2275
2276
2277 status_t
Flatten(void * buffer,ssize_t size) const2278 BTextParameter::Flatten(void* buffer, ssize_t size) const
2279 {
2280 if (buffer == NULL) {
2281 ERROR("BTextParameter::Flatten(): buffer is NULL\n");
2282 return B_NO_INIT;
2283 }
2284
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;
2289 }
2290
2291 status_t status = BParameter::Flatten(buffer, size);
2292 if (status != B_OK) {
2293 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n");
2294 return status;
2295 }
2296
2297 // add our data to the general flattened BParameter
2298
2299 skip_in_buffer(&buffer, parameterSize);
2300
2301 write_to_buffer<uint32>(&buffer, fMaxBytes);
2302
2303 return B_OK;
2304 }
2305
2306
2307 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)2308 BTextParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2309 {
2310 // we try to check if the buffer size is long enough to hold an object
2311 // as early as possible.
2312
2313 if (!AllowsTypeCode(code)) {
2314 ERROR("BTextParameter::Unflatten wrong type code\n");
2315 return B_BAD_TYPE;
2316 }
2317
2318 if (buffer == NULL) {
2319 ERROR("BTextParameter::Unflatten buffer is NULL\n");
2320 return B_NO_INIT;
2321 }
2322
2323 if (size < static_cast<ssize_t>(sizeof(fMaxBytes))) {
2324 ERROR("BTextParameter::Unflatten size too small\n");
2325 return B_ERROR;
2326 }
2327
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;
2332 }
2333
2334 ssize_t parameterSize = BParameter::FlattenedSize();
2335 skip_in_buffer(&buffer, parameterSize);
2336
2337 if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
2338 ERROR("BTextParameter::Unflatten(): buffer too small\n");
2339 return B_BAD_VALUE;
2340 }
2341
2342 fMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten());
2343
2344 return B_OK;
2345 }
2346
2347
BTextParameter(int32 id,media_type mediaType,BParameterWeb * web,const char * name,const char * kind,size_t maxBytes)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)
2352 {
2353 fMaxBytes = maxBytes;
2354 }
2355
2356
~BTextParameter()2357 BTextParameter::~BTextParameter()
2358 {
2359 }
2360
2361
2362 // #pragma mark - public BNullParameter
2363
2364
2365 type_code
ValueType()2366 BNullParameter::ValueType()
2367 {
2368 // NULL parameters have no value type
2369 return 0;
2370 }
2371
2372
2373 ssize_t
FlattenedSize() const2374 BNullParameter::FlattenedSize() const
2375 {
2376 return BParameter::FlattenedSize();
2377 }
2378
2379
2380 status_t
Flatten(void * buffer,ssize_t size) const2381 BNullParameter::Flatten(void* buffer, ssize_t size) const
2382 {
2383 return BParameter::Flatten(buffer, size);
2384 }
2385
2386
2387 status_t
Unflatten(type_code code,const void * buffer,ssize_t size)2388 BNullParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2389 {
2390 return BParameter::Unflatten(code, buffer, size);
2391 }
2392
2393
BNullParameter(int32 id,media_type mediaType,BParameterWeb * web,const char * name,const char * kind)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)
2397 {
2398 }
2399
2400
~BNullParameter()2401 BNullParameter::~BNullParameter()
2402 {
2403 }
2404
2405
2406 // #pragma mark - reserved functions
2407
2408
_Reserved_ControlWeb_0(void *)2409 status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; }
_Reserved_ControlWeb_1(void *)2410 status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; }
_Reserved_ControlWeb_2(void *)2411 status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; }
_Reserved_ControlWeb_3(void *)2412 status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; }
_Reserved_ControlWeb_4(void *)2413 status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; }
_Reserved_ControlWeb_5(void *)2414 status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; }
_Reserved_ControlWeb_6(void *)2415 status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; }
_Reserved_ControlWeb_7(void *)2416 status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; }
2417
_Reserved_ControlGroup_0(void *)2418 status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; }
_Reserved_ControlGroup_1(void *)2419 status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; }
_Reserved_ControlGroup_2(void *)2420 status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; }
_Reserved_ControlGroup_3(void *)2421 status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; }
_Reserved_ControlGroup_4(void *)2422 status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; }
_Reserved_ControlGroup_5(void *)2423 status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; }
_Reserved_ControlGroup_6(void *)2424 status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; }
_Reserved_ControlGroup_7(void *)2425 status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; }
2426
_Reserved_Control_0(void *)2427 status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; }
_Reserved_Control_1(void *)2428 status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; }
_Reserved_Control_2(void *)2429 status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; }
_Reserved_Control_3(void *)2430 status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; }
_Reserved_Control_4(void *)2431 status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; }
_Reserved_Control_5(void *)2432 status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; }
_Reserved_Control_6(void *)2433 status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; }
_Reserved_Control_7(void *)2434 status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; }
2435
_Reserved_ContinuousParameter_0(void *)2436 status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; }
_Reserved_ContinuousParameter_1(void *)2437 status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; }
_Reserved_ContinuousParameter_2(void *)2438 status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; }
_Reserved_ContinuousParameter_3(void *)2439 status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; }
_Reserved_ContinuousParameter_4(void *)2440 status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; }
_Reserved_ContinuousParameter_5(void *)2441 status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; }
_Reserved_ContinuousParameter_6(void *)2442 status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; }
_Reserved_ContinuousParameter_7(void *)2443 status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; }
2444
_Reserved_DiscreteParameter_0(void *)2445 status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; }
_Reserved_DiscreteParameter_1(void *)2446 status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; }
_Reserved_DiscreteParameter_2(void *)2447 status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; }
_Reserved_DiscreteParameter_3(void *)2448 status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; }
_Reserved_DiscreteParameter_4(void *)2449 status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; }
_Reserved_DiscreteParameter_5(void *)2450 status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; }
_Reserved_DiscreteParameter_6(void *)2451 status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; }
_Reserved_DiscreteParameter_7(void *)2452 status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; }
2453
_Reserved_NullParameter_0(void *)2454 status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; }
_Reserved_NullParameter_1(void *)2455 status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; }
_Reserved_NullParameter_2(void *)2456 status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; }
_Reserved_NullParameter_3(void *)2457 status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; }
_Reserved_NullParameter_4(void *)2458 status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; }
_Reserved_NullParameter_5(void *)2459 status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; }
_Reserved_NullParameter_6(void *)2460 status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; }
_Reserved_NullParameter_7(void *)2461 status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; }
2462
_Reserved_TextParameter_0(void *)2463 status_t BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR; }
_Reserved_TextParameter_1(void *)2464 status_t BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR; }
_Reserved_TextParameter_2(void *)2465 status_t BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR; }
_Reserved_TextParameter_3(void *)2466 status_t BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR; }
_Reserved_TextParameter_4(void *)2467 status_t BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR; }
_Reserved_TextParameter_5(void *)2468 status_t BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR; }
_Reserved_TextParameter_6(void *)2469 status_t BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR; }
_Reserved_TextParameter_7(void *)2470 status_t BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR; }
2471