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