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, NULL); 1260 1261 case BParameter::B_CONTINUOUS_PARAMETER: 1262 return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, NULL, 0, 0, 0); 1263 1264 case BParameter::B_TEXT_PARAMETER: 1265 return new BTextParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, NULL); 1266 1267 default: 1268 ERROR("BParameterGroup::MakeControl unknown type %ld\n", type); 1269 return NULL; 1270 } 1271 } 1272 1273 1274 // #pragma mark - 1275 1276 /************************************************************* 1277 * public BParameter 1278 *************************************************************/ 1279 1280 1281 BParameter::media_parameter_type 1282 BParameter::Type() const 1283 { 1284 return mType; 1285 } 1286 1287 1288 BParameterWeb * 1289 BParameter::Web() const 1290 { 1291 return mWeb; 1292 } 1293 1294 1295 BParameterGroup * 1296 BParameter::Group() const 1297 { 1298 return mGroup; 1299 } 1300 1301 1302 const char * 1303 BParameter::Name() const 1304 { 1305 return mName; 1306 } 1307 1308 1309 const char * 1310 BParameter::Kind() const 1311 { 1312 return mKind; 1313 } 1314 1315 1316 const char * 1317 BParameter::Unit() const 1318 { 1319 return mUnit; 1320 } 1321 1322 1323 int32 1324 BParameter::ID() const 1325 { 1326 return mID; 1327 } 1328 1329 1330 void 1331 BParameter::SetFlags(uint32 flags) 1332 { 1333 mFlags = flags; 1334 } 1335 1336 1337 uint32 1338 BParameter::Flags() const 1339 { 1340 return mFlags; 1341 } 1342 1343 1344 status_t 1345 BParameter::GetValue(void *buffer, size_t *_ioSize, bigtime_t *_when) 1346 { 1347 CALLED(); 1348 1349 if (buffer == NULL || _ioSize == NULL) 1350 return B_BAD_VALUE; 1351 1352 size_t ioSize = *_ioSize; 1353 if (ioSize <= 0) 1354 return B_NO_MEMORY; 1355 1356 if (mWeb == NULL) { 1357 ERROR("BParameter::GetValue: no parent BParameterWeb\n"); 1358 return B_NO_INIT; 1359 } 1360 1361 media_node node = mWeb->Node(); 1362 if (IS_INVALID_NODE(node)) { 1363 ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); 1364 return B_NO_INIT; 1365 } 1366 1367 controllable_get_parameter_data_request request; 1368 controllable_get_parameter_data_reply reply; 1369 1370 area_id area; 1371 void *data; 1372 if (ioSize > MAX_PARAMETER_DATA) { 1373 // create an area if large data needs to be transfered 1374 area = create_area("get parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(ioSize), 1375 B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1376 if (area < B_OK) { 1377 ERROR("BParameter::GetValue can't create area of %ld bytes\n", ioSize); 1378 return B_NO_MEMORY; 1379 } 1380 } else { 1381 area = -1; 1382 data = reply.rawdata; 1383 } 1384 1385 request.parameter_id = mID; 1386 request.requestsize = ioSize; 1387 request.area = area; 1388 1389 status_t status = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_DATA, &request, 1390 sizeof(request), &reply, sizeof(reply)); 1391 if (status == B_OK) { 1392 // we don't want to copy more than the buffer provides 1393 if (reply.size < ioSize) 1394 ioSize = reply.size; 1395 1396 memcpy(buffer, data, ioSize); 1397 1398 // store reported values 1399 1400 *_ioSize = reply.size; 1401 if (_when != NULL) 1402 *_when = reply.last_change; 1403 } else 1404 ERROR("BParameter::GetValue parameter '%s' querying node %d, port %d failed: %s\n", 1405 mName, node.node, node.port, strerror(status)); 1406 1407 if (area >= B_OK) 1408 delete_area(area); 1409 1410 return status; 1411 } 1412 1413 1414 status_t 1415 BParameter::SetValue(const void *buffer, size_t size, bigtime_t when) 1416 { 1417 CALLED(); 1418 1419 controllable_set_parameter_data_request request; 1420 controllable_set_parameter_data_reply reply; 1421 media_node node; 1422 area_id area; 1423 status_t rv; 1424 void *data; 1425 1426 if (buffer == 0) 1427 return B_BAD_VALUE; 1428 if (size <= 0) 1429 return B_NO_MEMORY; 1430 1431 if (mWeb == 0) { 1432 ERROR("BParameter::SetValue: no parent BParameterWeb\n"); 1433 return B_NO_INIT; 1434 } 1435 1436 node = mWeb->Node(); 1437 if (IS_INVALID_NODE(node)) { 1438 ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned to a BMediaNode\n"); 1439 return B_NO_INIT; 1440 } 1441 1442 if (size > MAX_PARAMETER_DATA) { 1443 // create an area if large data needs to be transfered 1444 area = create_area("set parameter data", &data, B_ANY_ADDRESS, ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1445 if (area < B_OK) { 1446 ERROR("BParameter::SetValue can't create area of %ld bytes\n", size); 1447 return B_NO_MEMORY; 1448 } 1449 } else { 1450 area = -1; 1451 data = request.rawdata; 1452 } 1453 1454 memcpy(data, buffer, size); 1455 request.parameter_id = mID; 1456 request.when = when; 1457 request.area = area; 1458 request.size = size; 1459 1460 rv = QueryPort(node.port, CONTROLLABLE_SET_PARAMETER_DATA, &request, sizeof(request), &reply, sizeof(reply)); 1461 if (rv != B_OK) 1462 ERROR("BParameter::SetValue querying node failed\n"); 1463 1464 if (area != -1) 1465 delete_area(area); 1466 1467 return rv; 1468 } 1469 1470 1471 int32 1472 BParameter::CountChannels() 1473 { 1474 return mChannels; 1475 } 1476 1477 1478 void 1479 BParameter::SetChannelCount(int32 channel_count) 1480 { 1481 mChannels = channel_count; 1482 } 1483 1484 1485 media_type 1486 BParameter::MediaType() 1487 { 1488 return mMediaType; 1489 } 1490 1491 1492 void 1493 BParameter::SetMediaType(media_type m_type) 1494 { 1495 mMediaType = m_type; 1496 } 1497 1498 1499 int32 1500 BParameter::CountInputs() 1501 { 1502 ASSERT(mInputs != NULL); 1503 1504 return mInputs->CountItems(); 1505 } 1506 1507 1508 BParameter * 1509 BParameter::InputAt(int32 index) 1510 { 1511 ASSERT(mInputs != NULL); 1512 1513 return static_cast<BParameter *>(mInputs->ItemAt(index)); 1514 } 1515 1516 1517 void 1518 BParameter::AddInput(BParameter *input) 1519 { 1520 CALLED(); 1521 1522 // BeBook has this method returning a status value, 1523 // but it should be updated 1524 if (input == NULL) 1525 return; 1526 1527 ASSERT(mInputs != NULL); 1528 1529 if (mInputs->HasItem(input)) { 1530 // if already in input list, don't duplicate. 1531 return; 1532 } 1533 1534 mInputs->AddItem(input); 1535 input->AddOutput(this); 1536 } 1537 1538 1539 int32 1540 BParameter::CountOutputs() 1541 { 1542 ASSERT(mOutputs != NULL); 1543 1544 return mOutputs->CountItems(); 1545 } 1546 1547 1548 BParameter * 1549 BParameter::OutputAt(int32 index) 1550 { 1551 ASSERT(mOutputs != NULL); 1552 1553 return static_cast<BParameter *>(mOutputs->ItemAt(index)); 1554 } 1555 1556 1557 void 1558 BParameter::AddOutput(BParameter *output) 1559 { 1560 CALLED(); 1561 1562 // BeBook has this method returning a status value, 1563 // but it should be updated 1564 if (output == NULL) 1565 return; 1566 1567 ASSERT(mOutputs != NULL); 1568 1569 if (mOutputs->HasItem(output)) { 1570 // if already in output list, don't duplicate. 1571 return; 1572 } 1573 1574 mOutputs->AddItem(output); 1575 output->AddInput(this); 1576 } 1577 1578 1579 bool 1580 BParameter::IsFixedSize() const 1581 { 1582 return false; 1583 } 1584 1585 1586 type_code 1587 BParameter::TypeCode() const 1588 { 1589 return B_MEDIA_PARAMETER_TYPE; 1590 } 1591 1592 1593 ssize_t 1594 BParameter::FlattenedSize() const 1595 { 1596 CALLED(); 1597 /* 1598 ?? (0x02040607): 4 bytes 1599 BParameter Struct Size (in bytes): 4 bytes 1600 ID: 4 bytes 1601 Name String Length: 1 byte (??) 1602 Name String: 'Name String Length' bytes 1603 Kind String Length: 1 byte (??) 1604 Kind String: 'Kind String Length' bytes 1605 Unit String Length: 1 byte (??) 1606 Unit String: 'Unit String Length' bytes 1607 Inputs Count: 4 bytes 1608 Inputs (pointers): ('Inputs Count')*4 bytes 1609 Outputs Count: 4 bytes 1610 Outputs (pointers): ('Outputs Count')*4 bytes 1611 Media Type: 4 bytes 1612 ChannelCount: 4 bytes 1613 Flags: 4 bytes 1614 */ 1615 //35 bytes are guaranteed, after that, add the variable length parts. 1616 ssize_t size = 35; 1617 1618 if (mName != NULL) 1619 size += strlen(mName); 1620 if (mKind != NULL) 1621 size += strlen(mKind); 1622 if (mUnit != NULL) 1623 size += strlen(mUnit); 1624 1625 if (mInputs != NULL) 1626 size += mInputs->CountItems() * sizeof(BParameter *); 1627 1628 if (mOutputs != NULL) 1629 size += mOutputs->CountItems() * sizeof(BParameter *); 1630 1631 return size; 1632 } 1633 1634 1635 status_t 1636 BParameter::Flatten(void *buffer, ssize_t size) const 1637 { 1638 CALLED(); 1639 1640 if (buffer == NULL) { 1641 ERROR("BParameter::Flatten buffer is NULL\n"); 1642 return B_NO_INIT; 1643 } 1644 1645 // NOTICE: It is important that this value is the size returned by 1646 // BParameter::FlattenedSize(), not by a descendent's override of this method. 1647 ssize_t actualSize = BParameter::FlattenedSize(); 1648 if (size < actualSize) { 1649 ERROR("BParameter::Flatten(): size too small\n"); 1650 return B_NO_MEMORY; 1651 } 1652 1653 write_to_buffer<uint32>(&buffer, kParameterMagic); 1654 write_to_buffer<ssize_t>(&buffer, actualSize); 1655 write_to_buffer<int32>(&buffer, mID); 1656 1657 write_string_to_buffer(&buffer, mName); 1658 write_string_to_buffer(&buffer, mKind); 1659 write_string_to_buffer(&buffer, mUnit); 1660 1661 // flatten and write the list of inputs 1662 ssize_t count = mInputs ? mInputs->CountItems() : 0; 1663 write_to_buffer<ssize_t>(&buffer, count); 1664 1665 if (count > 0) { 1666 memcpy(buffer, mInputs->Items(), sizeof(BParameter *) * count); 1667 skip_in_buffer(&buffer, sizeof(BParameter *) * count); 1668 } 1669 1670 // flatten and write the list of outputs 1671 count = mOutputs ? mOutputs->CountItems() : 0; 1672 write_to_buffer<ssize_t>(&buffer, count); 1673 1674 if (count > 0) { 1675 memcpy(buffer, mOutputs->Items(), sizeof(BParameter *) * count); 1676 skip_in_buffer(&buffer, sizeof(BParameter *) * count); 1677 } 1678 1679 write_to_buffer<media_type>(&buffer, mMediaType); 1680 write_to_buffer<int32>(&buffer, mChannels); 1681 write_to_buffer<uint32>(&buffer, mFlags); 1682 1683 return B_OK; 1684 } 1685 1686 1687 bool 1688 BParameter::AllowsTypeCode(type_code code) const 1689 { 1690 return (code == TypeCode()); 1691 } 1692 1693 1694 status_t 1695 BParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 1696 { 1697 CALLED(); 1698 1699 if (!AllowsTypeCode(code)) { 1700 ERROR("BParameter::Unflatten(): wrong type code\n"); 1701 return B_BAD_TYPE; 1702 } 1703 1704 if (buffer == NULL) { 1705 ERROR("BParameter::Unflatten(): buffer is NULL\n"); 1706 return B_NO_INIT; 1707 } 1708 1709 // if the buffer is smaller than the size needed to read the 1710 // signature and struct size fields, then there is a problem 1711 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 1712 ERROR("BParameter::Unflatten() size too small\n"); 1713 return B_BAD_VALUE; 1714 } 1715 1716 const void *bufferStart = buffer; 1717 1718 // check magic 1719 1720 uint32 magic = read_from_buffer<uint32>(&buffer); 1721 if (magic == B_SWAP_INT32(kParameterMagic)) 1722 mSwapDetected = true; 1723 else if (magic == kParameterMagic) 1724 mSwapDetected = false; 1725 else { 1726 ERROR("BParameter::Unflatten(): bad magic\n"); 1727 return B_BAD_TYPE; 1728 } 1729 1730 ssize_t parameterSize = read_from_buffer_swap32<ssize_t>(&buffer, mSwapDetected); 1731 if (parameterSize > size) { 1732 ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n", parameterSize, size); 1733 return B_BAD_VALUE; 1734 } 1735 1736 //if the struct doesn't meet the minimum size for 1737 //a flattened BParameter, then return an error. 1738 //MinFlattenedParamSize = 1739 //ID (4 bytes) 1740 //Name String Length (1 byte) 1741 //Kind String Length (1 byte) 1742 //Unit String Length (1 byte) 1743 //Inputs Count (4 bytes) 1744 //Outputs Count (4 bytes) 1745 //Media Type (4 bytes) 1746 //Channel Count (4 bytes) 1747 //Flags (4 bytes) 1748 //TOTAL: 27 bytes 1749 const ssize_t MinFlattenedParamSize(27); 1750 if (parameterSize < MinFlattenedParamSize) { 1751 ERROR("BParameter::Unflatten out of memory (2)\n"); 1752 return B_ERROR; 1753 } 1754 1755 mID = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1756 1757 if (read_string_from_buffer(&buffer, &mName, size_left(size, bufferStart, buffer)) < B_OK 1758 || read_string_from_buffer(&buffer, &mKind, size_left(size, bufferStart, buffer)) < B_OK 1759 || read_string_from_buffer(&buffer, &mUnit, size_left(size, bufferStart, buffer)) < B_OK) 1760 return B_NO_MEMORY; 1761 1762 // read the list of inputs 1763 1764 // it will directly add the pointers in the flattened message to the list; 1765 // these will be fixed to point to the real inputs/outputs later in FixRefs() 1766 1767 int32 count = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1768 1769 if (mInputs == NULL) 1770 mInputs = new BList(); 1771 else 1772 mInputs->MakeEmpty(); 1773 1774 for (int32 i = 0; i < count; i++) { 1775 mInputs->AddItem(read_from_buffer_swap32<BParameter * const>(&buffer, mSwapDetected)); 1776 } 1777 1778 // read the list of outputs 1779 1780 count = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1781 1782 if (mOutputs == NULL) 1783 mOutputs = new BList(); 1784 else 1785 mOutputs->MakeEmpty(); 1786 1787 for (int32 i = 0; i < count; i++) { 1788 mOutputs->AddItem(read_from_buffer_swap32<BParameter * const>(&buffer, mSwapDetected)); 1789 } 1790 1791 mMediaType = read_from_buffer_swap32<media_type>(&buffer, mSwapDetected); 1792 mChannels = read_from_buffer_swap32<int32>(&buffer, mSwapDetected); 1793 mFlags = read_from_buffer_swap32<uint32>(&buffer, mSwapDetected); 1794 1795 return B_OK; 1796 } 1797 1798 1799 /************************************************************* 1800 * private BParameter 1801 *************************************************************/ 1802 1803 1804 BParameter::BParameter(int32 id, media_type mediaType, media_parameter_type type, 1805 BParameterWeb *web, const char *name, const char *kind, const char *unit) 1806 : 1807 mID(id), 1808 mType(type), 1809 mWeb(web), 1810 mGroup(NULL), 1811 mSwapDetected(true), 1812 mMediaType(mediaType), 1813 mChannels(1), 1814 mFlags(0) 1815 { 1816 CALLED(); 1817 1818 mName = strndup(name, 256); 1819 mKind = strndup(kind, 256); 1820 mUnit = strndup(unit, 256); 1821 1822 // create empty input/output lists 1823 mInputs = new BList(); 1824 mOutputs = new BList(); 1825 } 1826 1827 1828 BParameter::~BParameter() 1829 { 1830 CALLED(); 1831 1832 // don't worry about the mWeb/mGroup properties, you don't need 1833 // to remove yourself from a web/group since the only way in which 1834 // a parameter is destroyed is when the owner web/group destroys it 1835 1836 free(mName); 1837 free(mKind); 1838 free(mUnit); 1839 1840 delete mInputs; 1841 delete mOutputs; 1842 1843 mName = NULL; mKind = NULL; mUnit = NULL; mInputs = NULL; mOutputs = NULL; 1844 } 1845 1846 1847 /** Replaces references to items in the old list with the corresponding 1848 * items in the updated list. The references are replaced in the input 1849 * and output lists. 1850 * This is called by BParameterWeb::Unflatten(). 1851 */ 1852 1853 void 1854 BParameter::FixRefs(BList &old, BList &updated) 1855 { 1856 CALLED(); 1857 ASSERT(mInputs != NULL); 1858 ASSERT(mOutputs != NULL); 1859 1860 // update inputs 1861 1862 void **items = static_cast<void **>(mInputs->Items()); 1863 int32 count = mInputs->CountItems(); 1864 1865 for (int32 i = 0; i < count; i++) { 1866 int32 index = old.IndexOf(items[i]); 1867 if (index >= 0) 1868 items[i] = updated.ItemAt(index); 1869 else { 1870 ERROR("BParameter::FixRefs(): No mapping found for input"); 1871 items[i] = NULL; 1872 } 1873 } 1874 1875 // remove all NULL inputs (those which couldn't be mapped) 1876 1877 for (int32 i = count; i-- > 0;) { 1878 if (items[i] == NULL) 1879 mInputs->RemoveItem(i); 1880 } 1881 1882 // update outputs 1883 1884 items = static_cast<void **>(mOutputs->Items()); 1885 count = mOutputs->CountItems(); 1886 1887 for (int32 i = 0; i < count; i++) { 1888 int32 index = old.IndexOf(items[i]); 1889 if (index >= 0) 1890 items[i] = updated.ItemAt(index); 1891 else { 1892 ERROR("BParameter::FixRefs(): No mapping found for output"); 1893 items[i] = NULL; 1894 } 1895 } 1896 1897 // remove all NULL outputs (those which couldn't be mapped) 1898 1899 for (int32 i = count; i-- > 0;) { 1900 if (items[i] == NULL) 1901 mOutputs->RemoveItem(i); 1902 } 1903 } 1904 1905 1906 // #pragma mark - 1907 1908 /************************************************************* 1909 * public BContinuousParameter 1910 *************************************************************/ 1911 1912 1913 type_code 1914 BContinuousParameter::ValueType() 1915 { 1916 return B_FLOAT_TYPE; 1917 } 1918 1919 1920 float 1921 BContinuousParameter::MinValue() 1922 { 1923 return mMinimum; 1924 } 1925 1926 1927 float 1928 BContinuousParameter::MaxValue() 1929 { 1930 return mMaximum; 1931 } 1932 1933 1934 float 1935 BContinuousParameter::ValueStep() 1936 { 1937 return mStepping; 1938 } 1939 1940 1941 void 1942 BContinuousParameter::SetResponse(int resp, float factor, float offset) 1943 { 1944 mResponse = static_cast<response>(resp); 1945 mFactor = factor; 1946 mOffset = offset; 1947 } 1948 1949 1950 void 1951 BContinuousParameter::GetResponse(int *resp, float *factor, float *offset) 1952 { 1953 if (resp != NULL) 1954 *resp = mResponse; 1955 if (factor != NULL) 1956 *factor = mFactor; 1957 if (offset != NULL) 1958 *offset = mOffset; 1959 } 1960 1961 1962 ssize_t 1963 BContinuousParameter::FlattenedSize() const 1964 { 1965 CALLED(); 1966 1967 // only adds a fixed amount of bytes 1968 return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize; 1969 } 1970 1971 1972 status_t 1973 BContinuousParameter::Flatten(void *buffer, ssize_t size) const 1974 { 1975 CALLED(); 1976 1977 if (buffer == NULL) { 1978 ERROR("BContinuousParameter::Flatten(): buffer is NULL\n"); 1979 return B_NO_INIT; 1980 } 1981 1982 ssize_t parameterSize = BParameter::FlattenedSize(); 1983 if (size < (parameterSize + kAdditionalContinuousParameterSize)) { 1984 ERROR("BContinuousParameter::Flatten(): size to small\n"); 1985 return B_NO_MEMORY; 1986 } 1987 1988 status_t status = BParameter::Flatten(buffer, size); 1989 if (status != B_OK) { 1990 ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n"); 1991 return status; 1992 } 1993 1994 // add our data to the general flattened BParameter 1995 1996 skip_in_buffer(&buffer, parameterSize); 1997 1998 write_to_buffer<float>(&buffer, mMinimum); 1999 write_to_buffer<float>(&buffer, mMaximum); 2000 write_to_buffer<float>(&buffer, mStepping); 2001 write_to_buffer<response>(&buffer, mResponse); 2002 write_to_buffer<float>(&buffer, mFactor); 2003 write_to_buffer<float>(&buffer, mOffset); 2004 2005 return B_OK; 2006 } 2007 2008 2009 status_t 2010 BContinuousParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2011 { 2012 CALLED(); 2013 2014 // we try to check if the buffer size is long enough to hold an object 2015 // as early as possible. 2016 2017 if (!AllowsTypeCode(code)) { 2018 ERROR("BContinuousParameter::Unflatten wrong type code\n"); 2019 return B_BAD_TYPE; 2020 } 2021 2022 if (buffer == NULL) { 2023 ERROR("BContinuousParameter::Unflatten buffer is NULL\n"); 2024 return B_NO_INIT; 2025 } 2026 2027 // if the buffer is smaller than the size needed to read the 2028 // signature and struct size fields, then there is a problem 2029 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 2030 ERROR("BContinuousParameter::Unflatten size too small\n"); 2031 return B_ERROR; 2032 } 2033 2034 status_t status = BParameter::Unflatten(code, buffer, size); 2035 if (status != B_OK) { 2036 ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten failed\n"); 2037 return status; 2038 } 2039 2040 ssize_t parameterSize = BParameter::FlattenedSize(); 2041 skip_in_buffer(&buffer, parameterSize); 2042 2043 if (size < (parameterSize + kAdditionalContinuousParameterSize)) { 2044 ERROR("BContinuousParameter::Unflatten(): buffer too small\n"); 2045 return B_BAD_VALUE; 2046 } 2047 2048 mMinimum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2049 mMaximum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2050 mStepping = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2051 mResponse = read_from_buffer_swap32<response>(&buffer, SwapOnUnflatten()); 2052 mFactor = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2053 mOffset = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten()); 2054 2055 return B_OK; 2056 } 2057 2058 2059 /************************************************************* 2060 * private BContinuousParameter 2061 *************************************************************/ 2062 2063 2064 BContinuousParameter::BContinuousParameter(int32 id, media_type m_type, 2065 BParameterWeb *web, const char *name, const char *kind, const char *unit, 2066 float minimum, float maximum, float stepping) 2067 : BParameter(id, m_type, B_CONTINUOUS_PARAMETER, web, name, kind, unit), 2068 mMinimum(minimum), mMaximum(maximum), mStepping(stepping), 2069 mResponse(B_LINEAR), mFactor(1.0), mOffset(0.0) 2070 { 2071 CALLED(); 2072 } 2073 2074 2075 BContinuousParameter::~BContinuousParameter() 2076 { 2077 CALLED(); 2078 } 2079 2080 2081 // #pragma mark - 2082 2083 /************************************************************* 2084 * public BDiscreteParameter 2085 *************************************************************/ 2086 2087 2088 type_code 2089 BDiscreteParameter::ValueType() 2090 { 2091 return B_INT32_TYPE; 2092 } 2093 2094 2095 int32 2096 BDiscreteParameter::CountItems() 2097 { 2098 ASSERT(mValues != NULL); 2099 2100 return mValues->CountItems(); 2101 } 2102 2103 2104 const char * 2105 BDiscreteParameter::ItemNameAt(int32 index) 2106 { 2107 ASSERT(mSelections != NULL); 2108 2109 return reinterpret_cast<const char *>(mSelections->ItemAt(index)); 2110 } 2111 2112 2113 int32 2114 BDiscreteParameter::ItemValueAt(int32 index) 2115 { 2116 ASSERT(mValues != NULL); 2117 2118 int32 *item = static_cast<int32 *>(mValues->ItemAt(index)); 2119 if (item == NULL) 2120 return 0; 2121 2122 return *item; 2123 } 2124 2125 2126 status_t 2127 BDiscreteParameter::AddItem(int32 value, const char *name) 2128 { 2129 CALLED(); 2130 //TRACE("\tthis = %p, value = %ld, name = \"%s\"\n", this, value, name); 2131 ASSERT(mValues != NULL); 2132 ASSERT(mSelections != NULL); 2133 2134 int32 *valueCopy = new int32(value); 2135 char *nameCopy = strndup(name, 256); 2136 if (name != NULL && nameCopy == NULL) 2137 return B_NO_MEMORY; 2138 2139 if (!mValues->AddItem(valueCopy) 2140 || !mSelections->AddItem(nameCopy)) 2141 return B_NO_MEMORY; 2142 2143 return B_OK; 2144 } 2145 2146 2147 status_t 2148 BDiscreteParameter::MakeItemsFromInputs() 2149 { 2150 CALLED(); 2151 ASSERT(mValues != NULL); 2152 ASSERT(mSelections != NULL); 2153 ASSERT(mInputs != NULL); 2154 2155 int32 count = mInputs->CountItems(); 2156 for(int32 i = 0; i < count; i++) { 2157 BParameter *parameter = static_cast<BParameter *>(mInputs->ItemAt(i)); 2158 AddItem(i, parameter->Name()); 2159 } 2160 2161 return B_OK; 2162 } 2163 2164 2165 status_t 2166 BDiscreteParameter::MakeItemsFromOutputs() 2167 { 2168 CALLED(); 2169 ASSERT(mValues != NULL); 2170 ASSERT(mSelections != NULL); 2171 ASSERT(mOutputs != NULL); 2172 2173 int32 count = mOutputs->CountItems(); 2174 for(int32 i = 0; i < count; i++) { 2175 BParameter *parameter = static_cast<BParameter *>(mOutputs->ItemAt(i)); 2176 AddItem(i, parameter->Name()); 2177 } 2178 2179 return B_OK; 2180 } 2181 2182 2183 void 2184 BDiscreteParameter::MakeEmpty() 2185 { 2186 CALLED(); 2187 ASSERT(mValues != NULL); 2188 ASSERT(mSelections != NULL); 2189 2190 for (int32 i = mValues->CountItems(); i-- > 0;) { 2191 delete static_cast<int32 *>(mValues->ItemAt(i)); 2192 } 2193 mValues->MakeEmpty(); 2194 2195 for(int32 i = mSelections->CountItems(); i-- > 0;) { 2196 free(static_cast<char *>(mSelections->ItemAt(i))); 2197 } 2198 mSelections->MakeEmpty(); 2199 } 2200 2201 2202 ssize_t 2203 BDiscreteParameter::FlattenedSize() const 2204 { 2205 CALLED(); 2206 2207 ssize_t size = BParameter::FlattenedSize() + kAdditionalDiscreteParameterSize; 2208 2209 int32 count = mValues ? mValues->CountItems() : 0; 2210 for (int32 i = 0; i < count; i++) { 2211 char *selection = static_cast<char *>(mSelections->ItemAt(i)); 2212 2213 if (selection != NULL) 2214 size += min_c(strlen(selection), 255); 2215 2216 size += 5; 2217 // string length + value 2218 } 2219 2220 return size; 2221 } 2222 2223 2224 status_t 2225 BDiscreteParameter::Flatten(void *buffer, ssize_t size) const 2226 { 2227 CALLED(); 2228 2229 if (buffer == NULL) { 2230 ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n"); 2231 return B_NO_INIT; 2232 } 2233 2234 ssize_t parameterSize = BParameter::FlattenedSize(); 2235 2236 if (size < FlattenedSize()) { 2237 ERROR("BDiscreteParameter::Flatten(): size too small\n"); 2238 return B_NO_MEMORY; 2239 } 2240 2241 status_t status = BParameter::Flatten(buffer, size); 2242 if (status != B_OK) { 2243 ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n"); 2244 return status; 2245 } 2246 2247 skip_in_buffer(&buffer, parameterSize); 2248 2249 int32 count = mValues ? mValues->CountItems() : 0; 2250 write_to_buffer<int32>(&buffer, count); 2251 2252 // write out all value/name pairs 2253 for (int32 i = 0; i < count; i++) { 2254 const char *selection = static_cast<char *>(mSelections->ItemAt(i)); 2255 const int32 *value = static_cast<int32 *>(mValues->ItemAt(i)); 2256 2257 write_string_to_buffer(&buffer, selection); 2258 write_to_buffer<int32>(&buffer, value ? *value : 0); 2259 } 2260 2261 return B_OK; 2262 } 2263 2264 2265 status_t 2266 BDiscreteParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2267 { 2268 CALLED(); 2269 2270 if (!AllowsTypeCode(code)) { 2271 ERROR("BDiscreteParameter::Unflatten(): bad type code\n"); 2272 return B_BAD_TYPE; 2273 } 2274 2275 if (buffer == NULL) { 2276 ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n"); 2277 return B_NO_INIT; 2278 } 2279 2280 // if the buffer is smaller than the size needed to read the 2281 // signature and struct size fields, then there is a problem 2282 if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) { 2283 ERROR("BDiscreteParameter::Unflatten(): size too small\n"); 2284 return B_ERROR; 2285 } 2286 2287 const void *bufferStart = buffer; 2288 2289 status_t status = BParameter::Unflatten(code, buffer, size); 2290 if (status != B_OK) { 2291 ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n"); 2292 return status; 2293 } 2294 2295 ssize_t parameterSize = BParameter::FlattenedSize(); 2296 skip_in_buffer(&buffer, parameterSize); 2297 2298 if (size < (parameterSize + kAdditionalDiscreteParameterSize)) { 2299 ERROR("BDiscreteParameter::Unflatten(): buffer too small\n"); 2300 return B_BAD_VALUE; 2301 } 2302 2303 int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten()); 2304 2305 // clear any existing name/value pairs 2306 MakeEmpty(); 2307 2308 for (int32 i = 0; i < count; i++) { 2309 char *name; 2310 if (read_string_from_buffer(&buffer, &name, size_left(size, bufferStart, buffer)) < B_OK) 2311 return B_BAD_DATA; 2312 2313 if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) 2314 return B_BAD_DATA; 2315 2316 int32 value = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten()); 2317 2318 AddItem(value, name); 2319 } 2320 2321 return B_OK; 2322 } 2323 2324 2325 /************************************************************* 2326 * private BDiscreteParameter 2327 *************************************************************/ 2328 2329 2330 BDiscreteParameter::BDiscreteParameter(int32 id, media_type mediaType, 2331 BParameterWeb *web, const char *name, const char *kind) 2332 : BParameter(id, mediaType, B_DISCRETE_PARAMETER, web, name, kind, NULL) 2333 { 2334 CALLED(); 2335 2336 mSelections = new BList(); 2337 mValues = new BList(); 2338 } 2339 2340 2341 BDiscreteParameter::~BDiscreteParameter() 2342 { 2343 CALLED(); 2344 2345 MakeEmpty(); 2346 2347 delete mSelections; 2348 delete mValues; 2349 2350 mSelections = NULL; mValues = NULL; 2351 } 2352 2353 2354 // #pragma mark - 2355 2356 /************************************************************* 2357 * public BNullParameter 2358 *************************************************************/ 2359 2360 2361 type_code 2362 BNullParameter::ValueType() 2363 { 2364 // NULL parameters have no value type 2365 return 0; 2366 } 2367 2368 2369 ssize_t 2370 BNullParameter::FlattenedSize() const 2371 { 2372 return BParameter::FlattenedSize(); 2373 } 2374 2375 2376 status_t 2377 BNullParameter::Flatten(void *buffer, ssize_t size) const 2378 { 2379 return BParameter::Flatten(buffer, size); 2380 } 2381 2382 2383 status_t 2384 BNullParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2385 { 2386 return BParameter::Unflatten(code, buffer, size); 2387 } 2388 2389 2390 /************************************************************* 2391 * private BNullParameter 2392 *************************************************************/ 2393 2394 2395 BNullParameter::BNullParameter(int32 id, media_type mediaType, BParameterWeb *web, 2396 const char *name, const char *kind) 2397 : BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL) 2398 { 2399 } 2400 2401 2402 BNullParameter::~BNullParameter() 2403 { 2404 } 2405 2406 2407 // #pragma mark - 2408 2409 /************************************************************* 2410 * public BTextParameter 2411 *************************************************************/ 2412 2413 2414 size_t 2415 BTextParameter::MaxBytes() const 2416 { 2417 // NULL parameters have no value type 2418 return mMaxBytes; 2419 } 2420 2421 2422 type_code 2423 BTextParameter::ValueType() 2424 { 2425 // NULL parameters have no value type 2426 return 0; 2427 } 2428 2429 2430 ssize_t 2431 BTextParameter::FlattenedSize() const 2432 { 2433 return BParameter::FlattenedSize() + sizeof(mMaxBytes); 2434 } 2435 2436 2437 status_t 2438 BTextParameter::Flatten(void *buffer, ssize_t size) const 2439 { 2440 if (buffer == NULL) { 2441 ERROR("BTextParameter::Flatten(): buffer is NULL\n"); 2442 return B_NO_INIT; 2443 } 2444 2445 ssize_t parameterSize = BParameter::FlattenedSize(); 2446 if (size < static_cast<ssize_t>(parameterSize + sizeof(mMaxBytes))) { 2447 ERROR("BContinuousParameter::Flatten(): size to small\n"); 2448 return B_NO_MEMORY; 2449 } 2450 2451 status_t status = BParameter::Flatten(buffer, size); 2452 if (status != B_OK) { 2453 ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n"); 2454 return status; 2455 } 2456 2457 // add our data to the general flattened BParameter 2458 2459 skip_in_buffer(&buffer, parameterSize); 2460 2461 write_to_buffer<uint32>(&buffer, mMaxBytes); 2462 2463 return B_OK; 2464 } 2465 2466 2467 status_t 2468 BTextParameter::Unflatten(type_code code, const void *buffer, ssize_t size) 2469 { 2470 // we try to check if the buffer size is long enough to hold an object 2471 // as early as possible. 2472 2473 if (!AllowsTypeCode(code)) { 2474 ERROR("BTextParameter::Unflatten wrong type code\n"); 2475 return B_BAD_TYPE; 2476 } 2477 2478 if (buffer == NULL) { 2479 ERROR("BTextParameter::Unflatten buffer is NULL\n"); 2480 return B_NO_INIT; 2481 } 2482 2483 if (size < static_cast<ssize_t>(sizeof(mMaxBytes))) { 2484 ERROR("BTextParameter::Unflatten size too small\n"); 2485 return B_ERROR; 2486 } 2487 2488 status_t status = BParameter::Unflatten(code, buffer, size); 2489 if (status != B_OK) { 2490 ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n"); 2491 return status; 2492 } 2493 2494 ssize_t parameterSize = BParameter::FlattenedSize(); 2495 skip_in_buffer(&buffer, parameterSize); 2496 2497 if (size < static_cast<ssize_t>(parameterSize + sizeof(mMaxBytes))) { 2498 ERROR("BTextParameter::Unflatten(): buffer too small\n"); 2499 return B_BAD_VALUE; 2500 } 2501 2502 mMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten()); 2503 2504 return B_OK; 2505 } 2506 2507 2508 /************************************************************* 2509 * private BTextParameter 2510 *************************************************************/ 2511 2512 2513 BTextParameter::BTextParameter(int32 id, media_type mediaType, BParameterWeb *web, 2514 const char *name, const char *kind, size_t max_bytes) 2515 : BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL) 2516 { 2517 mMaxBytes = max_bytes; 2518 } 2519 2520 2521 BTextParameter::~BTextParameter() 2522 { 2523 } 2524 2525 2526 // #pragma mark - 2527 // reserved functions 2528 2529 2530 status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; } 2531 status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; } 2532 status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; } 2533 status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; } 2534 status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; } 2535 status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; } 2536 status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; } 2537 status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; } 2538 2539 status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; } 2540 status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; } 2541 status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; } 2542 status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; } 2543 status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; } 2544 status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; } 2545 status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; } 2546 status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; } 2547 2548 status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; } 2549 status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; } 2550 status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; } 2551 status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; } 2552 status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; } 2553 status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; } 2554 status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; } 2555 status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; } 2556 2557 status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; } 2558 status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; } 2559 status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; } 2560 status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; } 2561 status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; } 2562 status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; } 2563 status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; } 2564 status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; } 2565 2566 status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; } 2567 status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; } 2568 status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; } 2569 status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; } 2570 status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; } 2571 status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; } 2572 status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; } 2573 status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; } 2574 2575 status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; } 2576 status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; } 2577 status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; } 2578 status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; } 2579 status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; } 2580 status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; } 2581 status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; } 2582 status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; } 2583 2584 status_t BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR; } 2585 status_t BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR; } 2586 status_t BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR; } 2587 status_t BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR; } 2588 status_t BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR; } 2589 status_t BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR; } 2590 status_t BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR; } 2591 status_t BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR; } 2592 2593 2594