root/trunk/libffado/src/libstreaming/generic/Port.cpp

Revision 750, 16.3 kB (checked in by ppalmers, 14 years ago)

Code refactoring. Tries to simplify things and tries to put all code where it belongs.

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "Port.h"
25
26 #include <stdlib.h>
27 #include <assert.h>
28
29 namespace Streaming {
30
31 IMPL_DEBUG_MODULE( Port, Port, DEBUG_LEVEL_NORMAL );
32
33 Port::Port(std::string name, enum E_PortType porttype, enum E_Direction direction)
34       : m_Name(name),
35     m_SignalType(E_PeriodSignalled),
36     m_BufferType(E_PointerBuffer),
37     m_disabled(true),
38     m_buffersize(0),
39     m_eventsize(0),
40     m_DataType(E_Int24),
41     m_PortType(porttype),
42     m_Direction(direction),
43     m_buffer(0),
44     m_ringbuffer(0),
45     m_use_external_buffer(false),
46     m_do_ratecontrol(false),
47     m_event_interval(0),
48     m_slot_interval(0),
49     m_rate_counter(0),
50     m_rate_counter_minimum(0),
51     m_average_ratecontrol(false),
52     m_State(E_Created)
53 {
54
55 }
56
57 /**
58  * The idea is that you set all port parameters, and then initialize the port.
59  * This allocates all resources and makes the port usable. However, you can't
60  * change the port properties anymore after this.
61  *
62  * @return true if successfull. false if not (all resources are freed).
63  */
64 bool Port::init() {
65     debugOutput( DEBUG_LEVEL_VERBOSE, "Initialize port %s\n", m_Name.c_str());
66     if (m_State != E_Created) {
67         debugFatal("Port (%s) not in E_Created state: %d\n", m_Name.c_str(), m_State);
68         return false;
69     }
70
71     if (m_buffersize==0) {
72         debugFatal("Cannot initialize a port with buffersize=0\n");
73         return false;
74     }
75
76     switch (m_BufferType) {
77         case E_PointerBuffer:
78             if (m_use_external_buffer) {
79                 // don't do anything
80             } else if (!allocateInternalBuffer()) {
81                 debugFatal("Could not allocate internal buffer!\n");
82                 return false;
83             }
84             break;
85
86         case E_RingBuffer:
87             if (m_use_external_buffer) {
88                 debugFatal("Cannot use an external ringbuffer! \n");
89                 return false;
90             } else if (!allocateInternalRingBuffer()) {
91                 debugFatal("Could not allocate internal ringbuffer!\n");
92                 return false;
93             }
94             break;
95         default:
96             debugFatal("Unsupported buffer type! (%d)\n",(int)m_BufferType);
97             return false;
98             break;
99     }
100
101     m_eventsize=getEventSize(); // this won't change, so cache it
102    
103     m_State = E_Initialized;
104     return true;
105 }
106
107 bool Port::reset() {
108     if (m_BufferType==E_RingBuffer) {
109         ffado_ringbuffer_reset(m_ringbuffer);
110     }
111     return true;
112 };
113
114 bool Port::setName(std::string name) {
115     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting name to %s for port %s\n",name.c_str(),m_Name.c_str());
116
117     if (m_State != E_Created) {
118         debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);
119         return false;
120     }
121     m_Name=name;
122     return true;
123 }
124
125 bool Port::setBufferSize(unsigned int newsize) {
126     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting buffersize to %d for port %s\n",newsize,m_Name.c_str());
127     if (m_State != E_Created) {
128         debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);
129         return false;
130     }
131     m_buffersize=newsize;
132     return true;
133 }
134
135 unsigned int Port::getEventSize() {
136     switch (m_DataType) {
137         case E_Float:
138             return sizeof(float);
139         case E_Int24: // 24 bit 2's complement, packed in a 32bit integer (LSB's)
140             return sizeof(uint32_t);
141         case E_MidiEvent:
142             return sizeof(uint32_t);
143         default:
144             return 0;
145     }
146 }
147
148 bool Port::setDataType(enum E_DataType d) {
149     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting datatype to %d for port %s\n",(int) d,m_Name.c_str());
150     if (m_State != E_Created) {
151         debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);
152         return false;
153     }
154
155     // do some sanity checks
156     bool type_is_ok=false;
157     switch (m_PortType) {
158         case E_Audio:
159             if(d == E_Int24) type_is_ok=true;
160             if(d == E_Float) type_is_ok=true;
161             break;
162         case E_Midi:
163             if(d == E_MidiEvent) type_is_ok=true;
164             break;
165         case E_Control:
166             if(d == E_Default) type_is_ok=true;
167             break;
168         default:
169             break;
170     }
171
172     if(!type_is_ok) {
173         debugFatal("Datatype not supported by this type of port!\n");
174         return false;
175     }
176
177     m_DataType=d;
178     return true;
179 }
180
181 bool Port::setSignalType(enum E_SignalType s) {
182     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting signaltype to %d for port %s\n",(int)s,m_Name.c_str());
183     if (m_State != E_Created) {
184         debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);
185         return false;
186     }
187
188     // do some sanity checks
189     bool type_is_ok=false;
190     switch (m_PortType) {
191         case E_Audio:
192             if(s == E_PeriodSignalled) type_is_ok=true;
193             break;
194         case E_Midi:
195             if(s == E_PacketSignalled) type_is_ok=true;
196             break;
197         case E_Control:
198             if(s == E_PeriodSignalled) type_is_ok=true;
199             break;
200         default:
201             break;
202     }
203     if(!type_is_ok) {
204         debugFatal("Signalling type not supported by this type of port!\n");
205         return false;
206     }
207     m_SignalType=s;
208     return true;
209 }
210
211 bool Port::setBufferType(enum E_BufferType b) {
212     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting buffer type to %d for port %s\n",(int)b,m_Name.c_str());
213     if (m_State != E_Created) {
214         debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);
215         return false;
216     }
217     // do some sanity checks
218     bool type_is_ok=false;
219     switch (m_PortType) {
220         case E_Audio:
221             if(b == E_PointerBuffer) type_is_ok=true;
222             break;
223         case E_Midi:
224             if(b == E_RingBuffer) type_is_ok=true;
225             break;
226         case E_Control:
227             break;
228         default:
229             break;
230     }
231     if(!type_is_ok) {
232         debugFatal("Buffer type not supported by this type of port!\n");
233         return false;
234     }
235     m_BufferType=b;
236     return true;
237 }
238
239 bool Port::useExternalBuffer(bool b) {
240     // If called on an initialised stream but the request isn't for a change silently
241     // allow it (relied on by C API as used by jack backend driver)
242     if (m_State==E_Initialized && m_use_external_buffer==b)
243         return true;
244
245     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting external buffer use to %d for port %s\n",(int)b,m_Name.c_str());
246
247     if (m_State != E_Created) {
248         debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);
249         return false;
250     }
251     m_use_external_buffer=b;
252     return true;
253 }
254
255 // buffer handling api's for pointer buffers
256 /**
257  * Get the buffer address (being the external or the internal one).
258  *
259  * @param buff
260  */
261 void *Port::getBufferAddress() {
262     assert(m_BufferType==E_PointerBuffer);
263     return m_buffer;
264 };
265
266 /**
267  * Set the external buffer address.
268  * only call this when you have specified that you will use
269  * an external buffer before doing the init()
270  *
271  * @param buff
272  */
273 void Port::setExternalBufferAddress(void *buff) {
274     assert(m_BufferType==E_PointerBuffer);
275     assert(m_use_external_buffer); // don't call this with an internal buffer!
276     m_buffer=buff;
277 };
278
279 // buffer handling api's for ringbuffers
280 bool Port::writeEvent(void *event) {
281
282 #ifdef DEBUG
283     if (m_State != E_Initialized) {
284         debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);
285         return false;
286     }
287    
288     if(m_BufferType!=E_RingBuffer) {
289         debugError("operation not allowed on non E_RingBuffer ports\n");
290         show();
291         return false;
292     }
293     assert(m_ringbuffer);
294 #endif
295
296     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Writing event %08X with size %d to port %s\n",*((quadlet_t *)event),m_eventsize, m_Name.c_str());
297
298     return (ffado_ringbuffer_write(m_ringbuffer, (char *)event, m_eventsize)==m_eventsize);
299 }
300
301 bool Port::readEvent(void *event) {
302
303 #ifdef DEBUG
304     if (m_State != E_Initialized) {
305         debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);
306         return false;
307     }
308    
309     if(m_BufferType!=E_RingBuffer) {
310         debugError("operation not allowed on non E_RingBuffer ports\n");
311         show();
312         return false;
313     }
314     assert(m_ringbuffer);
315 #endif
316
317    
318     unsigned int read=ffado_ringbuffer_read(m_ringbuffer, (char *)event, m_eventsize);
319    
320     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Reading event %X with size %d from port %s\n",*((quadlet_t *)event),m_eventsize,m_Name.c_str());
321
322
323     return (read==m_eventsize);
324 }
325
326 int Port::writeEvents(void *event, unsigned int nevents) {
327
328 #ifdef DEBUG
329     if (m_State != E_Initialized) {
330         debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);
331         return false;
332     }
333    
334     if(m_BufferType!=E_RingBuffer) {
335         debugError("operation not allowed on non E_RingBuffer ports\n");
336         show();
337         return false;
338     }
339     assert(m_ringbuffer);
340 #endif
341
342
343     unsigned int bytes2write=m_eventsize*nevents;
344
345     unsigned int written=ffado_ringbuffer_write(m_ringbuffer, (char *)event,bytes2write)/m_eventsize;
346
347 #ifdef DEBUG
348     if(written) {
349         unsigned int i=0;
350         quadlet_t * tmp=(quadlet_t *)event;
351         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Written %d events (",written);
352         for (i=0;i<written;i++) {
353             debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%X ", *(tmp+i));
354         }
355         debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, ") to port %s\n",m_Name.c_str());
356     }
357 #endif
358
359     return written;
360
361 }
362
363 int Port::readEvents(void *event, unsigned int nevents) {
364
365 #ifdef DEBUG
366     if (m_State != E_Initialized) {
367         debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);
368         return false;
369     }
370     if(m_BufferType!=E_RingBuffer) {
371         debugError("operation not allowed on non E_RingBuffer ports\n");
372         show();
373         return false;
374     }
375     assert(m_ringbuffer);
376 #endif
377
378
379     unsigned int bytes2read=m_eventsize*nevents;
380
381     unsigned int read=ffado_ringbuffer_read(m_ringbuffer, (char *)event, bytes2read)/m_eventsize;
382
383 #ifdef DEBUG
384     if(read) {
385         unsigned int i=0;
386         quadlet_t * tmp=(quadlet_t *)event;
387         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Read %d events (",read);
388         for (i=0;i<read;i++) {
389             debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%X ", *(tmp+i));
390         }
391         debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, ") from port %s\n",m_Name.c_str());
392     }
393 #endif
394
395     return read;
396 }
397
398 /* rate control */
399 bool Port::canRead() {
400     bool byte_present_in_buffer;
401
402     bool retval=false;
403
404     assert(m_ringbuffer);
405
406     byte_present_in_buffer=(ffado_ringbuffer_read_space(m_ringbuffer) >= m_eventsize);
407
408     if(byte_present_in_buffer) {
409
410         if(!m_do_ratecontrol) {
411             return true;
412         }
413
414         if(m_rate_counter <= 0) {
415             // update the counter
416             if(m_average_ratecontrol) {
417                 m_rate_counter += m_event_interval;
418                 assert(m_rate_counter<m_event_interval);
419             } else {
420                 m_rate_counter = m_event_interval;
421             }
422
423             retval=true;
424         } else {
425             debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Rate limit (%s)! rate_counter=%d \n",m_Name.c_str(),m_rate_counter);
426
427         }
428     }
429
430
431     m_rate_counter -= m_slot_interval;
432
433     // we have to limit the decrement of the ratecounter somehow.
434     // m_rate_counter_minimum is initialized when enabling ratecontrol
435     if(m_rate_counter < m_rate_counter_minimum) {
436         m_rate_counter = m_rate_counter_minimum;
437     }
438
439     return retval;
440 }
441
442 bool Port::useRateControl(bool use, unsigned int slot_interval,
443                                 unsigned int event_interval, bool average) {
444
445     if (use) {
446         debugOutput(DEBUG_LEVEL_VERBOSE, "Enabling rate control for port %s...\n",m_Name.c_str());
447         if(slot_interval>event_interval) {
448             debugWarning("Rate control not needed!\n",m_Name.c_str());
449             m_do_ratecontrol=false;
450             return false;
451         }
452         if(slot_interval==0) {
453             debugFatal("Cannot have slot interval == 0!\n");
454             m_do_ratecontrol=false;
455             return false;
456         }
457         if(event_interval==0) {
458             debugFatal("Cannot have event interval == 0!\n");
459             m_do_ratecontrol=false;
460             return false;
461         }
462         m_do_ratecontrol=use;
463         m_event_interval=event_interval;
464         m_slot_interval=slot_interval;
465         m_rate_counter=0;
466
467         // NOTE: pretty arbitrary, but in average mode this limits the peak stream rate
468         m_rate_counter_minimum=-(2*event_interval);
469
470         m_average_ratecontrol=average;
471
472     } else {
473         debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling rate control for port %s...\n",m_Name.c_str());
474         m_do_ratecontrol=use;
475     }
476     return true;
477 }
478
479 /// Enable the port. (this can be called anytime)
480 void
481 Port::enable()  {
482     debugOutput(DEBUG_LEVEL_VERBOSE, "Enabling port %s...\n",m_Name.c_str());
483     m_disabled=false;
484 };
485
486 /// Disable the port. (this can be called anytime)
487 void
488 Port::disable() {
489     debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling port %s...\n",m_Name.c_str());
490     m_disabled=false;
491 };
492
493
494 /* Private functions */
495
496 bool Port::allocateInternalBuffer() {
497     int event_size=getEventSize();
498
499     debugOutput(DEBUG_LEVEL_VERBOSE,
500                 "Allocating internal buffer of %d events with size %d (%s)\n",
501                 m_buffersize, event_size, m_Name.c_str());
502
503     if(m_buffer) {
504         debugWarning("already has an internal buffer attached, re-allocating\n");
505         freeInternalBuffer();
506     }
507
508     m_buffer=calloc(m_buffersize,event_size);
509     if (!m_buffer) {
510         debugFatal("could not allocate internal buffer\n");
511         m_buffersize=0;
512         return false;
513     }
514
515     return true;
516 }
517
518 void Port::freeInternalBuffer() {
519     debugOutput(DEBUG_LEVEL_VERBOSE,
520                 "Freeing internal buffer (%s)\n",m_Name.c_str());
521
522     if(m_buffer) {
523         free(m_buffer);
524         m_buffer=0;
525     }
526 }
527
528 bool Port::allocateInternalRingBuffer() {
529     int event_size=getEventSize();
530
531     debugOutput(DEBUG_LEVEL_VERBOSE,
532                 "Allocating internal buffer of %d events with size %d (%s)\n",
533                 m_buffersize, event_size, m_Name.c_str());
534
535     if(m_ringbuffer) {
536         debugWarning("already has an internal ringbuffer attached, re-allocating\n");
537         freeInternalRingBuffer();
538     }
539
540     m_ringbuffer=ffado_ringbuffer_create(m_buffersize * event_size);
541     if (!m_ringbuffer) {
542         debugFatal("could not allocate internal ringbuffer\n");
543         m_buffersize=0;
544         return false;
545     }
546
547     return true;
548 }
549
550 void Port::freeInternalRingBuffer() {
551     debugOutput(DEBUG_LEVEL_VERBOSE,
552                 "Freeing internal ringbuffer (%s)\n",m_Name.c_str());
553
554     if(m_ringbuffer) {
555         ffado_ringbuffer_free(m_ringbuffer);
556         m_ringbuffer=0;
557     }
558 }
559
560 void Port::show() {
561     debugOutput(DEBUG_LEVEL_VERBOSE,"Name          : %s\n", m_Name.c_str());
562     debugOutput(DEBUG_LEVEL_VERBOSE,"Signal Type   : %d\n", m_SignalType);
563     debugOutput(DEBUG_LEVEL_VERBOSE,"Buffer Type   : %d\n", m_BufferType);
564     debugOutput(DEBUG_LEVEL_VERBOSE,"Enabled?      : %d\n", m_disabled);
565     debugOutput(DEBUG_LEVEL_VERBOSE,"State?        : %d\n", m_State);
566     debugOutput(DEBUG_LEVEL_VERBOSE,"Buffer Size   : %d\n", m_buffersize);
567     debugOutput(DEBUG_LEVEL_VERBOSE,"Event Size    : %d\n", m_eventsize);
568     debugOutput(DEBUG_LEVEL_VERBOSE,"Data Type     : %d\n", m_DataType);
569     debugOutput(DEBUG_LEVEL_VERBOSE,"Port Type     : %d\n", m_PortType);
570     debugOutput(DEBUG_LEVEL_VERBOSE,"Direction     : %d\n", m_Direction);
571     debugOutput(DEBUG_LEVEL_VERBOSE,"Rate Control? : %d\n", m_do_ratecontrol);
572 }
573
574 void Port::setVerboseLevel(int l) {
575     setDebugLevel(l);
576 }
577
578 }
Note: See TracBrowser for help on using the browser.