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

Revision 554, 16.3 kB (checked in by ppalmers, 17 years ago)

Merge echoaudio branch into trunk.

This adds support for the Echo Audiofire devices to FFADO. Possibly also other devices working with the Apple Class Driver will work with this code. It is not fully complete yet, but the main rework is
done.

First of all the IAvDevice class/interface is renamed to FFADODevice, in order to separate the AV/C code from the FFADO API code. A device supported by FFADO implements a FFADODevice.

The BeBoB device has been split up into three groups:
- libavc/* : all code and commands that are specified by AV/C specs. Note that a lot of the code that used to be in BeBoB::AvDevice? now resides in AVC::Unit
- genericavc/* : a FFADODevice that uses AV/C descriptors & commands for discovery and config
- bebob/* : the bebob FFADODevice that inherits from GenericAVC::AvDevice? but that uses BridgeCo? commands for discovery

Everything has been moved as high as possible in the class hierarchy. If necessary, a subclass that uses device specific commands is introduced (e.g. BeBoB::Plug inherits from AVC::Plug and uses the
BridgeCo? extended plug info command to discover it's properties).

There are some other fixes along the way that have been done too.

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.