root/branches/echoaudio/src/libstreaming/Port.cpp

Revision 545, 16.3 kB (checked in by ppalmers, 15 years ago)

- Remove name parameter from PortInfo? since it's already in Port

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