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 BTextParameter * 786 BParameterGroup::MakeTextParameter(int32 id, media_type mediaType, const char *name, 787 const char *kind, size_t max_bytes) 788 { 789 CALLED(); 790 ASSERT(mControls != NULL); 791 792 BTextParameter *parameter = new BTextParameter(id, mediaType, mWeb, name, kind, max_bytes); 793 parameter->mGroup = this; 794 mControls->AddItem(parameter); 795 796 return parameter; 797 } 798 799 800 BContinuousParameter * 801 BParameterGroup::MakeContinuousParameter(int32 id, media_type mediaType, 802 const char *name, const char *kind, const char *unit, 803 float minimum, float maximum, float stepping) 804 { 805 CALLED(); 806 ASSERT(mControls != NULL); 807 808 BContinuousParameter *parameter = new BContinuousParameter(id, mediaType, mWeb, 809 name, kind, unit, minimum, maximum, stepping); 810 811 parameter->mGroup = this; 812 mControls->AddItem(parameter); 813 814 return parameter; 815 } 816 817 818 BDiscreteParameter * 819 BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType, 820 const char *name, const char *kind) 821 { 822 CALLED(); 823 ASSERT(mControls != NULL); 824 825 BDiscreteParameter *parameter = new BDiscreteParameter(id, mediaType, mWeb, name, kind); 826 if (parameter == NULL) 827 return NULL; 828 829 parameter->mGroup = this; 830 mControls->AddItem(parameter); 831 832 return parameter; 833 } 834 835 836 BParameterGroup * 837 BParameterGroup::MakeGroup(const char *name) 838 { 839 CALLED(); 840 ASSERT(mGroups != NULL); 841 842 BParameterGroup *group = new BParameterGroup(mWeb, name); 843 if (group != NULL) 844 mGroups->AddItem(group); 845 846 return group; 847 } 848 849 850 int32 851 BParameterGroup::CountParameters() 852 { 853 ASSERT(mControls != NULL); 854 855 return mControls->CountItems(); 856 } 857 858 859 BParameter * 860 BParameterGroup::ParameterAt(int32 index) 861 { 862 ASSERT(mControls != NULL); 863 864 return static_cast<BParameter *>(mControls->ItemAt(index)); 865 } 866 867 868 int32 869 BParameterGroup::CountGroups() 870 { 871 ASSERT(mGroups != NULL); 872 873 return mGroups->CountItems(); 874 } 875 876 877 BParameterGroup * 878 BParameterGroup::GroupAt(int32 index) 879 { 880 ASSERT(mGroups != NULL); 881 882 return static_cast<BParameterGroup *>(mGroups->ItemAt(index)); 883 } 884 885 886 bool 887 BParameterGroup::IsFixedSize() const 888 { 889 return false; 890 } 891 892 893 type_code 894 BParameterGroup::TypeCode() const 895 { 896 return B_MEDIA_PARAMETER_GROUP_TYPE; 897 } 898 899 900 ssize_t 901 BParameterGroup::FlattenedSize() const 902 { 903 CALLED(); 904 ASSERT(mControls != NULL); 905 ASSERT(mGroups != NULL); 906 907 /* 908 //--------BEGIN-CORE-BPARAMETERGROUP-STRUCT----------- 909 ?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes 910 (possible) Flags: 4 bytes 911 Name String Length: 1 byte (??) 912 Name String: 'Name String Length' bytes 913 Param Count: 4 bytes 914 //for each Param BEGIN 915 Pointer: 4 bytes 916 Parameter Type: 4 bytes 917 Flattened Parameter Size: 4 bytes 918 Flattened Parameter: 'Flattened Parameter Size' bytes 919 //for each Param END 920 Subgroup Count: 4 bytes 921 //for each SubGroup BEGIN 922 Pointer: 4 bytes 923 MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes 924 Flattened Group Size: 4 bytes 925 Flattened Group: 'Flattened Group Size' bytes 926 //for each SubGroup END 927 928 //---------END-CORE-BPARAMETERGROUP-STRUCT-------------- 929 */ 930 //13 guaranteed bytes, variable after that. 931 ssize_t size = 13; 932 933 if(mFlags != 0) 934 { 935 size += 4; 936 } 937 938 if(mName != NULL) 939 { 940 size += min_c(strlen(mName),255); 941 } 942 943 int i; 944 int limit; 945 946 limit = mControls->CountItems(); 947 for(i = 0; i < limit; i++) 948 { 949 BParameter *CurrentParameter = static_cast<BParameter *>(mControls->ItemAt(i)); 950 if(CurrentParameter != NULL) 951 { 952 //overhead for each parameter flattened 953 size += 16 + CurrentParameter->FlattenedSize(); 954 } 955 } 956 957 limit = mGroups->CountItems(); 958 for(i = 0; i < limit; i++) 959 { 960 BParameterGroup *CurrentGroup = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 961 if(CurrentGroup != NULL) 962 { 963 //overhead for each group flattened 964 size += 16 + CurrentGroup->FlattenedSize(); 965 } 966 } 967 968 return size; 969 } 970 971 972 status_t 973 BParameterGroup::Flatten(void *buffer, ssize_t size) const 974 { 975 CALLED(); 976 977 if (buffer == NULL) { 978 ERROR("BParameterGroup::Flatten buffer is NULL\n"); 979 return B_NO_INIT; 980 } 981 982 // NOTICE: It is important that this value is the size returned by 983 // BParameterGroup::FlattenedSize, not by a descendent's override of this method. 984 ssize_t actualSize = BParameterGroup::FlattenedSize(); 985 if (size < actualSize) { 986 ERROR("BParameterGroup::Flatten size to small\n"); 987 return B_NO_MEMORY; 988 } 989 990 if (mFlags != 0) { 991 write_to_buffer<int32>(&buffer, kBufferGroupMagic); 992 write_to_buffer<uint32>(&buffer, mFlags); 993 } else 994 write_to_buffer<int32>(&buffer, kBufferGroupMagicNoFlags); 995 996 write_string_to_buffer(&buffer, mName); 997 998 int32 count = mControls ? mControls->CountItems() : 0; 999 write_to_buffer<int32>(&buffer, count); 1000 1001 for (int32 i = 0; i < count; i++) { 1002 BParameter *parameter = static_cast<BParameter *>(mControls->ItemAt(i)); 1003 if (parameter == NULL) { 1004 ERROR("BParameterGroup::Flatten(): NULL parameter\n"); 1005 continue; 1006 } 1007 1008 write_to_buffer<BParameter *>(&buffer, parameter); 1009 write_to_buffer<BParameter::media_parameter_type>(&buffer, parameter->Type()); 1010 1011 // flatten parameter into this buffer 1012 1013 ssize_t parameterSize = parameter->FlattenedSize(); 1014 write_to_buffer<ssize_t>(&buffer, parameterSize); 1015 1016 status_t status = parameter->Flatten(buffer, parameterSize); 1017 // we have only that much bytes left to write in this buffer 1018 if (status < B_OK) 1019 return status; 1020 1021 skip_in_buffer(&buffer, parameterSize); 1022 } 1023 1024 count = mGroups ? mGroups->CountItems() : 0; 1025 write_to_buffer<int32>(&buffer, count); 1026 1027 for (int32 i = 0; i < count; i++) { 1028 BParameterGroup *group = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 1029 if (group == NULL) { 1030 ERROR("BParameterGroup::Flatten(): NULL group\n"); 1031 continue; 1032 } 1033 1034 write_to_buffer<BParameterGroup *>(&buffer, group); 1035 write_to_buffer<type_code>(&buffer, group->TypeCode()); 1036 1037 // flatten sub group into this buffer 1038 1039 ssize_t groupSize = group->FlattenedSize(); 1040 write_to_buffer<ssize_t>(&buffer, groupSize); 1041 1042 status_t status = group->Flatten(buffer, groupSize); 1043 // we have only that much bytes left to write in this buffer 1044 if (status < B_OK) 1045 return status; 1046 1047 skip_in_buffer(&buffer, groupSize); 1048 } 1049 1050 return B_OK; 1051 } 1052 1053 1054 bool 1055 BParameterGroup::AllowsTypeCode(type_code code) const 1056 { 1057 return code == TypeCode(); 1058 } 1059 1060 1061 status_t 1062 BParameterGroup::Unflatten(type_code code, const void *buffer, ssize_t size) 1063 { 1064 CALLED(); 1065 1066 if (!AllowsTypeCode(code)) { 1067 ERROR("BParameterGroup::Unflatten() wrong type code\n"); 1068 return B_BAD_TYPE; 1069 } 1070 1071 if (buffer == NULL) { 1072 ERROR("BParameterGroup::Unflatten() buffer is NULL\n"); 1073 return B_NO_INIT; 1074 } 1075 1076 // if the buffer is smaller than the size needed to read the 1077 // signature field, then there is a problem 1078 if (size < static_cast<ssize_t>(sizeof(int32))) { 1079 ERROR("BParameterGroup::Unflatten() size to small\n"); 1080 return B_ERROR; 1081 } 1082 1083 const void *bufferStart = buffer; 1084 // used to compute the rest length of the buffer when needed 1085 1086 uint32 magic = read_from_buffer<uint32>(&buffer); 1087 bool isSwapped = false; 1088 1089 if (magic == B_SWAP_INT32(kBufferGroupMagic) 1090 || magic == B_SWAP_INT32(kBufferGroupMagicNoFlags)) { 1091 isSwapped = true; 1092 magic = B_SWAP_INT32(magic); 1093 } 1094 1095 if (magic == kBufferGroupMagic) 1096 mFlags = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1097 else if (magic == kBufferGroupMagicNoFlags) 1098 mFlags = 0; 1099 else 1100 return B_BAD_TYPE; 1101 1102 if (read_string_from_buffer(&buffer, &mName, 1103 size - static_cast<ssize_t>((uint8 *)buffer - (uint8 *)bufferStart)) < B_OK) 1104 return B_BAD_VALUE; 1105 1106 // Currently disabled since it's not really used -- axeld. 1107 #if 0 1108 //Clear all existing parameters/subgroups 1109 int i; 1110 if(mControls != NULL) 1111 { 1112 for(i = 0; i < mControls->CountItems(); i++) 1113 { 1114 BParameter *CurrentItem = static_cast<BParameter *>(mControls->ItemAt(i)); 1115 if(CurrentItem != NULL) 1116 { 1117 delete CurrentItem; 1118 } 1119 } 1120 mControls->MakeEmpty(); 1121 } 1122 else 1123 { 1124 mControls = new BList(); 1125 } 1126 1127 if(mGroups != NULL) 1128 { 1129 for(i = 0; i < mGroups->CountItems(); i++) 1130 { 1131 BParameterGroup *CurrentItem = static_cast<BParameterGroup *>(mGroups->ItemAt(i)); 1132 if(CurrentItem != NULL) 1133 { 1134 delete CurrentItem; 1135 } 1136 } 1137 mGroups->MakeEmpty(); 1138 } 1139 else 1140 { 1141 mGroups = new BList(); 1142 } 1143 #endif 1144 1145 // unflatten parameter list 1146 1147 int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1148 if (count < 0 || count * kAdditionalParameterSize > size_left(size, bufferStart, buffer)) 1149 return B_BAD_VALUE; 1150 1151 for (int32 i = 0; i < count; i++) { 1152 // make sure we can read as many bytes 1153 if (size_left(size, bufferStart, buffer) < 12) 1154 return B_BAD_VALUE; 1155 1156 BParameter *oldPointer = read_from_buffer_swap32<BParameter *>(&buffer, isSwapped); 1157 BParameter::media_parameter_type mediaType = 1158 read_from_buffer_swap32<BParameter::media_parameter_type>(&buffer, isSwapped); 1159 1160 ssize_t parameterSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 1161 if (parameterSize > size_left(size, bufferStart, buffer)) 1162 return B_BAD_VALUE; 1163 1164 BParameter *parameter = MakeControl(mediaType); 1165 if (parameter == NULL) { 1166 ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n"); 1167 return B_ERROR; 1168 } 1169 1170 status_t status = parameter->Unflatten(parameter->TypeCode(), buffer, parameterSize); 1171 if (status < B_OK) { 1172 ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n"); 1173 delete parameter; 1174 return status; 1175 } 1176 1177 skip_in_buffer(&buffer, parameterSize); 1178 1179 // add the item to the list 1180 parameter->mGroup = this; 1181 parameter->mWeb = mWeb; 1182 mControls->AddItem(parameter); 1183 1184 // add it's old pointer value to the RefFix list kept by the owner web 1185 if (mWeb != NULL) 1186 mWeb->AddRefFix(oldPointer, parameter); 1187 } 1188 1189 // unflatten sub groups 1190 1191 count = read_from_buffer_swap32<int32>(&buffer, isSwapped); 1192 if (count < 0 || count * kAdditionalParameterGroupSize > size_left(size, bufferStart, buffer)) 1193 return B_BAD_VALUE; 1194 1195 for (int32 i = 0; i < count; i++) { 1196 // make sure we can read as many bytes 1197 if (size_left(size, bufferStart, buffer) < 12) 1198 return B_BAD_VALUE; 1199 1200 BParameterGroup *oldPointer = read_from_buffer_swap32<BParameterGroup *>(&buffer, isSwapped); 1201 type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped); 1202 1203 ssize_t groupSize = read_from_buffer_swap32<ssize_t>(&buffer, isSwapped); 1204 if (groupSize > size_left(size, bufferStart, buffer)) 1205 return B_BAD_VALUE; 1206 1207 BParameterGroup *group = new BParameterGroup(mWeb, "sub-unnamed"); 1208 if (group == NULL) { 1209 ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n"); 1210 return B_ERROR; 1211 } 1212 1213 status_t status = group->Unflatten(type, buffer, groupSize); 1214 if (status != B_OK) { 1215 ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n"); 1216 delete group; 1217 return status; 1218 } 1219 1220 skip_in_buffer(&buffer, groupSize); 1221 1222 mGroups->AddItem(group); 1223 1224 // add it's old pointer value to the RefFix list kept by the owner web 1225 if (mWeb != NULL) 1226 mWeb->AddRefFix(oldPointer, group); 1227 } 1228 1229 return B_OK; 1230 } 1231 1232 /************************************************************* 1233 * private BParameterGroup 1234 *************************************************************/ 1235 1236 /* 1237 // unimplemented 1238 BParameterGroup::BParameterGroup() 1239 BParameterGroup::BParameterGroup(const BParameterGroup &clone) 1240 BParameterGroup &BParameterGroup::operator=(const BParameterGroup &clone) 1241 */ 1242 1243 1244 /** Creates an uninitialized parameter of the specified type. 1245 * Unlike the BParameterGroup::MakeXXXParameter() type of methods, this 1246 * method does not add the parameter to this group automatically. 1247 */ 1248 1249 BParameter * 1250 BParameterGroup::MakeControl(int32 type) 1251 { 1252 CALLED(); 1253 1254 switch (type) { 1255 case BParameter::B_NULL_PARAMETER: 1256 return new BNullParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL); 1257 1258 case BParameter::B_DISCRETE_PARAMETER: 1259 return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, 1260 NULL); 1261 1262 case BParameter::B_CONTINUOUS_PARAMETER: 1263 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, 1264 NULL, NULL, 0, 0, 0); 1265 1266 case BParameter::B_TEXT_PARAMETER: 1267 return new BTextParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, 0); 1268 1269 default: 1270 ERROR("BParameterGroup::MakeControl unknown type %ld\n", type); 1271 return NULL; 1272 } 1273 } 1274 1275 1276 // #pragma mark - 1277 1278 /************************************************************* 1279 * public BParameter 1280 *************************************************************/ 1281 1282 1283 BParameter::media_parameter_type 1284 BParameter::Type() const 1285 { 1286 return mType; 1287 } 1288 1289 1290 BParameterWeb * 1291 BParameter::Web() const 1292 { 1293 return mWeb; 1294 } 1295 1296 1297 BParameterGroup * 1298 BParameter::Group() const 1299 { 1300 return mGroup; 1301 } 1302 1303 1304 const char * 1305 BParameter::Name() const 1306 { 1307 return mName; 1308 } 1309 1310 1311 const char * 1312 BParameter::Kind() const 1313 { 1314 return mKind; 1315 } 1316 1317 1318 const char * 1319 BParameter::Unit() const 1320 { 1321 return mUnit; 1322 } 1323 1324 1325 int32 1326 BParameter::ID() const 1327 { 1328 return mID; 1329 } 1330 1331 1332 void 1333 BParameter::SetFlags(uint32 flags) 1334 { 1335 mFlags = flags; 1336 } 1337 1338 1339 uint32 1340 BParameter::Flags() const 1341 { 1342 return mFlags; 1343 } 1344 1345 1346 status_t 1347 BParameter::GetValue(void *buffer, size_t *_ioSize, bigtime_t *_when) 1348 { 1349 CALLED(); 1350 1351 if (buffer == NULL || _ioSize == NULL) 1352 return B_BAD_VALUE; 1353 1354 size_t ioSize = *_ioSize; 1355 if (ioSize <= 0) 1356 return B_NO_MEMORY; 1357 1358 if (mWeb == NULL) { 1359 ERROR("BParameter::GetValue: no parent BParameterWeb\n"); 1360 return B_NO_INIT; 1361 } 1362 1363 media_node node = mWeb->Node(); 1364 if (IS_INVALID_NODE(node)) { 1365 ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); 1366 return B_NO_INIT; 1367 } 1368 1369 controllable_get_parameter_data_request request; 1370 controllable_get_parameter_data_reply reply; 1371 1372 area_id area; 1373 void *data; 1374 if (ioSize > MAX_PARAMETER_DATA) { 1375 // create an area if large data needs to be transfered 1376 area = create_area("get parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(ioSize), 1377 B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1378 if (area < B_OK) { 1379 ERROR("BParameter::GetValue can't create area of %ld bytes\n", ioSize); 1380 return B_NO_MEMORY; 1381 } 1382 } else { 1383 area = -1; 1384 data = reply.rawdata; 1385 } 1386 1387 request.parameter_id = mID; 1388 request.requestsize = ioSize; 1389 request.area = area; 1390 1391 status_t status = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_DATA, &request, 1392 sizeof(request), &reply, sizeof(reply)); 1393 if (status == B_OK) { 1394 // we don't want to copy more than the buffer provides 1395 if (reply.size < ioSize) 1396 ioSize = reply.size; 1397 1398 memcpy(buffer, data, ioSize); 1399 1400 // store reported values 1401 1402 *_ioSize = reply.size; 1403 if (_when != NULL) 1404 *_when = reply.last_change; 1405 } else 1406 ERROR("BParameter::GetValue parameter '%s' querying node %d, " 1407 "port %d failed: %s\n", mName, (int)node.node, (int)node.port, 1408 strerror(status)); 1409 1410 if (area >= B_OK) 1411 delete_area(area); 1412 1413 return status; 1414 } 1415 1416 1417 status_t 1418 BParameter::SetValue(const void *buffer, size_t size, bigtime_t when) 1419 { 1420 CALLED(); 1421 1422 controllable_set_parameter_data_request request; 1423 controllable_set_parameter_data_reply reply; 1424 media_node node; 1425 area_id area; 1426 status_t rv; 1427 void *data; 1428 1429 if (buffer == 0) 1430 return B_BAD_VALUE; 1431 if (size <= 0) 1432 return B_NO_MEMORY; 1433 1434 if (mWeb == 0) { 1435 ERROR("BParameter::SetValue: no parent BParameterWeb\n"); 1436 return B_NO_INIT; 1437 } 1438 1439 node = mWeb->Node(); 1440 if (IS_INVALID_NODE(node)) { 1441 ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); 1442 return B_NO_INIT; 1443 } 1444 1445 if (size > MAX_PARAMETER_DATA) { 1446 // create an area if large data needs to be transfered 1447 area = create_area("set parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1448 if (area < B_OK) { 1449 ERROR("BParameter::SetValue can't create area of %ld bytes\n", size); 1450 return B_NO_MEMORY; 1451 } 1452 } else { 1453 area = -1; 1454 data = request.rawdata; 1455 } 1456 1457 memcpy(data, buffer, size); 1458 request.parameter_id = mID; 1459 request.when = when; 1460 request.area = area; 1461 request.size = size; 1462 1463 rv = QueryPort(node.port, CONTROLLABLE_SET_PARAMETER_DATA, &request, sizeof(request), &reply, sizeof(reply)); 1464 if (rv != B_OK) 1465 ERROR("BParameter::SetValue querying node failed\n"); 1466 1467 if (area != -1) 1468 delete_area(area); 1469 1470 return rv; 1471 } 1472 1473 1474 int32 1475 BParameter::CountChannels() 1476 { 1477 return mChannels; 1478 } 1479 1480 1481 void 1482 BParameter::SetChannelCount(int32 channel_count) 1483 { 1484 mChannels = channel_count; 1485 } 1486 1487 1488 media_type 1489 BParameter::MediaType() 1490 { 1491 return mMediaType; 1492 } 1493 1494 1495 void 1496 BParameter::SetMediaType(media_type m_type) 1497 { 1498 mMediaType = m_type; 1499 } 1500 1501 1502 int32 1503 BParameter::CountInputs() 1504 { 1505 ASSERT(mInputs != NULL); 1506 1507 return mInputs->CountItems(); 1508 } 1509 1510 1511 BParameter * 1512 BParameter::InputAt(int32 index) 1513 { 1514 ASSERT(mInputs != NULL); 1515 1516 return static_cast<BParameter *>(mInputs->ItemAt(index)); 1517 } 1518 1519 1520 void 1521 BParameter::AddInput(BParameter *input) 1522 { 1523 CALLED(); 1524 1525 // BeBook has this method returning a status value, 1526 // but it should be updated 1527 if (input == NULL) 1528 return; 1529 1530 ASSERT(mInputs != NULL); 1531 1532 if (mInputs->HasItem(input)) { 1533 // if already in input list, don't duplicate. 1534 return; 1535 } 1536 1537 mInputs->AddItem(input); 1538 input->AddOutput(this); 1539 } 1540 1541 1542 int32 1543 BParameter::CountOutputs() 1544 { 1545 ASSERT(mOutputs != NULL); 1546 1547 return mOutputs->CountItems(); 1548 } 1549 1550 1551 BParameter * 1552 BParameter::OutputAt(int32 index) 1553 { 1554 ASSERT(mOutputs != NULL); 1555 1556 return static_cast<BParameter *>(mOutputs->ItemAt(index)); 1557 } 1558 1559 1560 void 1561 BParameter::AddOutput(BParameter *output) 1562 { 1563 CALLED(); 1564 1565 // BeBook has this method returning a status value, 1566 // but it should be updated 1567 if (output == NULL) 1568 return; 1569 1570 ASSERT(mOutputs != NULL); 1571 1572 if (mOutputs->HasItem(output)) { 1573 // if already in output list, don't duplicate. 1574 return; 1575 } 1576 1577 mOutputs->AddItem(output); 1578 output->AddInput(this); 1579 } 1580 1581 1582 bool 1583 BParameter::IsFixedSize() const 1584 { 1585 return false; 1586 } 1587 1588 1589 type_code 1590 BParameter::TypeCode() const 1591 { 1592 return B_MEDIA_PARAMETER_TYPE; 1593 } 1594 1595 1596 ssize_t 1597 BParameter::FlattenedSize() const 1598 { 1599 CALLED(); 1600 /* 1601 ?? (0x02040607): 4 bytes 1602 BParameter Struct Size (in bytes): 4 bytes 1603 ID: 4 bytes 1604 Name String Length: 1 byte (??) 1605 Name String: 'Name String Length' bytes 1606 Kind String Length: 1 byte (??) 1607 Kind String: 'Kind String Length' bytes 1608 Unit String Length: 1 byte (??) 1609 Unit String: 'Unit String Length' bytes 1610 Inputs Count: 4 bytes 1611 Inputs (pointers): ('Inputs Count')*4 bytes 1612 Outputs Count: 4 bytes 1613 Outputs (pointers): ('Outputs Count')*4 bytes 1614 Media Type: 4 bytes 1615 ChannelCount: 4 bytes 1616 Flags: 4 bytes 1617 */ 1618 //35 bytes are guaranteed, after that, add the variable length parts. 1619 ssize_t size = 35; 1620 1621 if (mName != NULL) 1622 size += strlen(mName); 1623 if (mKind != NULL) 1624 size += strlen(mKind); 1625 if (mUnit != NULL) 1626 size += strlen(mUnit); 1627 1628 if (mInputs != NULL) 1629 size += mInputs->CountItems() * sizeof(BParameter *); 1630 1631 if (mOutputs != NULL) 1632 size += mOutputs->CountItems() * sizeof(BParameter *); 1633 1634 return size; 1635 } 1636 1637 1638 status_t 1639 BParameter::Flatten(void *buffer, ssize_t size) const 1640 { 1641 CALLED(); 1642 1643 if (buffer == NULL) { 1644 ERROR("BParameter::Flatten buffer is NULL\n"); 1645 return B_NO_INIT; 1646 } 1647 1648 // NOTICE: It is important that this value is the size returned by 1649 // BParameter::FlattenedSize(), not by a descendent's override of this method. 1650 ssize_t actualSize = BParameter::FlattenedSize(); 1651 if (size < actualSize) { 1652 ERROR("BParameter::Flatten(): size too small\n"); 1653 return B_NO_MEMORY; 1654 } 1655 1656 write_to_buffer<uint32>(&buffer, kParameterMagic); 1657 write_to_buffer<ssize_t>(&buffer, actualSize); 1658 write_to_buffer<int32>(&buffer, mID); 1659 1660 write_string_to_buffer(&buffer, mName); 1661 write_string_to_buffer(&buffer, mKind); 1662 write_string_to_buffer(&buffer, mUnit); 1663 1664 // flatten and write the list of inputs 1665 ssize_t count = mInputs ? mInputs->CountItems() : 0; 1666 write_to_buffer<ssize_t>(&buffer, count); 1667 1668 if (count > 0) { 1669 memcpy(buffer, mInputs->Items(), sizeof(BParameter *) * count); 1670 skip_in_buffer(&buffer, sizeof(BParameter *) * count); 1671 } 1672 1673 // flatten and write the list of outputs 1674 count = mOutputs ? mOutputs->CountItems() : 0; 1675 write_to_buffer<ssize_t>(&buffer, count); 1676 1677 if (count > 0) { 1678 memcpy(buffer, mOutputs->Items(), sizeof(BParameter *) * count); 1679 skip_in_buffer(&buffer, sizeof(BParameter *) * count); 1680 } 1681 1682 write_to_buffer<media_type>(&buffer, mMediaType); 1683 write_to_buffer<int32>(&buffer, mChannels); 1684 write_to_buffer<uint32>(&buffer, mFlags); 1685 1686 return B_OK; 1687 } 1688 1689 1690 bool 1691 BParameter::AllowsTypeCode(type_code code) const 1692 { 1693 return (code == TypeCode()); 1694 } 1695 1696 1697 status_t 1698 BParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 1699 { 1700 CALLED(); 1701 1702 if (!AllowsTypeCode(code)) { 1703 ERROR("BParameter::Unflatten(): wrong type code\n"); 1704 return B_BAD_TYPE; 1705 } 1706 1707 if (buffer == NULL) { 1708 ERROR("BParameter::Unflatten(): buffer is NULL\n"); 1709 return B_NO_INIT; 1710 } 1711 1712 // if the buffer is smaller than the size needed to read the 1713 // signature and struct size fields, then there is a problem 1714 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 1715 ERROR("BParameter::Unflatten() size too small\n"); 1716 return B_BAD_VALUE; 1717 } 1718 1719 const void *bufferStart = buffer; 1720 1721 // check magic 1722 1723 uint32 magic = read_from_buffer<uint32>(&buffer); 1724 if (magic == B_SWAP_INT32(kParameterMagic)) 1725 mSwapDetected = true; 1726 else if (magic == kParameterMagic) 1727 mSwapDetected = false; 1728 else { 1729 ERROR("BParameter::Unflatten(): bad magic\n"); 1730 return B_BAD_TYPE; 1731 } 1732 1733 ssize_t parameterSize = read_from_buffer_swap32<ssize_t>(&buffer, mSwapDetected); 1734 if (parameterSize > size) { 1735 ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n", parameterSize, size); 1736 return B_BAD_VALUE; 1737 } 1738 1739 //if the struct doesn't meet the minimum size for 1740 //a flattened BParameter, then return an error. 1741 //MinFlattenedParamSize = 1742 //ID (4 bytes) 1743 //Name String Length (1 byte) 1744 //Kind String Length (1 byte) 1745 //Unit String Length (1 byte) 1746 //Inputs Count (4 bytes) 1747 //Outputs Count (4 bytes) 1748 //Media Type (4 bytes) 1749 //Channel Count (4 bytes) 1750 //Flags (4 bytes) 1751 //TOTAL: 27 bytes 1752 const ssize_t MinFlattenedParamSize(27); 1753 if (parameterSize < MinFlattenedParamSize) { 1754 ERROR("BParameter::Unflatten out of memory (2)\n"); 1755 return B_ERROR; 1756 } 1757 1758 mID = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1759 1760 if (read_string_from_buffer(&buffer, &mName, size_left(size, bufferStart, buffer)) < B_OK 1761 || read_string_from_buffer(&buffer, &mKind, size_left(size, bufferStart, buffer)) < B_OK 1762 || read_string_from_buffer(&buffer, &mUnit, size_left(size, bufferStart, buffer)) < B_OK) 1763 return B_NO_MEMORY; 1764 1765 // read the list of inputs 1766 1767 // it will directly add the pointers in the flattened message to the list; 1768 // these will be fixed to point to the real inputs/outputs later in FixRefs() 1769 1770 int32 count = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1771 1772 if (mInputs == NULL) 1773 mInputs = new BList(); 1774 else 1775 mInputs->MakeEmpty(); 1776 1777 for (int32 i = 0; i < count; i++) { 1778 mInputs->AddItem(read_from_buffer_swap32<BParameter * const>(&buffer, mSwapDetected)); 1779 } 1780 1781 // read the list of outputs 1782 1783 count = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1784 1785 if (mOutputs == NULL) 1786 mOutputs = new BList(); 1787 else 1788 mOutputs->MakeEmpty(); 1789 1790 for (int32 i = 0; i < count; i++) { 1791 mOutputs->AddItem(read_from_buffer_swap32<BParameter * const>(&buffer, mSwapDetected)); 1792 } 1793 1794 mMediaType = read_from_buffer_swap32<media_type>(&buffer, mSwapDetected); 1795 mChannels = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1796 mFlags = read_from_buffer_swap32<uint32>(&buffer, mSwapDetected); 1797 1798 return B_OK; 1799 } 1800 1801 1802 /************************************************************* 1803 * private BParameter 1804 *************************************************************/ 1805 1806 1807 BParameter::BParameter(int32 id, media_type mediaType, media_parameter_type type, 1808 BParameterWeb *web, const char *name, const char *kind, const char *unit) 1809 : 1810 mID(id), 1811 mType(type), 1812 mWeb(web), 1813 mGroup(NULL), 1814 mSwapDetected(true), 1815 mMediaType(mediaType), 1816 mChannels(1), 1817 mFlags(0) 1818 { 1819 CALLED(); 1820 1821 mName = strndup(name, 256); 1822 mKind = strndup(kind, 256); 1823 mUnit = strndup(unit, 256); 1824 1825 // create empty input/output lists 1826 mInputs = new BList(); 1827 mOutputs = new BList(); 1828 } 1829 1830 1831 BParameter::~BParameter() 1832 { 1833 CALLED(); 1834 1835 // don't worry about the mWeb/mGroup properties, you don't need 1836 // to remove yourself from a web/group since the only way in which 1837 // a parameter is destroyed is when the owner web/group destroys it 1838 1839 free(mName); 1840 free(mKind); 1841 free(mUnit); 1842 1843 delete mInputs; 1844 delete mOutputs; 1845 1846 mName = NULL; mKind = NULL; mUnit = NULL; mInputs = NULL; mOutputs = NULL; 1847 } 1848 1849 1850 /** Replaces references to items in the old list with the corresponding 1851 * items in the updated list. The references are replaced in the input 1852 * and output lists. 1853 * This is called by BParameterWeb::Unflatten(). 1854 */ 1855 1856 void 1857 BParameter::FixRefs(BList &old, BList &updated) 1858 { 1859 CALLED(); 1860 ASSERT(mInputs != NULL); 1861 ASSERT(mOutputs != NULL); 1862 1863 // update inputs 1864 1865 void **items = static_cast<void **>(mInputs->Items()); 1866 int32 count = mInputs->CountItems(); 1867 1868 for (int32 i = 0; i < count; i++) { 1869 int32 index = old.IndexOf(items[i]); 1870 if (index >= 0) 1871 items[i] = updated.ItemAt(index); 1872 else { 1873 ERROR("BParameter::FixRefs(): No mapping found for input"); 1874 items[i] = NULL; 1875 } 1876 } 1877 1878 // remove all NULL inputs (those which couldn't be mapped) 1879 1880 for (int32 i = count; i-- > 0;) { 1881 if (items[i] == NULL) 1882 mInputs->RemoveItem(i); 1883 } 1884 1885 // update outputs 1886 1887 items = static_cast<void **>(mOutputs->Items()); 1888 count = mOutputs->CountItems(); 1889 1890 for (int32 i = 0; i < count; i++) { 1891 int32 index = old.IndexOf(items[i]); 1892 if (index >= 0) 1893 items[i] = updated.ItemAt(index); 1894 else { 1895 ERROR("BParameter::FixRefs(): No mapping found for output"); 1896 items[i] = NULL; 1897 } 1898 } 1899 1900 // remove all NULL outputs (those which couldn't be mapped) 1901 1902 for (int32 i = count; i-- > 0;) { 1903 if (items[i] == NULL) 1904 mOutputs->RemoveItem(i); 1905 } 1906 } 1907 1908 1909 // #pragma mark - 1910 1911 /************************************************************* 1912 * public BContinuousParameter 1913 *************************************************************/ 1914 1915 1916 type_code 1917 BContinuousParameter::ValueType() 1918 { 1919 return B_FLOAT_TYPE; 1920 } 1921 1922 1923 float 1924 BContinuousParameter::MinValue() 1925 { 1926 return mMinimum; 1927 } 1928 1929 1930 float 1931 BContinuousParameter::MaxValue() 1932 { 1933 return mMaximum; 1934 } 1935 1936 1937 float 1938 BContinuousParameter::ValueStep() 1939 { 1940 return mStepping; 1941 } 1942 1943 1944 void 1945 BContinuousParameter::SetResponse(int resp, float factor, float offset) 1946 { 1947 mResponse = static_cast<response>(resp); 1948 mFactor = factor; 1949 mOffset = offset; 1950 } 1951 1952 1953 void 1954 BContinuousParameter::GetResponse(int *resp, float *factor, float *offset) 1955 { 1956 if (resp != NULL) 1957 *resp = mResponse; 1958 if (factor != NULL) 1959 *factor = mFactor; 1960 if (offset != NULL) 1961 *offset = mOffset; 1962 } 1963 1964 1965 ssize_t 1966 BContinuousParameter::FlattenedSize() const 1967 { 1968 CALLED(); 1969 1970 // only adds a fixed amount of bytes 1971 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize; 1972 } 1973 1974 1975 status_t 1976 BContinuousParameter::Flatten(void *buffer, ssize_t size) const 1977 { 1978 CALLED(); 1979 1980 if (buffer == NULL) { 1981 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n"); 1982 return B_NO_INIT; 1983 } 1984 1985 ssize_t parameterSize = BParameter::FlattenedSize(); 1986 if (size < (parameterSize + kAdditionalContinuousParameterSize)) { 1987 ERROR("BContinuousParameter::Flatten(): size to small\n"); 1988 return B_NO_MEMORY; 1989 } 1990 1991 status_t status = BParameter::Flatten(buffer, size); 1992 if (status != B_OK) { 1993 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n"); 1994 return status; 1995 } 1996 1997 // add our data to the general flattened BParameter 1998 1999 skip_in_buffer(&buffer, parameterSize); 2000 2001 write_to_buffer<float>(&buffer, mMinimum); 2002 write_to_buffer<float>(&buffer, mMaximum); 2003 write_to_buffer<float>(&buffer, mStepping); 2004 write_to_buffer<response>(&buffer, mResponse); 2005 write_to_buffer<float>(&buffer, mFactor); 2006 write_to_buffer<float>(&buffer, mOffset); 2007 2008 return B_OK; 2009 } 2010 2011 2012 status_t 2013 BContinuousParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2014 { 2015 CALLED(); 2016 2017 // we try to check if the buffer size is long enough to hold an object 2018 // as early as possible. 2019 2020 if (!AllowsTypeCode(code)) { 2021 ERROR("BContinuousParameter::Unflatten wrong type code\n"); 2022 return B_BAD_TYPE; 2023 } 2024 2025 if (buffer == NULL) { 2026 ERROR("BContinuousParameter::Unflatten buffer is NULL\n"); 2027 return B_NO_INIT; 2028 } 2029 2030 // if the buffer is smaller than the size needed to read the 2031 // signature and struct size fields, then there is a problem 2032 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 2033 ERROR("BContinuousParameter::Unflatten size too small\n"); 2034 return B_ERROR; 2035 } 2036 2037 status_t status = BParameter::Unflatten(code, buffer, size); 2038 if (status != B_OK) { 2039 ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten failed\n"); 2040 return status; 2041 } 2042 2043 ssize_t parameterSize = BParameter::FlattenedSize(); 2044 skip_in_buffer(&buffer, parameterSize); 2045 2046 if (size < (parameterSize + kAdditionalContinuousParameterSize)) { 2047 ERROR("BContinuousParameter::Unflatten(): buffer too small\n"); 2048 return B_BAD_VALUE; 2049 } 2050 2051 mMinimum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2052 mMaximum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2053 mStepping = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2054 mResponse = read_from_buffer_swap32<response>(&buffer, SwapOnUnflatten()); 2055 mFactor = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2056 mOffset = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2057 2058 return B_OK; 2059 } 2060 2061 2062 /************************************************************* 2063 * private BContinuousParameter 2064 *************************************************************/ 2065 2066 2067 BContinuousParameter::BContinuousParameter(int32 id, media_type m_type, 2068 BParameterWeb *web, const char *name, const char *kind, const char *unit, 2069 float minimum, float maximum, float stepping) 2070 : BParameter(id, m_type, B_CONTINUOUS_PARAMETER, web, name, kind, unit), 2071 mMinimum(minimum), mMaximum(maximum), mStepping(stepping), 2072 mResponse(B_LINEAR), mFactor(1.0), mOffset(0.0) 2073 { 2074 CALLED(); 2075 } 2076 2077 2078 BContinuousParameter::~BContinuousParameter() 2079 { 2080 CALLED(); 2081 } 2082 2083 2084 // #pragma mark - 2085 2086 /************************************************************* 2087 * public BDiscreteParameter 2088 *************************************************************/ 2089 2090 2091 type_code 2092 BDiscreteParameter::ValueType() 2093 { 2094 return B_INT32_TYPE; 2095 } 2096 2097 2098 int32 2099 BDiscreteParameter::CountItems() 2100 { 2101 ASSERT(mValues != NULL); 2102 2103 return mValues->CountItems(); 2104 } 2105 2106 2107 const char * 2108 BDiscreteParameter::ItemNameAt(int32 index) 2109 { 2110 ASSERT(mSelections != NULL); 2111 2112 return reinterpret_cast<const char *>(mSelections->ItemAt(index)); 2113 } 2114 2115 2116 int32 2117 BDiscreteParameter::ItemValueAt(int32 index) 2118 { 2119 ASSERT(mValues != NULL); 2120 2121 int32 *item = static_cast<int32 *>(mValues->ItemAt(index)); 2122 if (item == NULL) 2123 return 0; 2124 2125 return *item; 2126 } 2127 2128 2129 status_t 2130 BDiscreteParameter::AddItem(int32 value, const char *name) 2131 { 2132 CALLED(); 2133 //TRACE("\tthis = %p, value = %ld, name = \"%s\"\n", this, value, name); 2134 ASSERT(mValues != NULL); 2135 ASSERT(mSelections != NULL); 2136 2137 int32 *valueCopy = new int32(value); 2138 char *nameCopy = strndup(name, 256); 2139 if (name != NULL && nameCopy == NULL) 2140 return B_NO_MEMORY; 2141 2142 if (!mValues->AddItem(valueCopy) 2143 || !mSelections->AddItem(nameCopy)) 2144 return B_NO_MEMORY; 2145 2146 return B_OK; 2147 } 2148 2149 2150 status_t 2151 BDiscreteParameter::MakeItemsFromInputs() 2152 { 2153 CALLED(); 2154 ASSERT(mValues != NULL); 2155 ASSERT(mSelections != NULL); 2156 ASSERT(mInputs != NULL); 2157 2158 int32 count = mInputs->CountItems(); 2159 for(int32 i = 0; i < count; i++) { 2160 BParameter *parameter = static_cast<BParameter *>(mInputs->ItemAt(i)); 2161 AddItem(i, parameter->Name()); 2162 } 2163 2164 return B_OK; 2165 } 2166 2167 2168 status_t 2169 BDiscreteParameter::MakeItemsFromOutputs() 2170 { 2171 CALLED(); 2172 ASSERT(mValues != NULL); 2173 ASSERT(mSelections != NULL); 2174 ASSERT(mOutputs != NULL); 2175 2176 int32 count = mOutputs->CountItems(); 2177 for(int32 i = 0; i < count; i++) { 2178 BParameter *parameter = static_cast<BParameter *>(mOutputs->ItemAt(i)); 2179 AddItem(i, parameter->Name()); 2180 } 2181 2182 return B_OK; 2183 } 2184 2185 2186 void 2187 BDiscreteParameter::MakeEmpty() 2188 { 2189 CALLED(); 2190 ASSERT(mValues != NULL); 2191 ASSERT(mSelections != NULL); 2192 2193 for (int32 i = mValues->CountItems(); i-- > 0;) { 2194 delete static_cast<int32 *>(mValues->ItemAt(i)); 2195 } 2196 mValues->MakeEmpty(); 2197 2198 for(int32 i = mSelections->CountItems(); i-- > 0;) { 2199 free(static_cast<char *>(mSelections->ItemAt(i))); 2200 } 2201 mSelections->MakeEmpty(); 2202 } 2203 2204 2205 ssize_t 2206 BDiscreteParameter::FlattenedSize() const 2207 { 2208 CALLED(); 2209 2210 ssize_t size = BParameter::FlattenedSize() + kAdditionalDiscreteParameterSize; 2211 2212 int32 count = mValues ? mValues->CountItems() : 0; 2213 for (int32 i = 0; i < count; i++) { 2214 char *selection = static_cast<char *>(mSelections->ItemAt(i)); 2215 2216 if (selection != NULL) 2217 size += min_c(strlen(selection), 255); 2218 2219 size += 5; 2220 // string length + value 2221 } 2222 2223 return size; 2224 } 2225 2226 2227 status_t 2228 BDiscreteParameter::Flatten(void *buffer, ssize_t size) const 2229 { 2230 CALLED(); 2231 2232 if (buffer == NULL) { 2233 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n"); 2234 return B_NO_INIT; 2235 } 2236 2237 ssize_t parameterSize = BParameter::FlattenedSize(); 2238 2239 if (size < FlattenedSize()) { 2240 ERROR("BDiscreteParameter::Flatten(): size too small\n"); 2241 return B_NO_MEMORY; 2242 } 2243 2244 status_t status = BParameter::Flatten(buffer, size); 2245 if (status != B_OK) { 2246 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n"); 2247 return status; 2248 } 2249 2250 skip_in_buffer(&buffer, parameterSize); 2251 2252 int32 count = mValues ? mValues->CountItems() : 0; 2253 write_to_buffer<int32>(&buffer, count); 2254 2255 // write out all value/name pairs 2256 for (int32 i = 0; i < count; i++) { 2257 const char *selection = static_cast<char *>(mSelections->ItemAt(i)); 2258 const int32 *value = static_cast<int32 *>(mValues->ItemAt(i)); 2259 2260 write_string_to_buffer(&buffer, selection); 2261 write_to_buffer<int32>(&buffer, value ? *value : 0); 2262 } 2263 2264 return B_OK; 2265 } 2266 2267 2268 status_t 2269 BDiscreteParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2270 { 2271 CALLED(); 2272 2273 if (!AllowsTypeCode(code)) { 2274 ERROR("BDiscreteParameter::Unflatten(): bad type code\n"); 2275 return B_BAD_TYPE; 2276 } 2277 2278 if (buffer == NULL) { 2279 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n"); 2280 return B_NO_INIT; 2281 } 2282 2283 // if the buffer is smaller than the size needed to read the 2284 // signature and struct size fields, then there is a problem 2285 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 2286 ERROR("BDiscreteParameter::Unflatten(): size too small\n"); 2287 return B_ERROR; 2288 } 2289 2290 const void *bufferStart = buffer; 2291 2292 status_t status = BParameter::Unflatten(code, buffer, size); 2293 if (status != B_OK) { 2294 ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n"); 2295 return status; 2296 } 2297 2298 ssize_t parameterSize = BParameter::FlattenedSize(); 2299 skip_in_buffer(&buffer, parameterSize); 2300 2301 if (size < (parameterSize + kAdditionalDiscreteParameterSize)) { 2302 ERROR("BDiscreteParameter::Unflatten(): buffer too small\n"); 2303 return B_BAD_VALUE; 2304 } 2305 2306 int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten()); 2307 2308 // clear any existing name/value pairs 2309 MakeEmpty(); 2310 2311 for (int32 i = 0; i < count; i++) { 2312 char *name; 2313 if (read_string_from_buffer(&buffer, &name, size_left(size, bufferStart, buffer)) < B_OK) 2314 return B_BAD_DATA; 2315 2316 if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) 2317 return B_BAD_DATA; 2318 2319 int32 value = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten()); 2320 2321 AddItem(value, name); 2322 } 2323 2324 return B_OK; 2325 } 2326 2327 2328 /************************************************************* 2329 * private BDiscreteParameter 2330 *************************************************************/ 2331 2332 2333 BDiscreteParameter::BDiscreteParameter(int32 id, media_type mediaType, 2334 BParameterWeb *web, const char *name, const char *kind) 2335 : BParameter(id, mediaType, B_DISCRETE_PARAMETER, web, name, kind, NULL) 2336 { 2337 CALLED(); 2338 2339 mSelections = new BList(); 2340 mValues = new BList(); 2341 } 2342 2343 2344 BDiscreteParameter::~BDiscreteParameter() 2345 { 2346 CALLED(); 2347 2348 MakeEmpty(); 2349 2350 delete mSelections; 2351 delete mValues; 2352 2353 mSelections = NULL; mValues = NULL; 2354 } 2355 2356 2357 // #pragma mark - 2358 2359 /************************************************************* 2360 * public BNullParameter 2361 *************************************************************/ 2362 2363 2364 type_code 2365 BNullParameter::ValueType() 2366 { 2367 // NULL parameters have no value type 2368 return 0; 2369 } 2370 2371 2372 ssize_t 2373 BNullParameter::FlattenedSize() const 2374 { 2375 return BParameter::FlattenedSize(); 2376 } 2377 2378 2379 status_t 2380 BNullParameter::Flatten(void *buffer, ssize_t size) const 2381 { 2382 return BParameter::Flatten(buffer, size); 2383 } 2384 2385 2386 status_t 2387 BNullParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2388 { 2389 return BParameter::Unflatten(code, buffer, size); 2390 } 2391 2392 2393 /************************************************************* 2394 * private BNullParameter 2395 *************************************************************/ 2396 2397 2398 BNullParameter::BNullParameter(int32 id, media_type mediaType, BParameterWeb *web, 2399 const char *name, const char *kind) 2400 : BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL) 2401 { 2402 } 2403 2404 2405 BNullParameter::~BNullParameter() 2406 { 2407 } 2408 2409 2410 // #pragma mark - 2411 2412 /************************************************************* 2413 * public BTextParameter 2414 *************************************************************/ 2415 2416 2417 size_t 2418 BTextParameter::MaxBytes() const 2419 { 2420 // NULL parameters have no value type 2421 return mMaxBytes; 2422 } 2423 2424 2425 type_code 2426 BTextParameter::ValueType() 2427 { 2428 // NULL parameters have no value type 2429 return 0; 2430 } 2431 2432 2433 ssize_t 2434 BTextParameter::FlattenedSize() const 2435 { 2436 return BParameter::FlattenedSize() + sizeof(mMaxBytes); 2437 } 2438 2439 2440 status_t 2441 BTextParameter::Flatten(void *buffer, ssize_t size) const 2442 { 2443 if (buffer == NULL) { 2444 ERROR("BTextParameter::Flatten(): buffer is NULL\n"); 2445 return B_NO_INIT; 2446 } 2447 2448 ssize_t parameterSize = BParameter::FlattenedSize(); 2449 if (size < static_cast<ssize_t>(parameterSize + sizeof(mMaxBytes))) { 2450 ERROR("BContinuousParameter::Flatten(): size to small\n"); 2451 return B_NO_MEMORY; 2452 } 2453 2454 status_t status = BParameter::Flatten(buffer, size); 2455 if (status != B_OK) { 2456 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n"); 2457 return status; 2458 } 2459 2460 // add our data to the general flattened BParameter 2461 2462 skip_in_buffer(&buffer, parameterSize); 2463 2464 write_to_buffer<uint32>(&buffer, mMaxBytes); 2465 2466 return B_OK; 2467 } 2468 2469 2470 status_t 2471 BTextParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2472 { 2473 // we try to check if the buffer size is long enough to hold an object 2474 // as early as possible. 2475 2476 if (!AllowsTypeCode(code)) { 2477 ERROR("BTextParameter::Unflatten wrong type code\n"); 2478 return B_BAD_TYPE; 2479 } 2480 2481 if (buffer == NULL) { 2482 ERROR("BTextParameter::Unflatten buffer is NULL\n"); 2483 return B_NO_INIT; 2484 } 2485 2486 if (size < static_cast<ssize_t>(sizeof(mMaxBytes))) { 2487 ERROR("BTextParameter::Unflatten size too small\n"); 2488 return B_ERROR; 2489 } 2490 2491 status_t status = BParameter::Unflatten(code, buffer, size); 2492 if (status != B_OK) { 2493 ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n"); 2494 return status; 2495 } 2496 2497 ssize_t parameterSize = BParameter::FlattenedSize(); 2498 skip_in_buffer(&buffer, parameterSize); 2499 2500 if (size < static_cast<ssize_t>(parameterSize + sizeof(mMaxBytes))) { 2501 ERROR("BTextParameter::Unflatten(): buffer too small\n"); 2502 return B_BAD_VALUE; 2503 } 2504 2505 mMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten()); 2506 2507 return B_OK; 2508 } 2509 2510 2511 /************************************************************* 2512 * private BTextParameter 2513 *************************************************************/ 2514 2515 2516 BTextParameter::BTextParameter(int32 id, media_type mediaType, BParameterWeb *web, 2517 const char *name, const char *kind, size_t max_bytes) 2518 : BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL) 2519 { 2520 mMaxBytes = max_bytes; 2521 } 2522 2523 2524 BTextParameter::~BTextParameter() 2525 { 2526 } 2527 2528 2529 // #pragma mark - 2530 // reserved functions 2531 2532 2533 status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; } 2534 status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; } 2535 status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; } 2536 status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; } 2537 status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; } 2538 status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; } 2539 status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; } 2540 status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; } 2541 2542 status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; } 2543 status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; } 2544 status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; } 2545 status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; } 2546 status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; } 2547 status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; } 2548 status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; } 2549 status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; } 2550 2551 status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; } 2552 status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; } 2553 status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; } 2554 status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; } 2555 status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; } 2556 status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; } 2557 status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; } 2558 status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; } 2559 2560 status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; } 2561 status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; } 2562 status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; } 2563 status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; } 2564 status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; } 2565 status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; } 2566 status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; } 2567 status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; } 2568 2569 status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; } 2570 status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; } 2571 status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; } 2572 status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; } 2573 status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; } 2574 status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; } 2575 status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; } 2576 status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; } 2577 2578 status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; } 2579 status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; } 2580 status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; } 2581 status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; } 2582 status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; } 2583 status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; } 2584 status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; } 2585 status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; } 2586 2587 status_t BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR; } 2588 status_t BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR; } 2589 status_t BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR; } 2590 status_t BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR; } 2591 status_t BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR; } 2592 status_t BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR; } 2593 status_t BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR; } 2594 status_t BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR; } 2595 2596 2597