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