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