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