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