1 /* 2 * Copyright 2005-2014 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <ChannelControl.h> 8 #include <PropertyInfo.h> 9 10 #include <map> 11 #include <string> 12 13 struct limit_label { 14 std::string min_label; 15 std::string max_label; 16 }; 17 18 typedef std::map<int32, limit_label> label_map; 19 20 static property_info 21 sPropertyInfo[] = { 22 { "ChannelCount", 23 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 24 { B_DIRECT_SPECIFIER, 0 }, NULL, 0, { B_INT32_TYPE } 25 }, 26 27 { "CurrentChannel", 28 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 29 { B_DIRECT_SPECIFIER, 0 }, NULL, 0, { B_INT32_TYPE } 30 }, 31 32 { "MaxLimitLabel", 33 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 34 { B_DIRECT_SPECIFIER, 0 }, NULL, 0, { B_STRING_TYPE } 35 }, 36 37 { "MinLimitLabel", 38 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 39 { B_DIRECT_SPECIFIER, 0 }, NULL, 0, { B_STRING_TYPE } 40 }, 41 42 { 0 } 43 }; 44 45 46 BChannelControl::BChannelControl(BRect frame, const char* name, 47 const char* label, BMessage* model, int32 channel_count, 48 uint32 resizingMode, uint32 flags) 49 : 50 BControl(frame, name, label, model, resizingMode, flags), 51 fChannelCount(channel_count), 52 fCurrentChannel(0), 53 fChannelMin(NULL), 54 fChannelMax(NULL), 55 fChannelValues(NULL), 56 fMultiLabels(NULL), 57 fModificationMsg(NULL) 58 { 59 fChannelMin = new int32[channel_count]; 60 memset(fChannelMin, 0, sizeof(int32) * channel_count); 61 62 fChannelMax = new int32[channel_count]; 63 for (int32 i = 0; i < channel_count; i++) 64 fChannelMax[i] = 100; 65 66 fChannelValues = new int32[channel_count]; 67 memset(fChannelValues, 0, sizeof(int32) * channel_count); 68 69 fMultiLabels = (void*)new label_map; 70 } 71 72 73 BChannelControl::BChannelControl(const char* name, const char* label, 74 BMessage* model, int32 channelCount, uint32 flags) 75 : 76 BControl(name, label, model, flags), 77 fChannelCount(channelCount), 78 fCurrentChannel(0), 79 fChannelMin(NULL), 80 fChannelMax(NULL), 81 fChannelValues(NULL), 82 fMultiLabels(NULL), 83 fModificationMsg(NULL) 84 { 85 fChannelMin = new int32[channelCount]; 86 memset(fChannelMin, 0, sizeof(int32) * channelCount); 87 88 fChannelMax = new int32[channelCount]; 89 for (int32 i = 0; i < channelCount; i++) 90 fChannelMax[i] = 100; 91 92 fChannelValues = new int32[channelCount]; 93 memset(fChannelValues, 0, sizeof(int32) * channelCount); 94 95 fMultiLabels = (void*)new label_map; 96 } 97 98 99 BChannelControl::BChannelControl(BMessage* archive) 100 : 101 BControl(archive), 102 fChannelCount(0), 103 fCurrentChannel(0), 104 fChannelMin(NULL), 105 fChannelMax(NULL), 106 fChannelValues(NULL), 107 fMultiLabels(NULL), 108 fModificationMsg(NULL) 109 { 110 archive->FindInt32("be:_m_channel_count", &fChannelCount); 111 archive->FindInt32("be:_m_value_channel", &fCurrentChannel); 112 113 if (fChannelCount > 0) { 114 fChannelMin = new int32[fChannelCount]; 115 memset(fChannelMin, 0, sizeof(int32) * fChannelCount); 116 117 fChannelMax = new int32[fChannelCount]; 118 for (int32 i = 0; i < fChannelCount; i++) 119 fChannelMax[i] = 100; 120 121 fChannelValues = new int32[fChannelCount]; 122 memset(fChannelValues, 0, sizeof(int32) * fChannelCount); 123 124 for (int32 c = 0; c < fChannelCount; c++) { 125 archive->FindInt32("be:_m_channel_min", c, &fChannelMin[c]); 126 archive->FindInt32("be:_m_channel_max", c, &fChannelMax[c]); 127 archive->FindInt32("be:_m_channel_val", c, &fChannelValues[c]); 128 } 129 } 130 131 const char* label = NULL; 132 if (archive->FindString("be:_m_min_label", &label) == B_OK) 133 fMinLabel = label; 134 135 if (archive->FindString("be:_m_max_label", &label) == B_OK) 136 fMaxLabel = label; 137 138 BMessage* modificationMessage = new BMessage; 139 if (archive->FindMessage("_mod_msg", modificationMessage) == B_OK) 140 fModificationMsg = modificationMessage; 141 else 142 delete modificationMessage; 143 144 fMultiLabels = (void*)new label_map; 145 } 146 147 148 BChannelControl::~BChannelControl() 149 { 150 delete[] fChannelMin; 151 delete[] fChannelMax; 152 delete[] fChannelValues; 153 delete fModificationMsg; 154 delete reinterpret_cast<label_map*>(fMultiLabels); 155 } 156 157 158 status_t 159 BChannelControl::Archive(BMessage* data, bool deep) const 160 { 161 status_t status = BControl::Archive(data, deep); 162 if (status == B_OK) 163 status = data->AddInt32("be:_m_channel_count", fChannelCount); 164 165 if (status == B_OK) 166 status = data->AddInt32("be:_m_value_channel", fCurrentChannel); 167 168 if (status == B_OK) 169 status = data->AddString("be:_m_min_label", fMinLabel.String()); 170 171 if (status == B_OK) 172 status = data->AddString("be:_m_max_label", fMaxLabel.String()); 173 174 if (status == B_OK && fChannelValues != NULL 175 && fChannelMax != NULL && fChannelMin != NULL) { 176 for (int32 i = 0; i < fChannelCount; i++) { 177 status = data->AddInt32("be:_m_channel_min", fChannelMin[i]); 178 if (status < B_OK) 179 break; 180 181 status = data->AddInt32("be:_m_channel_max", fChannelMax[i]); 182 if (status < B_OK) 183 break; 184 185 status = data->AddInt32("be:_m_channel_val", fChannelValues[i]); 186 if (status < B_OK) 187 break; 188 } 189 } 190 191 return status; 192 } 193 194 195 void 196 BChannelControl::FrameResized(float newWidth, float newHeight) 197 { 198 BView::FrameResized(newWidth, newHeight); 199 } 200 201 202 void 203 BChannelControl::SetFont(const BFont* font, uint32 mask) 204 { 205 BView::SetFont(font, mask); 206 } 207 208 209 void 210 BChannelControl::AttachedToWindow() 211 { 212 BControl::AttachedToWindow(); 213 } 214 215 216 void 217 BChannelControl::DetachedFromWindow() 218 { 219 BControl::DetachedFromWindow(); 220 } 221 222 223 void 224 BChannelControl::ResizeToPreferred() 225 { 226 BControl::ResizeToPreferred(); 227 } 228 229 230 void 231 BChannelControl::MessageReceived(BMessage* message) 232 { 233 BControl::MessageReceived(message); 234 } 235 236 237 BHandler* 238 BChannelControl::ResolveSpecifier(BMessage* message, int32 index, 239 BMessage* specifier, int32 what, const char* property) 240 { 241 BHandler* target = this; 242 BPropertyInfo propertyInfo(sPropertyInfo); 243 if (propertyInfo.FindMatch(message, index, specifier, what, property) 244 < B_OK) { 245 target = BControl::ResolveSpecifier(message, index, specifier, 246 what, property); 247 } 248 249 return target; 250 } 251 252 253 status_t 254 BChannelControl::GetSupportedSuites(BMessage* data) 255 { 256 if (data == NULL) 257 return B_BAD_VALUE; 258 259 status_t err = data->AddString("suites", "suite/vnd.Be-channel-control"); 260 261 BPropertyInfo propertyInfo(sPropertyInfo); 262 if (err == B_OK) 263 err = data->AddFlat("messages", &propertyInfo); 264 265 if (err == B_OK) 266 return BControl::GetSupportedSuites(data); 267 268 return err; 269 } 270 271 272 void 273 BChannelControl::SetModificationMessage(BMessage* message) 274 { 275 delete fModificationMsg; 276 fModificationMsg = message; 277 } 278 279 280 BMessage* 281 BChannelControl::ModificationMessage() const 282 { 283 return fModificationMsg; 284 } 285 286 287 status_t 288 BChannelControl::Invoke(BMessage* message) 289 { 290 bool notify = false; 291 BMessage invokeMessage(InvokeKind(¬ify)); 292 293 if (message != NULL) 294 invokeMessage = *message; 295 else if (Message() != NULL) 296 invokeMessage = *Message(); 297 298 invokeMessage.AddInt32("be:current_channel", fCurrentChannel); 299 300 return BControl::Invoke(&invokeMessage); 301 } 302 303 304 status_t 305 BChannelControl::InvokeChannel(BMessage* message, int32 fromChannel, 306 int32 channelCount, const bool* _mask) 307 { 308 bool notify = false; 309 BMessage invokeMessage(InvokeKind(¬ify)); 310 311 if (message != NULL) 312 invokeMessage = *message; 313 else if (Message() != NULL) 314 invokeMessage = *Message(); 315 316 invokeMessage.AddInt32("be:current_channel", fCurrentChannel); 317 if (channelCount < 0) 318 channelCount = fChannelCount - fromChannel; 319 320 for (int32 i = 0; i < channelCount; i++) { 321 invokeMessage.AddInt32("be:channel_value", 322 fChannelValues[fromChannel + i]); 323 invokeMessage.AddBool("be:channel_changed", _mask ? _mask[i] : true); 324 } 325 326 return BControl::Invoke(&invokeMessage); 327 } 328 329 330 status_t 331 BChannelControl::InvokeNotifyChannel(BMessage* message, uint32 kind, 332 int32 fromChannel, int32 channelCount, const bool* _mask) 333 { 334 BeginInvokeNotify(kind); 335 status_t status = InvokeChannel(message, fromChannel, channelCount, _mask); 336 EndInvokeNotify(); 337 338 return status; 339 } 340 341 342 void 343 BChannelControl::SetValue(int32 value) 344 { 345 // Get real 346 if (value > fChannelMax[fCurrentChannel]) 347 value = fChannelMax[fCurrentChannel]; 348 349 if (value < fChannelMin[fCurrentChannel]) 350 value = fChannelMin[fCurrentChannel]; 351 352 if (value != fChannelValues[fCurrentChannel]) { 353 StuffValues(fCurrentChannel, 1, &value); 354 BControl::SetValue(value); 355 } 356 } 357 358 359 status_t 360 BChannelControl::SetCurrentChannel(int32 channel) 361 { 362 if (channel < 0 || channel >= fChannelCount) 363 return B_BAD_INDEX; 364 365 if (channel != fCurrentChannel) { 366 fCurrentChannel = channel; 367 BControl::SetValue(fChannelValues[fCurrentChannel]); 368 } 369 370 return B_OK; 371 } 372 373 374 int32 375 BChannelControl::CurrentChannel() const 376 { 377 return fCurrentChannel; 378 } 379 380 381 int32 382 BChannelControl::CountChannels() const 383 { 384 return fChannelCount; 385 } 386 387 388 status_t 389 BChannelControl::SetChannelCount(int32 channel_count) 390 { 391 if (channel_count < 0 || channel_count >= MaxChannelCount()) 392 return B_BAD_VALUE; 393 394 // TODO: Currently we only grow the buffer. Test what BeOS does 395 if (channel_count > fChannelCount) { 396 int32* newMin = new int32[channel_count]; 397 int32* newMax = new int32[channel_count]; 398 int32* newVal = new int32[channel_count]; 399 400 memcpy(newMin, fChannelMin, fChannelCount); 401 memcpy(newMax, fChannelMax, fChannelCount); 402 memcpy(newVal, fChannelValues, fChannelCount); 403 404 delete[] fChannelMin; 405 delete[] fChannelMax; 406 delete[] fChannelValues; 407 408 fChannelMin = newMin; 409 fChannelMax = newMax; 410 fChannelValues = newVal; 411 } 412 413 fChannelCount = channel_count; 414 415 return B_OK; 416 } 417 418 419 int32 420 BChannelControl::ValueFor(int32 channel) const 421 { 422 int32 value = 0; 423 if (GetValue(&value, channel, 1) <= 0) 424 return -1; 425 426 return value; 427 } 428 429 430 int32 431 BChannelControl::GetValue(int32* outValues, int32 fromChannel, 432 int32 channelCount) const 433 { 434 int32 i = 0; 435 for (i = 0; i < channelCount; i++) 436 outValues[i] = fChannelValues[fromChannel + i]; 437 438 return i; 439 } 440 441 442 status_t 443 BChannelControl::SetValueFor(int32 channel, int32 value) 444 { 445 return SetValue(channel, 1, &value); 446 } 447 448 449 status_t 450 BChannelControl::SetValue(int32 fromChannel, int32 channelCount, 451 const int32* values) 452 { 453 return StuffValues(fromChannel, channelCount, values); 454 } 455 456 457 status_t 458 BChannelControl::SetAllValue(int32 values) 459 { 460 int32* newValues = new int32[fChannelCount]; 461 for (int32 i = 0; i < fChannelCount; i++) { 462 int32 limitedValue = max_c(values, MinLimitList()[i]); 463 limitedValue = min_c(limitedValue, MaxLimitList()[i]); 464 465 newValues[i] = limitedValue; 466 } 467 468 delete[] fChannelValues; 469 fChannelValues = newValues; 470 BControl::SetValue(fChannelValues[fCurrentChannel]); 471 472 return B_OK; 473 } 474 475 476 status_t 477 BChannelControl::SetLimitsFor(int32 channel, int32 minimum, int32 maximum) 478 { 479 return SetLimitsFor(channel, 1, &minimum, &maximum); 480 } 481 482 483 status_t 484 BChannelControl::GetLimitsFor(int32 channel, int32* minimum, 485 int32* maximum) const 486 { 487 return GetLimitsFor(channel, 1, minimum, maximum); 488 } 489 490 491 status_t 492 BChannelControl::SetLimitsFor(int32 fromChannel, int32 channelCount, 493 const int32* minimum, const int32* maximum) 494 { 495 if (fromChannel + channelCount > CountChannels()) 496 channelCount = CountChannels() - fromChannel; 497 498 for (int i = 0; i < channelCount; i++) { 499 if (minimum[i] > maximum[i]) 500 return B_BAD_VALUE; 501 502 fChannelMin[fromChannel + i] = minimum[i]; 503 fChannelMax[fromChannel + i] = maximum[i]; 504 if (fChannelValues[fromChannel + i] < minimum[i]) 505 fChannelValues[fromChannel + i] = minimum[i]; 506 else if (fChannelValues[fromChannel + i] > maximum[i]) 507 fChannelValues[fromChannel + i] = maximum[i]; 508 } 509 510 return B_OK; 511 } 512 513 514 status_t 515 BChannelControl::GetLimitsFor(int32 fromChannel, int32 channelCount, 516 int32* minimum, int32* maximum) const 517 { 518 if (minimum == NULL || maximum == NULL) 519 return B_BAD_VALUE; 520 521 if (fChannelMin == NULL || fChannelMax == NULL) 522 return B_ERROR; 523 if (fromChannel + channelCount > CountChannels()) 524 channelCount = CountChannels() - fromChannel; 525 526 for (int i = 0; i < channelCount; i++) { 527 minimum[i] = fChannelMin[fromChannel + i]; 528 maximum[i] = fChannelMax[fromChannel + i]; 529 } 530 531 return B_OK; 532 } 533 534 535 status_t 536 BChannelControl::SetLimits(int32 minimum, int32 maximum) 537 { 538 if (minimum > maximum) 539 return B_BAD_VALUE; 540 541 int32 numChannels = CountChannels(); 542 543 for (int32 c = 0; c < numChannels; c++) { 544 fChannelMin[c] = minimum; 545 fChannelMax[c] = maximum; 546 if (fChannelValues[c] < minimum) 547 fChannelValues[c] = minimum; 548 else if (fChannelValues[c] > maximum) 549 fChannelValues[c] = maximum; 550 } 551 552 return B_OK; 553 } 554 555 556 status_t 557 BChannelControl::GetLimits(int32* outMinimum, int32* outMaximum) const 558 { 559 if (outMinimum == NULL || outMaximum == NULL) 560 return B_BAD_VALUE; 561 562 if (fChannelMin == NULL || fChannelMax == NULL) 563 return B_ERROR; 564 565 int32 numChannels = CountChannels(); 566 for (int32 c = 0; c < numChannels; c++) { 567 outMinimum[c] = fChannelMin[c]; 568 outMaximum[c] = fChannelMax[c]; 569 } 570 571 return B_OK; 572 } 573 574 575 status_t 576 BChannelControl::SetLimitLabels(const char* minLabel, const char* maxLabel) 577 { 578 if (minLabel != fMinLabel) 579 fMinLabel = minLabel; 580 581 if (maxLabel != fMaxLabel) 582 fMaxLabel = maxLabel; 583 584 Invalidate(); 585 586 return B_OK; 587 } 588 589 590 const char* 591 BChannelControl::MinLimitLabel() const 592 { 593 return fMinLabel.String(); 594 } 595 596 597 const char* 598 BChannelControl::MaxLimitLabel() const 599 { 600 return fMaxLabel.String(); 601 } 602 603 604 status_t 605 BChannelControl::SetLimitLabelsFor(int32 channel, const char* minLabel, 606 const char* maxLabel) 607 { 608 (*(label_map*)fMultiLabels)[channel].max_label = maxLabel; 609 (*(label_map*)fMultiLabels)[channel].min_label = minLabel; 610 return B_OK; 611 } 612 613 614 status_t 615 BChannelControl::SetLimitLabelsFor(int32 fromChannel, int32 channelCount, 616 const char* minLabel, const char* maxLabel) 617 { 618 for (int32 i = fromChannel; i < fromChannel + channelCount; i++) { 619 SetLimitLabelsFor(i, minLabel, maxLabel); 620 } 621 return B_OK; 622 } 623 624 625 const char* 626 BChannelControl::MinLimitLabelFor(int32 channel) const 627 { 628 if (fMultiLabels != NULL) { 629 label_map::const_iterator iter = ((label_map*)fMultiLabels)->find(channel); 630 if (iter != ((label_map*)fMultiLabels)->end()) 631 return (*iter).second.min_label.c_str(); 632 } 633 return NULL; 634 } 635 636 637 const char* 638 BChannelControl::MaxLimitLabelFor(int32 channel) const 639 { 640 if (fMultiLabels != NULL) { 641 label_map::const_iterator iter = ((label_map*)fMultiLabels)->find(channel); 642 if (iter != ((label_map*)fMultiLabels)->end()) 643 return (*iter).second.max_label.c_str(); 644 } 645 return NULL; 646 } 647 648 649 status_t 650 BChannelControl::StuffValues(int32 fromChannel, int32 channelCount, 651 const int32* values) 652 { 653 if (values == NULL) 654 return B_BAD_VALUE; 655 656 if (fromChannel < 0 || fromChannel > fChannelCount 657 || fromChannel + channelCount > fChannelCount) { 658 return B_BAD_INDEX; 659 } 660 661 for (int32 i = 0; i < channelCount; i++) { 662 if (values[i] <= fChannelMax[fromChannel + i] 663 && values[i] >= fChannelMin[fromChannel + i]) { 664 fChannelValues[fromChannel + i] = values[i]; 665 } 666 } 667 668 // if the current channel was updated, update also the control value 669 if (fCurrentChannel >= fromChannel 670 && fCurrentChannel <= fromChannel + channelCount) { 671 BControl::SetValue(fChannelValues[fCurrentChannel]); 672 } 673 674 return B_OK; 675 } 676 677 678 void BChannelControl::_Reserverd_ChannelControl_0(void*, ...) {} 679 void BChannelControl::_Reserverd_ChannelControl_1(void*, ...) {} 680 void BChannelControl::_Reserverd_ChannelControl_2(void*, ...) {} 681 void BChannelControl::_Reserverd_ChannelControl_3(void*, ...) {} 682 void BChannelControl::_Reserverd_ChannelControl_4(void*, ...) {} 683 void BChannelControl::_Reserverd_ChannelControl_5(void*, ...) {} 684 void BChannelControl::_Reserverd_ChannelControl_6(void*, ...) {} 685 void BChannelControl::_Reserverd_ChannelControl_7(void*, ...) {} 686 void BChannelControl::_Reserverd_ChannelControl_8(void*, ...) {} 687 void BChannelControl::_Reserverd_ChannelControl_9(void*, ...) {} 688 void BChannelControl::_Reserverd_ChannelControl_10(void*, ...) {} 689 void BChannelControl::_Reserverd_ChannelControl_11(void*, ...) {} 690