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
13struct limit_label {
14	std::string min_label;
15	std::string max_label;
16};
17
18typedef std::map<int32, limit_label> label_map;
19
20static property_info
21sPropertyInfo[] = {
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
46BChannelControl::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
73BChannelControl::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
99BChannelControl::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
148BChannelControl::~BChannelControl()
149{
150	delete[] fChannelMin;
151	delete[] fChannelMax;
152	delete[] fChannelValues;
153	delete fModificationMsg;
154	delete reinterpret_cast<label_map*>(fMultiLabels);
155}
156
157
158status_t
159BChannelControl::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
195void
196BChannelControl::FrameResized(float newWidth, float newHeight)
197{
198	BView::FrameResized(newWidth, newHeight);
199}
200
201
202void
203BChannelControl::SetFont(const BFont* font, uint32 mask)
204{
205	BView::SetFont(font, mask);
206}
207
208
209void
210BChannelControl::AttachedToWindow()
211{
212	BControl::AttachedToWindow();
213}
214
215
216void
217BChannelControl::DetachedFromWindow()
218{
219	BControl::DetachedFromWindow();
220}
221
222
223void
224BChannelControl::ResizeToPreferred()
225{
226	BControl::ResizeToPreferred();
227}
228
229
230void
231BChannelControl::MessageReceived(BMessage* message)
232{
233	BControl::MessageReceived(message);
234}
235
236
237BHandler*
238BChannelControl::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
253status_t
254BChannelControl::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
272void
273BChannelControl::SetModificationMessage(BMessage* message)
274{
275	delete fModificationMsg;
276	fModificationMsg = message;
277}
278
279
280BMessage*
281BChannelControl::ModificationMessage() const
282{
283	return fModificationMsg;
284}
285
286
287status_t
288BChannelControl::Invoke(BMessage* message)
289{
290	bool notify = false;
291	BMessage invokeMessage(InvokeKind(&notify));
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
304status_t
305BChannelControl::InvokeChannel(BMessage* message, int32 fromChannel,
306	int32 channelCount, const bool* _mask)
307{
308	bool notify = false;
309	BMessage invokeMessage(InvokeKind(&notify));
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
330status_t
331BChannelControl::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
342void
343BChannelControl::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
359status_t
360BChannelControl::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
374int32
375BChannelControl::CurrentChannel() const
376{
377	return fCurrentChannel;
378}
379
380
381int32
382BChannelControl::CountChannels() const
383{
384	return fChannelCount;
385}
386
387
388status_t
389BChannelControl::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
419int32
420BChannelControl::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
430int32
431BChannelControl::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
442status_t
443BChannelControl::SetValueFor(int32 channel, int32 value)
444{
445	return SetValue(channel, 1, &value);
446}
447
448
449status_t
450BChannelControl::SetValue(int32 fromChannel, int32 channelCount,
451	const int32* values)
452{
453	return StuffValues(fromChannel, channelCount, values);
454}
455
456
457status_t
458BChannelControl::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
476status_t
477BChannelControl::SetLimitsFor(int32 channel, int32 minimum, int32 maximum)
478{
479	return SetLimitsFor(channel, 1, &minimum, &maximum);
480}
481
482
483status_t
484BChannelControl::GetLimitsFor(int32 channel, int32* minimum,
485	int32* maximum) const
486{
487	return GetLimitsFor(channel, 1, minimum, maximum);
488}
489
490
491status_t
492BChannelControl::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
514status_t
515BChannelControl::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
535status_t
536BChannelControl::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
556status_t
557BChannelControl::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
575status_t
576BChannelControl::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
590const char*
591BChannelControl::MinLimitLabel() const
592{
593	return fMinLabel.String();
594}
595
596
597const char*
598BChannelControl::MaxLimitLabel() const
599{
600	return fMaxLabel.String();
601}
602
603
604status_t
605BChannelControl::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
614status_t
615BChannelControl::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
625const char*
626BChannelControl::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
637const char*
638BChannelControl::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
649status_t
650BChannelControl::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
678void BChannelControl::_Reserverd_ChannelControl_0(void*, ...) {}
679void BChannelControl::_Reserverd_ChannelControl_1(void*, ...) {}
680void BChannelControl::_Reserverd_ChannelControl_2(void*, ...) {}
681void BChannelControl::_Reserverd_ChannelControl_3(void*, ...) {}
682void BChannelControl::_Reserverd_ChannelControl_4(void*, ...) {}
683void BChannelControl::_Reserverd_ChannelControl_5(void*, ...) {}
684void BChannelControl::_Reserverd_ChannelControl_6(void*, ...) {}
685void BChannelControl::_Reserverd_ChannelControl_7(void*, ...) {}
686void BChannelControl::_Reserverd_ChannelControl_8(void*, ...) {}
687void BChannelControl::_Reserverd_ChannelControl_9(void*, ...) {}
688void BChannelControl::_Reserverd_ChannelControl_10(void*, ...) {}
689void BChannelControl::_Reserverd_ChannelControl_11(void*, ...) {}
690