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 for (int32 i = 0; i < mGroups->CountItems(); i++) { 605 BParameterGroup *CurrentItem = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 606 if (CurrentItem != NULL) { 607 delete CurrentItem; 608 } 609 } 610 mGroups->MakeEmpty(); 611 } else { 612 mGroups = new BList(); 613 } 614 #endif 615 616 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 617 618 mNode = read_from_buffer<media_node>(&buffer); 619 if (isSwapped) 620 swap_data(B_INT32_TYPE, &mNode, sizeof(media_node), B_SWAP_ALWAYS); 621 622 for (int32 i = 0; i < count; i++) { 623 ssize_t groupSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 624 if (groupSize > size_left(size, bufferStart, buffer)) { 625 ERROR("BParameterWeb::Unflatten(): buffer too small\n"); 626 return B_BAD_DATA; 627 } 628 629 BParameterGroup *group = new BParameterGroup(this, "unnamed"); 630 status_t status = group->Unflatten(group->TypeCode(), buffer, groupSize); 631 if (status < B_OK) { 632 ERROR("BParameterWeb::Unflatten(): unflatten group failed\n"); 633 delete group; 634 return status; 635 } 636 637 skip_in_buffer(&buffer, groupSize); 638 639 mGroups->AddItem(group); 640 } 641 642 // fix all references (ParameterAt() style) 643 644 if ((mOldRefs != NULL) && (mNewRefs != NULL)) { 645 BList groups(*mGroups); 646 647 for (int32 i = 0; i < groups.CountItems(); i++) { 648 BParameterGroup *group = static_cast<BParameterGroup *>(groups.ItemAt(i)); 649 650 for (int32 index = group->CountParameters(); index-- > 0;) { 651 BParameter *parameter = static_cast<BParameter *>(group->ParameterAt(index)); 652 653 parameter->FixRefs(*mOldRefs, *mNewRefs); 654 } 655 656 if (group->mGroups != NULL) 657 groups.AddList(group->mGroups); 658 } 659 660 mOldRefs->MakeEmpty(); 661 mNewRefs->MakeEmpty(); 662 } 663 664 return B_OK; 665 } 666 667 /************************************************************* 668 * private BParameterWeb 669 *************************************************************/ 670 671 /* 672 unimplemented 673 BParameterWeb::BParameterWeb(const BParameterWeb &clone) 674 BParameterWeb &BParameterWeb::operator=(const BParameterWeb &clone) 675 */ 676 677 678 void 679 BParameterWeb::AddRefFix(void *oldItem, void *newItem) 680 { 681 ASSERT(mOldRefs != NULL); 682 ASSERT(mNewRefs != NULL); 683 684 mOldRefs->AddItem(oldItem); 685 mNewRefs->AddItem(newItem); 686 } 687 688 689 // #pragma mark - 690 691 /************************************************************* 692 * private BParameterGroup 693 *************************************************************/ 694 695 696 BParameterGroup::BParameterGroup(BParameterWeb *web, const char *name) 697 : mWeb(web), 698 mFlags(0) 699 { 700 CALLED(); 701 TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web, name); 702 703 mName = strndup(name, 256); 704 705 mControls = new BList(); 706 mGroups = new BList(); 707 } 708 709 710 BParameterGroup::~BParameterGroup() 711 { 712 CALLED(); 713 714 if (mControls) { 715 BParameter **items = reinterpret_cast<BParameter **>(mControls->Items()); 716 for (int i = mControls->CountItems(); i-- > 0;) 717 delete items[i]; 718 719 delete mControls; 720 } 721 722 if (mGroups) { 723 BParameterGroup **items = reinterpret_cast<BParameterGroup **>(mGroups->Items()); 724 for (int i = mGroups->CountItems(); i-- > 0;) 725 delete items[i]; 726 727 delete mGroups; 728 } 729 730 free(mName); 731 } 732 733 /************************************************************* 734 * public BParameterGroup 735 *************************************************************/ 736 737 BParameterWeb * 738 BParameterGroup::Web() const 739 { 740 return mWeb; 741 } 742 743 744 const char * 745 BParameterGroup::Name() const 746 { 747 return mName; 748 } 749 750 751 void 752 BParameterGroup::SetFlags(uint32 flags) 753 { 754 mFlags = flags; 755 } 756 757 758 uint32 759 BParameterGroup::Flags() const 760 { 761 return mFlags; 762 } 763 764 765 BNullParameter * 766 BParameterGroup::MakeNullParameter(int32 id, media_type mediaType, const char *name, 767 const char *kind) 768 { 769 CALLED(); 770 ASSERT(mControls != NULL); 771 772 BNullParameter *parameter = new BNullParameter(id, mediaType, mWeb, name, kind); 773 parameter->mGroup = this; 774 mControls->AddItem(parameter); 775 776 return parameter; 777 } 778 779 780 BTextParameter * 781 BParameterGroup::MakeTextParameter(int32 id, media_type mediaType, const char *name, 782 const char *kind, size_t max_bytes) 783 { 784 CALLED(); 785 ASSERT(mControls != NULL); 786 787 BTextParameter *parameter = new BTextParameter(id, mediaType, mWeb, name, kind, max_bytes); 788 parameter->mGroup = this; 789 mControls->AddItem(parameter); 790 791 return parameter; 792 } 793 794 795 BContinuousParameter * 796 BParameterGroup::MakeContinuousParameter(int32 id, media_type mediaType, 797 const char *name, const char *kind, const char *unit, 798 float minimum, float maximum, float stepping) 799 { 800 CALLED(); 801 ASSERT(mControls != NULL); 802 803 BContinuousParameter *parameter = new BContinuousParameter(id, mediaType, mWeb, 804 name, kind, unit, minimum, maximum, stepping); 805 806 parameter->mGroup = this; 807 mControls->AddItem(parameter); 808 809 return parameter; 810 } 811 812 813 BDiscreteParameter * 814 BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType, 815 const char *name, const char *kind) 816 { 817 CALLED(); 818 ASSERT(mControls != NULL); 819 820 BDiscreteParameter *parameter = new BDiscreteParameter(id, mediaType, mWeb, name, kind); 821 if (parameter == NULL) 822 return NULL; 823 824 parameter->mGroup = this; 825 mControls->AddItem(parameter); 826 827 return parameter; 828 } 829 830 831 BParameterGroup * 832 BParameterGroup::MakeGroup(const char *name) 833 { 834 CALLED(); 835 ASSERT(mGroups != NULL); 836 837 BParameterGroup *group = new BParameterGroup(mWeb, name); 838 if (group != NULL) 839 mGroups->AddItem(group); 840 841 return group; 842 } 843 844 845 int32 846 BParameterGroup::CountParameters() 847 { 848 ASSERT(mControls != NULL); 849 850 return mControls->CountItems(); 851 } 852 853 854 BParameter * 855 BParameterGroup::ParameterAt(int32 index) 856 { 857 ASSERT(mControls != NULL); 858 859 return static_cast<BParameter *>(mControls->ItemAt(index)); 860 } 861 862 863 int32 864 BParameterGroup::CountGroups() 865 { 866 ASSERT(mGroups != NULL); 867 868 return mGroups->CountItems(); 869 } 870 871 872 BParameterGroup * 873 BParameterGroup::GroupAt(int32 index) 874 { 875 ASSERT(mGroups != NULL); 876 877 return static_cast<BParameterGroup *>(mGroups->ItemAt(index)); 878 } 879 880 881 bool 882 BParameterGroup::IsFixedSize() const 883 { 884 return false; 885 } 886 887 888 type_code 889 BParameterGroup::TypeCode() const 890 { 891 return B_MEDIA_PARAMETER_GROUP_TYPE; 892 } 893 894 895 ssize_t 896 BParameterGroup::FlattenedSize() const 897 { 898 CALLED(); 899 ASSERT(mControls != NULL); 900 ASSERT(mGroups != NULL); 901 902 /* 903 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT----------- 904 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes 905 (possible) Flags: 4 bytes 906 Name String Length: 1 byte (??) 907 Name String: 'Name String Length' bytes 908 Param Count: 4 bytes 909 //for each Param BEGIN 910 Pointer: 4 bytes 911 Parameter Type: 4 bytes 912 Flattened Parameter Size: 4 bytes 913 Flattened Parameter: 'Flattened Parameter Size' bytes 914 //for each Param END 915 Subgroup Count: 4 bytes 916 //for each SubGroup BEGIN 917 Pointer: 4 bytes 918 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes 919 Flattened Group Size: 4 bytes 920 Flattened Group: 'Flattened Group Size' bytes 921 //for each SubGroup END 922 923 //---------END-CORE-BPARAMETERGROUP-STRUCT-------------- 924 */ 925 //13 guaranteed bytes, variable after that. 926 ssize_t size = 13; 927 928 if (mFlags != 0) { 929 size += 4; 930 } 931 932 if (mName != NULL) { 933 size += min_c(strlen(mName),255); 934 } 935 936 int i; 937 int limit; 938 939 limit = mControls->CountItems(); 940 for (i = 0; i < limit; i++) { 941 BParameter *CurrentParameter = static_cast<BParameter *>(mControls->ItemAt(i)); 942 if (CurrentParameter != NULL) { 943 //overhead for each parameter flattened 944 size += 16 + CurrentParameter->FlattenedSize(); 945 } 946 } 947 948 limit = mGroups->CountItems(); 949 for (i = 0; i < limit; i++) { 950 BParameterGroup *CurrentGroup = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 951 if (CurrentGroup != NULL) { 952 //overhead for each group flattened 953 size += 16 + CurrentGroup->FlattenedSize(); 954 } 955 } 956 957 return size; 958 } 959 960 961 status_t 962 BParameterGroup::Flatten(void *buffer, ssize_t size) const 963 { 964 CALLED(); 965 966 if (buffer == NULL) { 967 ERROR("BParameterGroup::Flatten buffer is NULL\n"); 968 return B_NO_INIT; 969 } 970 971 // NOTICE: It is important that this value is the size returned by 972 // BParameterGroup::FlattenedSize, not by a descendent's override of this method. 973 ssize_t actualSize = BParameterGroup::FlattenedSize(); 974 if (size < actualSize) { 975 ERROR("BParameterGroup::Flatten size to small\n"); 976 return B_NO_MEMORY; 977 } 978 979 if (mFlags != 0) { 980 write_to_buffer<int32>(&buffer, kBufferGroupMagic); 981 write_to_buffer<uint32>(&buffer, mFlags); 982 } else 983 write_to_buffer<int32>(&buffer, kBufferGroupMagicNoFlags); 984 985 write_string_to_buffer(&buffer, mName); 986 987 int32 count = mControls ? mControls->CountItems() : 0; 988 write_to_buffer<int32>(&buffer, count); 989 990 for (int32 i = 0; i < count; i++) { 991 BParameter *parameter = static_cast<BParameter *>(mControls->ItemAt(i)); 992 if (parameter == NULL) { 993 ERROR("BParameterGroup::Flatten(): NULL parameter\n"); 994 continue; 995 } 996 997 write_to_buffer<BParameter *>(&buffer, parameter); 998 write_to_buffer<BParameter::media_parameter_type>(&buffer, parameter->Type()); 999 1000 // flatten parameter into this buffer 1001 1002 ssize_t parameterSize = parameter->FlattenedSize(); 1003 write_to_buffer<ssize_t>(&buffer, parameterSize); 1004 1005 status_t status = parameter->Flatten(buffer, parameterSize); 1006 // we have only that much bytes left to write in this buffer 1007 if (status < B_OK) 1008 return status; 1009 1010 skip_in_buffer(&buffer, parameterSize); 1011 } 1012 1013 count = mGroups ? mGroups->CountItems() : 0; 1014 write_to_buffer<int32>(&buffer, count); 1015 1016 for (int32 i = 0; i < count; i++) { 1017 BParameterGroup *group = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 1018 if (group == NULL) { 1019 ERROR("BParameterGroup::Flatten(): NULL group\n"); 1020 continue; 1021 } 1022 1023 write_to_buffer<BParameterGroup *>(&buffer, group); 1024 write_to_buffer<type_code>(&buffer, group->TypeCode()); 1025 1026 // flatten sub group into this buffer 1027 1028 ssize_t groupSize = group->FlattenedSize(); 1029 write_to_buffer<ssize_t>(&buffer, groupSize); 1030 1031 status_t status = group->Flatten(buffer, groupSize); 1032 // we have only that much bytes left to write in this buffer 1033 if (status < B_OK) 1034 return status; 1035 1036 skip_in_buffer(&buffer, groupSize); 1037 } 1038 1039 return B_OK; 1040 } 1041 1042 1043 bool 1044 BParameterGroup::AllowsTypeCode(type_code code) const 1045 { 1046 return code == TypeCode(); 1047 } 1048 1049 1050 status_t 1051 BParameterGroup::Unflatten(type_code code, const void *buffer, ssize_t size) 1052 { 1053 CALLED(); 1054 1055 if (!AllowsTypeCode(code)) { 1056 ERROR("BParameterGroup::Unflatten() wrong type code\n"); 1057 return B_BAD_TYPE; 1058 } 1059 1060 if (buffer == NULL) { 1061 ERROR("BParameterGroup::Unflatten() buffer is NULL\n"); 1062 return B_NO_INIT; 1063 } 1064 1065 // if the buffer is smaller than the size needed to read the 1066 // signature field, then there is a problem 1067 if (size < static_cast<ssize_t>(sizeof(int32))) { 1068 ERROR("BParameterGroup::Unflatten() size to small\n"); 1069 return B_ERROR; 1070 } 1071 1072 const void *bufferStart = buffer; 1073 // used to compute the rest length of the buffer when needed 1074 1075 uint32 magic = read_from_buffer<uint32>(&buffer); 1076 bool isSwapped = false; 1077 1078 if (magic == B_SWAP_INT32(kBufferGroupMagic) 1079 || magic == B_SWAP_INT32(kBufferGroupMagicNoFlags)) { 1080 isSwapped = true; 1081 magic = B_SWAP_INT32(magic); 1082 } 1083 1084 if (magic == kBufferGroupMagic) 1085 mFlags = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1086 else if (magic == kBufferGroupMagicNoFlags) 1087 mFlags = 0; 1088 else 1089 return B_BAD_TYPE; 1090 1091 if (read_string_from_buffer(&buffer, &mName, 1092 size - static_cast<ssize_t>((uint8 *)buffer - (uint8 *)bufferStart)) < B_OK) 1093 return B_BAD_VALUE; 1094 1095 // Currently disabled since it's not really used -- axeld. 1096 #if 0 1097 //Clear all existing parameters/subgroups 1098 int i; 1099 if (mControls != NULL) { 1100 for (i = 0; i < mControls->CountItems(); i++) { 1101 BParameter *CurrentItem = static_cast<BParameter *>(mControls->ItemAt(i)); 1102 if (CurrentItem != NULL) { 1103 delete CurrentItem; 1104 } 1105 } 1106 mControls->MakeEmpty(); 1107 } else { 1108 mControls = new BList(); 1109 } 1110 1111 if (mGroups != NULL) { 1112 for (i = 0; i < mGroups->CountItems(); i++) { 1113 BParameterGroup *CurrentItem = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 1114 if (CurrentItem != NULL) { 1115 delete CurrentItem; 1116 } 1117 } 1118 mGroups->MakeEmpty(); 1119 } else { 1120 mGroups = new BList(); 1121 } 1122 #endif 1123 1124 // unflatten parameter list 1125 1126 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1127 if (count < 0 || count * kAdditionalParameterSize > size_left(size, bufferStart, buffer)) 1128 return B_BAD_VALUE; 1129 1130 for (int32 i = 0; i < count; i++) { 1131 // make sure we can read as many bytes 1132 if (size_left(size, bufferStart, buffer) < 12) 1133 return B_BAD_VALUE; 1134 1135 BParameter *oldPointer = read_from_buffer_swap32<BParameter *>(&buffer, isSwapped); 1136 BParameter::media_parameter_type mediaType = 1137 read_from_buffer_swap32<BParameter::media_parameter_type>(&buffer, isSwapped); 1138 1139 ssize_t parameterSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 1140 if (parameterSize > size_left(size, bufferStart, buffer)) 1141 return B_BAD_VALUE; 1142 1143 BParameter *parameter = MakeControl(mediaType); 1144 if (parameter == NULL) { 1145 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n"); 1146 return B_ERROR; 1147 } 1148 1149 status_t status = parameter->Unflatten(parameter->TypeCode(), buffer, parameterSize); 1150 if (status < B_OK) { 1151 ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n"); 1152 delete parameter; 1153 return status; 1154 } 1155 1156 skip_in_buffer(&buffer, parameterSize); 1157 1158 // add the item to the list 1159 parameter->mGroup = this; 1160 parameter->mWeb = mWeb; 1161 mControls->AddItem(parameter); 1162 1163 // add it's old pointer value to the RefFix list kept by the owner web 1164 if (mWeb != NULL) 1165 mWeb->AddRefFix(oldPointer, parameter); 1166 } 1167 1168 // unflatten sub groups 1169 1170 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1171 if (count < 0 || count * kAdditionalParameterGroupSize > size_left(size, bufferStart, buffer)) 1172 return B_BAD_VALUE; 1173 1174 for (int32 i = 0; i < count; i++) { 1175 // make sure we can read as many bytes 1176 if (size_left(size, bufferStart, buffer) < 12) 1177 return B_BAD_VALUE; 1178 1179 BParameterGroup *oldPointer = read_from_buffer_swap32<BParameterGroup *>(&buffer, isSwapped); 1180 type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped); 1181 1182 ssize_t groupSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 1183 if (groupSize > size_left(size, bufferStart, buffer)) 1184 return B_BAD_VALUE; 1185 1186 BParameterGroup *group = new BParameterGroup(mWeb, "sub-unnamed"); 1187 if (group == NULL) { 1188 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n"); 1189 return B_ERROR; 1190 } 1191 1192 status_t status = group->Unflatten(type, buffer, groupSize); 1193 if (status != B_OK) { 1194 ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n"); 1195 delete group; 1196 return status; 1197 } 1198 1199 skip_in_buffer(&buffer, groupSize); 1200 1201 mGroups->AddItem(group); 1202 1203 // add it's old pointer value to the RefFix list kept by the owner web 1204 if (mWeb != NULL) 1205 mWeb->AddRefFix(oldPointer, group); 1206 } 1207 1208 return B_OK; 1209 } 1210 1211 /************************************************************* 1212 * private BParameterGroup 1213 *************************************************************/ 1214 1215 /* 1216 // unimplemented 1217 BParameterGroup::BParameterGroup() 1218 BParameterGroup::BParameterGroup(const BParameterGroup &clone) 1219 BParameterGroup &BParameterGroup::operator=(const BParameterGroup &clone) 1220 */ 1221 1222 1223 /** Creates an uninitialized parameter of the specified type. 1224 * Unlike the BParameterGroup::MakeXXXParameter() type of methods, this 1225 * method does not add the parameter to this group automatically. 1226 */ 1227 1228 BParameter * 1229 BParameterGroup::MakeControl(int32 type) 1230 { 1231 CALLED(); 1232 1233 switch (type) { 1234 case BParameter::B_NULL_PARAMETER: 1235 return new BNullParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL); 1236 1237 case BParameter::B_DISCRETE_PARAMETER: 1238 return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, 1239 NULL); 1240 1241 case BParameter::B_CONTINUOUS_PARAMETER: 1242 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, 1243 NULL, NULL, 0, 0, 0); 1244 1245 case BParameter::B_TEXT_PARAMETER: 1246 return new BTextParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, 0); 1247 1248 default: 1249 ERROR("BParameterGroup::MakeControl unknown type %ld\n", type); 1250 return NULL; 1251 } 1252 } 1253 1254 1255 // #pragma mark - 1256 1257 /************************************************************* 1258 * public BParameter 1259 *************************************************************/ 1260 1261 1262 BParameter::media_parameter_type 1263 BParameter::Type() const 1264 { 1265 return mType; 1266 } 1267 1268 1269 BParameterWeb * 1270 BParameter::Web() const 1271 { 1272 return mWeb; 1273 } 1274 1275 1276 BParameterGroup * 1277 BParameter::Group() const 1278 { 1279 return mGroup; 1280 } 1281 1282 1283 const char * 1284 BParameter::Name() const 1285 { 1286 return mName; 1287 } 1288 1289 1290 const char * 1291 BParameter::Kind() const 1292 { 1293 return mKind; 1294 } 1295 1296 1297 const char * 1298 BParameter::Unit() const 1299 { 1300 return mUnit; 1301 } 1302 1303 1304 int32 1305 BParameter::ID() const 1306 { 1307 return mID; 1308 } 1309 1310 1311 void 1312 BParameter::SetFlags(uint32 flags) 1313 { 1314 mFlags = flags; 1315 } 1316 1317 1318 uint32 1319 BParameter::Flags() const 1320 { 1321 return mFlags; 1322 } 1323 1324 1325 status_t 1326 BParameter::GetValue(void *buffer, size_t *_ioSize, bigtime_t *_when) 1327 { 1328 CALLED(); 1329 1330 if (buffer == NULL || _ioSize == NULL) 1331 return B_BAD_VALUE; 1332 1333 size_t ioSize = *_ioSize; 1334 if (ioSize <= 0) 1335 return B_NO_MEMORY; 1336 1337 if (mWeb == NULL) { 1338 ERROR("BParameter::GetValue: no parent BParameterWeb\n"); 1339 return B_NO_INIT; 1340 } 1341 1342 media_node node = mWeb->Node(); 1343 if (IS_INVALID_NODE(node)) { 1344 ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); 1345 return B_NO_INIT; 1346 } 1347 1348 controllable_get_parameter_data_request request; 1349 controllable_get_parameter_data_reply reply; 1350 1351 area_id area; 1352 void *data; 1353 if (ioSize > MAX_PARAMETER_DATA) { 1354 // create an area if large data needs to be transfered 1355 area = create_area("get parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(ioSize), 1356 B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1357 if (area < B_OK) { 1358 ERROR("BParameter::GetValue can't create area of %ld bytes\n", ioSize); 1359 return B_NO_MEMORY; 1360 } 1361 } else { 1362 area = -1; 1363 data = reply.rawdata; 1364 } 1365 1366 request.parameter_id = mID; 1367 request.requestsize = ioSize; 1368 request.area = area; 1369 1370 status_t status = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_DATA, &request, 1371 sizeof(request), &reply, sizeof(reply)); 1372 if (status == B_OK) { 1373 // we don't want to copy more than the buffer provides 1374 if (reply.size < ioSize) 1375 ioSize = reply.size; 1376 1377 memcpy(buffer, data, ioSize); 1378 1379 // store reported values 1380 1381 *_ioSize = reply.size; 1382 if (_when != NULL) 1383 *_when = reply.last_change; 1384 } else 1385 ERROR("BParameter::GetValue parameter '%s' querying node %d, " 1386 "port %d failed: %s\n", mName, (int)node.node, (int)node.port, 1387 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 2391 /************************************************************* 2392 * public BTextParameter 2393 *************************************************************/ 2394 2395 2396 size_t 2397 BTextParameter::MaxBytes() const 2398 { 2399 // NULL parameters have no value type 2400 return mMaxBytes; 2401 } 2402 2403 2404 type_code 2405 BTextParameter::ValueType() 2406 { 2407 // NULL parameters have no value type 2408 return 0; 2409 } 2410 2411 2412 ssize_t 2413 BTextParameter::FlattenedSize() const 2414 { 2415 return BParameter::FlattenedSize() + sizeof(mMaxBytes); 2416 } 2417 2418 2419 status_t 2420 BTextParameter::Flatten(void *buffer, ssize_t size) const 2421 { 2422 if (buffer == NULL) { 2423 ERROR("BTextParameter::Flatten(): buffer is NULL\n"); 2424 return B_NO_INIT; 2425 } 2426 2427 ssize_t parameterSize = BParameter::FlattenedSize(); 2428 if (size < static_cast<ssize_t>(parameterSize + sizeof(mMaxBytes))) { 2429 ERROR("BContinuousParameter::Flatten(): size to small\n"); 2430 return B_NO_MEMORY; 2431 } 2432 2433 status_t status = BParameter::Flatten(buffer, size); 2434 if (status != B_OK) { 2435 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n"); 2436 return status; 2437 } 2438 2439 // add our data to the general flattened BParameter 2440 2441 skip_in_buffer(&buffer, parameterSize); 2442 2443 write_to_buffer<uint32>(&buffer, mMaxBytes); 2444 2445 return B_OK; 2446 } 2447 2448 2449 status_t 2450 BTextParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2451 { 2452 // we try to check if the buffer size is long enough to hold an object 2453 // as early as possible. 2454 2455 if (!AllowsTypeCode(code)) { 2456 ERROR("BTextParameter::Unflatten wrong type code\n"); 2457 return B_BAD_TYPE; 2458 } 2459 2460 if (buffer == NULL) { 2461 ERROR("BTextParameter::Unflatten buffer is NULL\n"); 2462 return B_NO_INIT; 2463 } 2464 2465 if (size < static_cast<ssize_t>(sizeof(mMaxBytes))) { 2466 ERROR("BTextParameter::Unflatten size too small\n"); 2467 return B_ERROR; 2468 } 2469 2470 status_t status = BParameter::Unflatten(code, buffer, size); 2471 if (status != B_OK) { 2472 ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n"); 2473 return status; 2474 } 2475 2476 ssize_t parameterSize = BParameter::FlattenedSize(); 2477 skip_in_buffer(&buffer, parameterSize); 2478 2479 if (size < static_cast<ssize_t>(parameterSize + sizeof(mMaxBytes))) { 2480 ERROR("BTextParameter::Unflatten(): buffer too small\n"); 2481 return B_BAD_VALUE; 2482 } 2483 2484 mMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten()); 2485 2486 return B_OK; 2487 } 2488 2489 2490 /************************************************************* 2491 * private BTextParameter 2492 *************************************************************/ 2493 2494 2495 BTextParameter::BTextParameter(int32 id, media_type mediaType, BParameterWeb *web, 2496 const char *name, const char *kind, size_t max_bytes) 2497 : BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL) 2498 { 2499 mMaxBytes = max_bytes; 2500 } 2501 2502 2503 BTextParameter::~BTextParameter() 2504 { 2505 } 2506 2507 2508 // #pragma mark - 2509 // reserved functions 2510 2511 2512 status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; } 2513 status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; } 2514 status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; } 2515 status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; } 2516 status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; } 2517 status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; } 2518 status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; } 2519 status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; } 2520 2521 status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; } 2522 status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; } 2523 status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; } 2524 status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; } 2525 status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; } 2526 status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; } 2527 status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; } 2528 status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; } 2529 2530 status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; } 2531 status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; } 2532 status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; } 2533 status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; } 2534 status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; } 2535 status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; } 2536 status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; } 2537 status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; } 2538 2539 status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; } 2540 status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; } 2541 status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; } 2542 status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; } 2543 status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; } 2544 status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; } 2545 status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; } 2546 status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; } 2547 2548 status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; } 2549 status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; } 2550 status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; } 2551 status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; } 2552 status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; } 2553 status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; } 2554 status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; } 2555 status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; } 2556 2557 status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; } 2558 status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; } 2559 status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; } 2560 status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; } 2561 status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; } 2562 status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; } 2563 status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; } 2564 status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; } 2565 2566 status_t BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR; } 2567 status_t BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR; } 2568 status_t BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR; } 2569 status_t BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR; } 2570 status_t BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR; } 2571 status_t BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR; } 2572 status_t BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR; } 2573 status_t BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR; } 2574 2575 2576