1 /* ParameterWeb - implements the following classes: 2 ** BParameterWeb, BParameterGroup, BParameter, BNullParameter, 3 ** BContinuousParameter, BDiscreteParameter 4 ** 5 ** Author: Zousar Shaker 6 ** Axel Dörfler, axeld@pinc-software.de 7 ** Marcus Overhagen 8 ** 9 ** This file may be used under the terms of the OpenBeOS License. 10 */ 11 12 13 #include <ParameterWeb.h> 14 #include <MediaNode.h> 15 #include <string.h> 16 #include "DataExchange.h" 17 #include "MediaMisc.h" 18 19 20 #include "debug.h" 21 22 23 /* 24 The following is documentation on the flattened format 25 of structures/classes in this module: 26 27 //--------BEGIN-CORE-BPARAMETER-STRUCT--------------------- 28 ?? (0x02040607): 4 bytes 29 BParameter Struct Size (in bytes): 4 bytes 30 ID: 4 bytes 31 Name String Length: 1 byte (??) 32 Name String: 'Name String Length' bytes 33 Kind String Length: 1 byte (??) 34 Kind String: 'Kind String Length' bytes 35 Unit String Length: 1 byte (??) 36 Unit String: 'Unit String Length' bytes 37 Inputs Count: 4 bytes 38 Inputs (pointers): ('Inputs Count')*4 bytes 39 Outputs Count: 4 bytes 40 Outputs (pointers): ('Outputs Count')*4 bytes 41 Media Type: 4 bytes 42 ChannelCount: 4 bytes 43 Flags: 4 bytes 44 //---------END-CORE-BPARAMETER-STRUCT----------------------- 45 //--------BEGIN-BCONTINUOUSPARAMETER-STRUCT--------- 46 Min: 4 bytes (as float) 47 Max: 4 bytes (as float) 48 Stepping: 4 bytes (as float) 49 Response: 4 bytes (as int or enum) 50 Factor: 4 bytes (as float) 51 Offset: 4 bytes (as float) 52 //--------END-BCONTINUOUSPARAMETER-STRUCT------------- 53 //--------BEGIN-BDISCRETEPARAMETER-STRUCT---------------- 54 NumItems: 4 bytes (as int) 55 //for each item BEGIN 56 Item Name String Length: 1 byte 57 Item Name String: 'Item Name String Length' bytes 58 Item Value: 4 bytes (as int) 59 //for each item END 60 //--------END-BDISCRETEPARAMETER-STRUCT------------------- 61 62 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT----------- 63 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes 64 (possible) Flags: 4 bytes 65 Name String Length: 1 byte (??) 66 Name String: 'Name String Length' bytes 67 Param Count: 4 bytes 68 //for each Param BEGIN 69 Pointer: 4 bytes 70 Parameter Type: 4 bytes 71 Flattened Parameter Size: 4 bytes 72 Flattened Parameter: 'Flattened Parameter Size' bytes 73 //for each Param END 74 Subgroup Count: 4 bytes 75 //for each SubGroup BEGIN 76 Pointer: 4 bytes 77 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes 78 Flattened Group Size: 4 bytes 79 Flattened Group: 'Flattened Group Size' bytes 80 //for each SubGroup END 81 82 //---------END-CORE-BPARAMETERGROUP-STRUCT-------------- 83 84 //--------BEGIN-CORE-BPARAMETERWEB-STRUCT----------- 85 ?? 0x01030506: 4 bytes 86 ??: 4 bytes (is always 1) 87 Group Count: 4 bytes 88 Node (as media_node): 0x18 bytes (decimal 24 bytes) 89 //for each Group BEGIN 90 Flattened Group Size: 4 bytes 91 Flattened Group: 'Flattened Group Size' bytes 92 //for each Group END 93 //for each Group BEGIN 94 ??: 4 bytes (never get written to (holds uninitialized value)) 95 //for each Group END 96 //---------END-CORE-BPARAMETERWEB-STRUCT-------------- 97 98 */ 99 100 101 const char * const B_GENERIC = ""; 102 const char * const B_MASTER_GAIN = "Master"; 103 const char * const B_GAIN = "Gain"; 104 const char * const B_BALANCE = "Balance"; 105 const char * const B_FREQUENCY = "Frequency"; 106 const char * const B_LEVEL = "Level"; 107 const char * const B_SHUTTLE_SPEED = "Speed"; 108 const char * const B_CROSSFADE = "XFade"; 109 const char * const B_EQUALIZATION = "EQ"; 110 const char * const B_COMPRESSION = "Compression"; 111 const char * const B_QUALITY = "Quality"; 112 const char * const B_BITRATE = "Bitrate"; 113 const char * const B_GOP_SIZE = "GOPSize"; 114 const char * const B_MUTE = "Mute"; 115 const char * const B_ENABLE = "Enable"; 116 const char * const B_INPUT_MUX = "Input"; 117 const char * const B_OUTPUT_MUX = "Output"; 118 const char * const B_TUNER_CHANNEL = "Channel"; 119 const char * const B_TRACK = "Track"; 120 const char * const B_RECSTATE = "RecState"; 121 const char * const B_SHUTTLE_MODE = "Shuttle"; 122 const char * const B_RESOLUTION = "Resolution"; 123 const char * const B_COLOR_SPACE = "Colorspace"; 124 const char * const B_FRAME_RATE = "FrameRate"; 125 const char * const B_VIDEO_FORMAT = "VideoFormat"; 126 const char * const B_WEB_PHYSICAL_INPUT = "PhysInput"; 127 const char * const B_WEB_PHYSICAL_OUTPUT = "PhysOutput"; 128 const char * const B_WEB_ADC_CONVERTER = "ADC"; 129 const char * const B_WEB_DAC_CONVERTER = "DAC"; 130 const char * const B_WEB_LOGICAL_INPUT = "LogInput"; 131 const char * const B_WEB_LOGICAL_OUTPUT = "LogOutput"; 132 const char * const B_WEB_LOGICAL_BUS = "LogBus"; 133 const char * const B_WEB_BUFFER_INPUT = "DataInput"; 134 const char * const B_WEB_BUFFER_OUTPUT = "DataOutput"; 135 const char * const B_SIMPLE_TRANSPORT = "SimpleTransport"; 136 137 // Flattened data 138 139 static const int32 kCurrentParameterWebVersion = 1; 140 static const uint32 kParameterWebMagic = 0x01030506; 141 static const uint32 kBufferGroupMagic = 0x03040509; 142 static const uint32 kBufferGroupMagicNoFlags = 0x03040507; 143 static const uint32 kParameterMagic = 0x02040607; 144 145 static const ssize_t kAdditionalParameterGroupSize = 12; 146 static const ssize_t kAdditionalParameterSize = 35; 147 148 /* BContinuousParameter - FlattenedSize() fixed part 149 * Min: 4 bytes (as float) 150 * Max: 4 bytes (as float) 151 * Stepping: 4 bytes (as float) 152 * Response: 4 bytes (as int or enum) 153 * Factor: 4 bytes (as float) 154 * Offset: 4 bytes (as float) 155 */ 156 static const ssize_t kAdditionalContinuousParameterSize = 24; 157 static const ssize_t kAdditionalDiscreteParameterSize = sizeof(ssize_t); 158 159 160 // helper functions 161 162 163 template<class Type> Type 164 read_from_buffer(const void **_buffer) 165 { 166 const Type *typedBuffer = static_cast<const Type *>(*_buffer); 167 Type value = *typedBuffer; 168 169 typedBuffer++; 170 *_buffer = static_cast<const void *>(typedBuffer); 171 172 return value; 173 } 174 175 176 static status_t 177 read_string_from_buffer(const void **_buffer, char **_string, ssize_t size) 178 { 179 if (size < 1) 180 return B_BAD_VALUE; 181 182 const uint8 *buffer = static_cast<const uint8 *>(*_buffer); 183 uint8 length = *buffer++; 184 if (length > size - 1) 185 return B_BAD_VALUE; 186 187 char *string = (char *)malloc(length + 1); 188 if (string == NULL) 189 return B_NO_MEMORY; 190 191 memcpy(string, buffer, length); 192 string[length] = '\0'; 193 194 *_buffer = static_cast<const void *>(buffer + length); 195 *_string = string; 196 return B_OK; 197 } 198 199 200 // currently unused 201 #if 0 202 template<class Type> Type * 203 reserve_in_buffer(void **_buffer) 204 { 205 Type *typedBuffer = static_cast<Type *>(*_buffer); 206 207 *typedBuffer = 0; 208 typedBuffer++; 209 210 *_buffer = static_cast<void *>(typedBuffer); 211 } 212 #endif 213 214 template<class Type> void 215 write_to_buffer(void **_buffer, Type value) 216 { 217 Type *typedBuffer = static_cast<Type *>(*_buffer); 218 219 *typedBuffer = value; 220 typedBuffer++; 221 222 *_buffer = static_cast<void *>(typedBuffer); 223 } 224 225 226 void 227 write_string_to_buffer(void **_buffer, const char *string) 228 { 229 uint8 *buffer = static_cast<uint8 *>(*_buffer); 230 uint32 length = string ? strlen(string) : 0; 231 if (length > 255) 232 length = 255; 233 234 *buffer++ = static_cast<uint8>(length); 235 if (length) { 236 memcpy(buffer, string, length); 237 buffer += length; 238 } 239 240 *_buffer = static_cast<void *>(buffer); 241 } 242 243 244 static void 245 skip_in_buffer(const void **_buffer, uint32 bytes) 246 { 247 const uint8 *buffer = static_cast<const uint8 *>(*_buffer); 248 249 buffer += bytes; 250 251 *_buffer = static_cast<const void *>(buffer); 252 } 253 254 255 static void inline 256 skip_in_buffer(void **_buffer, uint32 bytes) 257 { 258 // This actually shouldn't be necessary, but I believe it's a 259 // bug in Be's gcc - it complains about "adds cv-quals without intervening `const'" 260 // when passing a "const void **" pointer as the first argument. 261 // Maybe I am just stupid, though -- axeld. 262 263 skip_in_buffer((const void **)_buffer, bytes); 264 } 265 266 267 template<class Type> Type 268 swap32(Type value, bool doSwap) 269 { 270 STATIC_ASSERT(sizeof(Type) == 4); 271 272 if (doSwap) 273 return (Type)B_SWAP_INT32((int32)value); 274 275 return value; 276 } 277 278 279 template<class Type> Type 280 read_from_buffer_swap32(const void **_buffer, bool doSwap) 281 { 282 return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap); 283 } 284 285 286 static inline ssize_t 287 size_left(ssize_t size, const void *bufferStart, const void *buffer) 288 { 289 return size - static_cast<ssize_t>((const uint8 *)buffer - (const uint8 *)bufferStart); 290 } 291 292 293 /** Copies the source string into a new buffer with the specified 294 * maximum size. This always includes a trailing zero byte. 295 * Returns NULL if the source string is either NULL or empty, or 296 * if there wasn't enough memory to allocate the buffer. 297 * The buffer returned is to be freed by the caller using free(). 298 */ 299 300 static char * 301 strndup(const char *source, size_t maxBufferSize) 302 { 303 if (source == NULL || source[0] == '\0') 304 return NULL; 305 306 uint32 size = strlen(source) + 1; 307 if (size > maxBufferSize) 308 size = maxBufferSize; 309 310 char *target = (char *)malloc(size); 311 if (target == NULL) 312 return NULL; 313 314 memcpy(target, source, size - 1); 315 target[size - 1] = '\0'; 316 317 return target; 318 } 319 320 321 // #pragma mark - 322 323 /************************************************************* 324 * public BParameterWeb 325 *************************************************************/ 326 327 328 BParameterWeb::BParameterWeb() 329 : mNode(media_node::null) // mNode is set in BControllable::SetParameterWeb() 330 { 331 CALLED(); 332 333 mGroups = new BList(); 334 335 mOldRefs = new BList(); 336 mNewRefs = new BList(); 337 338 ASSERT(mGroups != NULL && mOldRefs != NULL && mNewRefs != NULL); 339 } 340 341 342 BParameterWeb::~BParameterWeb() 343 { 344 CALLED(); 345 346 if (mGroups != NULL) { 347 for(int32 i = mGroups->CountItems(); i-- > 0;) { 348 delete static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 349 } 350 351 delete mGroups; 352 } 353 354 delete mOldRefs; 355 delete mNewRefs; 356 } 357 358 359 media_node 360 BParameterWeb::Node() 361 { 362 return mNode; 363 } 364 365 366 BParameterGroup * 367 BParameterWeb::MakeGroup(const char *name) 368 { 369 CALLED(); 370 ASSERT(mGroups != NULL); 371 372 BParameterGroup *group = new BParameterGroup(this, name); 373 mGroups->AddItem(group); 374 375 return group; 376 } 377 378 379 int32 380 BParameterWeb::CountGroups() 381 { 382 ASSERT(mGroups != NULL); 383 384 return mGroups->CountItems(); 385 } 386 387 388 BParameterGroup * 389 BParameterWeb::GroupAt(int32 index) 390 { 391 ASSERT(mGroups != NULL); 392 393 return static_cast<BParameterGroup *>(mGroups->ItemAt(index)); 394 } 395 396 397 int32 398 BParameterWeb::CountParameters() 399 { 400 CALLED(); 401 ASSERT(mGroups != NULL); 402 403 // Counts over all groups (and sub-groups) in the web. 404 // The "groups" list is used as count stack 405 406 BList groups(*mGroups); 407 int32 count = 0; 408 409 for (int32 i = 0; i < groups.CountItems(); i++) { 410 BParameterGroup *group = static_cast<BParameterGroup *>(groups.ItemAt(i)); 411 412 count += group->CountParameters(); 413 414 if (group->mGroups != NULL) 415 groups.AddList(group->mGroups); 416 } 417 418 return count; 419 } 420 421 422 BParameter * 423 BParameterWeb::ParameterAt(int32 index) 424 { 425 CALLED(); 426 ASSERT(mGroups != NULL); 427 428 // Iterates over all groups (and sub-groups) in the web. 429 // The "groups" list is used as iteration stack (breadth search style) 430 // Maintains the same order as the Be implementation 431 432 BList groups(*mGroups); 433 434 for (int32 i = 0; i < groups.CountItems(); i++) { 435 BParameterGroup *group = 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->mGroups != NULL) 444 groups.AddList(group->mGroups); 445 } 446 447 TRACE("*** could not find parameter at %ld (count = %ld)\n", index, CountParameters()); 448 return NULL; 449 } 450 451 452 bool 453 BParameterWeb::IsFixedSize() const 454 { 455 return false; 456 } 457 458 459 type_code 460 BParameterWeb::TypeCode() const 461 { 462 return B_MEDIA_PARAMETER_WEB_TYPE; 463 } 464 465 466 ssize_t 467 BParameterWeb::FlattenedSize() const 468 { 469 CALLED(); 470 471 /* 472 //--------BEGIN-CORE-BPARAMETERWEB-STRUCT----------- 473 ?? 0x01030506: 4 bytes 474 ??: 4 bytes (is always 1) 475 Group Count: 4 bytes 476 Node (as media_node): 0x18 bytes (decimal 24 bytes) 477 //for each Group BEGIN 478 Flattened Group Size: 4 bytes 479 Flattened Group: 'Flattened Group Size' bytes 480 //for each Group END 481 //for each Group BEGIN 482 ??: 4 bytes (never get written to (holds uninitialized value)) 483 //for each Group END 484 //---------END-CORE-BPARAMETERWEB-STRUCT-------------- 485 */ 486 //36 guaranteed bytes, variable after that. 487 ssize_t size = sizeof(int32) + 2*sizeof(int32) + sizeof(media_node); 488 489 for (int32 i = mGroups->CountItems(); i-- > 0;) { 490 BParameterGroup *group = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 491 if (group != NULL) { 492 size += 4 + group->FlattenedSize(); 493 // 4 bytes for the flattened size 494 } 495 } 496 497 return size; 498 } 499 500 501 status_t 502 BParameterWeb::Flatten(void *buffer, ssize_t size) const 503 { 504 CALLED(); 505 506 if (buffer == NULL) 507 return B_NO_INIT; 508 509 ssize_t actualSize = BParameterWeb::FlattenedSize(); 510 if (size < actualSize) 511 return B_NO_MEMORY; 512 513 void *bufferStart = buffer; 514 515 write_to_buffer<int32>(&buffer, kParameterWebMagic); 516 write_to_buffer<int32>(&buffer, kCurrentParameterWebVersion); 517 518 // flatten all groups into this buffer 519 520 int32 count = mGroups ? mGroups->CountItems() : 0; 521 write_to_buffer<int32>(&buffer, count); 522 523 write_to_buffer<media_node>(&buffer, mNode); 524 525 for (int32 i = 0; i < count; i++) { 526 BParameterGroup *group = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 527 if (group == NULL) { 528 ERROR("BParameterWeb::Flatten(): group is NULL\n"); 529 continue; 530 } 531 532 ssize_t groupSize = group->FlattenedSize(); 533 if (groupSize > size_left(size, bufferStart, buffer)) { 534 ERROR("BParameterWeb::Flatten(): buffer too small\n"); 535 return B_BAD_VALUE; 536 } 537 538 write_to_buffer<ssize_t>(&buffer, groupSize); 539 540 // write the flattened sub group 541 status_t status = group->Flatten(buffer, groupSize); 542 if (status < B_OK) 543 return status; 544 545 skip_in_buffer(&buffer, groupSize); 546 } 547 548 return B_OK; 549 } 550 551 552 bool 553 BParameterWeb::AllowsTypeCode(type_code code) const 554 { 555 return code == TypeCode(); 556 } 557 558 559 status_t 560 BParameterWeb::Unflatten(type_code code, const void *buffer, ssize_t size) 561 { 562 CALLED(); 563 564 if (!AllowsTypeCode(code)) { 565 ERROR("BParameterWeb::Unflatten(): wrong type code\n"); 566 return B_BAD_TYPE; 567 } 568 569 if (buffer == NULL) { 570 ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n"); 571 return B_NO_INIT; 572 } 573 574 // if the buffer is smaller than the size needed to read the 575 // signature field, the mystery field, the group count, and the Node, then there is a problem 576 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(int32) + sizeof(ssize_t) + sizeof(media_node)) ) 577 { 578 ERROR("BParameterWeb::Unflatten(): size to small\n"); 579 return B_ERROR; 580 } 581 582 const void *bufferStart = buffer; 583 584 uint32 magic = read_from_buffer<uint32>(&buffer); 585 bool isSwapped = false; 586 587 if (magic == B_SWAP_INT32(kParameterWebMagic)) { 588 isSwapped = true; 589 magic = B_SWAP_INT32(magic); 590 } 591 if (magic != kParameterWebMagic) 592 return B_BAD_DATA; 593 594 // Note, it's not completely sure that this field is the version 595 // information - but it doesn't seem to have another purpose 596 int32 version = read_from_buffer_swap32<int32>(&buffer, isSwapped); 597 if (version != kCurrentParameterWebVersion) { 598 ERROR("BParameterWeb::Unflatten(): wrong version %ld (%lx)?!\n", version, version); 599 return B_ERROR; 600 } 601 602 #if 0 603 if(mGroups != NULL) 604 { 605 for (int32 i = 0; i < mGroups->CountItems(); i++) 606 { 607 BParameterGroup *CurrentItem = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 608 if(CurrentItem != NULL) 609 { 610 delete CurrentItem; 611 } 612 } 613 mGroups->MakeEmpty(); 614 } 615 else 616 { 617 mGroups = new BList(); 618 } 619 #endif 620 621 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 622 623 mNode = read_from_buffer<media_node>(&buffer); 624 if (isSwapped) 625 swap_data(B_INT32_TYPE, &mNode, sizeof(media_node), B_SWAP_ALWAYS); 626 627 for (int32 i = 0; i < count; i++) { 628 ssize_t groupSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 629 if (groupSize > size_left(size, bufferStart, buffer)) { 630 ERROR("BParameterWeb::Unflatten(): buffer too small\n"); 631 return B_BAD_DATA; 632 } 633 634 BParameterGroup *group = new BParameterGroup(this, "unnamed"); 635 status_t status = group->Unflatten(group->TypeCode(), buffer, groupSize); 636 if (status < B_OK) { 637 ERROR("BParameterWeb::Unflatten(): unflatten group failed\n"); 638 delete group; 639 return status; 640 } 641 642 skip_in_buffer(&buffer, groupSize); 643 644 mGroups->AddItem(group); 645 } 646 647 // fix all references (ParameterAt() style) 648 649 if ((mOldRefs != NULL) && (mNewRefs != NULL)) { 650 BList groups(*mGroups); 651 652 for (int32 i = 0; i < groups.CountItems(); i++) { 653 BParameterGroup *group = static_cast<BParameterGroup *>(groups.ItemAt(i)); 654 655 for (int32 index = group->CountParameters(); index-- > 0;) { 656 BParameter *parameter = static_cast<BParameter *>(group->ParameterAt(index)); 657 658 parameter->FixRefs(*mOldRefs, *mNewRefs); 659 } 660 661 if (group->mGroups != NULL) 662 groups.AddList(group->mGroups); 663 } 664 665 mOldRefs->MakeEmpty(); 666 mNewRefs->MakeEmpty(); 667 } 668 669 return B_OK; 670 } 671 672 /************************************************************* 673 * private BParameterWeb 674 *************************************************************/ 675 676 /* 677 unimplemented 678 BParameterWeb::BParameterWeb(const BParameterWeb &clone) 679 BParameterWeb &BParameterWeb::operator=(const BParameterWeb &clone) 680 */ 681 682 683 void 684 BParameterWeb::AddRefFix(void *oldItem, void *newItem) 685 { 686 ASSERT(mOldRefs != NULL); 687 ASSERT(mNewRefs != NULL); 688 689 mOldRefs->AddItem(oldItem); 690 mNewRefs->AddItem(newItem); 691 } 692 693 694 // #pragma mark - 695 696 /************************************************************* 697 * private BParameterGroup 698 *************************************************************/ 699 700 701 BParameterGroup::BParameterGroup(BParameterWeb *web, const char *name) 702 : mWeb(web), 703 mFlags(0) 704 { 705 CALLED(); 706 TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web, name); 707 708 mName = strndup(name, 256); 709 710 mControls = new BList(); 711 mGroups = new BList(); 712 } 713 714 715 BParameterGroup::~BParameterGroup() 716 { 717 CALLED(); 718 719 if (mControls) { 720 BParameter **items = reinterpret_cast<BParameter **>(mControls->Items()); 721 for (int i = mControls->CountItems(); i-- > 0;) 722 delete items[i]; 723 724 delete mControls; 725 } 726 727 if (mGroups) { 728 BParameterGroup **items = reinterpret_cast<BParameterGroup **>(mGroups->Items()); 729 for (int i = mGroups->CountItems(); i-- > 0;) 730 delete items[i]; 731 732 delete mGroups; 733 } 734 735 free(mName); 736 } 737 738 /************************************************************* 739 * public BParameterGroup 740 *************************************************************/ 741 742 BParameterWeb * 743 BParameterGroup::Web() const 744 { 745 return mWeb; 746 } 747 748 749 const char * 750 BParameterGroup::Name() const 751 { 752 return mName; 753 } 754 755 756 void 757 BParameterGroup::SetFlags(uint32 flags) 758 { 759 mFlags = flags; 760 } 761 762 763 uint32 764 BParameterGroup::Flags() const 765 { 766 return mFlags; 767 } 768 769 770 BNullParameter * 771 BParameterGroup::MakeNullParameter(int32 id, media_type mediaType, const char *name, 772 const char *kind) 773 { 774 CALLED(); 775 ASSERT(mControls != NULL); 776 777 BNullParameter *parameter = new BNullParameter(id, mediaType, mWeb, name, kind); 778 parameter->mGroup = this; 779 mControls->AddItem(parameter); 780 781 return parameter; 782 } 783 784 785 BContinuousParameter * 786 BParameterGroup::MakeContinuousParameter(int32 id, media_type mediaType, 787 const char *name, const char *kind, const char *unit, 788 float minimum, float maximum, float stepping) 789 { 790 CALLED(); 791 ASSERT(mControls != NULL); 792 793 BContinuousParameter *parameter = new BContinuousParameter(id, mediaType, mWeb, 794 name, kind, unit, minimum, maximum, stepping); 795 796 parameter->mGroup = this; 797 mControls->AddItem(parameter); 798 799 return parameter; 800 } 801 802 803 BDiscreteParameter * 804 BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType, 805 const char *name, const char *kind) 806 { 807 CALLED(); 808 ASSERT(mControls != NULL); 809 810 BDiscreteParameter *parameter = new BDiscreteParameter(id, mediaType, mWeb, name, kind); 811 if (parameter == NULL) 812 return NULL; 813 814 parameter->mGroup = this; 815 mControls->AddItem(parameter); 816 817 return parameter; 818 } 819 820 821 BParameterGroup * 822 BParameterGroup::MakeGroup(const char *name) 823 { 824 CALLED(); 825 ASSERT(mGroups != NULL); 826 827 BParameterGroup *group = new BParameterGroup(mWeb, name); 828 if (group != NULL) 829 mGroups->AddItem(group); 830 831 return group; 832 } 833 834 835 int32 836 BParameterGroup::CountParameters() 837 { 838 ASSERT(mControls != NULL); 839 840 return mControls->CountItems(); 841 } 842 843 844 BParameter * 845 BParameterGroup::ParameterAt(int32 index) 846 { 847 ASSERT(mControls != NULL); 848 849 return static_cast<BParameter *>(mControls->ItemAt(index)); 850 } 851 852 853 int32 854 BParameterGroup::CountGroups() 855 { 856 ASSERT(mGroups != NULL); 857 858 return mGroups->CountItems(); 859 } 860 861 862 BParameterGroup * 863 BParameterGroup::GroupAt(int32 index) 864 { 865 ASSERT(mGroups != NULL); 866 867 return static_cast<BParameterGroup *>(mGroups->ItemAt(index)); 868 } 869 870 871 bool 872 BParameterGroup::IsFixedSize() const 873 { 874 return false; 875 } 876 877 878 type_code 879 BParameterGroup::TypeCode() const 880 { 881 return B_MEDIA_PARAMETER_GROUP_TYPE; 882 } 883 884 885 ssize_t 886 BParameterGroup::FlattenedSize() const 887 { 888 CALLED(); 889 ASSERT(mControls != NULL); 890 ASSERT(mGroups != NULL); 891 892 /* 893 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT----------- 894 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes 895 (possible) Flags: 4 bytes 896 Name String Length: 1 byte (??) 897 Name String: 'Name String Length' bytes 898 Param Count: 4 bytes 899 //for each Param BEGIN 900 Pointer: 4 bytes 901 Parameter Type: 4 bytes 902 Flattened Parameter Size: 4 bytes 903 Flattened Parameter: 'Flattened Parameter Size' bytes 904 //for each Param END 905 Subgroup Count: 4 bytes 906 //for each SubGroup BEGIN 907 Pointer: 4 bytes 908 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes 909 Flattened Group Size: 4 bytes 910 Flattened Group: 'Flattened Group Size' bytes 911 //for each SubGroup END 912 913 //---------END-CORE-BPARAMETERGROUP-STRUCT-------------- 914 */ 915 //13 guaranteed bytes, variable after that. 916 ssize_t size = 13; 917 918 if(mFlags != 0) 919 { 920 size += 4; 921 } 922 923 if(mName != NULL) 924 { 925 size += min_c(strlen(mName),255); 926 } 927 928 int i; 929 int limit; 930 931 limit = mControls->CountItems(); 932 for(i = 0; i < limit; i++) 933 { 934 BParameter *CurrentParameter = static_cast<BParameter *>(mControls->ItemAt(i)); 935 if(CurrentParameter != NULL) 936 { 937 //overhead for each parameter flattened 938 size += 16 + CurrentParameter->FlattenedSize(); 939 } 940 } 941 942 limit = mGroups->CountItems(); 943 for(i = 0; i < limit; i++) 944 { 945 BParameterGroup *CurrentGroup = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 946 if(CurrentGroup != NULL) 947 { 948 //overhead for each group flattened 949 size += 16 + CurrentGroup->FlattenedSize(); 950 } 951 } 952 953 return size; 954 } 955 956 957 status_t 958 BParameterGroup::Flatten(void *buffer, ssize_t size) const 959 { 960 CALLED(); 961 962 if (buffer == NULL) { 963 ERROR("BParameterGroup::Flatten buffer is NULL\n"); 964 return B_NO_INIT; 965 } 966 967 // NOTICE: It is important that this value is the size returned by 968 // BParameterGroup::FlattenedSize, not by a descendent's override of this method. 969 ssize_t actualSize = BParameterGroup::FlattenedSize(); 970 if (size < actualSize) { 971 ERROR("BParameterGroup::Flatten size to small\n"); 972 return B_NO_MEMORY; 973 } 974 975 if (mFlags != 0) { 976 write_to_buffer<int32>(&buffer, kBufferGroupMagic); 977 write_to_buffer<uint32>(&buffer, mFlags); 978 } else 979 write_to_buffer<int32>(&buffer, kBufferGroupMagicNoFlags); 980 981 write_string_to_buffer(&buffer, mName); 982 983 int32 count = mControls ? mControls->CountItems() : 0; 984 write_to_buffer<int32>(&buffer, count); 985 986 for (int32 i = 0; i < count; i++) { 987 BParameter *parameter = static_cast<BParameter *>(mControls->ItemAt(i)); 988 if (parameter == NULL) { 989 ERROR("BParameterGroup::Flatten(): NULL parameter\n"); 990 continue; 991 } 992 993 write_to_buffer<BParameter *>(&buffer, parameter); 994 write_to_buffer<BParameter::media_parameter_type>(&buffer, parameter->Type()); 995 996 // flatten parameter into this buffer 997 998 ssize_t parameterSize = parameter->FlattenedSize(); 999 write_to_buffer<ssize_t>(&buffer, parameterSize); 1000 1001 status_t status = parameter->Flatten(buffer, parameterSize); 1002 // we have only that much bytes left to write in this buffer 1003 if (status < B_OK) 1004 return status; 1005 1006 skip_in_buffer(&buffer, parameterSize); 1007 } 1008 1009 count = mGroups ? mGroups->CountItems() : 0; 1010 write_to_buffer<int32>(&buffer, count); 1011 1012 for (int32 i = 0; i < count; i++) { 1013 BParameterGroup *group = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 1014 if (group == NULL) { 1015 ERROR("BParameterGroup::Flatten(): NULL group\n"); 1016 continue; 1017 } 1018 1019 write_to_buffer<BParameterGroup *>(&buffer, group); 1020 write_to_buffer<type_code>(&buffer, group->TypeCode()); 1021 1022 // flatten sub group into this buffer 1023 1024 ssize_t groupSize = group->FlattenedSize(); 1025 write_to_buffer<ssize_t>(&buffer, groupSize); 1026 1027 status_t status = group->Flatten(buffer, groupSize); 1028 // we have only that much bytes left to write in this buffer 1029 if (status < B_OK) 1030 return status; 1031 1032 skip_in_buffer(&buffer, groupSize); 1033 } 1034 1035 return B_OK; 1036 } 1037 1038 1039 bool 1040 BParameterGroup::AllowsTypeCode(type_code code) const 1041 { 1042 return code == TypeCode(); 1043 } 1044 1045 1046 status_t 1047 BParameterGroup::Unflatten(type_code code, const void *buffer, ssize_t size) 1048 { 1049 CALLED(); 1050 1051 if (!AllowsTypeCode(code)) { 1052 ERROR("BParameterGroup::Unflatten() wrong type code\n"); 1053 return B_BAD_TYPE; 1054 } 1055 1056 if (buffer == NULL) { 1057 ERROR("BParameterGroup::Unflatten() buffer is NULL\n"); 1058 return B_NO_INIT; 1059 } 1060 1061 // if the buffer is smaller than the size needed to read the 1062 // signature field, then there is a problem 1063 if (size < static_cast<ssize_t>(sizeof(int32))) { 1064 ERROR("BParameterGroup::Unflatten() size to small\n"); 1065 return B_ERROR; 1066 } 1067 1068 const void *bufferStart = buffer; 1069 // used to compute the rest length of the buffer when needed 1070 1071 uint32 magic = read_from_buffer<uint32>(&buffer); 1072 bool isSwapped = false; 1073 1074 if (magic == B_SWAP_INT32(kBufferGroupMagic) 1075 || magic == B_SWAP_INT32(kBufferGroupMagicNoFlags)) { 1076 isSwapped = true; 1077 magic = B_SWAP_INT32(magic); 1078 } 1079 1080 if (magic == kBufferGroupMagic) 1081 mFlags = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1082 else if (magic == kBufferGroupMagicNoFlags) 1083 mFlags = 0; 1084 else 1085 return B_BAD_TYPE; 1086 1087 if (read_string_from_buffer(&buffer, &mName, 1088 size - static_cast<ssize_t>((uint8 *)buffer - (uint8 *)bufferStart)) < B_OK) 1089 return B_BAD_VALUE; 1090 1091 // Currently disabled since it's not really used -- axeld. 1092 #if 0 1093 //Clear all existing parameters/subgroups 1094 int i; 1095 if(mControls != NULL) 1096 { 1097 for(i = 0; i < mControls->CountItems(); i++) 1098 { 1099 BParameter *CurrentItem = static_cast<BParameter *>(mControls->ItemAt(i)); 1100 if(CurrentItem != NULL) 1101 { 1102 delete CurrentItem; 1103 } 1104 } 1105 mControls->MakeEmpty(); 1106 } 1107 else 1108 { 1109 mControls = new BList(); 1110 } 1111 1112 if(mGroups != NULL) 1113 { 1114 for(i = 0; i < mGroups->CountItems(); i++) 1115 { 1116 BParameterGroup *CurrentItem = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 1117 if(CurrentItem != NULL) 1118 { 1119 delete CurrentItem; 1120 } 1121 } 1122 mGroups->MakeEmpty(); 1123 } 1124 else 1125 { 1126 mGroups = new BList(); 1127 } 1128 #endif 1129 1130 // unflatten parameter list 1131 1132 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1133 if (count < 0 || count * kAdditionalParameterSize > size_left(size, bufferStart, buffer)) 1134 return B_BAD_VALUE; 1135 1136 for (int32 i = 0; i < count; i++) { 1137 // make sure we can read as many bytes 1138 if (size_left(size, bufferStart, buffer) < 12) 1139 return B_BAD_VALUE; 1140 1141 BParameter *oldPointer = read_from_buffer_swap32<BParameter *>(&buffer, isSwapped); 1142 BParameter::media_parameter_type mediaType = 1143 read_from_buffer_swap32<BParameter::media_parameter_type>(&buffer, isSwapped); 1144 1145 ssize_t parameterSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 1146 if (parameterSize > size_left(size, bufferStart, buffer)) 1147 return B_BAD_VALUE; 1148 1149 BParameter *parameter = MakeControl(mediaType); 1150 if (parameter == NULL) { 1151 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n"); 1152 return B_ERROR; 1153 } 1154 1155 status_t status = parameter->Unflatten(parameter->TypeCode(), buffer, parameterSize); 1156 if (status < B_OK) { 1157 ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n"); 1158 delete parameter; 1159 return status; 1160 } 1161 1162 skip_in_buffer(&buffer, parameterSize); 1163 1164 // add the item to the list 1165 parameter->mGroup = this; 1166 parameter->mWeb = mWeb; 1167 mControls->AddItem(parameter); 1168 1169 // add it's old pointer value to the RefFix list kept by the owner web 1170 if (mWeb != NULL) 1171 mWeb->AddRefFix(oldPointer, parameter); 1172 } 1173 1174 // unflatten sub groups 1175 1176 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1177 if (count < 0 || count * kAdditionalParameterGroupSize > size_left(size, bufferStart, buffer)) 1178 return B_BAD_VALUE; 1179 1180 for (int32 i = 0; i < count; i++) { 1181 // make sure we can read as many bytes 1182 if (size_left(size, bufferStart, buffer) < 12) 1183 return B_BAD_VALUE; 1184 1185 BParameterGroup *oldPointer = read_from_buffer_swap32<BParameterGroup *>(&buffer, isSwapped); 1186 type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped); 1187 1188 ssize_t groupSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 1189 if (groupSize > size_left(size, bufferStart, buffer)) 1190 return B_BAD_VALUE; 1191 1192 BParameterGroup *group = new BParameterGroup(mWeb, "sub-unnamed"); 1193 if (group == NULL) { 1194 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n"); 1195 return B_ERROR; 1196 } 1197 1198 status_t status = group->Unflatten(type, buffer, groupSize); 1199 if (status != B_OK) { 1200 ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n"); 1201 delete group; 1202 return status; 1203 } 1204 1205 skip_in_buffer(&buffer, groupSize); 1206 1207 mGroups->AddItem(group); 1208 1209 // add it's old pointer value to the RefFix list kept by the owner web 1210 if (mWeb != NULL) 1211 mWeb->AddRefFix(oldPointer, group); 1212 } 1213 1214 return B_OK; 1215 } 1216 1217 /************************************************************* 1218 * private BParameterGroup 1219 *************************************************************/ 1220 1221 /* 1222 // unimplemented 1223 BParameterGroup::BParameterGroup() 1224 BParameterGroup::BParameterGroup(const BParameterGroup &clone) 1225 BParameterGroup &BParameterGroup::operator=(const BParameterGroup &clone) 1226 */ 1227 1228 1229 /** Creates an uninitialized parameter of the specified type. 1230 * Unlike the BParameterGroup::MakeXXXParameter() type of methods, this 1231 * method does not add the parameter to this group automatically. 1232 */ 1233 1234 BParameter * 1235 BParameterGroup::MakeControl(int32 type) 1236 { 1237 CALLED(); 1238 1239 switch (type) { 1240 case BParameter::B_NULL_PARAMETER: 1241 return new BNullParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL); 1242 1243 case BParameter::B_DISCRETE_PARAMETER: 1244 return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL); 1245 1246 case BParameter::B_CONTINUOUS_PARAMETER: 1247 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, NULL, 0, 0, 0); 1248 1249 default: 1250 ERROR("BParameterGroup::MakeControl unknown type %ld\n", type); 1251 return NULL; 1252 } 1253 } 1254 1255 1256 // #pragma mark - 1257 1258 /************************************************************* 1259 * public BParameter 1260 *************************************************************/ 1261 1262 1263 BParameter::media_parameter_type 1264 BParameter::Type() const 1265 { 1266 return mType; 1267 } 1268 1269 1270 BParameterWeb * 1271 BParameter::Web() const 1272 { 1273 return mWeb; 1274 } 1275 1276 1277 BParameterGroup * 1278 BParameter::Group() const 1279 { 1280 return mGroup; 1281 } 1282 1283 1284 const char * 1285 BParameter::Name() const 1286 { 1287 return mName; 1288 } 1289 1290 1291 const char * 1292 BParameter::Kind() const 1293 { 1294 return mKind; 1295 } 1296 1297 1298 const char * 1299 BParameter::Unit() const 1300 { 1301 return mUnit; 1302 } 1303 1304 1305 int32 1306 BParameter::ID() const 1307 { 1308 return mID; 1309 } 1310 1311 1312 void 1313 BParameter::SetFlags(uint32 flags) 1314 { 1315 mFlags = flags; 1316 } 1317 1318 1319 uint32 1320 BParameter::Flags() const 1321 { 1322 return mFlags; 1323 } 1324 1325 1326 status_t 1327 BParameter::GetValue(void *buffer, size_t *_ioSize, bigtime_t *_when) 1328 { 1329 CALLED(); 1330 1331 if (buffer == NULL || _ioSize == NULL) 1332 return B_BAD_VALUE; 1333 1334 size_t ioSize = *_ioSize; 1335 if (ioSize <= 0) 1336 return B_NO_MEMORY; 1337 1338 if (mWeb == NULL) { 1339 ERROR("BParameter::GetValue: no parent BParameterWeb\n"); 1340 return B_NO_INIT; 1341 } 1342 1343 media_node node = mWeb->Node(); 1344 if (IS_INVALID_NODE(node)) { 1345 ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); 1346 return B_NO_INIT; 1347 } 1348 1349 controllable_get_parameter_data_request request; 1350 controllable_get_parameter_data_reply reply; 1351 1352 area_id area; 1353 void *data; 1354 if (ioSize > MAX_PARAMETER_DATA) { 1355 // create an area if large data needs to be transfered 1356 area = create_area("get parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(ioSize), 1357 B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1358 if (area < B_OK) { 1359 ERROR("BParameter::GetValue can't create area of %ld bytes\n", ioSize); 1360 return B_NO_MEMORY; 1361 } 1362 } else { 1363 area = -1; 1364 data = reply.rawdata; 1365 } 1366 1367 request.parameter_id = mID; 1368 request.requestsize = ioSize; 1369 request.area = area; 1370 1371 status_t status = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_DATA, &request, 1372 sizeof(request), &reply, sizeof(reply)); 1373 if (status == B_OK) { 1374 // we don't want to copy more than the buffer provides 1375 if (reply.size < ioSize) 1376 ioSize = reply.size; 1377 1378 memcpy(buffer, data, ioSize); 1379 1380 // store reported values 1381 1382 *_ioSize = reply.size; 1383 if (_when != NULL) 1384 *_when = reply.last_change; 1385 } else 1386 ERROR("BParameter::GetValue parameter '%s' querying node %d, port %d failed: %s\n", 1387 mName, node.node, node.port, strerror(status)); 1388 1389 if (area >= B_OK) 1390 delete_area(area); 1391 1392 return status; 1393 } 1394 1395 1396 status_t 1397 BParameter::SetValue(const void *buffer, size_t size, bigtime_t when) 1398 { 1399 CALLED(); 1400 1401 controllable_set_parameter_data_request request; 1402 controllable_set_parameter_data_reply reply; 1403 media_node node; 1404 area_id area; 1405 status_t rv; 1406 void *data; 1407 1408 if (buffer == 0) 1409 return B_BAD_VALUE; 1410 if (size <= 0) 1411 return B_NO_MEMORY; 1412 1413 if (mWeb == 0) { 1414 ERROR("BParameter::SetValue: no parent BParameterWeb\n"); 1415 return B_NO_INIT; 1416 } 1417 1418 node = mWeb->Node(); 1419 if (IS_INVALID_NODE(node)) { 1420 ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); 1421 return B_NO_INIT; 1422 } 1423 1424 if (size > MAX_PARAMETER_DATA) { 1425 // create an area if large data needs to be transfered 1426 area = create_area("set parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1427 if (area < B_OK) { 1428 ERROR("BParameter::SetValue can't create area of %ld bytes\n", size); 1429 return B_NO_MEMORY; 1430 } 1431 } else { 1432 area = -1; 1433 data = request.rawdata; 1434 } 1435 1436 memcpy(data, buffer, size); 1437 request.parameter_id = mID; 1438 request.when = when; 1439 request.area = area; 1440 request.size = size; 1441 1442 rv = QueryPort(node.port, CONTROLLABLE_SET_PARAMETER_DATA, &request, sizeof(request), &reply, sizeof(reply)); 1443 if (rv != B_OK) 1444 ERROR("BParameter::SetValue querying node failed\n"); 1445 1446 if (area != -1) 1447 delete_area(area); 1448 1449 return rv; 1450 } 1451 1452 1453 int32 1454 BParameter::CountChannels() 1455 { 1456 return mChannels; 1457 } 1458 1459 1460 void 1461 BParameter::SetChannelCount(int32 channel_count) 1462 { 1463 mChannels = channel_count; 1464 } 1465 1466 1467 media_type 1468 BParameter::MediaType() 1469 { 1470 return mMediaType; 1471 } 1472 1473 1474 void 1475 BParameter::SetMediaType(media_type m_type) 1476 { 1477 mMediaType = m_type; 1478 } 1479 1480 1481 int32 1482 BParameter::CountInputs() 1483 { 1484 ASSERT(mInputs != NULL); 1485 1486 return mInputs->CountItems(); 1487 } 1488 1489 1490 BParameter * 1491 BParameter::InputAt(int32 index) 1492 { 1493 ASSERT(mInputs != NULL); 1494 1495 return static_cast<BParameter *>(mInputs->ItemAt(index)); 1496 } 1497 1498 1499 void 1500 BParameter::AddInput(BParameter *input) 1501 { 1502 CALLED(); 1503 1504 // BeBook has this method returning a status value, 1505 // but it should be updated 1506 if (input == NULL) 1507 return; 1508 1509 ASSERT(mInputs != NULL); 1510 1511 if (mInputs->HasItem(input)) { 1512 // if already in input list, don't duplicate. 1513 return; 1514 } 1515 1516 mInputs->AddItem(input); 1517 input->AddOutput(this); 1518 } 1519 1520 1521 int32 1522 BParameter::CountOutputs() 1523 { 1524 ASSERT(mOutputs != NULL); 1525 1526 return mOutputs->CountItems(); 1527 } 1528 1529 1530 BParameter * 1531 BParameter::OutputAt(int32 index) 1532 { 1533 ASSERT(mOutputs != NULL); 1534 1535 return static_cast<BParameter *>(mOutputs->ItemAt(index)); 1536 } 1537 1538 1539 void 1540 BParameter::AddOutput(BParameter *output) 1541 { 1542 CALLED(); 1543 1544 // BeBook has this method returning a status value, 1545 // but it should be updated 1546 if (output == NULL) 1547 return; 1548 1549 ASSERT(mOutputs != NULL); 1550 1551 if (mOutputs->HasItem(output)) { 1552 // if already in output list, don't duplicate. 1553 return; 1554 } 1555 1556 mOutputs->AddItem(output); 1557 output->AddInput(this); 1558 } 1559 1560 1561 bool 1562 BParameter::IsFixedSize() const 1563 { 1564 return false; 1565 } 1566 1567 1568 type_code 1569 BParameter::TypeCode() const 1570 { 1571 return B_MEDIA_PARAMETER_TYPE; 1572 } 1573 1574 1575 ssize_t 1576 BParameter::FlattenedSize() const 1577 { 1578 CALLED(); 1579 /* 1580 ?? (0x02040607): 4 bytes 1581 BParameter Struct Size (in bytes): 4 bytes 1582 ID: 4 bytes 1583 Name String Length: 1 byte (??) 1584 Name String: 'Name String Length' bytes 1585 Kind String Length: 1 byte (??) 1586 Kind String: 'Kind String Length' bytes 1587 Unit String Length: 1 byte (??) 1588 Unit String: 'Unit String Length' bytes 1589 Inputs Count: 4 bytes 1590 Inputs (pointers): ('Inputs Count')*4 bytes 1591 Outputs Count: 4 bytes 1592 Outputs (pointers): ('Outputs Count')*4 bytes 1593 Media Type: 4 bytes 1594 ChannelCount: 4 bytes 1595 Flags: 4 bytes 1596 */ 1597 //35 bytes are guaranteed, after that, add the variable length parts. 1598 ssize_t size = 35; 1599 1600 if (mName != NULL) 1601 size += strlen(mName); 1602 if (mKind != NULL) 1603 size += strlen(mKind); 1604 if (mUnit != NULL) 1605 size += strlen(mUnit); 1606 1607 if (mInputs != NULL) 1608 size += mInputs->CountItems() * sizeof(BParameter *); 1609 1610 if (mOutputs != NULL) 1611 size += mOutputs->CountItems() * sizeof(BParameter *); 1612 1613 return size; 1614 } 1615 1616 1617 status_t 1618 BParameter::Flatten(void *buffer, ssize_t size) const 1619 { 1620 CALLED(); 1621 1622 if (buffer == NULL) { 1623 ERROR("BParameter::Flatten buffer is NULL\n"); 1624 return B_NO_INIT; 1625 } 1626 1627 // NOTICE: It is important that this value is the size returned by 1628 // BParameter::FlattenedSize(), not by a descendent's override of this method. 1629 ssize_t actualSize = BParameter::FlattenedSize(); 1630 if (size < actualSize) { 1631 ERROR("BParameter::Flatten(): size too small\n"); 1632 return B_NO_MEMORY; 1633 } 1634 1635 write_to_buffer<uint32>(&buffer, kParameterMagic); 1636 write_to_buffer<ssize_t>(&buffer, actualSize); 1637 write_to_buffer<int32>(&buffer, mID); 1638 1639 write_string_to_buffer(&buffer, mName); 1640 write_string_to_buffer(&buffer, mKind); 1641 write_string_to_buffer(&buffer, mUnit); 1642 1643 // flatten and write the list of inputs 1644 ssize_t count = mInputs ? mInputs->CountItems() : 0; 1645 write_to_buffer<ssize_t>(&buffer, count); 1646 1647 if (count > 0) { 1648 memcpy(buffer, mInputs->Items(), sizeof(BParameter *) * count); 1649 skip_in_buffer(&buffer, sizeof(BParameter *) * count); 1650 } 1651 1652 // flatten and write the list of outputs 1653 count = mOutputs ? mOutputs->CountItems() : 0; 1654 write_to_buffer<ssize_t>(&buffer, count); 1655 1656 if (count > 0) { 1657 memcpy(buffer, mOutputs->Items(), sizeof(BParameter *) * count); 1658 skip_in_buffer(&buffer, sizeof(BParameter *) * count); 1659 } 1660 1661 write_to_buffer<media_type>(&buffer, mMediaType); 1662 write_to_buffer<int32>(&buffer, mChannels); 1663 write_to_buffer<uint32>(&buffer, mFlags); 1664 1665 return B_OK; 1666 } 1667 1668 1669 bool 1670 BParameter::AllowsTypeCode(type_code code) const 1671 { 1672 return (code == TypeCode()); 1673 } 1674 1675 1676 status_t 1677 BParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 1678 { 1679 CALLED(); 1680 1681 if (!AllowsTypeCode(code)) { 1682 ERROR("BParameter::Unflatten(): wrong type code\n"); 1683 return B_BAD_TYPE; 1684 } 1685 1686 if (buffer == NULL) { 1687 ERROR("BParameter::Unflatten(): buffer is NULL\n"); 1688 return B_NO_INIT; 1689 } 1690 1691 // if the buffer is smaller than the size needed to read the 1692 // signature and struct size fields, then there is a problem 1693 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 1694 ERROR("BParameter::Unflatten() size too small\n"); 1695 return B_BAD_VALUE; 1696 } 1697 1698 const void *bufferStart = buffer; 1699 1700 // check magic 1701 1702 uint32 magic = read_from_buffer<uint32>(&buffer); 1703 if (magic == B_SWAP_INT32(kParameterMagic)) 1704 mSwapDetected = true; 1705 else if (magic == kParameterMagic) 1706 mSwapDetected = false; 1707 else { 1708 ERROR("BParameter::Unflatten(): bad magic\n"); 1709 return B_BAD_TYPE; 1710 } 1711 1712 ssize_t parameterSize = read_from_buffer_swap32<ssize_t>(&buffer, mSwapDetected); 1713 if (parameterSize > size) { 1714 ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n", parameterSize, size); 1715 return B_BAD_VALUE; 1716 } 1717 1718 //if the struct doesn't meet the minimum size for 1719 //a flattened BParameter, then return an error. 1720 //MinFlattenedParamSize = 1721 //ID (4 bytes) 1722 //Name String Length (1 byte) 1723 //Kind String Length (1 byte) 1724 //Unit String Length (1 byte) 1725 //Inputs Count (4 bytes) 1726 //Outputs Count (4 bytes) 1727 //Media Type (4 bytes) 1728 //Channel Count (4 bytes) 1729 //Flags (4 bytes) 1730 //TOTAL: 27 bytes 1731 const ssize_t MinFlattenedParamSize(27); 1732 if (parameterSize < MinFlattenedParamSize) { 1733 ERROR("BParameter::Unflatten out of memory (2)\n"); 1734 return B_ERROR; 1735 } 1736 1737 mID = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1738 1739 if (read_string_from_buffer(&buffer, &mName, size_left(size, bufferStart, buffer)) < B_OK 1740 || read_string_from_buffer(&buffer, &mKind, size_left(size, bufferStart, buffer)) < B_OK 1741 || read_string_from_buffer(&buffer, &mUnit, size_left(size, bufferStart, buffer)) < B_OK) 1742 return B_NO_MEMORY; 1743 1744 // read the list of inputs 1745 1746 // it will directly add the pointers in the flattened message to the list; 1747 // these will be fixed to point to the real inputs/outputs later in FixRefs() 1748 1749 int32 count = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1750 1751 if (mInputs == NULL) 1752 mInputs = new BList(); 1753 else 1754 mInputs->MakeEmpty(); 1755 1756 for (int32 i = 0; i < count; i++) { 1757 mInputs->AddItem(read_from_buffer_swap32<BParameter * const>(&buffer, mSwapDetected)); 1758 } 1759 1760 // read the list of outputs 1761 1762 count = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1763 1764 if (mOutputs == NULL) 1765 mOutputs = new BList(); 1766 else 1767 mOutputs->MakeEmpty(); 1768 1769 for (int32 i = 0; i < count; i++) { 1770 mOutputs->AddItem(read_from_buffer_swap32<BParameter * const>(&buffer, mSwapDetected)); 1771 } 1772 1773 mMediaType = read_from_buffer_swap32<media_type>(&buffer, mSwapDetected); 1774 mChannels = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1775 mFlags = read_from_buffer_swap32<uint32>(&buffer, mSwapDetected); 1776 1777 return B_OK; 1778 } 1779 1780 1781 /************************************************************* 1782 * private BParameter 1783 *************************************************************/ 1784 1785 1786 BParameter::BParameter(int32 id, media_type mediaType, media_parameter_type type, 1787 BParameterWeb *web, const char *name, const char *kind, const char *unit) 1788 : 1789 mID(id), 1790 mType(type), 1791 mWeb(web), 1792 mGroup(NULL), 1793 mSwapDetected(true), 1794 mMediaType(mediaType), 1795 mChannels(1), 1796 mFlags(0) 1797 { 1798 CALLED(); 1799 1800 mName = strndup(name, 256); 1801 mKind = strndup(kind, 256); 1802 mUnit = strndup(unit, 256); 1803 1804 // create empty input/output lists 1805 mInputs = new BList(); 1806 mOutputs = new BList(); 1807 } 1808 1809 1810 BParameter::~BParameter() 1811 { 1812 CALLED(); 1813 1814 // don't worry about the mWeb/mGroup properties, you don't need 1815 // to remove yourself from a web/group since the only way in which 1816 // a parameter is destroyed is when the owner web/group destroys it 1817 1818 free(mName); 1819 free(mKind); 1820 free(mUnit); 1821 1822 delete mInputs; 1823 delete mOutputs; 1824 1825 mName = NULL; mKind = NULL; mUnit = NULL; mInputs = NULL; mOutputs = NULL; 1826 } 1827 1828 1829 /** Replaces references to items in the old list with the corresponding 1830 * items in the updated list. The references are replaced in the input 1831 * and output lists. 1832 * This is called by BParameterWeb::Unflatten(). 1833 */ 1834 1835 void 1836 BParameter::FixRefs(BList &old, BList &updated) 1837 { 1838 CALLED(); 1839 ASSERT(mInputs != NULL); 1840 ASSERT(mOutputs != NULL); 1841 1842 // update inputs 1843 1844 void **items = static_cast<void **>(mInputs->Items()); 1845 int32 count = mInputs->CountItems(); 1846 1847 for (int32 i = 0; i < count; i++) { 1848 int32 index = old.IndexOf(items[i]); 1849 if (index >= 0) 1850 items[i] = updated.ItemAt(index); 1851 else { 1852 ERROR("BParameter::FixRefs(): No mapping found for input"); 1853 items[i] = NULL; 1854 } 1855 } 1856 1857 // remove all NULL inputs (those which couldn't be mapped) 1858 1859 for (int32 i = count; i-- > 0;) { 1860 if (items[i] == NULL) 1861 mInputs->RemoveItem(i); 1862 } 1863 1864 // update outputs 1865 1866 items = static_cast<void **>(mOutputs->Items()); 1867 count = mOutputs->CountItems(); 1868 1869 for (int32 i = 0; i < count; i++) { 1870 int32 index = old.IndexOf(items[i]); 1871 if (index >= 0) 1872 items[i] = updated.ItemAt(index); 1873 else { 1874 ERROR("BParameter::FixRefs(): No mapping found for output"); 1875 items[i] = NULL; 1876 } 1877 } 1878 1879 // remove all NULL outputs (those which couldn't be mapped) 1880 1881 for (int32 i = count; i-- > 0;) { 1882 if (items[i] == NULL) 1883 mOutputs->RemoveItem(i); 1884 } 1885 } 1886 1887 1888 // #pragma mark - 1889 1890 /************************************************************* 1891 * public BContinuousParameter 1892 *************************************************************/ 1893 1894 1895 type_code 1896 BContinuousParameter::ValueType() 1897 { 1898 return B_FLOAT_TYPE; 1899 } 1900 1901 1902 float 1903 BContinuousParameter::MinValue() 1904 { 1905 return mMinimum; 1906 } 1907 1908 1909 float 1910 BContinuousParameter::MaxValue() 1911 { 1912 return mMaximum; 1913 } 1914 1915 1916 float 1917 BContinuousParameter::ValueStep() 1918 { 1919 return mStepping; 1920 } 1921 1922 1923 void 1924 BContinuousParameter::SetResponse(int resp, float factor, float offset) 1925 { 1926 mResponse = static_cast<response>(resp); 1927 mFactor = factor; 1928 mOffset = offset; 1929 } 1930 1931 1932 void 1933 BContinuousParameter::GetResponse(int *resp, float *factor, float *offset) 1934 { 1935 if (resp != NULL) 1936 *resp = mResponse; 1937 if (factor != NULL) 1938 *factor = mFactor; 1939 if (offset != NULL) 1940 *offset = mOffset; 1941 } 1942 1943 1944 ssize_t 1945 BContinuousParameter::FlattenedSize() const 1946 { 1947 CALLED(); 1948 1949 // only adds a fixed amount of bytes 1950 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize; 1951 } 1952 1953 1954 status_t 1955 BContinuousParameter::Flatten(void *buffer, ssize_t size) const 1956 { 1957 CALLED(); 1958 1959 if (buffer == NULL) { 1960 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n"); 1961 return B_NO_INIT; 1962 } 1963 1964 ssize_t parameterSize = BParameter::FlattenedSize(); 1965 if (size < (parameterSize + kAdditionalContinuousParameterSize)) { 1966 ERROR("BContinuousParameter::Flatten(): size to small\n"); 1967 return B_NO_MEMORY; 1968 } 1969 1970 status_t status = BParameter::Flatten(buffer, size); 1971 if (status != B_OK) { 1972 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n"); 1973 return status; 1974 } 1975 1976 // add our data to the general flattened BParameter 1977 1978 skip_in_buffer(&buffer, parameterSize); 1979 1980 write_to_buffer<float>(&buffer, mMinimum); 1981 write_to_buffer<float>(&buffer, mMaximum); 1982 write_to_buffer<float>(&buffer, mStepping); 1983 write_to_buffer<response>(&buffer, mResponse); 1984 write_to_buffer<float>(&buffer, mFactor); 1985 write_to_buffer<float>(&buffer, mOffset); 1986 1987 return B_OK; 1988 } 1989 1990 1991 status_t 1992 BContinuousParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 1993 { 1994 CALLED(); 1995 1996 // we try to check if the buffer size is long enough to hold an object 1997 // as early as possible. 1998 1999 if (!AllowsTypeCode(code)) { 2000 ERROR("BContinuousParameter::Unflatten wrong type code\n"); 2001 return B_BAD_TYPE; 2002 } 2003 2004 if (buffer == NULL) { 2005 ERROR("BContinuousParameter::Unflatten buffer is NULL\n"); 2006 return B_NO_INIT; 2007 } 2008 2009 // if the buffer is smaller than the size needed to read the 2010 // signature and struct size fields, then there is a problem 2011 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 2012 ERROR("BContinuousParameter::Unflatten size too small\n"); 2013 return B_ERROR; 2014 } 2015 2016 status_t status = BParameter::Unflatten(code, buffer, size); 2017 if (status != B_OK) { 2018 ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten failed\n"); 2019 return status; 2020 } 2021 2022 ssize_t parameterSize = BParameter::FlattenedSize(); 2023 skip_in_buffer(&buffer, parameterSize); 2024 2025 if (size < (parameterSize + kAdditionalContinuousParameterSize)) { 2026 ERROR("BContinuousParameter::Unflatten(): buffer too small\n"); 2027 return B_BAD_VALUE; 2028 } 2029 2030 mMinimum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2031 mMaximum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2032 mStepping = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2033 mResponse = read_from_buffer_swap32<response>(&buffer, SwapOnUnflatten()); 2034 mFactor = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2035 mOffset = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2036 2037 return B_OK; 2038 } 2039 2040 2041 /************************************************************* 2042 * private BContinuousParameter 2043 *************************************************************/ 2044 2045 2046 BContinuousParameter::BContinuousParameter(int32 id, media_type m_type, 2047 BParameterWeb *web, const char *name, const char *kind, const char *unit, 2048 float minimum, float maximum, float stepping) 2049 : BParameter(id, m_type, B_CONTINUOUS_PARAMETER, web, name, kind, unit), 2050 mMinimum(minimum), mMaximum(maximum), mStepping(stepping), 2051 mResponse(B_LINEAR), mFactor(1.0), mOffset(0.0) 2052 { 2053 CALLED(); 2054 } 2055 2056 2057 BContinuousParameter::~BContinuousParameter() 2058 { 2059 CALLED(); 2060 } 2061 2062 2063 // #pragma mark - 2064 2065 /************************************************************* 2066 * public BDiscreteParameter 2067 *************************************************************/ 2068 2069 2070 type_code 2071 BDiscreteParameter::ValueType() 2072 { 2073 return B_INT32_TYPE; 2074 } 2075 2076 2077 int32 2078 BDiscreteParameter::CountItems() 2079 { 2080 ASSERT(mValues != NULL); 2081 2082 return mValues->CountItems(); 2083 } 2084 2085 2086 const char * 2087 BDiscreteParameter::ItemNameAt(int32 index) 2088 { 2089 ASSERT(mSelections != NULL); 2090 2091 return reinterpret_cast<const char *>(mSelections->ItemAt(index)); 2092 } 2093 2094 2095 int32 2096 BDiscreteParameter::ItemValueAt(int32 index) 2097 { 2098 ASSERT(mValues != NULL); 2099 2100 int32 *item = static_cast<int32 *>(mValues->ItemAt(index)); 2101 if (item == NULL) 2102 return 0; 2103 2104 return *item; 2105 } 2106 2107 2108 status_t 2109 BDiscreteParameter::AddItem(int32 value, const char *name) 2110 { 2111 CALLED(); 2112 //TRACE("\tthis = %p, value = %ld, name = \"%s\"\n", this, value, name); 2113 ASSERT(mValues != NULL); 2114 ASSERT(mSelections != NULL); 2115 2116 int32 *valueCopy = new int32(value); 2117 char *nameCopy = strndup(name, 256); 2118 if (name != NULL && nameCopy == NULL) 2119 return B_NO_MEMORY; 2120 2121 if (!mValues->AddItem(valueCopy) 2122 || !mSelections->AddItem(nameCopy)) 2123 return B_NO_MEMORY; 2124 2125 return B_OK; 2126 } 2127 2128 2129 status_t 2130 BDiscreteParameter::MakeItemsFromInputs() 2131 { 2132 CALLED(); 2133 ASSERT(mValues != NULL); 2134 ASSERT(mSelections != NULL); 2135 ASSERT(mInputs != NULL); 2136 2137 int32 count = mInputs->CountItems(); 2138 for(int32 i = 0; i < count; i++) { 2139 BParameter *parameter = static_cast<BParameter *>(mInputs->ItemAt(i)); 2140 AddItem(i, parameter->Name()); 2141 } 2142 2143 return B_OK; 2144 } 2145 2146 2147 status_t 2148 BDiscreteParameter::MakeItemsFromOutputs() 2149 { 2150 CALLED(); 2151 ASSERT(mValues != NULL); 2152 ASSERT(mSelections != NULL); 2153 ASSERT(mOutputs != NULL); 2154 2155 int32 count = mOutputs->CountItems(); 2156 for(int32 i = 0; i < count; i++) { 2157 BParameter *parameter = static_cast<BParameter *>(mOutputs->ItemAt(i)); 2158 AddItem(i, parameter->Name()); 2159 } 2160 2161 return B_OK; 2162 } 2163 2164 2165 void 2166 BDiscreteParameter::MakeEmpty() 2167 { 2168 CALLED(); 2169 ASSERT(mValues != NULL); 2170 ASSERT(mSelections != NULL); 2171 2172 for (int32 i = mValues->CountItems(); i-- > 0;) { 2173 delete static_cast<int32 *>(mValues->ItemAt(i)); 2174 } 2175 mValues->MakeEmpty(); 2176 2177 for(int32 i = mSelections->CountItems(); i-- > 0;) { 2178 free(static_cast<char *>(mSelections->ItemAt(i))); 2179 } 2180 mSelections->MakeEmpty(); 2181 } 2182 2183 2184 ssize_t 2185 BDiscreteParameter::FlattenedSize() const 2186 { 2187 CALLED(); 2188 2189 ssize_t size = BParameter::FlattenedSize() + kAdditionalDiscreteParameterSize; 2190 2191 int32 count = mValues ? mValues->CountItems() : 0; 2192 for (int32 i = 0; i < count; i++) { 2193 char *selection = static_cast<char *>(mSelections->ItemAt(i)); 2194 2195 if (selection != NULL) 2196 size += min_c(strlen(selection), 255); 2197 2198 size += 5; 2199 // string length + value 2200 } 2201 2202 return size; 2203 } 2204 2205 2206 status_t 2207 BDiscreteParameter::Flatten(void *buffer, ssize_t size) const 2208 { 2209 CALLED(); 2210 2211 if (buffer == NULL) { 2212 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n"); 2213 return B_NO_INIT; 2214 } 2215 2216 ssize_t parameterSize = BParameter::FlattenedSize(); 2217 2218 if (size < FlattenedSize()) { 2219 ERROR("BDiscreteParameter::Flatten(): size too small\n"); 2220 return B_NO_MEMORY; 2221 } 2222 2223 status_t status = BParameter::Flatten(buffer, size); 2224 if (status != B_OK) { 2225 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n"); 2226 return status; 2227 } 2228 2229 skip_in_buffer(&buffer, parameterSize); 2230 2231 int32 count = mValues ? mValues->CountItems() : 0; 2232 write_to_buffer<int32>(&buffer, count); 2233 2234 // write out all value/name pairs 2235 for (int32 i = 0; i < count; i++) { 2236 const char *selection = static_cast<char *>(mSelections->ItemAt(i)); 2237 const int32 *value = static_cast<int32 *>(mValues->ItemAt(i)); 2238 2239 write_string_to_buffer(&buffer, selection); 2240 write_to_buffer<int32>(&buffer, value ? *value : 0); 2241 } 2242 2243 return B_OK; 2244 } 2245 2246 2247 status_t 2248 BDiscreteParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2249 { 2250 CALLED(); 2251 2252 if (!AllowsTypeCode(code)) { 2253 ERROR("BDiscreteParameter::Unflatten(): bad type code\n"); 2254 return B_BAD_TYPE; 2255 } 2256 2257 if (buffer == NULL) { 2258 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n"); 2259 return B_NO_INIT; 2260 } 2261 2262 // if the buffer is smaller than the size needed to read the 2263 // signature and struct size fields, then there is a problem 2264 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 2265 ERROR("BDiscreteParameter::Unflatten(): size too small\n"); 2266 return B_ERROR; 2267 } 2268 2269 const void *bufferStart = buffer; 2270 2271 status_t status = BParameter::Unflatten(code, buffer, size); 2272 if (status != B_OK) { 2273 ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n"); 2274 return status; 2275 } 2276 2277 ssize_t parameterSize = BParameter::FlattenedSize(); 2278 skip_in_buffer(&buffer, parameterSize); 2279 2280 if (size < (parameterSize + kAdditionalDiscreteParameterSize)) { 2281 ERROR("BDiscreteParameter::Unflatten(): buffer too small\n"); 2282 return B_BAD_VALUE; 2283 } 2284 2285 int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten()); 2286 2287 // clear any existing name/value pairs 2288 MakeEmpty(); 2289 2290 for (int32 i = 0; i < count; i++) { 2291 char *name; 2292 if (read_string_from_buffer(&buffer, &name, size_left(size, bufferStart, buffer)) < B_OK) 2293 return B_BAD_DATA; 2294 2295 if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) 2296 return B_BAD_DATA; 2297 2298 int32 value = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten()); 2299 2300 AddItem(value, name); 2301 } 2302 2303 return B_OK; 2304 } 2305 2306 2307 /************************************************************* 2308 * private BDiscreteParameter 2309 *************************************************************/ 2310 2311 2312 BDiscreteParameter::BDiscreteParameter(int32 id, media_type mediaType, 2313 BParameterWeb *web, const char *name, const char *kind) 2314 : BParameter(id, mediaType, B_DISCRETE_PARAMETER, web, name, kind, NULL) 2315 { 2316 CALLED(); 2317 2318 mSelections = new BList(); 2319 mValues = new BList(); 2320 } 2321 2322 2323 BDiscreteParameter::~BDiscreteParameter() 2324 { 2325 CALLED(); 2326 2327 MakeEmpty(); 2328 2329 delete mSelections; 2330 delete mValues; 2331 2332 mSelections = NULL; mValues = NULL; 2333 } 2334 2335 2336 // #pragma mark - 2337 2338 /************************************************************* 2339 * public BNullParameter 2340 *************************************************************/ 2341 2342 2343 type_code 2344 BNullParameter::ValueType() 2345 { 2346 // NULL parameters have no value type 2347 return 0; 2348 } 2349 2350 2351 ssize_t 2352 BNullParameter::FlattenedSize() const 2353 { 2354 return BParameter::FlattenedSize(); 2355 } 2356 2357 2358 status_t 2359 BNullParameter::Flatten(void *buffer, ssize_t size) const 2360 { 2361 return BParameter::Flatten(buffer, size); 2362 } 2363 2364 2365 status_t 2366 BNullParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2367 { 2368 return BParameter::Unflatten(code, buffer, size); 2369 } 2370 2371 2372 /************************************************************* 2373 * private BNullParameter 2374 *************************************************************/ 2375 2376 2377 BNullParameter::BNullParameter(int32 id, media_type mediaType, BParameterWeb *web, 2378 const char *name, const char *kind) 2379 : BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL) 2380 { 2381 } 2382 2383 2384 BNullParameter::~BNullParameter() 2385 { 2386 } 2387 2388 2389 // #pragma mark - 2390 // reserved functions 2391 2392 2393 status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; } 2394 status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; } 2395 status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; } 2396 status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; } 2397 status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; } 2398 status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; } 2399 status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; } 2400 status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; } 2401 2402 status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; } 2403 status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; } 2404 status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; } 2405 status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; } 2406 status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; } 2407 status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; } 2408 status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; } 2409 status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; } 2410 2411 status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; } 2412 status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; } 2413 status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; } 2414 status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; } 2415 status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; } 2416 status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; } 2417 status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; } 2418 status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; } 2419 2420 status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; } 2421 status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; } 2422 status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; } 2423 status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; } 2424 status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; } 2425 status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; } 2426 status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; } 2427 status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; } 2428 2429 status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; } 2430 status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; } 2431 status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; } 2432 status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; } 2433 status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; } 2434 status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; } 2435 status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; } 2436 status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; } 2437 2438 status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; } 2439 status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; } 2440 status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; } 2441 status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; } 2442 status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; } 2443 status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; } 2444 status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; } 2445 status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; } 2446 2447 2448