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

Revision 719, 16.3 kB (checked in by ppalmers, 16 years ago)

backup commit

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