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