root/branches/libfreebob-2.0/src/libstreaming/Port.h

Revision 228, 10.0 kB (checked in by pieterpalmers, 16 years ago)

- generic rate control added for ringbuffer based ports.

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2005,2006 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28 #ifndef __FREEBOB_PORT__
29 #define __FREEBOB_PORT__
30
31 #include "../debugmodule/debugmodule.h"
32 #include <string>
33 #include "ringbuffer.h"
34
35 namespace FreebobStreaming {
36
37 /*!
38 \brief The Base Class for Ports
39
40  Ports are the entities that provide the interface between the ISO streaming
41  layer and the datatype-specific layer. You can define plug types by subclassing
42  the base port type.
43  
44  After creating a port, you have to set its parameters and then call the init() function.
45  This is because a port needs information from two sources to operate:
46  1) the stream composition information from the AvDevice
47  2) the streaming API setup (buffer type, data type, ...)
48  
49  \note There are not much virtual functions here because of the high frequency of
50        calling. We try to do everything with a base class getter, and a child class
51        setter. If this isn't possible, we do a static_cast. This however can only be
52        done inside the streamprocessor that handles the specific sub-class types of
53        the ports. i.e. by design you should make sure that the static_cast will be
54        OK.
55        
56  \todo rework the implementation into something more beautifull
57 */
58 class Port {
59
60 public:
61         friend class PortManager;
62        
63         /*!
64         \brief Specifies the buffer type for ports
65        
66         A PointerBuffer uses the getBufferAddress() and setBufferAddres() interface
67         A Ringbuffer uses the read/write interface
68         */
69         enum E_BufferType {
70                 E_PointerBuffer,
71                 E_RingBuffer
72         };
73        
74         /*!
75         \brief Specifies the signalling type for ports
76         */
77         enum E_SignalType {
78                 E_PacketSignalled, ///< the port is to be processed for every packet
79                 E_PeriodSignalled, ///< the port is to be processed after a period of frames
80 //              E_SampleSignalled ///< the port is to be processed after each frame (sample)
81         };
82
83         /*!
84         \brief The datatype of the port buffer
85         */
86         enum E_DataType {
87                 E_Float,
88                 E_Int24,
89                 E_MidiEvent,
90                 E_Default,
91         };
92
93         /*!
94         \brief The port type
95         */
96         enum E_PortType {
97                 E_Audio,
98                 E_Midi,
99                 E_Control,
100         };
101
102         /*!
103         \brief The port direction
104         */
105         enum E_Direction {
106                 E_Playback,
107                 E_Capture,
108         };
109
110         Port(std::string name, enum E_PortType porttype, enum E_Direction direction);
111
112         virtual ~Port()
113           {};
114        
115        
116         /// Enable the port. (this can be called anytime)
117         void enable()  {m_enabled=true;};
118         /// Disable the port. (this can be called anytime)
119         void disable() {m_enabled=false;};
120         /// is the port enabled? (this can be called anytime)
121         bool isEnabled() {return m_enabled;};
122
123         /*!
124         \brief Initialize the port
125         */
126         bool init();
127        
128         bool prepare() {return true;};
129         bool reset() {return true;};
130
131         std::string getName() {return m_Name;};
132         bool setName(std::string name);
133
134         /**
135          * \brief returns the size of the events in the port buffer, in bytes
136          *
137          */
138         unsigned int getEventSize();
139
140         /**
141          * \brief sets the event type for the port buffer
142          *
143          * \note use before calling init()
144          */
145         virtual bool setDataType(enum E_DataType);
146        
147         enum E_DataType getDataType() {return m_DataType;};
148        
149         /**
150          * \brief sets the event type for the port buffer
151          *
152          * \note use before calling init()
153          */
154         virtual bool setSignalType(enum E_SignalType );
155        
156         enum E_SignalType getSignalType() {return m_SignalType;}; ///< returns the signalling type of the port
157        
158         /**
159          * \brief sets the buffer type for the port
160          *
161          * \note use before calling init()
162          */
163         virtual bool setBufferType(enum E_BufferType );
164        
165         enum E_BufferType getBufferType() {return m_BufferType;}; ///< returns the buffer type of the port
166
167         enum E_PortType getPortType() {return m_PortType;}; ///< returns the port type (is fixed)
168         enum E_Direction getDirection() {return m_Direction;}; ///< returns the direction (is fixed)
169
170         /**
171          * \brief returns the size of the port buffer
172          *
173          * counted in number of E_DataType units (events), not in bytes
174          *
175          */
176         unsigned int getBufferSize() {return m_buffersize;};
177        
178         /**
179          * \brief sets the size of the port buffer
180          *
181          * counted in number of E_DataType units, not in bytes
182          *
183          * if there is an external buffer assigned, it should
184          * be large enough
185          * if there is an internal buffer, it will be resized
186          *
187          * \note use before calling init()
188          */
189         virtual bool setBufferSize(unsigned int);
190        
191         /**
192          * \brief use an external buffer (or not)
193          *
194          * \note use before calling init()
195          */
196         virtual bool useExternalBuffer(bool b);
197        
198         void setExternalBufferAddress(void *buff);
199
200
201         /**
202          * \brief enable/disable ratecontrol
203          *
204          * Rate control is nescessary for some types of ports (most notably
205          * midi). The StreamProcessor that handles the port should call canRead()
206          * everytime a 'slot' that could be filled with an event passes. The canRead
207          * function will return true if
208          *  (1) there is an event ready in the buffer
209          *  (2) we are allowed to send an event in this slot
210          *
211          * Setting the rate works is done with the slot_interval and the event_interval
212          * parameters. On every call to canRead(), a counter is decremented with
213          * slot_interval. If the counter drops below 0, canRead() returns true and resets
214          * the counter to event_interval.
215          *
216          * e.g. for AMDTP midi, we are only allowed to send a midi byte every 320us
217          *      if the SYT interval is 8, there is exactly one midi slot every packet.
218          *      therefore the slot_interval is 1/8000s (=125us), and the event_interval
219          *      is 320us.
220          *     
221          *      Note that the interval parameters are unitless, so you can adapt them
222          *      to your needs. In the AMDTP case for example, when the SYT interval is 32
223          *      (when the samplerate is 192kHz for example) there are 4 midi slots in
224          *      each packet, making the slot time interval 125us/4 = 31.25us.
225          *      The event time interval stays the same (320us). We can however set the
226          *      slot_interval to 3125 and the event_interval to 32000, as we can choose
227          *      the unit of the counter time step (chosen to be 10ns in this case).
228          *
229          * The average argument deserves some attention too. If average is true, we use
230          * average rate control. This means that on average there will be a delay of
231          * event_interval between two events, but that sometimes there can be a smaller
232          * delay. This mode fixes the average rate of the stream.
233          * If average is false, there will always be a minimal delay of event_interval
234          * between two events. This means that the maximum rate of the stream is fixed,
235          * and that the average rate will be lower than (or at max equal to) the rate in
236          * average mode.
237          *
238          *
239          * \note only works for the E_RingBuffer ports
240          * \note use before calling init()
241          *
242          * @param use set this to true to use rate control
243          * @param slot_interval the interval between slots
244          * @param event_interval the interval between events
245          * @param average use average rate control
246          * @return true if rate control was enabled/disabled successfully
247          */
248         virtual bool useRateControl(bool use, unsigned int slot_interval,
249                                     unsigned int event_interval, bool average);
250        
251         bool usingRateControl() { return m_do_ratecontrol;}; ///< are we using rate control?
252        
253         /**
254          * Can we send an event in this slot. subject to rate control and
255          * byte availability.
256          * @return true if we can send an event on this slot
257          */
258         bool canRead();
259
260         // FIXME: this is not really OO, but for performance???
261         void *getBufferAddress();
262
263         // TODO: extend this with a blocking interface
264         bool writeEvent(void *event); ///< write one event
265         bool readEvent(void *event); ///< read one event
266         int writeEvents(void *event, unsigned int nevents); ///< write multiple events
267         int readEvents(void *event, unsigned int nevents); ///< read multiple events
268
269         virtual void setVerboseLevel(int l);
270
271 protected:
272         std::string m_Name; ///< Port name, [at construction]
273
274         enum E_SignalType m_SignalType; ///< Signalling type, [at construction]
275         enum E_BufferType m_BufferType; ///< Buffer type, [at construction]
276
277         bool m_enabled; ///< is the port enabled?, [anytime]
278         bool m_initialized; ///< is the port initialized? [after init()]
279
280         unsigned int m_buffersize;
281         unsigned int m_eventsize;
282
283         enum E_DataType m_DataType;
284         enum E_PortType m_PortType;
285         enum E_Direction m_Direction;
286
287         void *m_buffer;
288         freebob_ringbuffer_t *m_ringbuffer;
289         bool m_use_external_buffer;
290        
291         bool m_do_ratecontrol;
292         int m_event_interval;
293         int m_slot_interval;
294         int m_rate_counter;
295         int m_rate_counter_minimum;
296         bool m_average_ratecontrol;
297
298         bool allocateInternalBuffer();
299         void freeInternalBuffer();
300        
301         bool allocateInternalRingBuffer();
302         void freeInternalRingBuffer();
303
304     DECLARE_DEBUG_MODULE;
305
306 };
307
308 /*!
309 \brief The Base Class for an Audio Port
310
311
312 */
313 class AudioPort : public Port {
314
315 public:
316
317         AudioPort(std::string name, enum E_Direction direction)
318           : Port(name, E_Audio, direction)
319         {};
320
321         virtual ~AudioPort() {};
322
323 protected:
324
325  
326 };
327
328 /*!
329 \brief The Base Class for a Midi Port
330
331
332 */
333 class MidiPort : public Port {
334
335 public:
336
337         MidiPort(std::string name, enum E_Direction direction)
338           : Port(name, E_Midi, direction)
339         {};
340         virtual ~MidiPort() {};
341
342
343 protected:
344
345
346 };
347
348 /*!
349 \brief The Base Class for a control port
350
351
352 */
353 class ControlPort : public Port {
354
355 public:
356
357         ControlPort(std::string name, enum E_SignalType type, enum E_BufferType buffertype, enum E_Direction direction)
358           : Port(name, E_Control, direction)
359         {};
360         virtual ~ControlPort() {};
361
362
363 protected:
364
365
366 };
367
368 }
369
370 #endif /* __FREEBOB_PORT__ */
371
372
Note: See TracBrowser for help on using the browser.