1/*
2	ToneProducer.h
3
4	Copyright 1999, Be Incorporated.   All Rights Reserved.
5	This file may be used under the terms of the Be Sample Code License.
6
7	NOTES eamoon@meadgroup.com 11june99
8	- this node has some holes in it, but it's pretty useful starting
9	  point for writing producers.
10	- I've tried to clean up the format negotiation a bit, which didn't
11	  fare too well when faced with an apathetic downstream node
12	  (LoggingConsumer.)
13
14	KNOWN BUGS
15	  eamoon 17jun99
16	  * Can't handle 2 channels, but is too polite to refuse.
17	    How embarrassing.
18
19*/
20
21#ifndef ToneProducer_H
22#define ToneProducer_H 1
23
24#include <media/BufferProducer.h>
25#include <media/MediaEventLooper.h>
26#include <media/Controllable.h>
27
28class BMediaAddOn;
29
30// ----------------
31// ToneProducer - a node to generate precisely defined digital tones
32class ToneProducer : public BBufferProducer,  public BControllable, public BMediaEventLooper
33{
34public:
35	enum event_t {
36		// e.moon 2jun99
37		_PARAMETER_EVENT 		= BTimedEventQueue::B_USER_EVENT
38	};
39
40public:
41	// add-on-friendly ctor
42	// e.moon [8jun99]
43	ToneProducer(BMediaAddOn* pAddOn=0);
44	~ToneProducer();
45
46// BMediaNode methods
47	BMediaAddOn* AddOn(	int32* internal_id) const;
48
49// BControllable methods
50	status_t GetParameterValue(
51		int32 id,
52		bigtime_t* last_change,
53		void* value,
54		size_t* ioSize);
55
56	void SetParameterValue(
57		int32 id,
58		bigtime_t when,
59		const void* value,
60		size_t size);
61
62	status_t StartControlPanel(
63		BMessenger* pMessenger);
64
65// BBufferProducer methods
66	status_t FormatSuggestionRequested(
67		media_type type,
68		int32 quality,
69		media_format* format);
70
71	status_t FormatProposal(
72		const media_source& output,
73		media_format* format);
74
75	/* If the format isn't good, put a good format into *io_format and return error */
76	/* If format has wildcard, specialize to what you can do (and change). */
77	/* If you can change the format, return OK. */
78	/* The request comes from your destination sychronously, so you cannot ask it */
79	/* whether it likes it -- you should assume it will since it asked. */
80	status_t FormatChangeRequested(
81		const media_source& source,
82		const media_destination& destination,
83		media_format* io_format,
84		int32* _deprecated_);
85
86	status_t GetNextOutput(	/* cookie starts as 0 */
87		int32* cookie,
88		media_output* out_output);
89
90	status_t DisposeOutputCookie(
91		int32 cookie);
92
93	/* In this function, you should either pass on the group to your upstream guy, */
94	/* or delete your current group and hang on to this group. Deleting the previous */
95	/* group (unless you passed it on with the reclaim flag set to false) is very */
96	/* important, else you will 1) leak memory and 2) block someone who may want */
97	/* to reclaim the buffers living in that group. */
98	status_t SetBufferGroup(
99		const media_source& for_source,
100		BBufferGroup* group);
101
102	/* Iterates over all outputs and maxes the latency found */
103	status_t GetLatency(
104		bigtime_t* out_latency);
105
106	status_t PrepareToConnect(
107		const media_source& what,
108		const media_destination& where,
109		media_format* format,
110		media_source* out_source,
111		char* out_name);
112
113	void Connect(
114		status_t error,
115		const media_source& source,
116		const media_destination& destination,
117		const media_format& format,
118		char* io_name);
119
120	void Disconnect(
121		const media_source& what,
122		const media_destination& where);
123
124	void LateNoticeReceived(
125		const media_source& what,
126		bigtime_t how_much,
127		bigtime_t performance_time);
128
129	void EnableOutput(
130		const media_source & what,
131		bool enabled,
132		int32* _deprecated_);
133
134	status_t SetPlayRate(
135		int32 numer,
136		int32 denom);
137
138	status_t HandleMessage(
139		int32 message,
140		const void* data,
141		size_t size);
142
143	void AdditionalBufferRequested(
144		const media_source& source,
145		media_buffer_id prev_buffer,
146		bigtime_t prev_time,
147		const media_seek_tag* prev_tag);	//	may be NULL
148
149	void LatencyChanged(
150		const media_source& source,
151		const media_destination& destination,
152		bigtime_t new_latency,
153		uint32 flags);
154
155// BMediaEventLooper methods
156	void NodeRegistered();
157
158	void Start(bigtime_t performance_time);
159
160	// Workaround for a Metrowerks PPC compiler bug
161	void Stop(bigtime_t performance_time, bool immediate);
162
163	void SetRunMode(run_mode mode);
164
165	void HandleEvent(
166		const media_timed_event* event,
167		bigtime_t lateness,
168		bool realTimeEvent = false);
169
170private:
171	void AllocateBuffers();
172	BBuffer* FillNextBuffer(bigtime_t event_time);
173
174	// 20sep99 e.moon: stereo support
175	void FillSineBuffer(float* data, size_t numFrames, bool stereo);
176	void FillTriangleBuffer(float* data, size_t numFrames, bool stereo);
177	void FillSawtoothBuffer(float* data, size_t numFrames, bool stereo);
178
179	BParameterWeb* mWeb;
180	BBufferGroup* mBufferGroup;
181	bigtime_t mLatency, mInternalLatency;
182	media_output mOutput;
183	bool mOutputEnabled;
184	media_format mPreferredFormat;
185
186	// These next attributes are related to tone buffer generation
187	double mTheta;			// generic parameter used by all generators
188	bool mWaveAscending;		// used by the triangle-wave generator
189	float mFrequency;		// can be anything, in Hertz
190	float mGain;				// should be in the range [0,1]
191	int32 mWaveform;
192	uint64 mFramesSent;
193	bigtime_t mStartTime;
194
195	// more parameter handling
196	bigtime_t mGainLastChanged;
197	bigtime_t mFreqLastChanged;
198	bigtime_t mWaveLastChanged;
199
200	// host addon
201	// [8jun99] e.moon
202	BMediaAddOn*		m_pAddOn;
203};
204
205#endif
206