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