root/branches/ppalmers-streaming/src/libstreaming/generic/Port.cpp

Revision 705, 16.3 kB (checked in by ppalmers, 13 years ago)

restructure the streaming directory

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