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 | | |
---|
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; |
---|
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 | | } |
---|