1/*
2 * Copyright 2002-2012, Haiku. All Rights Reserved.
3 * This file may be used under the terms of the MIT License.
4 *
5 * Author: Zousar Shaker
6 *         Axel D��rfler, axeld@pinc-software.de
7 *         Marcus Overhagen
8 */
9
10
11/*! Implements the following classes:
12	BParameterWeb, BParameterGroup, BParameter, BNullParameter,
13	BContinuousParameter, BDiscreteParameter
14*/
15
16
17#include <ParameterWeb.h>
18
19#include <new>
20#include <string.h>
21
22#include <MediaNode.h>
23#include <MediaRoster.h>
24
25#include "DataExchange.h"
26#include "MediaDebug.h"
27#include "MediaMisc.h"
28
29
30/*
31	The following is documentation on the flattened format
32	of structures/classes in this module:
33
34	//--------BEGIN-CORE-BPARAMETER-STRUCT---------------------
35	?? (0x02040607): 4 bytes
36	BParameter Struct Size (in bytes): 4 bytes
37	ID: 4 bytes
38	Name String Length: 1 byte (??)
39		Name String: 'Name String Length' bytes
40	Kind String Length: 1 byte (??)
41		Kind String: 'Kind String Length' bytes
42	Unit String Length: 1 byte (??)
43		Unit String: 'Unit String Length' bytes
44	Inputs Count: 4 bytes
45		Inputs (pointers): ('Inputs Count')*4 bytes
46	Outputs Count: 4 bytes
47		Outputs (pointers): ('Outputs Count')*4 bytes
48	Media Type: 4 bytes
49	ChannelCount: 4 bytes
50	Flags: 4 bytes
51	//---------END-CORE-BPARAMETER-STRUCT-----------------------
52	//--------BEGIN-BCONTINUOUSPARAMETER-STRUCT---------
53	Min: 4 bytes (as float)
54	Max: 4 bytes (as float)
55	Stepping: 4 bytes (as float)
56	Response: 4 bytes (as int or enum)
57	Factor: 4 bytes (as float)
58	Offset: 4 bytes (as float)
59	//--------END-BCONTINUOUSPARAMETER-STRUCT-------------
60	//--------BEGIN-BDISCRETEPARAMETER-STRUCT----------------
61	NumItems: 4 bytes (as int)
62		//for each item BEGIN
63		Item Name String Length: 1 byte
64			Item Name String: 'Item Name String Length' bytes
65		Item Value: 4 bytes (as int)
66		//for each item END
67	//--------END-BDISCRETEPARAMETER-STRUCT-------------------
68
69	//--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
70	?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
71	(possible) Flags: 4 bytes
72	Name String Length: 1 byte (??)
73		Name String: 'Name String Length' bytes
74	Param Count: 4 bytes
75		//for each Param BEGIN
76		Pointer: 4 bytes
77		Parameter Type: 4 bytes
78		Flattened Parameter Size: 4 bytes
79		Flattened Parameter: 'Flattened Parameter Size' bytes
80		//for each Param END
81	Subgroup Count: 4 bytes
82		//for each SubGroup BEGIN
83		Pointer: 4 bytes
84		MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
85		Flattened Group Size: 4 bytes
86		Flattened Group: 'Flattened Group Size' bytes
87		//for each SubGroup END
88
89	//---------END-CORE-BPARAMETERGROUP-STRUCT--------------
90
91	//--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
92	?? 0x01030506: 4 bytes
93	??: 4 bytes (is always 1)
94	Group Count: 4 bytes
95	Node (as media_node): 0x18 bytes (decimal 24 bytes)
96		//for each Group BEGIN
97		Flattened Group Size: 4 bytes
98		Flattened Group: 'Flattened Group Size' bytes
99		//for each Group END
100		//for each Group BEGIN
101		??: 4 bytes (never get written to (holds uninitialized value))
102		//for each Group END
103	//---------END-CORE-BPARAMETERWEB-STRUCT--------------
104
105*/
106
107
108const char * const B_GENERIC			 = "";
109const char * const B_MASTER_GAIN		 = "Master";
110const char * const B_GAIN				 = "Gain";
111const char * const B_BALANCE			 = "Balance";
112const char * const B_FREQUENCY			 = "Frequency";
113const char * const B_LEVEL				 = "Level";
114const char * const B_SHUTTLE_SPEED		 = "Speed";
115const char * const B_CROSSFADE			 = "XFade";
116const char * const B_EQUALIZATION		 = "EQ";
117const char * const B_COMPRESSION		 = "Compression";
118const char * const B_QUALITY			 = "Quality";
119const char * const B_BITRATE			 = "Bitrate";
120const char * const B_GOP_SIZE			 = "GOPSize";
121const char * const B_MUTE				 = "Mute";
122const char * const B_ENABLE				 = "Enable";
123const char * const B_INPUT_MUX			 = "Input";
124const char * const B_OUTPUT_MUX			 = "Output";
125const char * const B_TUNER_CHANNEL		 = "Channel";
126const char * const B_TRACK				 = "Track";
127const char * const B_RECSTATE			 = "RecState";
128const char * const B_SHUTTLE_MODE		 = "Shuttle";
129const char * const B_RESOLUTION			 = "Resolution";
130const char * const B_COLOR_SPACE		 = "Colorspace";
131const char * const B_FRAME_RATE			 = "FrameRate";
132const char * const B_VIDEO_FORMAT		 = "VideoFormat";
133const char * const B_WEB_PHYSICAL_INPUT	 = "PhysInput";
134const char * const B_WEB_PHYSICAL_OUTPUT = "PhysOutput";
135const char * const B_WEB_ADC_CONVERTER	 = "ADC";
136const char * const B_WEB_DAC_CONVERTER	 = "DAC";
137const char * const B_WEB_LOGICAL_INPUT	 = "LogInput";
138const char * const B_WEB_LOGICAL_OUTPUT	 = "LogOutput";
139const char * const B_WEB_LOGICAL_BUS	 = "LogBus";
140const char * const B_WEB_BUFFER_INPUT	 = "DataInput";
141const char * const B_WEB_BUFFER_OUTPUT	 = "DataOutput";
142const char * const B_SIMPLE_TRANSPORT	 = "SimpleTransport";
143
144// Flattened data
145
146static const int32 kCurrentParameterWebVersion = 1;
147static const uint32 kParameterWebMagic = 0x01030506;
148static const uint32 kBufferGroupMagic = 0x03040509;
149static const uint32 kBufferGroupMagicNoFlags = 0x03040507;
150static const uint32 kParameterMagic = 0x02040607;
151
152static const ssize_t kAdditionalParameterGroupSize = 12;
153static const ssize_t kAdditionalParameterSize = 23 + 3 * sizeof(ssize_t);
154
155/* BContinuousParameter - FlattenedSize() fixed part
156 *	Min: 4 bytes (as float)
157 *	Max: 4 bytes (as float)
158 *	Stepping: 4 bytes (as float)
159 *	Response: 4 bytes (as int or enum)
160 *	Factor: 4 bytes (as float)
161 *	Offset: 4 bytes (as float)
162 */
163static const ssize_t kAdditionalContinuousParameterSize = 5 * sizeof(float)
164	+ sizeof(BContinuousParameter::response);
165static const ssize_t kAdditionalDiscreteParameterSize = sizeof(ssize_t);
166
167
168// helper functions
169
170
171template<class Type> Type
172read_from_buffer(const void **_buffer)
173{
174	const Type *typedBuffer = static_cast<const Type *>(*_buffer);
175	Type value = *typedBuffer;
176
177	typedBuffer++;
178	*_buffer = static_cast<const void *>(typedBuffer);
179
180	return value;
181}
182
183
184static status_t
185read_string_from_buffer(const void **_buffer, char **_string, ssize_t size)
186{
187	if (size < 1)
188		return B_BAD_VALUE;
189
190	const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
191	uint8 length = *buffer++;
192	if (length > size - 1)
193		return B_BAD_VALUE;
194
195	char *string = (char *)malloc(length + 1);
196	if (string == NULL)
197		return B_NO_MEMORY;
198
199	memcpy(string, buffer, length);
200	string[length] = '\0';
201
202	free(*_string);
203
204	*_buffer = static_cast<const void *>(buffer + length);
205	*_string = string;
206	return B_OK;
207}
208
209
210// currently unused
211#if 0
212template<class Type> Type *
213reserve_in_buffer(void **_buffer)
214{
215	Type *typedBuffer = static_cast<Type *>(*_buffer);
216
217	*typedBuffer = 0;
218	typedBuffer++;
219
220	*_buffer = static_cast<void *>(typedBuffer);
221}
222#endif
223
224template<class Type> void
225write_to_buffer(void **_buffer, Type value)
226{
227	Type *typedBuffer = static_cast<Type *>(*_buffer);
228
229	*typedBuffer = value;
230	typedBuffer++;
231
232	*_buffer = static_cast<void *>(typedBuffer);
233}
234
235
236void
237write_string_to_buffer(void **_buffer, const char *string)
238{
239	uint8 *buffer = static_cast<uint8 *>(*_buffer);
240	uint32 length = string ? strlen(string) : 0;
241	if (length > 255)
242		length = 255;
243
244	*buffer++ = static_cast<uint8>(length);
245	if (length) {
246		memcpy(buffer, string, length);
247		buffer += length;
248	}
249
250	*_buffer = static_cast<void *>(buffer);
251}
252
253
254static void
255skip_in_buffer(const void **_buffer, uint32 bytes)
256{
257	const uint8 *buffer = static_cast<const uint8 *>(*_buffer);
258
259	buffer += bytes;
260
261	*_buffer = static_cast<const void *>(buffer);
262}
263
264
265static void inline
266skip_in_buffer(void **_buffer, uint32 bytes)
267{
268	// This actually shouldn't be necessary, but I believe it's a
269	// bug in Be's gcc - it complains about "adds cv-quals without intervening `const'"
270	// when passing a "const void **" pointer as the first argument.
271	// Maybe I am just stupid, though -- axeld.
272
273	skip_in_buffer((const void **)_buffer, bytes);
274}
275
276
277template<class Type> Type
278swap32(Type value, bool doSwap)
279{
280	STATIC_ASSERT(sizeof(Type) == 4);
281
282	if (doSwap)
283		return (Type)B_SWAP_INT32((int32)value);
284
285	return value;
286}
287
288
289template<class Type> Type
290swap64(Type value, bool doSwap)
291{
292	STATIC_ASSERT(sizeof(Type) == 8);
293
294	if (doSwap)
295		return (Type)B_SWAP_INT64((int64)value);
296
297	return value;
298}
299
300
301template<class Type> Type
302read_from_buffer_swap32(const void **_buffer, bool doSwap)
303{
304	return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
305}
306
307
308template<class Type> Type
309read_pointer_from_buffer_swap(const void **_buffer, bool doSwap)
310{
311#if B_HAIKU_32_BIT
312	return swap32<Type>(read_from_buffer<Type>(_buffer), doSwap);
313#elif B_HAIKU_64_BIT
314	return swap64<Type>(read_from_buffer<Type>(_buffer), doSwap);
315#else
316#	error Interesting
317#endif
318}
319
320
321static inline ssize_t
322size_left(ssize_t size, const void *bufferStart, const void *buffer)
323{
324	return size - static_cast<ssize_t>((const uint8 *)buffer - (const uint8 *)bufferStart);
325}
326
327
328//	#pragma mark - BParameterWeb
329
330
331BParameterWeb::BParameterWeb()
332	:
333	fNode(media_node::null)
334		// fNode is set in BControllable::SetParameterWeb()
335{
336	CALLED();
337
338	fGroups = new BList();
339	fOldRefs = new BList();
340	fNewRefs = new BList();
341}
342
343
344BParameterWeb::~BParameterWeb()
345{
346	CALLED();
347
348	for (int32 i = fGroups->CountItems(); i-- > 0;) {
349		delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
350	}
351
352	delete fGroups;
353	delete fOldRefs;
354	delete fNewRefs;
355}
356
357
358media_node
359BParameterWeb::Node()
360{
361	return fNode;
362}
363
364
365BParameterGroup*
366BParameterWeb::MakeGroup(const char* name)
367{
368	CALLED();
369
370	BParameterGroup* group = new(std::nothrow) BParameterGroup(this, name);
371	if (group == NULL)
372		return NULL;
373
374	if (!fGroups->AddItem(group)) {
375		delete group;
376		return NULL;
377	}
378
379	return group;
380}
381
382
383int32
384BParameterWeb::CountGroups()
385{
386	return fGroups->CountItems();
387}
388
389
390BParameterGroup*
391BParameterWeb::GroupAt(int32 index)
392{
393	return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
394}
395
396
397int32
398BParameterWeb::CountParameters()
399{
400	CALLED();
401
402	// Counts over all groups (and sub-groups) in the web.
403	// The "groups" list is used as count stack
404
405	BList groups(*fGroups);
406	int32 count = 0;
407
408	for (int32 i = 0; i < groups.CountItems(); i++) {
409		BParameterGroup* group
410			= static_cast<BParameterGroup*>(groups.ItemAt(i));
411
412		count += group->CountParameters();
413
414		if (group->fGroups != NULL)
415			groups.AddList(group->fGroups);
416	}
417
418	return count;
419}
420
421
422BParameter*
423BParameterWeb::ParameterAt(int32 index)
424{
425	CALLED();
426
427	// Iterates over all groups (and sub-groups) in the web.
428	// The "groups" list is used as iteration stack (breadth search style)
429	// Maintains the same order as the Be implementation
430
431	BList groups(*fGroups);
432
433	for (int32 i = 0; i < groups.CountItems(); i++) {
434		BParameterGroup* group
435			= static_cast<BParameterGroup*>(groups.ItemAt(i));
436		int32 count = group->CountParameters();
437		if (index < count)
438			return group->ParameterAt(index);
439
440		index -= count;
441			// the index is always relative to the start of the current group
442
443		if (group->fGroups != NULL)
444			groups.AddList(group->fGroups);
445	}
446
447	TRACE("*** could not find parameter at %"
448		B_PRId32 " (count = %" B_PRId32 ")\n", index, CountParameters());
449
450	return NULL;
451}
452
453
454bool
455BParameterWeb::IsFixedSize() const
456{
457	return false;
458}
459
460
461type_code
462BParameterWeb::TypeCode() const
463{
464	return B_MEDIA_PARAMETER_WEB_TYPE;
465}
466
467
468ssize_t
469BParameterWeb::FlattenedSize() const
470{
471	CALLED();
472
473/*
474	//--------BEGIN-CORE-BPARAMETERWEB-STRUCT-----------
475	?? 0x01030506: 4 bytes
476	??: 4 bytes (is always 1)
477	Group Count: 4 bytes
478	Node (as media_node): 0x18 bytes (decimal 24 bytes)
479		//for each Group BEGIN
480		Flattened Group Size: 4 bytes
481		Flattened Group: 'Flattened Group Size' bytes
482		//for each Group END
483		//for each Group BEGIN
484		??: 4 bytes (never get written to (holds uninitialized value))
485		//for each Group END
486	//---------END-CORE-BPARAMETERWEB-STRUCT--------------
487*/
488	//36 guaranteed bytes, variable after that.
489	ssize_t size = sizeof(int32) + 2 * sizeof(int32) + sizeof(media_node);
490
491	for (int32 i = fGroups->CountItems(); i-- > 0;) {
492		BParameterGroup* group
493			= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
494		if (group != NULL) {
495			size += sizeof(ssize_t) + group->FlattenedSize();
496		}
497	}
498
499	return size;
500}
501
502
503status_t
504BParameterWeb::Flatten(void* buffer, ssize_t size) const
505{
506	CALLED();
507
508	if (buffer == NULL)
509		return B_NO_INIT;
510
511	ssize_t actualSize = BParameterWeb::FlattenedSize();
512	if (size < actualSize)
513		return B_NO_MEMORY;
514
515	void* bufferStart = buffer;
516
517	write_to_buffer<int32>(&buffer, kParameterWebMagic);
518	write_to_buffer<int32>(&buffer, kCurrentParameterWebVersion);
519
520	// flatten all groups into this buffer
521
522	int32 count = fGroups->CountItems();
523	write_to_buffer<int32>(&buffer, count);
524
525	write_to_buffer<media_node>(&buffer, fNode);
526
527	for (int32 i = 0; i < count; i++) {
528		BParameterGroup* group
529			= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
530		if (group == NULL) {
531			ERROR("BParameterWeb::Flatten(): group is NULL\n");
532			continue;
533		}
534
535		ssize_t groupSize = group->FlattenedSize();
536		if (groupSize > size_left(size, bufferStart, buffer)) {
537			ERROR("BParameterWeb::Flatten(): buffer too small\n");
538			return B_BAD_VALUE;
539		}
540
541		write_to_buffer<ssize_t>(&buffer, groupSize);
542
543		// write the flattened sub group
544		status_t status = group->Flatten(buffer, groupSize);
545		if (status < B_OK)
546			return status;
547
548		skip_in_buffer(&buffer, groupSize);
549	}
550
551	return B_OK;
552}
553
554
555bool
556BParameterWeb::AllowsTypeCode(type_code code) const
557{
558	return code == TypeCode();
559}
560
561
562status_t
563BParameterWeb::Unflatten(type_code code, const void* buffer, ssize_t size)
564{
565	CALLED();
566
567	if (!AllowsTypeCode(code)) {
568		ERROR("BParameterWeb::Unflatten(): wrong type code\n");
569		return B_BAD_TYPE;
570	}
571
572	if (buffer == NULL) {
573		ERROR("BParameterWeb::Unflatten(): NULL buffer pointer\n");
574		return B_NO_INIT;
575	}
576
577	// if the buffer is smaller than the size needed to read the
578	// signature field, the mystery field, the group count, and the Node, then there is a problem
579	if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(int32)
580			+ sizeof(ssize_t) + sizeof(media_node))) {
581		ERROR("BParameterWeb::Unflatten(): size to small\n");
582		return B_ERROR;
583	}
584
585	const void* bufferStart = buffer;
586
587	uint32 magic = read_from_buffer<uint32>(&buffer);
588	bool isSwapped = false;
589
590	if (magic == B_SWAP_INT32(kParameterWebMagic)) {
591		isSwapped = true;
592		magic = B_SWAP_INT32(magic);
593	}
594	if (magic != kParameterWebMagic)
595		return B_BAD_DATA;
596
597	// Note, it's not completely sure that this field is the version
598	// information - but it doesn't seem to have another purpose
599	int32 version = read_from_buffer_swap32<int32>(&buffer, isSwapped);
600	if (version != kCurrentParameterWebVersion) {
601		ERROR("BParameterWeb::Unflatten(): wrong version %" B_PRId32 " (%"
602			B_PRIx32 ")?!\n", version, version);
603		return B_ERROR;
604	}
605
606	for (int32 i = 0; i < fGroups->CountItems(); i++) {
607		delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
608	}
609	fGroups->MakeEmpty();
610
611	int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
612
613	fNode = read_from_buffer<media_node>(&buffer);
614	if (isSwapped)
615		swap_data(B_INT32_TYPE, &fNode, sizeof(media_node), B_SWAP_ALWAYS);
616
617	for (int32 i = 0; i < count; i++) {
618		ssize_t groupSize
619			= read_pointer_from_buffer_swap<ssize_t>(&buffer, isSwapped);
620		if (groupSize > size_left(size, bufferStart, buffer)) {
621			ERROR("BParameterWeb::Unflatten(): buffer too small\n");
622			return B_BAD_DATA;
623		}
624
625		BParameterGroup* group = new BParameterGroup(this, "unnamed");
626		status_t status = group->Unflatten(group->TypeCode(), buffer,
627			groupSize);
628		if (status < B_OK) {
629			ERROR("BParameterWeb::Unflatten(): unflatten group failed\n");
630			delete group;
631			return status;
632		}
633
634		skip_in_buffer(&buffer, groupSize);
635
636		fGroups->AddItem(group);
637	}
638
639	// fix all references (ParameterAt() style)
640
641	BList groups(*fGroups);
642
643	for (int32 i = 0; i < groups.CountItems(); i++) {
644		BParameterGroup* group
645			= static_cast<BParameterGroup*>(groups.ItemAt(i));
646
647		for (int32 index = group->CountParameters(); index-- > 0;) {
648			BParameter* parameter
649				= static_cast<BParameter*>(group->ParameterAt(index));
650
651			parameter->FixRefs(*fOldRefs, *fNewRefs);
652		}
653
654		if (group->fGroups != NULL)
655			groups.AddList(group->fGroups);
656	}
657
658	fOldRefs->MakeEmpty();
659	fNewRefs->MakeEmpty();
660
661	return B_OK;
662}
663
664
665void
666BParameterWeb::AddRefFix(void* oldItem, void* newItem)
667{
668	fOldRefs->AddItem(oldItem);
669	fNewRefs->AddItem(newItem);
670}
671
672
673//	#pragma mark - BParameterGroup
674
675
676BParameterGroup::BParameterGroup(BParameterWeb* web, const char* name)
677	:
678	fWeb(web),
679	fFlags(0)
680{
681	CALLED();
682	TRACE("BParameterGroup: web = %p, name = \"%s\"\n", web, name);
683
684	fName = strndup(name, 255);
685
686	fControls = new BList();
687	fGroups = new BList();
688}
689
690
691BParameterGroup::~BParameterGroup()
692{
693	CALLED();
694
695	for (int i = fControls->CountItems(); i-- > 0;) {
696		delete static_cast<BParameter*>(fControls->ItemAt(i));
697	}
698	delete fControls;
699
700	for (int i = fGroups->CountItems(); i-- > 0;) {
701		delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
702	}
703	delete fGroups;
704
705	free(fName);
706}
707
708
709BParameterWeb*
710BParameterGroup::Web() const
711{
712	return fWeb;
713}
714
715
716const char*
717BParameterGroup::Name() const
718{
719	return fName;
720}
721
722
723void
724BParameterGroup::SetFlags(uint32 flags)
725{
726	fFlags = flags;
727}
728
729
730uint32
731BParameterGroup::Flags() const
732{
733	return fFlags;
734}
735
736
737BNullParameter*
738BParameterGroup::MakeNullParameter(int32 id, media_type mediaType,
739	const char* name, const char* kind)
740{
741	CALLED();
742
743	BNullParameter* parameter = new(std::nothrow) BNullParameter(id, mediaType,
744		fWeb, name, kind);
745	if (parameter == NULL)
746		return NULL;
747
748	parameter->fGroup = this;
749	fControls->AddItem(parameter);
750
751	return parameter;
752}
753
754
755BContinuousParameter*
756BParameterGroup::MakeContinuousParameter(int32 id, media_type mediaType,
757	const char* name, const char* kind, const char* unit,
758	float minimum, float maximum, float stepping)
759{
760	CALLED();
761
762	BContinuousParameter* parameter
763		= new(std::nothrow) BContinuousParameter(id, mediaType, fWeb, name,
764			kind, unit, minimum, maximum, stepping);
765	if (parameter == NULL)
766		return NULL;
767
768	parameter->fGroup = this;
769	fControls->AddItem(parameter);
770
771	return parameter;
772}
773
774
775BDiscreteParameter*
776BParameterGroup::MakeDiscreteParameter(int32 id, media_type mediaType,
777	const char* name, const char* kind)
778{
779	CALLED();
780
781	BDiscreteParameter* parameter = new(std::nothrow) BDiscreteParameter(id,
782		mediaType, fWeb, name, kind);
783	if (parameter == NULL)
784		return NULL;
785
786	parameter->fGroup = this;
787	fControls->AddItem(parameter);
788
789	return parameter;
790}
791
792
793BTextParameter*
794BParameterGroup::MakeTextParameter(int32 id, media_type mediaType,
795	const char* name, const char* kind, size_t maxBytes)
796{
797	CALLED();
798
799	BTextParameter* parameter = new(std::nothrow) BTextParameter(id, mediaType,
800		fWeb, name, kind, maxBytes);
801	if (parameter == NULL)
802		return NULL;
803
804	parameter->fGroup = this;
805	fControls->AddItem(parameter);
806
807	return parameter;
808}
809
810
811BParameterGroup*
812BParameterGroup::MakeGroup(const char* name)
813{
814	CALLED();
815
816	BParameterGroup* group = new(std::nothrow) BParameterGroup(fWeb, name);
817	if (group != NULL)
818		fGroups->AddItem(group);
819
820	return group;
821}
822
823
824int32
825BParameterGroup::CountParameters()
826{
827	return fControls->CountItems();
828}
829
830
831BParameter*
832BParameterGroup::ParameterAt(int32 index)
833{
834	return static_cast<BParameter*>(fControls->ItemAt(index));
835}
836
837
838int32
839BParameterGroup::CountGroups()
840{
841	return fGroups->CountItems();
842}
843
844
845BParameterGroup*
846BParameterGroup::GroupAt(int32 index)
847{
848	return static_cast<BParameterGroup*>(fGroups->ItemAt(index));
849}
850
851
852bool
853BParameterGroup::IsFixedSize() const
854{
855	return false;
856}
857
858
859type_code
860BParameterGroup::TypeCode() const
861{
862	return B_MEDIA_PARAMETER_GROUP_TYPE;
863}
864
865
866ssize_t
867BParameterGroup::FlattenedSize() const
868{
869	CALLED();
870
871	/*
872		//--------BEGIN-CORE-BPARAMETERGROUP-STRUCT-----------
873		?? (0x03040507 OR 0x03040509 depending if the flags field is included or not???): 4 bytes
874		(possible) Flags: 4 bytes
875		Name String Length: 1 byte (??)
876			Name String: 'Name String Length' bytes
877		Param Count: 4 bytes
878			//for each Param BEGIN
879			Pointer: 4 bytes
880			Parameter Type: 4 bytes
881			Flattened Parameter Size: 4 bytes
882			Flattened Parameter: 'Flattened Parameter Size' bytes
883			//for each Param END
884		Subgroup Count: 4 bytes
885			//for each SubGroup BEGIN
886			Pointer: 4 bytes
887			MEDIA PARAMETER GROUP TYPE('BMCG' (opposite byte order in file)): 4 bytes
888			Flattened Group Size: 4 bytes
889			Flattened Group: 'Flattened Group Size' bytes
890			//for each SubGroup END
891
892		//---------END-CORE-BPARAMETERGROUP-STRUCT--------------
893	*/
894	//13 guaranteed bytes, variable after that.
895	ssize_t size = 13;
896
897	if (fFlags != 0)
898		size += sizeof(uint32);
899
900	if (fName != NULL)
901		size += min_c(strlen(fName), 255);
902
903	int limit = fControls->CountItems();
904	for (int i = 0; i < limit; i++) {
905		BParameter* parameter = static_cast<BParameter*>(fControls->ItemAt(i));
906		if (parameter != NULL) {
907			// overhead for each parameter flattened
908			size += sizeof(BParameter*) + sizeof(BParameter::media_parameter_type)
909				 + sizeof(ssize_t) + parameter->FlattenedSize();
910		}
911	}
912
913	limit = fGroups->CountItems();
914	for (int i = 0; i < limit; i++) {
915		BParameterGroup* group
916			= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
917		if (group != NULL) {
918			// overhead for each group flattened
919			size += sizeof(BParameterGroup*) + sizeof(type_code)
920				+ sizeof(ssize_t) + group->FlattenedSize();
921		}
922	}
923
924	return size;
925}
926
927
928status_t
929BParameterGroup::Flatten(void* buffer, ssize_t size) const
930{
931	CALLED();
932
933	if (buffer == NULL) {
934		ERROR("BParameterGroup::Flatten buffer is NULL\n");
935		return B_NO_INIT;
936	}
937
938	// NOTICE: It is important that this value is the size returned by
939	// BParameterGroup::FlattenedSize, not by a descendent's override of this method.
940	ssize_t actualSize = BParameterGroup::FlattenedSize();
941	if (size < actualSize) {
942		ERROR("BParameterGroup::Flatten size to small\n");
943		return B_NO_MEMORY;
944	}
945
946	if (fFlags != 0) {
947		write_to_buffer<int32>(&buffer, kBufferGroupMagic);
948		write_to_buffer<uint32>(&buffer, fFlags);
949	} else
950		write_to_buffer<int32>(&buffer, kBufferGroupMagicNoFlags);
951
952	write_string_to_buffer(&buffer, fName);
953
954	int32 count = fControls->CountItems();
955	write_to_buffer<int32>(&buffer, count);
956
957	for (int32 i = 0; i < count; i++) {
958		BParameter* parameter = static_cast<BParameter*>(fControls->ItemAt(i));
959		if (parameter == NULL) {
960			ERROR("BParameterGroup::Flatten(): NULL parameter\n");
961			continue;
962		}
963
964		write_to_buffer<BParameter*>(&buffer, parameter);
965		write_to_buffer<BParameter::media_parameter_type>(&buffer,
966			parameter->Type());
967
968		// flatten parameter into this buffer
969
970		ssize_t parameterSize = parameter->FlattenedSize();
971		write_to_buffer<ssize_t>(&buffer, parameterSize);
972
973		status_t status = parameter->Flatten(buffer, parameterSize);
974			// we have only that much bytes left to write in this buffer
975		if (status < B_OK)
976			return status;
977
978		skip_in_buffer(&buffer, parameterSize);
979	}
980
981	count = fGroups->CountItems();
982	write_to_buffer<int32>(&buffer, count);
983
984	for (int32 i = 0; i < count; i++) {
985		BParameterGroup* group
986			= static_cast<BParameterGroup*>(fGroups->ItemAt(i));
987		if (group == NULL) {
988			ERROR("BParameterGroup::Flatten(): NULL group\n");
989			continue;
990		}
991
992		write_to_buffer<BParameterGroup*>(&buffer, group);
993		write_to_buffer<type_code>(&buffer, group->TypeCode());
994
995		// flatten sub group into this buffer
996
997		ssize_t groupSize = group->FlattenedSize();
998		write_to_buffer<ssize_t>(&buffer, groupSize);
999
1000		status_t status = group->Flatten(buffer, groupSize);
1001			// we have only that much bytes left to write in this buffer
1002		if (status < B_OK)
1003			return status;
1004
1005		skip_in_buffer(&buffer, groupSize);
1006	}
1007
1008	return B_OK;
1009}
1010
1011
1012bool
1013BParameterGroup::AllowsTypeCode(type_code code) const
1014{
1015	return code == TypeCode();
1016}
1017
1018
1019status_t
1020BParameterGroup::Unflatten(type_code code, const void* buffer, ssize_t size)
1021{
1022	CALLED();
1023
1024	if (!AllowsTypeCode(code)) {
1025		ERROR("BParameterGroup::Unflatten() wrong type code\n");
1026		return B_BAD_TYPE;
1027	}
1028
1029	if (buffer == NULL) {
1030		ERROR("BParameterGroup::Unflatten() buffer is NULL\n");
1031		return B_NO_INIT;
1032	}
1033
1034	// if the buffer is smaller than the size needed to read the
1035	// signature field, then there is a problem
1036	if (size < static_cast<ssize_t>(sizeof(int32))) {
1037		ERROR("BParameterGroup::Unflatten() size to small\n");
1038		return B_ERROR;
1039	}
1040
1041	const void* bufferStart = buffer;
1042		// used to compute the rest length of the buffer when needed
1043
1044	uint32 magic = read_from_buffer<uint32>(&buffer);
1045	bool isSwapped = false;
1046
1047	if (magic == B_SWAP_INT32(kBufferGroupMagic)
1048		|| magic == B_SWAP_INT32(kBufferGroupMagicNoFlags)) {
1049		isSwapped = true;
1050		magic = B_SWAP_INT32(magic);
1051	}
1052
1053	if (magic == kBufferGroupMagic)
1054		fFlags = read_from_buffer_swap32<int32>(&buffer, isSwapped);
1055	else if (magic == kBufferGroupMagicNoFlags)
1056		fFlags = 0;
1057	else
1058		return B_BAD_TYPE;
1059
1060	if (read_string_from_buffer(&buffer, &fName,
1061			size - (ssize_t)((uint8*)buffer - (uint8*)bufferStart)) < B_OK)
1062		return B_BAD_VALUE;
1063
1064	// Clear all existing parameters/subgroups
1065	for (int32 i = 0; i < fControls->CountItems(); i++) {
1066		delete static_cast<BParameter*>(fControls->ItemAt(i));
1067	}
1068	fControls->MakeEmpty();
1069
1070	for (int32 i = 0; i < fGroups->CountItems(); i++) {
1071		delete static_cast<BParameterGroup*>(fGroups->ItemAt(i));
1072	}
1073	fGroups->MakeEmpty();
1074
1075	// unflatten parameter list
1076
1077	int32 count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
1078	if (count < 0 || count * kAdditionalParameterSize
1079			> size_left(size, bufferStart, buffer))
1080		return B_BAD_VALUE;
1081
1082	for (int32 i = 0; i < count; i++) {
1083		// make sure we can read as many bytes
1084		if (size_left(size, bufferStart, buffer) < (ssize_t)(
1085				sizeof(BParameter*) + sizeof(BParameter::media_parameter_type)
1086				+ sizeof(ssize_t))) {
1087			return B_BAD_VALUE;
1088		}
1089
1090		BParameter* oldPointer = read_pointer_from_buffer_swap<BParameter*>(
1091			&buffer, isSwapped);
1092		BParameter::media_parameter_type mediaType
1093			= read_from_buffer_swap32<BParameter::media_parameter_type>(&buffer,
1094				isSwapped);
1095
1096		ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1097			isSwapped);
1098		if (parameterSize > size_left(size, bufferStart, buffer))
1099			return B_BAD_VALUE;
1100
1101		BParameter* parameter = MakeControl(mediaType);
1102		if (parameter == NULL) {
1103			ERROR("BParameterGroup::Unflatten(): MakeControl() failed\n");
1104			return B_ERROR;
1105		}
1106
1107		status_t status = parameter->Unflatten(parameter->TypeCode(), buffer,
1108			parameterSize);
1109		if (status < B_OK) {
1110			ERROR("BParameterGroup::Unflatten(): parameter->Unflatten() failed\n");
1111			delete parameter;
1112			return status;
1113		}
1114
1115		skip_in_buffer(&buffer, parameterSize);
1116
1117		// add the item to the list
1118		parameter->fGroup = this;
1119		parameter->fWeb = fWeb;
1120		fControls->AddItem(parameter);
1121
1122		// add it's old pointer value to the RefFix list kept by the owner web
1123		if (fWeb != NULL)
1124			fWeb->AddRefFix(oldPointer, parameter);
1125	}
1126
1127	// unflatten sub groups
1128
1129	count = read_from_buffer_swap32<int32>(&buffer, isSwapped);
1130	if (count < 0 || count * kAdditionalParameterGroupSize
1131			> size_left(size, bufferStart, buffer))
1132		return B_BAD_VALUE;
1133
1134	for (int32 i = 0; i < count; i++) {
1135		// make sure we can read as many bytes
1136		if (size_left(size, bufferStart, buffer) < (ssize_t)(
1137				sizeof(BParameterGroup*) + sizeof(type_code)
1138				+ sizeof(ssize_t))) {
1139			return B_BAD_VALUE;
1140		}
1141
1142		BParameterGroup* oldPointer = read_pointer_from_buffer_swap<
1143			BParameterGroup*>(&buffer, isSwapped);
1144		type_code type = read_from_buffer_swap32<type_code>(&buffer, isSwapped);
1145
1146		ssize_t groupSize
1147			= read_pointer_from_buffer_swap<ssize_t>(&buffer, isSwapped);
1148		if (groupSize > size_left(size, bufferStart, buffer))
1149			return B_BAD_VALUE;
1150
1151		BParameterGroup* group = new BParameterGroup(fWeb, "sub-unnamed");
1152		if (group == NULL) {
1153			ERROR("BParameterGroup::Unflatten(): MakeGroup() failed\n");
1154			return B_ERROR;
1155		}
1156
1157		status_t status = group->Unflatten(type, buffer, groupSize);
1158		if (status != B_OK) {
1159			ERROR("BParameterGroup::Unflatten(): group->Unflatten() failed\n");
1160			delete group;
1161			return status;
1162		}
1163
1164		skip_in_buffer(&buffer, groupSize);
1165
1166		fGroups->AddItem(group);
1167
1168		// add it's old pointer value to the RefFix list kept by the owner web
1169		if (fWeb != NULL)
1170			fWeb->AddRefFix(oldPointer, group);
1171	}
1172
1173	return B_OK;
1174}
1175
1176
1177/*!	Creates an uninitialized parameter of the specified type.
1178	Unlike the BParameterGroup::MakeXXXParameter() type of methods, this
1179	method does not add the parameter to this group automatically.
1180*/
1181BParameter*
1182BParameterGroup::MakeControl(int32 type)
1183{
1184	CALLED();
1185
1186	switch (type) {
1187		case BParameter::B_NULL_PARAMETER:
1188			return new BNullParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL);
1189
1190		case BParameter::B_DISCRETE_PARAMETER:
1191			return new BDiscreteParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
1192				NULL);
1193
1194		case BParameter::B_CONTINUOUS_PARAMETER:
1195			return new BContinuousParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL,
1196				NULL, NULL, 0, 0, 0);
1197
1198		case BParameter::B_TEXT_PARAMETER:
1199			return new BTextParameter(-1, B_MEDIA_NO_TYPE, NULL, NULL, NULL, 0);
1200
1201		default:
1202			ERROR("BParameterGroup::MakeControl unknown type %" B_PRId32 "\n",
1203				type);
1204			return NULL;
1205	}
1206}
1207
1208
1209//	#pragma mark - BParameter
1210
1211
1212BParameter::media_parameter_type
1213BParameter::Type() const
1214{
1215	return fType;
1216}
1217
1218
1219BParameterWeb*
1220BParameter::Web() const
1221{
1222	return fWeb;
1223}
1224
1225
1226BParameterGroup*
1227BParameter::Group() const
1228{
1229	return fGroup;
1230}
1231
1232
1233const char*
1234BParameter::Name() const
1235{
1236	return fName;
1237}
1238
1239
1240const char*
1241BParameter::Kind() const
1242{
1243	return fKind;
1244}
1245
1246
1247const char*
1248BParameter::Unit() const
1249{
1250	return fUnit;
1251}
1252
1253
1254int32
1255BParameter::ID() const
1256{
1257	return fID;
1258}
1259
1260
1261void
1262BParameter::SetFlags(uint32 flags)
1263{
1264	fFlags = flags;
1265}
1266
1267
1268uint32
1269BParameter::Flags() const
1270{
1271	return fFlags;
1272}
1273
1274
1275status_t
1276BParameter::GetValue(void* buffer, size_t* _size, bigtime_t* _when)
1277{
1278	CALLED();
1279
1280	if (buffer == NULL || _size == NULL)
1281		return B_BAD_VALUE;
1282
1283	size_t size = *_size;
1284	if (size <= 0)
1285		return B_NO_MEMORY;
1286
1287	if (fWeb == NULL) {
1288		ERROR("BParameter::GetValue: no parent BParameterWeb\n");
1289		return B_NO_INIT;
1290	}
1291
1292	media_node node = fWeb->Node();
1293	if (IS_INVALID_NODE(node)) {
1294		ERROR("BParameter::GetValue: the parent BParameterWeb is not assigned to a BMediaNode\n");
1295		return B_NO_INIT;
1296	}
1297
1298	controllable_get_parameter_data_request request;
1299	controllable_get_parameter_data_reply reply;
1300
1301	area_id area;
1302	void* data;
1303	if (size > MAX_PARAMETER_DATA) {
1304		// create an area if large data needs to be transfered
1305		area = create_area("get parameter data", &data, B_ANY_ADDRESS,
1306			ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1307		if (area < B_OK) {
1308			ERROR("BParameter::GetValue can't create area of %ld bytes\n",
1309				size);
1310			return B_NO_MEMORY;
1311		}
1312	} else {
1313		area = -1;
1314		data = reply.raw_data;
1315	}
1316
1317	request.parameter_id = fID;
1318	request.request_size = size;
1319	request.area = area;
1320
1321	status_t status = QueryPort(node.port, CONTROLLABLE_GET_PARAMETER_DATA,
1322		&request, sizeof(request), &reply, sizeof(reply));
1323	if (status == B_OK) {
1324		// we don't want to copy more than the buffer provides
1325		if (reply.size < size)
1326			size = reply.size;
1327
1328		memcpy(buffer, data, size);
1329
1330		// store reported values
1331
1332		*_size = reply.size;
1333		if (_when != NULL)
1334			*_when = reply.last_change;
1335	} else {
1336		ERROR("BParameter::GetValue parameter '%s' querying node %d, "
1337			"port %d failed: %s\n",  fName, (int)node.node, (int)node.port,
1338			strerror(status));
1339	}
1340
1341	if (area >= B_OK)
1342		delete_area(area);
1343
1344	return status;
1345}
1346
1347
1348status_t
1349BParameter::SetValue(const void* buffer, size_t size, bigtime_t when)
1350{
1351	CALLED();
1352
1353	if (buffer == 0)
1354		return B_BAD_VALUE;
1355	if (size <= 0)
1356		return B_NO_MEMORY;
1357
1358	if (fWeb == 0) {
1359		ERROR("BParameter::SetValue: no parent BParameterWeb\n");
1360		return B_NO_INIT;
1361	}
1362
1363	media_node node = fWeb->Node();
1364	if (IS_INVALID_NODE(node)) {
1365		ERROR("BParameter::SetValue: the parent BParameterWeb is not assigned "
1366			"to a BMediaNode\n");
1367		return B_NO_INIT;
1368	}
1369
1370	controllable_set_parameter_data_request request;
1371	controllable_set_parameter_data_reply reply;
1372	area_id area;
1373	void* data;
1374
1375	if (size > MAX_PARAMETER_DATA) {
1376		// create an area if large data needs to be transfered
1377		area = create_area("set parameter data", &data, B_ANY_ADDRESS,
1378			ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1379		if (area < B_OK) {
1380			ERROR("BParameter::SetValue can't create area of %ld bytes\n", size);
1381			return B_NO_MEMORY;
1382		}
1383	} else {
1384		area = -1;
1385		data = request.raw_data;
1386	}
1387
1388	memcpy(data, buffer, size);
1389	request.parameter_id = fID;
1390	request.when = when;
1391	request.area = area;
1392	request.size = size;
1393
1394	status_t status = QueryPort(node.port, CONTROLLABLE_SET_PARAMETER_DATA,
1395		&request, sizeof(request), &reply, sizeof(reply));
1396	if (status != B_OK) {
1397		ERROR("BParameter::SetValue querying node failed: %s\n",
1398			strerror(status));
1399	}
1400
1401	if (area != -1)
1402		delete_area(area);
1403
1404	return status;
1405}
1406
1407
1408int32
1409BParameter::CountChannels()
1410{
1411	return fChannels;
1412}
1413
1414
1415void
1416BParameter::SetChannelCount(int32 count)
1417{
1418	fChannels = count;
1419}
1420
1421
1422media_type
1423BParameter::MediaType()
1424{
1425	return fMediaType;
1426}
1427
1428
1429void
1430BParameter::SetMediaType(media_type type)
1431{
1432	fMediaType = type;
1433}
1434
1435
1436int32
1437BParameter::CountInputs()
1438{
1439	return fInputs->CountItems();
1440}
1441
1442
1443BParameter*
1444BParameter::InputAt(int32 index)
1445{
1446	return static_cast<BParameter*>(fInputs->ItemAt(index));
1447}
1448
1449
1450void
1451BParameter::AddInput(BParameter* input)
1452{
1453	CALLED();
1454
1455	// BeBook has this method returning a status value,
1456	// but it should be updated
1457	if (input == NULL)
1458		return;
1459
1460	if (fInputs->HasItem(input)) {
1461		// if already in input list, don't duplicate.
1462		return;
1463	}
1464
1465	fInputs->AddItem(input);
1466	input->AddOutput(this);
1467}
1468
1469
1470int32
1471BParameter::CountOutputs()
1472{
1473	return fOutputs->CountItems();
1474}
1475
1476
1477BParameter*
1478BParameter::OutputAt(int32 index)
1479{
1480	return static_cast<BParameter*>(fOutputs->ItemAt(index));
1481}
1482
1483
1484void
1485BParameter::AddOutput(BParameter* output)
1486{
1487	CALLED();
1488
1489	// BeBook has this method returning a status value,
1490	// but it should be updated
1491	if (output == NULL)
1492		return;
1493
1494	if (fOutputs->HasItem(output)) {
1495		// if already in output list, don't duplicate.
1496		return;
1497	}
1498
1499	fOutputs->AddItem(output);
1500	output->AddInput(this);
1501}
1502
1503
1504bool
1505BParameter::IsFixedSize() const
1506{
1507	return false;
1508}
1509
1510
1511type_code
1512BParameter::TypeCode() const
1513{
1514	return B_MEDIA_PARAMETER_TYPE;
1515}
1516
1517
1518ssize_t
1519BParameter::FlattenedSize() const
1520{
1521	CALLED();
1522	/*
1523		?? (0x02040607): 4 bytes
1524		BParameter Struct Size (in bytes): 4 bytes
1525		ID: 4 bytes
1526		Name String Length: 1 byte (??)
1527			Name String: 'Name String Length' bytes
1528		Kind String Length: 1 byte (??)
1529			Kind String: 'Kind String Length' bytes
1530		Unit String Length: 1 byte (??)
1531			Unit String: 'Unit String Length' bytes
1532		Inputs Count: 4 bytes
1533			Inputs (pointers): ('Inputs Count')*4 bytes
1534		Outputs Count: 4 bytes
1535			Outputs (pointers): ('Outputs Count')*4 bytes
1536		Media Type: 4 bytes
1537		ChannelCount: 4 bytes
1538		Flags: 4 bytes
1539	*/
1540	//35 bytes are guaranteed, after that, add the variable length parts.
1541	ssize_t size = kAdditionalParameterSize;
1542
1543	if (fName != NULL)
1544		size += strlen(fName);
1545	if (fKind != NULL)
1546		size += strlen(fKind);
1547	if (fUnit != NULL)
1548		size += strlen(fUnit);
1549
1550	size += fInputs->CountItems() * sizeof(BParameter*);
1551	size += fOutputs->CountItems() * sizeof(BParameter*);
1552
1553	return size;
1554}
1555
1556
1557status_t
1558BParameter::Flatten(void* buffer, ssize_t size) const
1559{
1560	CALLED();
1561
1562	if (buffer == NULL) {
1563		ERROR("BParameter::Flatten buffer is NULL\n");
1564		return B_NO_INIT;
1565	}
1566
1567	// NOTICE: It is important that this value is the size returned by
1568	// BParameter::FlattenedSize(), not by a descendent's override of this method.
1569	ssize_t actualSize = BParameter::FlattenedSize();
1570	if (size < actualSize) {
1571		ERROR("BParameter::Flatten(): size too small\n");
1572		return B_NO_MEMORY;
1573	}
1574
1575	write_to_buffer<uint32>(&buffer, kParameterMagic);
1576	write_to_buffer<ssize_t>(&buffer, actualSize);
1577	write_to_buffer<int32>(&buffer, fID);
1578
1579	write_string_to_buffer(&buffer, fName);
1580	write_string_to_buffer(&buffer, fKind);
1581	write_string_to_buffer(&buffer, fUnit);
1582
1583	// flatten and write the list of inputs
1584	ssize_t count = fInputs->CountItems();
1585	write_to_buffer<ssize_t>(&buffer, count);
1586
1587	if (count > 0) {
1588		memcpy(buffer, fInputs->Items(), sizeof(BParameter*) * count);
1589		skip_in_buffer(&buffer, sizeof(BParameter*) * count);
1590	}
1591
1592	// flatten and write the list of outputs
1593	count = fOutputs->CountItems();
1594	write_to_buffer<ssize_t>(&buffer, count);
1595
1596	if (count > 0) {
1597		memcpy(buffer, fOutputs->Items(), sizeof(BParameter*) * count);
1598		skip_in_buffer(&buffer, sizeof(BParameter*) * count);
1599	}
1600
1601	write_to_buffer<media_type>(&buffer, fMediaType);
1602	write_to_buffer<int32>(&buffer, fChannels);
1603	write_to_buffer<uint32>(&buffer, fFlags);
1604
1605	return B_OK;
1606}
1607
1608
1609bool
1610BParameter::AllowsTypeCode(type_code code) const
1611{
1612	return code == TypeCode();
1613}
1614
1615
1616status_t
1617BParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
1618{
1619	CALLED();
1620
1621	if (!AllowsTypeCode(code)) {
1622		ERROR("BParameter::Unflatten(): wrong type code\n");
1623		return B_BAD_TYPE;
1624	}
1625
1626	if (buffer == NULL) {
1627		ERROR("BParameter::Unflatten(): buffer is NULL\n");
1628		return B_NO_INIT;
1629	}
1630
1631	// if the buffer is smaller than the size needed to read the
1632	// signature and struct size fields, then there is a problem
1633	if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
1634		ERROR("BParameter::Unflatten() size too small\n");
1635		return B_BAD_VALUE;
1636	}
1637
1638	const void* bufferStart = buffer;
1639
1640	// check magic
1641
1642	uint32 magic = read_from_buffer<uint32>(&buffer);
1643	if (magic == B_SWAP_INT32(kParameterMagic))
1644		fSwapDetected = true;
1645	else if (magic == kParameterMagic)
1646		fSwapDetected = false;
1647	else {
1648		ERROR("BParameter::Unflatten(): bad magic\n");
1649		return B_BAD_TYPE;
1650	}
1651
1652	ssize_t parameterSize = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1653		fSwapDetected);
1654	if (parameterSize > size) {
1655		ERROR("BParameter::Unflatten(): buffer too small (%ld > %ld)\n",
1656			parameterSize, size);
1657		return B_BAD_VALUE;
1658	}
1659
1660	// if the struct doesn't meet the minimum size for
1661	// a flattened BParameter, then return an error.
1662	// MinFlattenedParamSize =
1663	// ID (4 bytes)
1664	// Name String Length (1 byte)
1665	// Kind String Length (1 byte)
1666	// Unit String Length (1 byte)
1667	// Inputs Count (4 bytes)
1668	// Outputs Count (4 bytes)
1669	// Media Type (4 bytes)
1670	// Channel Count (4 bytes)
1671	// Flags (4 bytes)
1672	// TOTAL: 27 bytes
1673	const ssize_t kMinFlattenedParamSize = 15 + 3 * sizeof(ssize_t);
1674	if (parameterSize < kMinFlattenedParamSize) {
1675		ERROR("BParameter::Unflatten out of memory (2)\n");
1676		return B_ERROR;
1677	}
1678
1679	fID = read_from_buffer_swap32<int32>(&buffer, fSwapDetected);
1680
1681	if (read_string_from_buffer(&buffer, &fName,
1682				size_left(size, bufferStart, buffer)) < B_OK
1683		|| read_string_from_buffer(&buffer, &fKind,
1684				size_left(size, bufferStart, buffer)) < B_OK
1685		|| read_string_from_buffer(&buffer, &fUnit,
1686				size_left(size, bufferStart, buffer)) < B_OK)
1687		return B_NO_MEMORY;
1688
1689	// read the list of inputs
1690
1691	// it will directly add the pointers in the flattened message to the list;
1692	// these will be fixed to point to the real inputs/outputs later in FixRefs()
1693
1694	ssize_t count = read_pointer_from_buffer_swap<ssize_t>(&buffer,
1695		fSwapDetected);
1696
1697	fInputs->MakeEmpty();
1698	for (ssize_t i = 0; i < count; i++) {
1699		fInputs->AddItem(read_pointer_from_buffer_swap<BParameter * const>(
1700			&buffer, fSwapDetected));
1701	}
1702
1703	// read the list of outputs
1704
1705	count = read_pointer_from_buffer_swap<ssize_t>(&buffer, fSwapDetected);
1706
1707	fOutputs->MakeEmpty();
1708	for (ssize_t i = 0; i < count; i++) {
1709		fOutputs->AddItem(read_pointer_from_buffer_swap<BParameter * const>(
1710			&buffer, fSwapDetected));
1711	}
1712
1713	fMediaType = read_from_buffer_swap32<media_type>(&buffer, fSwapDetected);
1714	fChannels = read_from_buffer_swap32<int32>(&buffer, fSwapDetected);
1715	fFlags = read_from_buffer_swap32<uint32>(&buffer, fSwapDetected);
1716
1717	return B_OK;
1718}
1719
1720
1721BParameter::BParameter(int32 id, media_type mediaType,
1722		media_parameter_type type, BParameterWeb* web, const char* name,
1723		const char* kind, const char* unit)
1724	:
1725	fID(id),
1726	fType(type),
1727	fWeb(web),
1728	fGroup(NULL),
1729	fSwapDetected(true),
1730	fMediaType(mediaType),
1731	fChannels(1),
1732	fFlags(0)
1733{
1734	CALLED();
1735
1736	fName = strndup(name, 255);
1737	fKind = strndup(kind, 255);
1738	fUnit = strndup(unit, 255);
1739
1740	// create empty input/output lists
1741	fInputs = new BList();
1742	fOutputs = new BList();
1743}
1744
1745
1746BParameter::~BParameter()
1747{
1748	CALLED();
1749
1750	// don't worry about the fWeb/fGroup properties, you don't need
1751	// to remove yourself from a web/group since the only way in which
1752	// a parameter is destroyed is when the owner web/group destroys it
1753
1754	free(fName);
1755	free(fKind);
1756	free(fUnit);
1757
1758	delete fInputs;
1759	delete fOutputs;
1760}
1761
1762
1763/*!	Replaces references to items in the old list with the corresponding
1764	items in the updated list. The references are replaced in the input
1765	and output lists.
1766	This is called by BParameterWeb::Unflatten().
1767*/
1768void
1769BParameter::FixRefs(BList& old, BList& updated)
1770{
1771	CALLED();
1772
1773	// update inputs
1774
1775	void** items = static_cast<void**>(fInputs->Items());
1776	int32 count = fInputs->CountItems();
1777
1778	for (int32 i = 0; i < count; i++) {
1779		int32 index = old.IndexOf(items[i]);
1780		if (index >= 0)
1781			items[i] = updated.ItemAt(index);
1782		else {
1783			ERROR("BParameter::FixRefs(): No mapping found for input");
1784			items[i] = NULL;
1785		}
1786	}
1787
1788	// remove all NULL inputs (those which couldn't be mapped)
1789
1790	for (int32 i = count; i-- > 0;) {
1791		if (items[i] == NULL)
1792			fInputs->RemoveItem(i);
1793	}
1794
1795	// update outputs
1796
1797	items = static_cast<void **>(fOutputs->Items());
1798	count = fOutputs->CountItems();
1799
1800	for (int32 i = 0; i < count; i++) {
1801		int32 index = old.IndexOf(items[i]);
1802		if (index >= 0)
1803			items[i] = updated.ItemAt(index);
1804		else {
1805			ERROR("BParameter::FixRefs(): No mapping found for output");
1806			items[i] = NULL;
1807		}
1808	}
1809
1810	// remove all NULL outputs (those which couldn't be mapped)
1811
1812	for (int32 i = count; i-- > 0;) {
1813		if (items[i] == NULL)
1814			fOutputs->RemoveItem(i);
1815	}
1816}
1817
1818
1819//	#pragma mark - public BContinuousParameter
1820
1821
1822type_code
1823BContinuousParameter::ValueType()
1824{
1825	return B_FLOAT_TYPE;
1826}
1827
1828
1829float
1830BContinuousParameter::MinValue()
1831{
1832	return fMinimum;
1833}
1834
1835
1836float
1837BContinuousParameter::MaxValue()
1838{
1839	return fMaximum;
1840}
1841
1842
1843float
1844BContinuousParameter::ValueStep()
1845{
1846	return fStepping;
1847}
1848
1849
1850void
1851BContinuousParameter::SetResponse(int resp, float factor, float offset)
1852{
1853	fResponse = static_cast<response>(resp);
1854	fFactor = factor;
1855	fOffset = offset;
1856}
1857
1858
1859void
1860BContinuousParameter::GetResponse(int* _resp, float* _factor, float* _offset)
1861{
1862	if (_resp != NULL)
1863		*_resp = fResponse;
1864	if (_factor != NULL)
1865		*_factor = fFactor;
1866	if (_offset != NULL)
1867		*_offset = fOffset;
1868}
1869
1870
1871ssize_t
1872BContinuousParameter::FlattenedSize() const
1873{
1874	CALLED();
1875
1876	// only adds a fixed amount of bytes
1877	return BParameter::FlattenedSize() + kAdditionalContinuousParameterSize;
1878}
1879
1880
1881status_t
1882BContinuousParameter::Flatten(void* buffer, ssize_t size) const
1883{
1884	CALLED();
1885
1886	if (buffer == NULL) {
1887		ERROR("BContinuousParameter::Flatten(): buffer is NULL\n");
1888		return B_NO_INIT;
1889	}
1890
1891	ssize_t parameterSize = BParameter::FlattenedSize();
1892	if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
1893		ERROR("BContinuousParameter::Flatten(): size to small\n");
1894		return B_NO_MEMORY;
1895	}
1896
1897	status_t status = BParameter::Flatten(buffer, size);
1898	if (status != B_OK) {
1899		ERROR("BContinuousParameter::Flatten(): BParameter::Flatten() failed\n");
1900		return status;
1901	}
1902
1903	// add our data to the general flattened BParameter
1904
1905	skip_in_buffer(&buffer, parameterSize);
1906
1907	write_to_buffer<float>(&buffer, fMinimum);
1908	write_to_buffer<float>(&buffer, fMaximum);
1909	write_to_buffer<float>(&buffer, fStepping);
1910	write_to_buffer<response>(&buffer, fResponse);
1911	write_to_buffer<float>(&buffer, fFactor);
1912	write_to_buffer<float>(&buffer, fOffset);
1913
1914	return B_OK;
1915}
1916
1917
1918status_t
1919BContinuousParameter::Unflatten(type_code code, const void* buffer,
1920	ssize_t size)
1921{
1922	CALLED();
1923
1924	// we try to check if the buffer size is long enough to hold an object
1925	// as early as possible.
1926
1927	if (!AllowsTypeCode(code)) {
1928		ERROR("BContinuousParameter::Unflatten wrong type code\n");
1929		return B_BAD_TYPE;
1930	}
1931
1932	if (buffer == NULL) {
1933		ERROR("BContinuousParameter::Unflatten buffer is NULL\n");
1934		return B_NO_INIT;
1935	}
1936
1937	// if the buffer is smaller than the size needed to read the
1938	// signature and struct size fields, then there is a problem
1939	if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
1940		ERROR("BContinuousParameter::Unflatten size too small\n");
1941		return B_ERROR;
1942	}
1943
1944	status_t status = BParameter::Unflatten(code, buffer, size);
1945	if (status != B_OK) {
1946		ERROR("BContinuousParameter::Unflatten(): BParameter::Unflatten "
1947			"failed: %s\n", strerror(status));
1948		return status;
1949	}
1950
1951	ssize_t parameterSize = BParameter::FlattenedSize();
1952	skip_in_buffer(&buffer, parameterSize);
1953
1954	if (size < (parameterSize + kAdditionalContinuousParameterSize)) {
1955		ERROR("BContinuousParameter::Unflatten(): buffer too small\n");
1956		return B_BAD_VALUE;
1957	}
1958
1959	fMinimum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1960	fMaximum = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1961	fStepping = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1962	fResponse = read_from_buffer_swap32<response>(&buffer, SwapOnUnflatten());
1963	fFactor = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1964	fOffset = read_from_buffer_swap32<float>(&buffer, SwapOnUnflatten());
1965
1966	return B_OK;
1967}
1968
1969
1970BContinuousParameter::BContinuousParameter(int32 id, media_type mediaType,
1971		BParameterWeb* web, const char* name, const char* kind,
1972		const char* unit, float minimum, float maximum, float stepping)
1973	: BParameter(id, mediaType, B_CONTINUOUS_PARAMETER, web, name, kind, unit),
1974	fMinimum(minimum),
1975	fMaximum(maximum),
1976	fStepping(stepping),
1977	fResponse(B_LINEAR),
1978	fFactor(1.0),
1979	fOffset(0.0)
1980{
1981	CALLED();
1982}
1983
1984
1985BContinuousParameter::~BContinuousParameter()
1986{
1987	CALLED();
1988}
1989
1990
1991//	#pragma mark - public BDiscreteParameter
1992
1993
1994type_code
1995BDiscreteParameter::ValueType()
1996{
1997	return B_INT32_TYPE;
1998}
1999
2000
2001int32
2002BDiscreteParameter::CountItems()
2003{
2004	return fValues->CountItems();
2005}
2006
2007
2008const char*
2009BDiscreteParameter::ItemNameAt(int32 index)
2010{
2011	return reinterpret_cast<const char*>(fSelections->ItemAt(index));
2012}
2013
2014
2015int32
2016BDiscreteParameter::ItemValueAt(int32 index)
2017{
2018	int32* item = static_cast<int32*>(fValues->ItemAt(index));
2019	if (item == NULL)
2020		return 0;
2021
2022	return *item;
2023}
2024
2025
2026status_t
2027BDiscreteParameter::AddItem(int32 value, const char* name)
2028{
2029	CALLED();
2030
2031	int32* valueCopy = new(std::nothrow) int32(value);
2032	if (valueCopy == NULL)
2033		return B_NO_MEMORY;
2034	char* nameCopy = strndup(name, 255);
2035	if (name != NULL && nameCopy == NULL) {
2036		delete valueCopy;
2037		return B_NO_MEMORY;
2038	}
2039
2040	if (!fValues->AddItem(valueCopy))
2041		goto err;
2042	if (!fSelections->AddItem(nameCopy)) {
2043		fValues->RemoveItem(valueCopy);
2044		goto err;
2045	}
2046	return B_OK;
2047
2048err:
2049	free(nameCopy);
2050	delete valueCopy;
2051	return B_NO_MEMORY;
2052}
2053
2054
2055status_t
2056BDiscreteParameter::MakeItemsFromInputs()
2057{
2058	CALLED();
2059
2060	int32 count = fInputs->CountItems();
2061	for (int32 i = 0; i < count; i++) {
2062		BParameter* parameter = static_cast<BParameter*>(fInputs->ItemAt(i));
2063		AddItem(i, parameter->Name());
2064	}
2065
2066	return B_OK;
2067}
2068
2069
2070status_t
2071BDiscreteParameter::MakeItemsFromOutputs()
2072{
2073	CALLED();
2074
2075	int32 count = fOutputs->CountItems();
2076	for (int32 i = 0; i < count; i++) {
2077		BParameter* parameter = static_cast<BParameter*>(fOutputs->ItemAt(i));
2078		AddItem(i, parameter->Name());
2079	}
2080
2081	return B_OK;
2082}
2083
2084
2085void
2086BDiscreteParameter::MakeEmpty()
2087{
2088	CALLED();
2089
2090	for (int32 i = fValues->CountItems(); i-- > 0;) {
2091		delete static_cast<int32*>(fValues->ItemAt(i));
2092	}
2093	fValues->MakeEmpty();
2094
2095	for (int32 i = fSelections->CountItems(); i-- > 0;) {
2096		free(static_cast<char*>(fSelections->ItemAt(i)));
2097	}
2098	fSelections->MakeEmpty();
2099}
2100
2101
2102ssize_t
2103BDiscreteParameter::FlattenedSize() const
2104{
2105	CALLED();
2106
2107	ssize_t size = BParameter::FlattenedSize()
2108		+ kAdditionalDiscreteParameterSize;
2109
2110	int32 count = fValues->CountItems();
2111	for (int32 i = 0; i < count; i++) {
2112		char* selection = static_cast<char*>(fSelections->ItemAt(i));
2113
2114		if (selection != NULL)
2115			size += min_c(strlen(selection), 255);
2116
2117		size += 5;
2118			// string length + value
2119	}
2120
2121	return size;
2122}
2123
2124
2125status_t
2126BDiscreteParameter::Flatten(void* buffer, ssize_t size) const
2127{
2128	CALLED();
2129
2130	if (buffer == NULL) {
2131		ERROR("BDiscreteParameter::Flatten(): buffer is NULL\n");
2132		return B_NO_INIT;
2133	}
2134
2135	ssize_t parameterSize = BParameter::FlattenedSize();
2136
2137	if (size < FlattenedSize()) {
2138		ERROR("BDiscreteParameter::Flatten(): size too small\n");
2139		return B_NO_MEMORY;
2140	}
2141
2142	status_t status = BParameter::Flatten(buffer, size);
2143	if (status != B_OK) {
2144		ERROR("BDiscreteParameter::Flatten(): BParameter::Flatten failed\n");
2145		return status;
2146	}
2147
2148	skip_in_buffer(&buffer, parameterSize);
2149
2150	int32 count = fValues->CountItems();
2151	write_to_buffer<int32>(&buffer, count);
2152
2153	// write out all value/name pairs
2154	for (int32 i = 0; i < count; i++) {
2155		const char* selection = static_cast<char*>(fSelections->ItemAt(i));
2156		const int32* value = static_cast<int32*>(fValues->ItemAt(i));
2157
2158		write_string_to_buffer(&buffer, selection);
2159		write_to_buffer<int32>(&buffer, value ? *value : 0);
2160	}
2161
2162	return B_OK;
2163}
2164
2165
2166status_t
2167BDiscreteParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2168{
2169	CALLED();
2170
2171	if (!AllowsTypeCode(code)) {
2172		ERROR("BDiscreteParameter::Unflatten(): bad type code\n");
2173		return B_BAD_TYPE;
2174	}
2175
2176	if (buffer == NULL) {
2177		ERROR("BDiscreteParameter::Unflatten(): buffer is NULL\n");
2178		return B_NO_INIT;
2179	}
2180
2181	// if the buffer is smaller than the size needed to read the
2182	// signature and struct size fields, then there is a problem
2183	if (size < static_cast<ssize_t>(sizeof(int32) + sizeof(ssize_t))) {
2184		ERROR("BDiscreteParameter::Unflatten(): size too small\n");
2185		return B_ERROR;
2186	}
2187
2188	const void* bufferStart = buffer;
2189
2190	status_t status = BParameter::Unflatten(code, buffer, size);
2191	if (status != B_OK) {
2192		ERROR("BDiscreteParameter::Unflatten(): BParameter::Unflatten failed\n");
2193		return status;
2194	}
2195
2196	ssize_t parameterSize = BParameter::FlattenedSize();
2197	skip_in_buffer(&buffer, parameterSize);
2198
2199	if (size < (parameterSize + kAdditionalDiscreteParameterSize)) {
2200		ERROR("BDiscreteParameter::Unflatten(): buffer too small\n");
2201		return B_BAD_VALUE;
2202	}
2203
2204	int32 count = read_from_buffer_swap32<int32>(&buffer, SwapOnUnflatten());
2205
2206	// clear any existing name/value pairs
2207	MakeEmpty();
2208
2209	for (int32 i = 0; i < count; i++) {
2210		char* name = NULL;
2211		if (read_string_from_buffer(&buffer, &name, size_left(size, bufferStart,
2212				buffer)) < B_OK)
2213			return B_BAD_DATA;
2214
2215		if (size_left(size, bufferStart, buffer) < (int)sizeof(int32)) {
2216			free(name);
2217			return B_BAD_DATA;
2218		}
2219
2220		int32 value = read_from_buffer_swap32<int32>(&buffer,
2221			SwapOnUnflatten());
2222
2223		AddItem(value, name);
2224		free(name);
2225	}
2226
2227	return B_OK;
2228}
2229
2230
2231BDiscreteParameter::BDiscreteParameter(int32 id, media_type mediaType,
2232	BParameterWeb* web, const char* name, const char* kind)
2233	:	BParameter(id, mediaType, B_DISCRETE_PARAMETER, web, name, kind, NULL)
2234{
2235	CALLED();
2236
2237	fSelections = new BList();
2238	fValues = new BList();
2239}
2240
2241
2242BDiscreteParameter::~BDiscreteParameter()
2243{
2244	CALLED();
2245
2246	MakeEmpty();
2247
2248	delete fSelections;
2249	delete fValues;
2250}
2251
2252
2253//	#pragma mark - public BTextParameter
2254
2255
2256size_t
2257BTextParameter::MaxBytes() const
2258{
2259	return fMaxBytes;
2260}
2261
2262
2263type_code
2264BTextParameter::ValueType()
2265{
2266	return B_FLOAT_TYPE;
2267}
2268
2269
2270ssize_t
2271BTextParameter::FlattenedSize() const
2272{
2273	return BParameter::FlattenedSize() + sizeof(fMaxBytes);
2274}
2275
2276
2277status_t
2278BTextParameter::Flatten(void* buffer, ssize_t size) const
2279{
2280	if (buffer == NULL) {
2281		ERROR("BTextParameter::Flatten(): buffer is NULL\n");
2282		return B_NO_INIT;
2283	}
2284
2285	ssize_t parameterSize = BParameter::FlattenedSize();
2286	if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
2287		ERROR("BContinuousParameter::Flatten(): size to small\n");
2288		return B_NO_MEMORY;
2289	}
2290
2291	status_t status = BParameter::Flatten(buffer, size);
2292	if (status != B_OK) {
2293		ERROR("BTextParameter::Flatten(): BParameter::Flatten() failed\n");
2294		return status;
2295	}
2296
2297	// add our data to the general flattened BParameter
2298
2299	skip_in_buffer(&buffer, parameterSize);
2300
2301	write_to_buffer<uint32>(&buffer, fMaxBytes);
2302
2303	return B_OK;
2304}
2305
2306
2307status_t
2308BTextParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2309{
2310	// we try to check if the buffer size is long enough to hold an object
2311	// as early as possible.
2312
2313	if (!AllowsTypeCode(code)) {
2314		ERROR("BTextParameter::Unflatten wrong type code\n");
2315		return B_BAD_TYPE;
2316	}
2317
2318	if (buffer == NULL) {
2319		ERROR("BTextParameter::Unflatten buffer is NULL\n");
2320		return B_NO_INIT;
2321	}
2322
2323	if (size < static_cast<ssize_t>(sizeof(fMaxBytes))) {
2324		ERROR("BTextParameter::Unflatten size too small\n");
2325		return B_ERROR;
2326	}
2327
2328	status_t status = BParameter::Unflatten(code, buffer, size);
2329	if (status != B_OK) {
2330		ERROR("BTextParameter::Unflatten(): BParameter::Unflatten failed\n");
2331		return status;
2332	}
2333
2334	ssize_t parameterSize = BParameter::FlattenedSize();
2335	skip_in_buffer(&buffer, parameterSize);
2336
2337	if (size < static_cast<ssize_t>(parameterSize + sizeof(fMaxBytes))) {
2338		ERROR("BTextParameter::Unflatten(): buffer too small\n");
2339		return B_BAD_VALUE;
2340	}
2341
2342	fMaxBytes = read_from_buffer_swap32<uint32>(&buffer, SwapOnUnflatten());
2343
2344	return B_OK;
2345}
2346
2347
2348BTextParameter::BTextParameter(int32 id, media_type mediaType,
2349		BParameterWeb* web, const char* name, const char* kind,
2350		size_t maxBytes)
2351	: BParameter(id, mediaType, B_TEXT_PARAMETER, web, name, kind, NULL)
2352{
2353	fMaxBytes = maxBytes;
2354}
2355
2356
2357BTextParameter::~BTextParameter()
2358{
2359}
2360
2361
2362//	#pragma mark - public BNullParameter
2363
2364
2365type_code
2366BNullParameter::ValueType()
2367{
2368	// NULL parameters have no value type
2369	return 0;
2370}
2371
2372
2373ssize_t
2374BNullParameter::FlattenedSize() const
2375{
2376	return BParameter::FlattenedSize();
2377}
2378
2379
2380status_t
2381BNullParameter::Flatten(void* buffer, ssize_t size) const
2382{
2383	return BParameter::Flatten(buffer, size);
2384}
2385
2386
2387status_t
2388BNullParameter::Unflatten(type_code code, const void* buffer, ssize_t size)
2389{
2390	return BParameter::Unflatten(code, buffer, size);
2391}
2392
2393
2394BNullParameter::BNullParameter(int32 id, media_type mediaType,
2395		BParameterWeb* web, const char* name, const char* kind)
2396	: BParameter(id, mediaType, B_NULL_PARAMETER, web, name, kind, NULL)
2397{
2398}
2399
2400
2401BNullParameter::~BNullParameter()
2402{
2403}
2404
2405
2406//	#pragma mark - reserved functions
2407
2408
2409status_t BParameterWeb::_Reserved_ControlWeb_0(void *) { return B_ERROR; }
2410status_t BParameterWeb::_Reserved_ControlWeb_1(void *) { return B_ERROR; }
2411status_t BParameterWeb::_Reserved_ControlWeb_2(void *) { return B_ERROR; }
2412status_t BParameterWeb::_Reserved_ControlWeb_3(void *) { return B_ERROR; }
2413status_t BParameterWeb::_Reserved_ControlWeb_4(void *) { return B_ERROR; }
2414status_t BParameterWeb::_Reserved_ControlWeb_5(void *) { return B_ERROR; }
2415status_t BParameterWeb::_Reserved_ControlWeb_6(void *) { return B_ERROR; }
2416status_t BParameterWeb::_Reserved_ControlWeb_7(void *) { return B_ERROR; }
2417
2418status_t BParameterGroup::_Reserved_ControlGroup_0(void *) { return B_ERROR; }
2419status_t BParameterGroup::_Reserved_ControlGroup_1(void *) { return B_ERROR; }
2420status_t BParameterGroup::_Reserved_ControlGroup_2(void *) { return B_ERROR; }
2421status_t BParameterGroup::_Reserved_ControlGroup_3(void *) { return B_ERROR; }
2422status_t BParameterGroup::_Reserved_ControlGroup_4(void *) { return B_ERROR; }
2423status_t BParameterGroup::_Reserved_ControlGroup_5(void *) { return B_ERROR; }
2424status_t BParameterGroup::_Reserved_ControlGroup_6(void *) { return B_ERROR; }
2425status_t BParameterGroup::_Reserved_ControlGroup_7(void *) { return B_ERROR; }
2426
2427status_t BParameter::_Reserved_Control_0(void *) { return B_ERROR; }
2428status_t BParameter::_Reserved_Control_1(void *) { return B_ERROR; }
2429status_t BParameter::_Reserved_Control_2(void *) { return B_ERROR; }
2430status_t BParameter::_Reserved_Control_3(void *) { return B_ERROR; }
2431status_t BParameter::_Reserved_Control_4(void *) { return B_ERROR; }
2432status_t BParameter::_Reserved_Control_5(void *) { return B_ERROR; }
2433status_t BParameter::_Reserved_Control_6(void *) { return B_ERROR; }
2434status_t BParameter::_Reserved_Control_7(void *) { return B_ERROR; }
2435
2436status_t BContinuousParameter::_Reserved_ContinuousParameter_0(void *) { return B_ERROR; }
2437status_t BContinuousParameter::_Reserved_ContinuousParameter_1(void *) { return B_ERROR; }
2438status_t BContinuousParameter::_Reserved_ContinuousParameter_2(void *) { return B_ERROR; }
2439status_t BContinuousParameter::_Reserved_ContinuousParameter_3(void *) { return B_ERROR; }
2440status_t BContinuousParameter::_Reserved_ContinuousParameter_4(void *) { return B_ERROR; }
2441status_t BContinuousParameter::_Reserved_ContinuousParameter_5(void *) { return B_ERROR; }
2442status_t BContinuousParameter::_Reserved_ContinuousParameter_6(void *) { return B_ERROR; }
2443status_t BContinuousParameter::_Reserved_ContinuousParameter_7(void *) { return B_ERROR; }
2444
2445status_t BDiscreteParameter::_Reserved_DiscreteParameter_0(void *) { return B_ERROR; }
2446status_t BDiscreteParameter::_Reserved_DiscreteParameter_1(void *) { return B_ERROR; }
2447status_t BDiscreteParameter::_Reserved_DiscreteParameter_2(void *) { return B_ERROR; }
2448status_t BDiscreteParameter::_Reserved_DiscreteParameter_3(void *) { return B_ERROR; }
2449status_t BDiscreteParameter::_Reserved_DiscreteParameter_4(void *) { return B_ERROR; }
2450status_t BDiscreteParameter::_Reserved_DiscreteParameter_5(void *) { return B_ERROR; }
2451status_t BDiscreteParameter::_Reserved_DiscreteParameter_6(void *) { return B_ERROR; }
2452status_t BDiscreteParameter::_Reserved_DiscreteParameter_7(void *) { return B_ERROR; }
2453
2454status_t BNullParameter::_Reserved_NullParameter_0(void *) { return B_ERROR; }
2455status_t BNullParameter::_Reserved_NullParameter_1(void *) { return B_ERROR; }
2456status_t BNullParameter::_Reserved_NullParameter_2(void *) { return B_ERROR; }
2457status_t BNullParameter::_Reserved_NullParameter_3(void *) { return B_ERROR; }
2458status_t BNullParameter::_Reserved_NullParameter_4(void *) { return B_ERROR; }
2459status_t BNullParameter::_Reserved_NullParameter_5(void *) { return B_ERROR; }
2460status_t BNullParameter::_Reserved_NullParameter_6(void *) { return B_ERROR; }
2461status_t BNullParameter::_Reserved_NullParameter_7(void *) { return B_ERROR; }
2462
2463status_t BTextParameter::_Reserved_TextParameter_0(void *) { return B_ERROR; }
2464status_t BTextParameter::_Reserved_TextParameter_1(void *) { return B_ERROR; }
2465status_t BTextParameter::_Reserved_TextParameter_2(void *) { return B_ERROR; }
2466status_t BTextParameter::_Reserved_TextParameter_3(void *) { return B_ERROR; }
2467status_t BTextParameter::_Reserved_TextParameter_4(void *) { return B_ERROR; }
2468status_t BTextParameter::_Reserved_TextParameter_5(void *) { return B_ERROR; }
2469status_t BTextParameter::_Reserved_TextParameter_6(void *) { return B_ERROR; }
2470status_t BTextParameter::_Reserved_TextParameter_7(void *) { return B_ERROR; }
2471