Changeset 833
- Timestamp:
- 01/10/08 13:36:13 (15 years ago)
- Files:
-
- trunk/libffado/config.h.in (modified) (1 diff)
- trunk/libffado/libffado/ffado.h (modified) (4 diffs)
- trunk/libffado/SConstruct (modified) (1 diff)
- trunk/libffado/src/bebob/focusrite/focusrite_saffirepro.cpp (modified) (5 diffs)
- trunk/libffado/src/bebob/focusrite/focusrite_saffirepro.h (modified) (3 diffs)
- trunk/libffado/src/bounce/bounce_avdevice.cpp (modified) (4 diffs)
- trunk/libffado/src/devicemanager.cpp (modified) (1 diff)
- trunk/libffado/src/devicemanager.h (modified) (2 diffs)
- trunk/libffado/src/dice/dice_avdevice.cpp (modified) (3 diffs)
- trunk/libffado/src/ffado.cpp (modified) (6 diffs)
- trunk/libffado/src/genericavc/avc_avdevice.cpp (modified) (7 diffs)
- trunk/libffado/src/libieee1394/IsoHandler.cpp (modified) (6 diffs)
- trunk/libffado/src/libieee1394/IsoHandlerManager.cpp (modified) (2 diffs)
- trunk/libffado/src/libstreaming/amdtp/AmdtpPort.h (modified) (2 diffs)
- trunk/libffado/src/libstreaming/amdtp/AmdtpPortInfo.h (modified) (1 diff)
- trunk/libffado/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp (modified) (9 diffs)
- trunk/libffado/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h (modified) (1 diff)
- trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp (modified) (8 diffs)
- trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h (modified) (2 diffs)
- trunk/libffado/src/libstreaming/generic/Port.cpp (modified) (8 diffs)
- trunk/libffado/src/libstreaming/generic/Port.h (modified) (8 diffs)
- trunk/libffado/src/libstreaming/generic/PortManager.cpp (modified) (8 diffs)
- trunk/libffado/src/libstreaming/generic/PortManager.h (modified) (3 diffs)
- trunk/libffado/src/libstreaming/generic/StreamProcessor.cpp (modified) (40 diffs)
- trunk/libffado/src/libstreaming/generic/StreamProcessor.h (modified) (3 diffs)
- trunk/libffado/src/libstreaming/motu/MotuPort.h (modified) (3 diffs)
- trunk/libffado/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp (modified) (6 diffs)
- trunk/libffado/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp (modified) (11 diffs)
- trunk/libffado/src/libstreaming/StreamProcessorManager.cpp (modified) (13 diffs)
- trunk/libffado/src/libstreaming/StreamProcessorManager.h (modified) (3 diffs)
- trunk/libffado/src/libutil/TimestampedBuffer.cpp (modified) (17 diffs)
- trunk/libffado/src/libutil/TimestampedBuffer.h (modified) (3 diffs)
- trunk/libffado/src/motu/motu_avdevice.cpp (modified) (3 diffs)
- trunk/libffado/tests/streaming/debugtools.c (deleted)
- trunk/libffado/tests/streaming/debugtools.h (deleted)
- trunk/libffado/tests/streaming/SConscript (modified) (1 diff)
- trunk/libffado/tests/streaming/testmidistreaming1.c (deleted)
- trunk/libffado/tests/streaming/teststreaming.c (deleted)
- trunk/libffado/tests/streaming/teststreaming2.c (deleted)
- trunk/libffado/tests/streaming/teststreaming3.cpp (modified) (12 diffs)
- trunk/libffado/tests/test-ieee1394service.cpp (modified) (1 diff)
- trunk/libffado/tests/test-streamdump.cpp (modified) (1 diff)
- trunk/libffado/tests/test-timestampedbuffer.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/config.h.in
r807 r833 67 67 #define STREAMPROCESSORMANAGER_PRESTART_CYCLES_FOR_XMIT 20 68 68 #define STREAMPROCESSORMANAGER_PRESTART_CYCLES_FOR_RECV 0 69 #define STREAMPROCESSORMANAGER_SYNCSTART_TRIES 10 70 #define STREAMPROCESSORMANAGER_SYNC_WAIT_TIME_MSEC 200 69 71 #define STREAMPROCESSORMANAGER_ALIGN_AVERAGE_TIME_MSEC 200 70 72 #define STREAMPROCESSORMANAGER_NB_ALIGN_TRIES 40 trunk/libffado/libffado/ffado.h
r742 r833 206 206 207 207 /** 208 * 209 * Buffertypes known to the API210 * 208 * 209 * Audio data types known to the API 210 * 211 211 */ 212 212 typedef enum { 213 ffado_buffer_type_per_stream = -1, // use this to use the per-stream read functions 214 ffado_buffer_type_int24 = 0, 215 ffado_buffer_type_float = 1, 216 ffado_buffer_type_midi = 2, 217 } ffado_streaming_buffer_type; 213 ffado_audio_datatype_error = -1, 214 ffado_audio_datatype_int24 = 0, 215 ffado_audio_datatype_float = 1, 216 } ffado_streaming_audio_datatype; 217 218 /** 219 * 220 * Wait responses 221 * 222 */ 223 typedef enum { 224 ffado_wait_error = -2, 225 ffado_wait_xrun = -1, 226 ffado_wait_ok = 0, 227 } ffado_wait_response; 218 228 219 229 /** … … 339 349 340 350 int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int number, char *buff); 341 int ffado_streaming_set_capture_buffer_type(ffado_device_t *dev, int i, ffado_streaming_buffer_type t);342 351 int ffado_streaming_capture_stream_onoff(ffado_device_t *dev, int number, int on); 343 352 … … 355 364 */ 356 365 int ffado_streaming_set_playback_stream_buffer(ffado_device_t *dev, int number, char *buff); 357 int ffado_streaming_set_playback_buffer_type(ffado_device_t *dev, int i, ffado_streaming_buffer_type t);358 366 int ffado_streaming_playback_stream_onoff(ffado_device_t *dev, int number, int on); 359 367 368 ffado_streaming_audio_datatype ffado_streaming_get_audio_datatype(ffado_device_t *dev); 369 int ffado_streaming_set_audio_datatype(ffado_device_t *dev, ffado_streaming_audio_datatype t); 360 370 361 371 /** … … 409 419 * @return The number of frames ready. -1 when a problem occurred. 410 420 */ 411 int ffado_streaming_wait(ffado_device_t *dev); 412 413 /** 414 * Reads from a specific channel to a supplied buffer. 415 * 416 * @param dev the ffado device 417 * @param number the stream number 418 * @param buffer the buffer to copy the samples into 419 * @param nsamples the number of samples to be read. the buffer has to be big enough for this amount of samples. 420 * 421 * @return the amount of samples actually read. -1 on error (xrun). 422 */ 423 int ffado_streaming_read(ffado_device_t *dev, int number, ffado_sample_t *buffer, int nsamples); 424 425 /** 426 * Write to a specific channel from a supplied buffer. 427 * 428 * @param dev the ffado device 429 * @param number the stream number 430 * @param buffer the buffer to copy the samples from 431 * @param nsamples the number of samples to be written. 432 * 433 * @return the amount of samples actually written. -1 on error. 434 */ 435 int ffado_streaming_write(ffado_device_t *dev, int number, ffado_sample_t *buffer, int nsamples); 421 ffado_wait_response ffado_streaming_wait(ffado_device_t *dev); 436 422 437 423 /** trunk/libffado/SConstruct
r823 r833 331 331 env['REVISION'] = '' 332 332 333 env['FFADO_API_VERSION']=" 5"333 env['FFADO_API_VERSION']="7" 334 334 335 335 env['PACKAGE'] = "libffado" 336 env['VERSION'] = "1.999.1 1"336 env['VERSION'] = "1.999.13" 337 337 env['LIBVERSION'] = "1.0.0" 338 338 trunk/libffado/src/bebob/focusrite/focusrite_saffirepro.cpp
r783 r833 231 231 "UseHighVoltageRail", "Use High Supply", "Prefer the high voltage power supply rail")); 232 232 233 result &= m_ControlContainer->addElement( 234 new SaffireProMultiControl(*this, SaffireProMultiControl::eTCT_ExitStandalone, 235 "ExitStandalone", "Exit Standalone mode", "Try to leave standalonbe mode")); 236 237 result &= m_ControlContainer->addElement( 238 new SaffireProMultiControl(*this, SaffireProMultiControl::eTCT_PllLockRange, 239 "PllLockRange", "PLL Lock Range", "Get/Set PLL Lock range")); 240 233 241 if (!result) { 234 242 debugWarning("One or more device control elements could not be created."); … … 484 492 485 493 void 494 SaffireProDevice::exitStandalone() { 495 debugOutput( DEBUG_LEVEL_VERBOSE, "exit standalone mode...\n" ); 496 if ( !setSpecificValue(FR_SAFFIREPRO_CMD_ID_EXIT_STANDALONE, 497 FR_SAFFIREPRO_CMD_EXIT_STANDALONE_CODE ) ) { 498 debugError( "setSpecificValue failed\n" ); 499 } 500 } 501 502 void 486 503 SaffireProDevice::flashLed() { 487 504 int ledFlashDuration=2; … … 570 587 } 571 588 589 void 590 SaffireProDevice::setPllLockRange(unsigned int i) { 591 uint32_t reg=i; 592 debugOutput( DEBUG_LEVEL_VERBOSE, "set PLL lock range: %d ...\n", i ); 593 594 if ( !setSpecificValue(FR_SAFFIREPRO_CMD_ID_PLL_LOCK_RANGE, 595 reg ) ) { 596 debugError( "setSpecificValue failed\n" ); 597 } 598 } 599 600 unsigned int 601 SaffireProDevice::getPllLockRange() { 602 uint32_t retval; 603 if ( !getSpecificValue(FR_SAFFIREPRO_CMD_ID_PLL_LOCK_RANGE, &retval ) ) { 604 debugError( "getSpecificValue failed\n" ); 605 return false; 606 } 607 608 debugOutput( DEBUG_LEVEL_VERBOSE, 609 "PLL lock range: %d\n", retval ); 610 return retval; 611 } 612 572 613 // swiss army knife control element 573 SaffireProMultiControl::SaffireProMultiControl(SaffireProDevice& parent, enum e TriggerControlType t)614 SaffireProMultiControl::SaffireProMultiControl(SaffireProDevice& parent, enum eMultiControlType t) 574 615 : Control::Discrete() 575 616 , m_Parent(parent) 576 617 , m_type ( t ) 577 618 {} 578 SaffireProMultiControl::SaffireProMultiControl(SaffireProDevice& parent, enum e TriggerControlType t,619 SaffireProMultiControl::SaffireProMultiControl(SaffireProDevice& parent, enum eMultiControlType t, 579 620 std::string name, std::string label, std::string descr) 580 621 : Control::Discrete() … … 594 635 case eTCT_FlashLed: m_Parent.flashLed(); return true; 595 636 case eTCT_UseHighVoltageRail: m_Parent.useHighVoltageRail(v); return true; 637 case eTCT_ExitStandalone: m_Parent.exitStandalone(); return true; 638 case eTCT_PllLockRange: m_Parent.setPllLockRange(v); return true; 596 639 } 597 640 return false; … … 605 648 case eTCT_FlashLed: return 0; 606 649 case eTCT_UseHighVoltageRail: return m_Parent.usingHighVoltageRail(); 650 case eTCT_ExitStandalone: return 0; 651 case eTCT_PllLockRange: return m_Parent.getPllLockRange(); 607 652 } 608 653 return -1; trunk/libffado/src/bebob/focusrite/focusrite_saffirepro.h
r750 r833 254 254 { 255 255 public: 256 enum e TriggerControlType {256 enum eMultiControlType { 257 257 eTCT_Reboot, 258 258 eTCT_FlashLed, 259 259 eTCT_UseHighVoltageRail, 260 eTCT_ExitStandalone, 261 eTCT_PllLockRange, 260 262 }; 261 263 262 264 public: 263 SaffireProMultiControl(SaffireProDevice& parent, enum e TriggerControlType);264 SaffireProMultiControl(SaffireProDevice& parent, enum e TriggerControlType,265 SaffireProMultiControl(SaffireProDevice& parent, enum eMultiControlType); 266 SaffireProMultiControl(SaffireProDevice& parent, enum eMultiControlType, 265 267 std::string name, std::string label, std::string descr); 266 268 … … 270 272 private: 271 273 SaffireProDevice& m_Parent; 272 enum e TriggerControlType m_type;274 enum eMultiControlType m_type; 273 275 }; 274 276 … … 320 322 bool isExtClockLocked(); 321 323 uint32_t getCount32(); 324 void exitStandalone(); 322 325 323 326 void useHighVoltageRail(bool useIt); 324 327 bool usingHighVoltageRail(); 328 unsigned int getPllLockRange(); 329 void setPllLockRange(unsigned int); 330 325 331 private: 326 332 virtual bool setSamplingFrequencyDo( uint32_t ); trunk/libffado/src/bounce/bounce_avdevice.cpp
r742 r833 212 212 Streaming::Port *p=NULL; 213 213 p=new Streaming::AmdtpAudioPort( 214 *processor, 214 215 buff, 215 216 direction, … … 224 225 if (!p) { 225 226 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); 226 } else {227 228 if (!processor->addPort(p)) {229 debugWarning("Could not register port with stream processor\n");230 free(buff);231 return false;232 } else {233 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);234 }235 227 } 236 228 free(buff); … … 243 235 Streaming::Port *p=NULL; 244 236 p=new Streaming::AmdtpMidiPort( 237 *processor, 245 238 buff, 246 239 direction, … … 255 248 if (!p) { 256 249 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); 257 } else {258 259 if (!processor->addPort(p)) {260 debugWarning("Could not register port with stream processor\n");261 free(buff);262 return false;263 } else {264 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);265 }266 250 } 267 251 free(buff); trunk/libffado/src/devicemanager.cpp
r826 r833 553 553 } 554 554 555 bool 555 enum DeviceManager::eWaitResult 556 556 DeviceManager::waitForPeriod() { 557 557 if(m_processorManager->waitForPeriod()) { 558 return true;558 return eWR_OK; 559 559 } else { 560 560 debugWarning("XRUN detected\n"); 561 561 // do xrun recovery 562 562 if(m_processorManager->handleXrun()) { 563 return false;563 return eWR_Xrun; 564 564 } else { 565 565 debugError("Could not handle XRUN\n"); 566 return false;566 return eWR_Error; 567 567 } 568 568 } trunk/libffado/src/devicemanager.h
r826 r833 61 61 { 62 62 public: 63 enum eWaitResult { 64 eWR_OK, 65 eWR_Xrun, 66 eWR_Error, 67 }; 68 63 69 DeviceManager(); 64 70 ~DeviceManager(); … … 79 85 bool stopStreaming(); 80 86 bool resetStreaming(); 81 boolwaitForPeriod();87 enum eWaitResult waitForPeriod(); 82 88 bool setStreamingParams(unsigned int period, unsigned int rate, unsigned int nb_buffers); 83 89 trunk/libffado/src/dice/dice_avdevice.cpp
r785 r833 839 839 case ePT_Analog: 840 840 p=new Streaming::AmdtpAudioPort( 841 *processor, 841 842 portname.str(), 842 843 direction, … … 849 850 case ePT_MIDI: 850 851 p=new Streaming::AmdtpMidiPort( 852 *processor, 851 853 portname.str(), 852 854 direction, … … 864 866 if (!p) { 865 867 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str()); 866 } else {867 868 if (!processor->addPort(p)) {869 debugWarning("Could not register port with stream processor\n");870 return false;871 }872 868 } 873 869 trunk/libffado/src/ffado.cpp
r807 r833 184 184 if(!dev->m_deviceManager->prepareStreaming()) { 185 185 debugFatal("Could not prepare the streaming system\n"); 186 return 0;186 return -1; 187 187 } 188 188 return 0; … … 226 226 } 227 227 228 int ffado_streaming_wait(ffado_device_t *dev) { 228 ffado_wait_response 229 ffado_streaming_wait(ffado_device_t *dev) { 229 230 static int periods=0; 230 231 static int periods_print=0; … … 242 243 } 243 244 244 if(dev->m_deviceManager->waitForPeriod()) { 245 return dev->options.period_size; 245 enum DeviceManager::eWaitResult result; 246 result = dev->m_deviceManager->waitForPeriod(); 247 if(result == DeviceManager::eWR_OK) { 248 return ffado_wait_ok; 249 } else if (result == DeviceManager::eWR_Xrun) { 250 debugWarning("Handled XRUN\n"); 251 xruns++; 252 return ffado_wait_xrun; 246 253 } else { 247 debug Warning("XRUN\n");254 debugError("Unhandled XRUN (BUG)\n"); 248 255 xruns++; 249 return -1;256 return ffado_wait_error; 250 257 } 251 258 } … … 261 268 int ffado_streaming_transfer_buffers(ffado_device_t *dev) { 262 269 return dev->m_deviceManager->getStreamProcessorManager().transfer(); 263 }264 265 266 int ffado_streaming_write(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) {267 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);268 // use an assert here performancewise,269 // it should already have failed before, if not correct270 assert(p);271 272 return p->writeEvents((void *)buffer, nsamples);273 }274 275 int ffado_streaming_read(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) {276 Streaming::Port *p=dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);277 // use an assert here performancewise,278 // it should already have failed before, if not correct279 assert(p);280 281 return p->readEvents((void *)buffer, nsamples);282 270 } 283 271 … … 354 342 } 355 343 356 int ffado_streaming_set_stream_buffer_type(ffado_device_t *dev, int i, 357 ffado_streaming_buffer_type t, enum Streaming::Port::E_Direction direction) { 358 359 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, direction); 360 if(!p) { 361 debugWarning("Could not get %s port at index %d\n", 362 (direction==Streaming::Port::E_Playback?"Playback":"Capture"),i); 363 return -1; 364 } 365 344 int ffado_streaming_set_audio_datatype(ffado_device_t *dev, 345 ffado_streaming_audio_datatype t) { 366 346 switch(t) { 367 case ffado_buffer_type_int24: 368 if (!p->setDataType(Streaming::Port::E_Int24)) { 369 debugWarning("%s: Could not set data type to Int24\n",p->getName().c_str()); 347 case ffado_audio_datatype_int24: 348 if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType( 349 Streaming::StreamProcessorManager::eADT_Int24)) { 350 debugError("Could not set datatype\n"); 351 return -1; 352 } 353 break; 354 case ffado_audio_datatype_float: 355 if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType( 356 Streaming::StreamProcessorManager::eADT_Float)) { 357 debugError("Could not set datatype\n"); 358 return -1; 359 } 360 break; 361 default: 362 debugError("Invalid audio datatype\n"); 370 363 return -1; 371 } 372 if (!p->setBufferType(Streaming::Port::E_PointerBuffer)) { 373 debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str()); 374 return -1; 375 } 376 break; 377 case ffado_buffer_type_float: 378 if (!p->setDataType(Streaming::Port::E_Float)) { 379 debugWarning("%s: Could not set data type to Float\n",p->getName().c_str()); 380 return -1; 381 } 382 if (!p->setBufferType(Streaming::Port::E_PointerBuffer)) { 383 debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str()); 384 return -1; 385 } 386 break; 387 case ffado_buffer_type_midi: 388 if (!p->setDataType(Streaming::Port::E_MidiEvent)) { 389 debugWarning("%s: Could not set data type to MidiEvent\n",p->getName().c_str()); 390 return -1; 391 } 392 if (!p->setBufferType(Streaming::Port::E_RingBuffer)) { 393 debugWarning("%s: Could not set buffer type to Ringbuffer\n",p->getName().c_str()); 394 return -1; 395 } 396 break; 397 default: 398 debugWarning("%s: Unsupported buffer type\n",p->getName().c_str()); 399 return -1; 400 } 401 return 0; 402 403 } 404 405 int ffado_streaming_set_playback_buffer_type(ffado_device_t *dev, int i, ffado_streaming_buffer_type t) { 406 return ffado_streaming_set_stream_buffer_type(dev, i, t, Streaming::Port::E_Playback); 407 } 408 409 int ffado_streaming_set_capture_buffer_type(ffado_device_t *dev, int i, ffado_streaming_buffer_type t) { 410 return ffado_streaming_set_stream_buffer_type(dev, i, t, Streaming::Port::E_Capture); 364 } 365 return 0; 366 } 367 368 ffado_streaming_audio_datatype ffado_streaming_get_audio_datatype(ffado_device_t *dev) { 369 switch(dev->m_deviceManager->getStreamProcessorManager().getAudioDataType()) { 370 case Streaming::StreamProcessorManager::eADT_Int24: 371 return ffado_audio_datatype_int24; 372 case Streaming::StreamProcessorManager::eADT_Float: 373 return ffado_audio_datatype_float; 374 default: 375 debugError("Invalid audio datatype\n"); 376 return ffado_audio_datatype_error; 377 } 378 #warning FIXME 411 379 } 412 380 … … 435 403 } 436 404 437 // TODO: the way port buffers are set in the C api doesn't satisfy me438 405 int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int i, char *buff) { 439 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture); 440 441 // use an assert here performancewise, 442 // it should already have failed before, if not correct 443 assert(p); 444 445 p->useExternalBuffer(true); 446 p->setExternalBufferAddress((void *)buff); 447 448 return 0; 449 406 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture); 407 // use an assert here performancewise, 408 // it should already have failed before, if not correct 409 assert(p); 410 p->setBufferAddress((void *)buff); 411 return 0; 450 412 } 451 413 452 414 int ffado_streaming_set_playback_stream_buffer(ffado_device_t *dev, int i, char *buff) { 453 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback); 454 // use an assert here performancewise, 455 // it should already have failed before, if not correct 456 assert(p); 457 458 p->useExternalBuffer(true); 459 p->setExternalBufferAddress((void *)buff); 460 461 return 0; 462 } 415 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback); 416 // use an assert here performancewise, 417 // it should already have failed before, if not correct 418 assert(p); 419 p->setBufferAddress((void *)buff); 420 return 0; 421 } trunk/libffado/src/genericavc/avc_avdevice.cpp
r784 r833 443 443 } 444 444 445 if (!addPlugToProcessor(*outputPlug, p,445 if (!addPlugToProcessor(*outputPlug, p, 446 446 Streaming::Port::E_Capture)) { 447 447 debugFatal("Could not add plug to processor!\n"); … … 472 472 473 473 if (snoopMode) { 474 if (!addPlugToProcessor(*inputPlug, p,474 if (!addPlugToProcessor(*inputPlug, p, 475 475 Streaming::Port::E_Capture)) { 476 476 debugFatal("Could not add plug to processor!\n"); … … 478 478 } 479 479 } else { 480 if (!addPlugToProcessor(*inputPlug, p,480 if (!addPlugToProcessor(*inputPlug, p, 481 481 Streaming::Port::E_Playback)) { 482 482 debugFatal("Could not add plug to processor!\n"); … … 532 532 channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location); 533 533 p=new Streaming::AmdtpAudioPort( 534 *processor, 534 535 portname.str(), 535 536 direction, … … 544 545 channelInfo->m_name.c_str(), channelInfo->m_streamPosition, processor->getPortCount(Streaming::Port::E_Midi)); 545 546 p=new Streaming::AmdtpMidiPort( 547 *processor, 546 548 portname.str(), 547 549 direction, … … 565 567 channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location); 566 568 p=new Streaming::AmdtpAudioPort( 569 *processor, 567 570 portname.str(), 568 571 direction, … … 581 584 if (!p) { 582 585 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str()); 583 } else {584 585 if (!processor->addPort(p)) {586 debugWarning("Could not register port with stream processor\n");587 return false;588 }589 586 } 590 587 } trunk/libffado/src/libieee1394/IsoHandler.cpp
r807 r833 174 174 IsoHandler::waitForClient() 175 175 { 176 debugOutput(DEBUG_LEVEL_VERBOSE, "waiting...\n");176 //debugOutput(DEBUG_LEVEL_VERBOSE, "waiting...\n"); 177 177 if(m_Client) { 178 178 bool result = m_Client->waitForSignal(); 179 debugOutput(DEBUG_LEVEL_VERBOSE, " returns %d\n", result);179 //debugOutput(DEBUG_LEVEL_VERBOSE, " returns %d\n", result); 180 180 return result; 181 181 } else { … … 188 188 IsoHandler::tryWaitForClient() 189 189 { 190 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n");190 //debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n"); 191 191 if(m_Client) { 192 192 bool result = m_Client->tryWaitForSignal(); 193 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result);193 //debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result); 194 194 return result; 195 195 } else { … … 214 214 // wait for the availability of frames in the client 215 215 // (blocking for transmit handlers) 216 #if def DEBUG216 #if 0 //#ifdef DEBUG 217 217 if (getType() == eHT_Transmit) { 218 debugOutput(DEBUG_LEVEL_VER BOSE, "(%p) Waiting for Client to signal frame availability...\n", this);218 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p) Waiting for Client to signal frame availability...\n", this); 219 219 } 220 220 #endif … … 222 222 223 223 #if ISOHANDLER_USE_POLL 224 uint64_t poll_enter = m_manager.get1394Service().getCurrentTimeAsUsecs(); 225 err = poll(&m_poll_fd, 1, m_poll_timeout); 226 uint64_t poll_exit = m_manager.get1394Service().getCurrentTimeAsUsecs(); 227 if (err == -1) { 228 if (errno == EINTR) { 229 return true; 230 } 231 debugFatal("%p, poll error: %s\n", this, strerror (errno)); 232 return false; 233 } 234 uint64_t iter_enter=0; 235 uint64_t iter_exit=0; 236 if(m_poll_fd.revents & (POLLIN)) { 237 iter_enter = m_manager.get1394Service().getCurrentTimeAsUsecs(); 238 if(!iterate()) { 239 debugOutput( DEBUG_LEVEL_VERBOSE, 240 "IsoHandler (%p): Failed to iterate handler\n", 241 this); 224 bool result = true; 225 while(result && m_Client && m_Client->canProcessPackets()) { 226 int err = poll(&m_poll_fd, 1, m_poll_timeout); 227 if (err == -1) { 228 if (errno == EINTR) { 229 return true; 230 } 231 debugFatal("%p, poll error: %s\n", this, strerror (errno)); 242 232 return false; 243 233 } 244 iter_exit = m_manager.get1394Service().getCurrentTimeAsUsecs(); 245 } else { 246 if (m_poll_fd.revents & POLLERR) { 247 debugWarning("error on fd for %p\n", this); 234 235 if(m_poll_fd.revents & (POLLIN)) { 236 result=iterate(); 237 if(!result) { 238 debugOutput( DEBUG_LEVEL_VERBOSE, 239 "IsoHandler (%p): Failed to iterate handler\n", 240 this); 241 } 242 } else { 243 if (m_poll_fd.revents & POLLERR) { 244 debugWarning("error on fd for %p\n", this); 245 } 246 if (m_poll_fd.revents & POLLHUP) { 247 debugWarning("hangup on fd for %p\n",this); 248 } 249 break; 248 250 } 249 if (m_poll_fd.revents & POLLHUP) { 250 debugWarning("hangup on fd for %p\n",this); 251 } 252 } 253 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%c %p) poll took %lldus, iterate took %lldus\n", 254 (getType()==eHT_Receive?'R':'X'), this, 255 poll_exit-poll_enter, iter_exit-iter_enter); 256 return true; 251 } 252 return result; 257 253 #else 258 // iterate blocksif no 1394 data is available254 // iterate() is blocking if no 1394 data is available 259 255 // so poll'ing is not really necessary 260 261 256 bool result = true; 262 while(result && m_Client ->canProcessPackets()) {257 while(result && m_Client && m_Client->canProcessPackets()) { 263 258 result = iterate(); 264 debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Iterate returned: %d\n", 265 this, (m_type==eHT_Receive?"Receive":"Transmit"), result); 259 // if (getType() == eHT_Receive) { 260 // debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p, %s) Iterate returned: %d\n", 261 // this, (m_type==eHT_Receive?"Receive":"Transmit"), result); 262 // } 266 263 } 267 264 return result; … … 275 272 bool 276 273 IsoHandler::iterate() { 277 debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Iterating ISO handler\n", 278 this, (m_type==eHT_Receive?"Receive":"Transmit")); 274 // if(m_type==eHT_Receive) { 275 // debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Iterating ISO handler\n", 276 // this, (m_type==eHT_Receive?"Receive":"Transmit")); 277 // } 279 278 if(m_State == E_Running) { 280 279 #if ISOHANDLER_FLUSH_BEFORE_ITERATE … … 282 281 #endif 283 282 if(raw1394_loop_iterate(m_handle)) { 284 debugOutput( DEBUG_LEVEL_VERBOSE, 285 "IsoHandler (%p): Failed to iterate handler: %s\n", 283 debugError( "IsoHandler (%p): Failed to iterate handler: %s\n", 286 284 this, strerror(errno)); 287 285 return false; 288 286 } 287 // debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) done iterating ISO handler\n", 288 // this, (m_type==eHT_Receive?"Receive":"Transmit")); 289 289 return true; 290 290 } else { trunk/libffado/src/libieee1394/IsoHandlerManager.cpp
r807 r833 378 378 } 379 379 380 max_packet_size = page_size;380 //max_packet_size = page_size; // HACK 381 381 unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD; 382 382 if(irq_interval <= 0) irq_interval=1; … … 395 395 return false; 396 396 } 397 397 398 } else { 398 399 debugFatal("Bad stream type\n"); trunk/libffado/src/libstreaming/amdtp/AmdtpPort.h
r742 r833 47 47 public: 48 48 49 AmdtpAudioPort(std::string name, 50 enum E_Direction direction, 49 AmdtpAudioPort(PortManager &m, 50 std::string name, 51 enum E_Direction direction, 51 52 int position, 52 53 int location, 53 54 enum E_Formats format) 54 : AudioPort( name, direction),55 : AudioPort(m, name, direction), 55 56 AmdtpPortInfo(position, location, format) 56 57 {}; 57 58 58 59 virtual ~AmdtpAudioPort() {}; 59 60 protected:61 62 60 }; 63 61 … … 74 72 public: 75 73 76 AmdtpMidiPort(std::string name, 77 enum E_Direction direction, 78 int position, 79 int location, 80 enum E_Formats format) 81 : MidiPort(name, direction), 74 AmdtpMidiPort(PortManager &m, 75 std::string name, 76 enum E_Direction direction, 77 int position, 78 int location, 79 enum E_Formats format) 80 : MidiPort(m, name, direction), 82 81 AmdtpPortInfo(position, location, format) 83 82 {}; 84 83 85 86 84 virtual ~AmdtpMidiPort() {}; 87 88 protected:89 90 85 }; 91 86 trunk/libffado/src/libstreaming/amdtp/AmdtpPortInfo.h
r742 r833 60 60 61 61 62 int getLocation() {return m_location;};63 int getPosition() {return m_position;};62 unsigned int getLocation() {return m_location;}; 63 unsigned int getPosition() {return m_position;}; 64 64 enum E_Formats getFormat() {return m_format;}; 65 65 66 66 protected: 67 int m_position;68 int m_location;67 unsigned int m_position; 68 unsigned int m_location; 69 69 enum E_Formats m_format; 70 70 trunk/libffado/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp
r790 r833 167 167 168 168 if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) { 169 // process all ports that should be handled on a per-packet base170 // this is MIDI for AMDTP (due to the need of DBC)171 if(isRunning()) {172 if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {173 debugWarning("Problem decoding Packet Ports\n");174 }175 }176 169 return eCRV_OK; 177 170 } else { … … 193 186 bool no_problem=true; 194 187 195 for ( PortVectorIterator it = m_P eriodPorts.begin();196 it != m_P eriodPorts.end();188 for ( PortVectorIterator it = m_Ports.begin(); 189 it != m_Ports.end(); 197 190 ++it ) 198 191 { … … 213 206 case AmdtpPortInfo::E_SPDIF: // still unimplemented 214 207 break; 215 /* for this processor, midi is a packet based port216 208 case AmdtpPortInfo::E_Midi: 217 break;*/ 209 if(decodeMidiEventsToPort(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 210 debugWarning("Could not decode packet Midi to port %s",(*it)->getName().c_str()); 211 no_problem=false; 212 } 213 break; 218 214 default: // ignore 219 215 break; … … 223 219 } 224 220 225 /**226 * @brief decode a packet for the packet-based ports227 *228 * @param data Packet data229 * @param nevents number of events in data (including events of other ports & port types)230 * @param dbc DataBlockCount value for this packet231 * @return true if all successfull232 */233 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)234 {235 bool ok=true;236 237 quadlet_t *target_event=NULL;238 unsigned int j;239 240 for ( PortVectorIterator it = m_PacketPorts.begin();241 it != m_PacketPorts.end();242 ++it )243 {244 245 #ifdef DEBUG246 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);247 assert(pinfo); // this should not fail!!248 249 // the only packet type of events for AMDTP is MIDI in mbla250 assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);251 #endif252 AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);253 254 // we decode this directly (no function call) due to the high frequency255 /* idea:256 spec says: current_midi_port=(dbc+j)%8;257 => if we start at (dbc+stream->location-1)%8,258 we'll start at the right event for the midi port.259 => if we increment j with 8, we stay at the right event.260 */261 // FIXME: as we know in advance how big a packet is (syt_interval) we can262 // predict how much loops will be present here263 for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) {264 target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));265 quadlet_t sample_int=ntohl(*target_event);266 // FIXME: this assumes that 2X and 3X speed isn't used,267 // because only the 1X slot is put into the ringbuffer268 if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {269 sample_int=(sample_int >> 16) & 0x000000FF;270 if(!mp->writeEvent(&sample_int)) {271 debugWarning("Packet port events lost\n");272 ok=false;273 }274 }275 }276 277 }278 279 return ok;280 }281 282 221 #if USE_SSE 222 #error broken 283 223 typedef float v4sf __attribute__ ((vector_size (16))); 284 224 typedef int v4si __attribute__ ((vector_size (16))); … … 306 246 switch(p->getDataType()) { 307 247 default: 248 debugError("bad type: %d\n", p->getDataType()); 249 return -1; 308 250 case Port::E_Int24: 309 251 { … … 374 316 } 375 317 318 int 319 AmdtpReceiveStreamProcessor::decodeMidiEventsToPort( 320 AmdtpMidiPort *p, quadlet_t *data, 321 unsigned int offset, unsigned int nevents) 322 { 323 #warning implement 324 } 325 376 326 #else 377 327 … … 386 336 target_event=(quadlet_t *)(data + p->getPosition()); 387 337 388 switch( p->getDataType()) {338 switch(m_StreamProcessorManager.getAudioDataType()) { 389 339 default: 390 case Port::E_Int24: 340 debugError("bad type: %d\n", m_StreamProcessorManager.getAudioDataType()); 341 return -1; 342 case StreamProcessorManager::eADT_Int24: 391 343 { 392 344 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); … … 403 355 } 404 356 break; 405 case Port::E_Float:357 case StreamProcessorManager::eADT_Float: 406 358 { 407 359 const float multiplier = 1.0f / (float)(0x7FFFFF); … … 429 381 return 0; 430 382 } 383 384 int 385 AmdtpReceiveStreamProcessor::decodeMidiEventsToPort( 386 AmdtpMidiPort *p, quadlet_t *data, 387 unsigned int offset, unsigned int nevents) 388 { 389 unsigned int j=0; 390 quadlet_t *target_event; 391 quadlet_t sample_int; 392 unsigned int position = p->getPosition(); 393 unsigned int location = p->getLocation(); 394 395 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 396 397 assert(nevents + offset <= p->getBufferSize()); 398 399 buffer+=offset; 400 401 // clear 402 memset(buffer, 0, nevents * 4); 403 404 // assumes that dbc%8 == 0, which is always true if data points to the 405 // start of a packet in blocking mode 406 // midi events that belong to the same time mpx-ed block should all be 407 // timed at the SYT timestamp of the packet. This basically means that they 408 // all correspond to the first audio frame in the packet. 409 for(j = location; j < nevents; j += 8) { 410 target_event=(quadlet_t *)(data + ((j * m_dimension) + position)); 411 sample_int=ntohl(*target_event); 412 // FIXME: this assumes that 2X and 3X speed isn't used, 413 // because only the 1X slot is put into the ringbuffer 414 if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { 415 sample_int=(sample_int >> 16) & 0x000000FF; 416 sample_int |= 0x01000000; // flag that there is a midi event present 417 *buffer = sample_int; 418 debugOutput(DEBUG_LEVEL_VERBOSE, "Received midi byte %08X on port %p index %d\n", sample_int, p, j-location); 419 } 420 buffer += 8; // skip 8 frames 421 } 422 423 return 0; 424 } 425 431 426 #endif 432 427 } // end of namespace Streaming trunk/libffado/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h
r750 r833 101 101 102 102 private: 103 bool decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc);104 103 int decodeMBLAEventsToPort(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); 104 int decodeMidiEventsToPort(AmdtpMidiPort *p, quadlet_t *data, unsigned int offset, unsigned int nevents); 105 105 106 106 unsigned int getSytInterval(); trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp
r798 r833 37 37 #include <assert.h> 38 38 39 #define AMDTP_FLOAT_MULTIPLIER 2147483392.0 40 39 41 namespace Streaming 40 42 { … … 45 47 , m_dimension( dimension ) 46 48 , m_dbc( 0 ) 49 , m_nb_audio_ports( 0 ) 50 , m_nb_midi_ports( 0 ) 47 51 {} 48 52 … … 53 57 int cycle, unsigned int dropped, unsigned int max_length ) 54 58 { 55 struct iec61883_packet *packet = ( struct iec61883_packet * ) data; 59 __builtin_prefetch(data, 1, 0); // prefetch events for write, no temporal locality 60 struct iec61883_packet *packet = (struct iec61883_packet *)data; 56 61 /* Our node ID can change after a bus reset, so it is best to fetch 57 62 * our node ID for each packet. */ 58 packet->sid = m_ 1394service.getLocalNodeId() & 0x3f;63 packet->sid = m_local_node_id; 59 64 60 65 packet->dbs = m_dimension; … … 249 254 int cycle, unsigned int dropped, unsigned int max_length ) 250 255 { 251 struct iec61883_packet *packet = ( struct iec61883_packet * ) data;252 256 if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) ) 253 257 { 254 // process all ports that should be handled on a per-packet base255 // this is MIDI for AMDTP (due to the need of DBC)256 if ( !encodePacketPorts ( ( quadlet_t * ) ( data+8 ), m_syt_interval, packet->dbc ) )257 {258 debugWarning ( "Problem encoding Packet Ports\n" );259 }260 258 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT DATA (cy %04d): TSP=%011llu (%04u)\n", 261 259 cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) ); … … 278 276 /* Our node ID can change after a bus reset, so it is best to fetch 279 277 * our node ID for each packet. */ 280 packet->sid = m_ 1394service.getLocalNodeId() & 0x3f;278 packet->sid = m_local_node_id; 281 279 282 280 packet->dbs = m_dimension; … … 395 393 m_syt_interval ); 396 394 397 for ( PortVectorIterator it = m_Ports.begin(); 398 it != m_Ports.end(); 399 ++it ) 400 { 401 if ( ( *it )->getPortType() == Port::E_Midi ) 402 { 403 // we use a timing unit of 10ns 404 // this makes sure that for the max syt interval 405 // we don't have rounding, and keeps the numbers low 406 // we have 1 slot every 8 events 407 // we have syt_interval events per packet 408 // => syt_interval/8 slots per packet 409 // packet rate is 8000pkt/sec => interval=125us 410 // so the slot interval is (1/8000)/(syt_interval/8) 411 // or: 1/(1000 * syt_interval) sec 412 // which is 1e9/(1000*syt_interval) nsec 413 // or 100000/syt_interval 'units' 414 // the event interval is fixed to 320us = 32000 'units' 415 if ( ! ( *it )->useRateControl ( true, ( 100000/m_syt_interval ),32000, false ) ) 416 { 417 debugFatal ( "Could not set signal type to PeriodSignalling" ); 418 return false; 419 } 420 break; 421 } 422 } 395 if (!initPortCache()) { 396 debugError("Could not init port cache\n"); 397 return false; 398 } 399 423 400 return true; 424 401 } … … 430 407 unsigned int nevents, unsigned int offset ) 431 408 { 432 bool no_problem = true; 433 434 for ( PortVectorIterator it = m_PeriodPorts.begin(); 435 it != m_PeriodPorts.end(); 436 ++it ) 409 updatePortCache(); 410 switch(m_StreamProcessorManager.getAudioDataType()) { 411 case StreamProcessorManager::eADT_Int24: 412 encodeAudioPortsInt24((quadlet_t *)data, offset, nevents); 413 break; 414 case StreamProcessorManager::eADT_Float: 415 encodeAudioPortsFloat((quadlet_t *)data, offset, nevents); 416 break; 417 } 418 encodeMidiPorts((quadlet_t *)data, offset, nevents); 419 return true; 420 } 421 422 bool 423 AmdtpTransmitStreamProcessor::transmitSilenceBlock( 424 char *data, unsigned int nevents, unsigned int offset) 425 { 426 // no need to update the port cache when transmitting silence since 427 // no dynamic values are used to do so. 428 429 encodeAudioPortsSilence((quadlet_t *)data, offset, nevents); 430 encodeMidiPortsSilence((quadlet_t *)data, offset, nevents); 431 return true; 432 } 433 434 /** 435 * @brief encodes all audio ports in the cache to events (silent data) 436 * @param data 437 * @param offset 438 * @param nevents 439 */ 440 void 441 AmdtpTransmitStreamProcessor::encodeAudioPortsSilence(quadlet_t *data, 442 unsigned int offset, 443 unsigned int nevents) 444 { 445 unsigned int j; 446 quadlet_t *target_event; 447 unsigned int i; 448 449 for (i = 0; i < m_nb_audio_ports; i++) { 450 target_event = (quadlet_t *)(data + i); 451 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 452 453 for (j = 0;j < nevents; j += 1) 454 { 455 *target_event = htonl( 0x40000000 ); 456 target_event += m_dimension; 457 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 458 } 459 } 460 } 461 462 /** 463 * @brief encodes all audio ports in the cache to events (float data) 464 * @param data 465 * @param offset 466 * @param nevents 467 */ 468 void 469 AmdtpTransmitStreamProcessor::encodeAudioPortsFloat(quadlet_t *data, 470 unsigned int offset, 471 unsigned int nevents) 472 { 473 unsigned int j; 474 quadlet_t *target_event; 475 unsigned int i; 476 477 for (i = 0; i < m_nb_audio_ports; i++) { 478 struct _MBLA_port_cache &p = m_audio_ports.at(i); 479 target_event = (quadlet_t *)(data + i); 480 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 481 assert(nevents + offset <= p.buffer_size ); 482 483 if(p.buffer && p.enabled) { 484 float *buffer = (float *)(p.buffer); 485 buffer += offset; 486 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 487 488 for (j = 0;j < nevents; j += 1) 489 { 490 // don't care for overflow 491 float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER; 492 unsigned int tmp = ((int) v); 493 *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 494 buffer++; 495 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 496 target_event += m_dimension; 497 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 498 } 499 } else { 500 for (j = 0;j < nevents; j += 1) 501 { 502 *target_event = htonl( 0x40000000 ); 503 target_event += m_dimension; 504 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 505 } 506 } 507 } 508 } 509 510 /** 511 * @brief encodes all audio ports in the cache to events (int24 data) 512 * @param data 513 * @param offset 514 * @param nevents 515 */ 516 void 517 AmdtpTransmitStreamProcessor::encodeAudioPortsInt24(quadlet_t *data, 518 unsigned int offset, 519 unsigned int nevents) 520 { 521 unsigned int j; 522 quadlet_t *target_event; 523 unsigned int i; 524 525 for (i = 0; i < m_nb_audio_ports; i++) { 526 struct _MBLA_port_cache &p = m_audio_ports.at(i); 527 target_event = (quadlet_t *)(data + i); 528 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 529 assert(nevents + offset <= p.buffer_size ); 530 531 if(p.buffer && p.enabled) { 532 uint32_t *buffer = (uint32_t *)(p.buffer); 533 buffer += offset; 534 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 535 536 for (j = 0; j < nevents; j += 1) 537 { 538 *target_event = htonl(((*buffer) & 0x00FFFFFF) | 0x40000000); 539 buffer++; 540 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 541 542 target_event += m_dimension; 543 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 544 } 545 } else { 546 for (j = 0;j < nevents; j += 1) 547 { 548 *target_event = htonl( 0x40000000 ); 549 target_event += m_dimension; 550 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 551 } 552 } 553 } 554 } 555 556 /** 557 * @brief encodes all midi ports in the cache to events (silence) 558 * @param data 559 * @param offset 560 * @param nevents 561 */ 562 void 563 AmdtpTransmitStreamProcessor::encodeMidiPortsSilence(quadlet_t *data, 564 unsigned int offset, 565 unsigned int nevents) 566 { 567 quadlet_t *target_event; 568 unsigned int i,j; 569 570 for (i = 0; i < m_nb_midi_ports; i++) { 571 struct _MIDI_port_cache &p = m_midi_ports.at(i); 572 573 for (j = p.location;j < nevents; j += 8) { 574 target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position)); 575 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 576 *target_event = htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA)); 577 } 578 } 579 } 580 581 /** 582 * @brief encodes all midi ports in the cache to events 583 * @param data 584 * @param offset 585 * @param nevents 586 */ 587 void 588 AmdtpTransmitStreamProcessor::encodeMidiPorts(quadlet_t *data, 589 unsigned int offset, 590 unsigned int nevents) 591 { 592 quadlet_t *target_event; 593 unsigned int i,j; 594 595 for (i = 0; i < m_nb_midi_ports; i++) { 596 struct _MIDI_port_cache &p = m_midi_ports.at(i); 597 if (p.buffer && p.enabled) { 598 uint32_t *buffer = (quadlet_t *)(p.buffer); 599 buffer += offset; 600 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 601 602 for (j = p.location;j < nevents; j += 8) { 603 target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position)); 604 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 605 606 if ( *buffer & 0xFF000000 ) // we can send a byte 607 { 608 quadlet_t tmpval; 609 tmpval = ((*buffer)<<16) & 0x00FF0000; 610 tmpval = IEC61883_AM824_SET_LABEL(tmpval, IEC61883_AM824_LABEL_MIDI_1X); 611 *target_event = htonl(tmpval); 612 613 // debugOutput ( DEBUG_LEVEL_VERBOSE, "MIDI port %s, pos=%u, loc=%u, nevents=%u, dim=%d\n", 614 // p.port->getName().c_str(), p.position, p.location, nevents, m_dimension ); 615 // debugOutput ( DEBUG_LEVEL_VERBOSE, "base=%p, target=%p, value=%08X\n", 616 // data, target_event, tmpval ); 617 } else { 618 // can't send a byte, either because there is no byte, 619 // or because this would exceed the maximum rate 620 // FIXME: this can be ifdef optimized since it's a constant 621 *target_event = htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA)); 622 } 623 buffer+=8; 624 } 625 } else { 626 for (j = p.location;j < nevents; j += 8) { 627 target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position)); 628 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 629 *target_event = htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA)); 630 } 631 } 632 } 633 } 634 635 bool 636 AmdtpTransmitStreamProcessor::initPortCache() { 637 // make use of the fact that audio ports are the first ports in 638 // the cluster as per AMDTP. so we can sort the ports by position 639 // and have very efficient lookups: 640 // m_float_ports.at(i).buffer -> audio stream i buffer 641 // for midi ports we simply cache all port info since they are (usually) not 642 // that numerous 643 m_nb_audio_ports = 0; 644 m_audio_ports.clear(); 645 646 m_nb_midi_ports = 0; 647 m_midi_ports.clear(); 648 649 for(PortVectorIterator it = m_Ports.begin(); 650 it != m_Ports.end(); 651 ++it ) 437 652 { 438 if ( (*it)->isDisabled() ) { continue; }; 439 440 //FIXME: make this into a static_cast when not DEBUG? 441 AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); 442 assert ( pinfo ); // this should not fail!! 653 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 654 assert(pinfo); // this should not fail!! 443 655 444 656 switch( pinfo->getFormat() ) 445 657 { 446 658 case AmdtpPortInfo::E_MBLA: 447 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 448 { 449 debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); 450 no_problem = false; 451 } 659 m_nb_audio_ports++; 452 660 break; 453 661 case AmdtpPortInfo::E_SPDIF: // still unimplemented 454 662 break; 455 default: // ignore 456 break; 457 } 458 } 459 return no_problem; 460 } 461 462 bool 463 AmdtpTransmitStreamProcessor::transmitSilenceBlock( 464 char *data, unsigned int nevents, unsigned int offset) 465 { 466 bool no_problem = true; 467 for(PortVectorIterator it = m_PeriodPorts.begin(); 468 it != m_PeriodPorts.end(); 469 ++it ) 470 { 471 //FIXME: make this into a static_cast when not DEBUG? 472 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 473 assert(pinfo); // this should not fail!! 474 475 switch( pinfo->getFormat() ) 476 { 477 case AmdtpPortInfo::E_MBLA: 478 if ( encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 479 { 480 debugWarning("Could not encode port %s to MBLA events", (*it)->getName().c_str()); 481 no_problem = false; 482 } 483 break; 484 case AmdtpPortInfo::E_SPDIF: // still unimplemented 663 case AmdtpPortInfo::E_Midi: 664 m_nb_midi_ports++; 485 665 break; 486 666 default: // ignore … … 488 668 } 489 669 } 490 return no_problem; 491 } 492 493 /** 494 * @brief decode a packet for the packet-based ports 495 * 496 * @param data Packet data 497 * @param nevents number of events in data (including events of other ports & port types) 498 * @param dbc DataBlockCount value for this packet 499 * @return true if all successfull 500 */ 501 bool AmdtpTransmitStreamProcessor::encodePacketPorts ( quadlet_t *data, unsigned int nevents, unsigned int dbc ) 502 { 503 bool ok=true; 504 quadlet_t byte; 505 506 quadlet_t *target_event=NULL; 507 unsigned int j; 508 509 for ( PortVectorIterator it = m_PacketPorts.begin(); 510 it != m_PacketPorts.end(); 670 671 unsigned int idx; 672 for (idx = 0; idx < m_nb_audio_ports; idx++) { 673 for(PortVectorIterator it = m_Ports.begin(); 674 it != m_Ports.end(); 511 675 ++it ) 676 { 677 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 678 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "idx %u: looking at port %s at position %u\n", 679 idx, (*it)->getName().c_str(), pinfo->getPosition()); 680 if(pinfo->getPosition() == idx) { 681 struct _MBLA_port_cache p; 682 p.port = dynamic_cast<AmdtpAudioPort *>(*it); 683 if(p.port == NULL) { 684 debugError("Port is not an AmdtpAudioPort!\n"); 685 return false; 686 } 687 p.buffer = NULL; // to be filled by updatePortCache 688 #ifdef DEBUG 689 p.buffer_size = (*it)->getBufferSize(); 690 #endif 691 692 m_audio_ports.push_back(p); 693 debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n", 694 p.port->getName().c_str(), idx); 695 goto next_index; 696 } 697 } 698 debugError("No MBLA port found for position %d\n", idx); 699 return false; 700 next_index: 701 continue; 702 } 703 704 for(PortVectorIterator it = m_Ports.begin(); 705 it != m_Ports.end(); 706 ++it ) 512 707 { 513 514 #ifdef DEBUG 515 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *> ( *it ); 516 assert ( pinfo ); // this should not fail!! 517 518 // the only packet type of events for AMDTP is MIDI in mbla 519 assert ( pinfo->getFormat() ==AmdtpPortInfo::E_Midi ); 520 #endif 521 522 AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *> ( *it ); 523 524 // we encode this directly (no function call) due to the high frequency 525 /* idea: 526 spec says: current_midi_port=(dbc+j)%8; 527 => if we start at (dbc+stream->location-1)%8, 528 we'll start at the right event for the midi port. 529 => if we increment j with 8, we stay at the right event. 530 */ 531 // FIXME: as we know in advance how big a packet is (syt_interval) we can 532 // predict how much loops will be present here 533 // first prefill the buffer with NO_DATA's on all time muxed channels 534 535 for ( j = ( dbc & 0x07 ) +mp->getLocation(); j < nevents; j += 8 ) 536 { 537 538 quadlet_t tmpval; 539 540 target_event= ( quadlet_t * ) ( data + ( ( j * m_dimension ) + mp->getPosition() ) ); 541 542 if ( mp->canRead() ) // we can send a byte 543 { 544 mp->readEvent ( &byte ); 545 byte &= 0xFF; 546 tmpval=htonl ( 547 IEC61883_AM824_SET_LABEL ( ( byte ) <<16, 548 IEC61883_AM824_LABEL_MIDI_1X ) ); 549 550 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n", 551 mp->getName().c_str(), mp->getPosition(), mp->getLocation(), dbc, nevents, m_dimension ); 552 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", 553 data, target_event, tmpval ); 554 555 } 556 else 557 { 558 // can't send a byte, either because there is no byte, 559 // or because this would exceed the maximum rate 560 tmpval=htonl ( 561 IEC61883_AM824_SET_LABEL ( 0,IEC61883_AM824_LABEL_MIDI_NO_DATA ) ); 562 } 563 564 *target_event=tmpval; 565 } 566 567 } 568 return ok; 569 } 570 571 #if USE_SSE 572 typedef float v4sf __attribute__ ((vector_size (16))); 573 typedef int v4si __attribute__ ((vector_size (16))); 574 typedef int v2si __attribute__ ((vector_size (8))); 575 576 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 577 unsigned int offset, unsigned int nevents ) 578 { 579 static const float sse_multiplier[4] __attribute__((aligned(16))) = { 580 (float)(0x7FFFFF00), 581 (float)(0x7FFFFF00), 582 (float)(0x7FFFFF00), 583 (float)(0x7FFFFF00) 584 }; 585 586 static const int sse_mask[4] __attribute__((aligned(16))) = { 587 0x40000000, 0x40000000, 0x40000000, 0x40000000 588 }; 589 590 unsigned int out[4]; 591 592 unsigned int j=0; 593 unsigned int read=0; 594 595 quadlet_t *target_event; 596 597 target_event= ( quadlet_t * ) ( data + p->getPosition() ); 598 599 switch ( p->getDataType() ) 600 { 601 default: 602 case Port::E_Int24: 603 { 604 quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() ); 605 606 assert ( nevents + offset <= p->getBufferSize() ); 607 608 buffer+=offset; 609 610 for ( j = 0; j < nevents; j += 1 ) // decode max nsamples 611 { 612 *target_event = htonl ( ( * ( buffer ) & 0x00FFFFFF ) | 0x40000000 ); 613 buffer++; 614 target_event += m_dimension; 615 } 616 } 617 break; 618 case Port::E_Float: 619 { 620 const float multiplier = ( float ) ( 0x7FFFFF00 ); 621 float *buffer= ( float * ) ( p->getBufferAddress() ); 622 623 assert ( nevents + offset <= p->getBufferSize() ); 624 625 buffer+=offset; 626 627 j=0; 628 if(read>3) { 629 for (j = 0; j < read-3; j += 4) { 630 asm("movups %[floatbuff], %%xmm0\n\t" 631 "mulps %[ssemult], %%xmm0\n\t" 632 "cvttps2pi %%xmm0, %[out1]\n\t" 633 "movhlps %%xmm0, %%xmm0\n\t" 634 "psrld $8, %[out1]\n\t" 635 "cvttps2pi %%xmm0, %[out2]\n\t" 636 "por %[mmxmask], %[out1]\n\t" 637 "psrld $8, %[out2]\n\t" 638 "por %[mmxmask], %[out2]\n\t" 639 : [out1] "=&y" (*(v2si*)&out[0]), 640 [out2] "=&y" (*(v2si*)&out[2]) 641 : [floatbuff] "m" (*(v4sf*)buffer), 642 [ssemult] "x" (*(v4sf*)sse_multiplier), 643 [mmxmask] "y" (*(v2si*)sse_mask) 644 : "xmm0"); 645 buffer += 4; 646 *target_event = htonl(out[0]); 647 target_event += m_dimension; 648 *target_event = htonl(out[1]); 649 target_event += m_dimension; 650 *target_event = htonl(out[2]); 651 target_event += m_dimension; 652 *target_event = htonl(out[3]); 653 target_event += m_dimension; 654 } 655 } 656 for(; j < read; ++j) { 657 // don't care for overflow 658 float v = *buffer * multiplier; // v: -231 .. 231 659 unsigned int tmp = (int)v; 660 *target_event = htonl((tmp >> 8) | 0x40000000); 661 662 buffer++; 663 target_event += m_dimension; 664 } 665 666 asm volatile("emms"); 667 break; 668 } 669 break; 670 } 671 672 return 0; 673 } 674 675 #else 676 677 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 678 unsigned int offset, unsigned int nevents ) 679 { 680 unsigned int j=0; 681 682 quadlet_t *target_event; 683 684 target_event= ( quadlet_t * ) ( data + p->getPosition() ); 685 686 switch ( p->getDataType() ) 687 { 688 default: 689 case Port::E_Int24: 690 { 691 quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() ); 692 693 assert ( nevents + offset <= p->getBufferSize() ); 694 695 buffer+=offset; 696 697 for ( j = 0; j < nevents; j += 1 ) // decode max nsamples 698 { 699 *target_event = htonl ( ( * ( buffer ) & 0x00FFFFFF ) | 0x40000000 ); 700 buffer++; 701 target_event += m_dimension; 702 } 703 } 704 break; 705 case Port::E_Float: 706 { 707 const float multiplier = ( float ) ( 0x7FFFFF00 ); 708 float *buffer= ( float * ) ( p->getBufferAddress() ); 709 710 assert ( nevents + offset <= p->getBufferSize() ); 711 712 buffer+=offset; 713 714 for ( j = 0; j < nevents; j += 1 ) // decode max nsamples 715 { 716 717 // don't care for overflow 718 float v = *buffer * multiplier; // v: -231 .. 231 719 unsigned int tmp = ( ( int ) v ); 720 *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 721 722 buffer++; 723 target_event += m_dimension; 724 } 725 } 726 break; 727 } 728 729 return 0; 730 } 731 #endif 732 733 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 734 unsigned int offset, unsigned int nevents ) 735 { 736 unsigned int j=0; 737 738 quadlet_t *target_event; 739 740 target_event= ( quadlet_t * ) ( data + p->getPosition() ); 741 742 switch ( p->getDataType() ) 743 { 744 default: 745 case Port::E_Int24: 746 case Port::E_Float: 747 { 748 for ( j = 0; j < nevents; j += 1 ) // decode max nsamples 749 { 750 *target_event = htonl ( 0x40000000 ); 751 target_event += m_dimension; 752 } 753 } 754 break; 755 } 756 757 return 0; 708 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 709 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "idx %u: looking at port %s at position %u, location %u\n", 710 idx, (*it)->getName().c_str(), pinfo->getPosition(), pinfo->getLocation()); 711 if ((*it)->getPortType() == Port::E_Midi) { 712 struct _MIDI_port_cache p; 713 p.port = dynamic_cast<AmdtpMidiPort *>(*it); 714 if(p.port == NULL) { 715 debugError("Port is not an AmdtpMidiPort!\n"); 716 return false; 717 } 718 p.position = pinfo->getPosition(); 719 p.location = pinfo->getLocation(); 720 p.buffer = NULL; // to be filled by updatePortCache 721 #ifdef DEBUG 722 p.buffer_size = (*it)->getBufferSize(); 723 #endif 724 725 m_midi_ports.push_back(p); 726 debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u, location %u\n", 727 p.port->getName().c_str(), p.position, p.location); 728 } 729 } 730 731 return true; 732 } 733 734 void 735 AmdtpTransmitStreamProcessor::updatePortCache() { 736 unsigned int idx; 737 for (idx = 0; idx < m_nb_audio_ports; idx++) { 738 struct _MBLA_port_cache& p = m_audio_ports.at(idx); 739 AmdtpAudioPort *port = p.port; 740 p.buffer = port->getBufferAddress(); 741 p.enabled = !port->isDisabled(); 742 } 743 for (idx = 0; idx < m_nb_midi_ports; idx++) { 744 struct _MIDI_port_cache& p = m_midi_ports.at(idx); 745 AmdtpMidiPort *port = p.port; 746 p.buffer = port->getBufferAddress(); 747 p.enabled = !port->isDisabled(); 748 } 758 749 } 759 750 trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h
r750 r833 115 115 unsigned int offset); 116 116 117 bool encodePacketPorts(quadlet_t *data, unsigned int nevents, 118 unsigned int dbc); 119 120 int encodePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 121 unsigned int offset, unsigned int nevents); 122 int encodeSilencePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 123 unsigned int offset, unsigned int nevents); 117 void encodeAudioPortsSilence(quadlet_t *data, unsigned int offset, unsigned int nevents); 118 void encodeAudioPortsFloat(quadlet_t *data, unsigned int offset, unsigned int nevents); 119 void encodeAudioPortsInt24(quadlet_t *data, unsigned int offset, unsigned int nevents); 120 void encodeMidiPortsSilence(quadlet_t *data, unsigned int offset, unsigned int nevents); 121 void encodeMidiPorts(quadlet_t *data, unsigned int offset, unsigned int nevents); 124 122 125 123 unsigned int getFDF(); … … 131 129 int m_fdf; 132 130 unsigned int m_dbc; 131 132 private: // local port caching for performance 133 struct _MBLA_port_cache { 134 AmdtpAudioPort* port; 135 void* buffer; 136 bool enabled; 137 #ifdef DEBUG 138 unsigned int buffer_size; 139 #endif 140 }; 141 std::vector<struct _MBLA_port_cache> m_audio_ports; 142 unsigned int m_nb_audio_ports; 143 144 struct _MIDI_port_cache { 145 AmdtpMidiPort* port; 146 void* buffer; 147 bool enabled; 148 unsigned int position; 149 unsigned int location; 150 #ifdef DEBUG 151 unsigned int buffer_size; 152 #endif 153 }; 154 std::vector<struct _MIDI_port_cache> m_midi_ports; 155 unsigned int m_nb_midi_ports; 156 157 bool initPortCache(); 158 void updatePortCache(); 133 159 }; 134 160 trunk/libffado/src/libstreaming/generic/Port.cpp
r750 r833 23 23 24 24 #include "Port.h" 25 #include "PortManager.h" 25 26 26 27 #include <stdlib.h> … … 31 32 IMPL_DEBUG_MODULE( Port, Port, DEBUG_LEVEL_NORMAL ); 32 33 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) 34 Port::Port(PortManager& m, std::string name, 35 enum E_PortType porttype, enum E_Direction direction) 36 : m_Name( name ) 37 , m_disabled( true ) 38 , m_buffersize( 0 ) 39 , m_PortType( porttype ) 40 , m_Direction( direction ) 41 , m_buffer( NULL ) 42 , m_manager( m ) 43 , m_State( E_Created ) 53 44 { 45 m_manager.registerPort(this); 46 } 54 47 48 Port::~Port() { 49 debugOutput( DEBUG_LEVEL_VERBOSE, "deleting port %s\n", getName().c_str()); 50 m_manager.unregisterPort(this); 55 51 } 56 52 … … 69 65 } 70 66 71 if (m_buffersize ==0) {67 if (m_buffersize == 0) { 72 68 debugFatal("Cannot initialize a port with buffersize=0\n"); 73 69 return false; 74 70 } 75 71 76 switch (m_BufferType) {77 case E_PointerBuffer:78 if (m_use_external_buffer) {79 // don't do anything80 } else if (!allocateInternalBuffer()) {81 debugFatal("Could not allocate internal buffer!\n");82 return false;83 }84 break;85 86 case E_RingBuffer:87 if (m_use_external_buffer) {88 debugFatal("Cannot use an external ringbuffer! \n");89 return false;90 } else if (!allocateInternalRingBuffer()) {91 debugFatal("Could not allocate internal ringbuffer!\n");92 return false;93 }94 break;95 default:96 debugFatal("Unsupported buffer type! (%d)\n",(int)m_BufferType);97 return false;98 break;99 }100 101 m_eventsize=getEventSize(); // this won't change, so cache it102 103 72 m_State = E_Initialized; 104 73 return true; … … 106 75 107 76 bool Port::reset() { 108 if (m_BufferType==E_RingBuffer) {109 ffado_ringbuffer_reset(m_ringbuffer);110 }111 77 return true; 112 } ;78 } 113 79 114 80 bool Port::setName(std::string name) { … … 134 100 135 101 unsigned int Port::getEventSize() { 136 switch (m_DataType) { 137 case E_Float: 138 return sizeof(float); 139 case E_Int24: // 24 bit 2's complement, packed in a 32bit integer (LSB's) 140 return sizeof(uint32_t); 141 case E_MidiEvent: 142 return sizeof(uint32_t); 143 default: 144 return 0; 145 } 146 } 147 148 bool Port::setDataType(enum E_DataType d) { 149 debugOutput( DEBUG_LEVEL_VERBOSE, "Setting datatype to %d for port %s\n",(int) d,m_Name.c_str()); 150 if (m_State != E_Created) { 151 debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State); 152 return false; 153 } 154 155 // do some sanity checks 156 bool type_is_ok=false; 157 switch (m_PortType) { 158 case E_Audio: 159 if(d == E_Int24) type_is_ok=true; 160 if(d == E_Float) type_is_ok=true; 161 break; 162 case E_Midi: 163 if(d == E_MidiEvent) type_is_ok=true; 164 break; 165 case E_Control: 166 if(d == E_Default) type_is_ok=true; 167 break; 168 default: 169 break; 170 } 171 172 if(!type_is_ok) { 173 debugFatal("Datatype not supported by this type of port!\n"); 174 return false; 175 } 176 177 m_DataType=d; 178 return true; 179 } 180 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; 102 return 4; // whether it's float, int24, midi or control, it's 4 253 103 } 254 104 255 105 // buffer handling api's for pointer buffers 256 106 /** 257 * Get the buffer address (being the external or the internal one).107 * Get the buffer address 258 108 * 259 109 * @param buff 260 110 */ 261 111 void *Port::getBufferAddress() { 262 assert(m_BufferType==E_PointerBuffer);263 112 return m_buffer; 264 113 }; … … 266 115 /** 267 116 * Set the external buffer address. 268 * only call this when you have specified that you will use269 * an external buffer before doing the init()270 117 * 271 118 * @param buff 272 119 */ 273 void Port::setExternalBufferAddress(void *buff) { 274 assert(m_BufferType==E_PointerBuffer); 275 assert(m_use_external_buffer); // don't call this with an internal buffer! 120 void Port::setBufferAddress(void *buff) { 276 121 m_buffer=buff; 277 };278 279 // buffer handling api's for ringbuffers280 bool Port::writeEvent(void *event) {281 282 #ifdef DEBUG283 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 #endif295 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 DEBUG304 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 #endif316 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 DEBUG329 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 #endif341 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 DEBUG348 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 #endif358 359 return written;360 361 }362 363 int Port::readEvents(void *event, unsigned int nevents) {364 365 #ifdef DEBUG366 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 #endif377 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 DEBUG384 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 #endif394 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 counter416 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 ratecontrol435 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 rate468 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;477 122 } 478 123 … … 482 127 debugOutput(DEBUG_LEVEL_VERBOSE, "Enabling port %s...\n",m_Name.c_str()); 483 128 m_disabled=false; 484 } ;129 } 485 130 486 131 /// Disable the port. (this can be called anytime) … … 489 134 debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling port %s...\n",m_Name.c_str()); 490 135 m_disabled=false; 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 }558 136 } 559 137 560 138 void Port::show() { 561 139 debugOutput(DEBUG_LEVEL_VERBOSE,"Name : %s\n", m_Name.c_str()); 562 debugOutput(DEBUG_LEVEL_VERBOSE,"Signal Type : %d\n", m_SignalType);563 debugOutput(DEBUG_LEVEL_VERBOSE,"Buffer Type : %d\n", m_BufferType);564 140 debugOutput(DEBUG_LEVEL_VERBOSE,"Enabled? : %d\n", m_disabled); 565 141 debugOutput(DEBUG_LEVEL_VERBOSE,"State? : %d\n", m_State); 566 142 debugOutput(DEBUG_LEVEL_VERBOSE,"Buffer Size : %d\n", m_buffersize); 567 debugOutput(DEBUG_LEVEL_VERBOSE,"Event Size : %d\n", m_eventsize); 568 debugOutput(DEBUG_LEVEL_VERBOSE,"Data Type : %d\n", m_DataType); 143 debugOutput(DEBUG_LEVEL_VERBOSE,"Event Size : %d\n", getEventSize()); 569 144 debugOutput(DEBUG_LEVEL_VERBOSE,"Port Type : %d\n", m_PortType); 570 145 debugOutput(DEBUG_LEVEL_VERBOSE,"Direction : %d\n", m_Direction); 571 debugOutput(DEBUG_LEVEL_VERBOSE,"Rate Control? : %d\n", m_do_ratecontrol);572 146 } 573 147 trunk/libffado/src/libstreaming/generic/Port.h
r742 r833 33 33 34 34 namespace Streaming { 35 class PortManager; 35 36 36 37 /*! … … 53 54 OK. 54 55 55 \todo rework the implementation into something more beautifull56 56 */ 57 57 class Port { 58 58 59 59 public: 60 friend class PortManager;61 62 /*63 * IMPORTANT: if you add something to any of these enum's, be sure to64 * check the code where they are used.65 */66 67 /*!68 \brief Specifies the buffer type for ports69 70 A PointerBuffer uses the getBufferAddress() and setBufferAddres() interface71 A Ringbuffer uses the read/write interface72 */73 enum E_BufferType {74 E_PointerBuffer,75 E_RingBuffer76 };77 78 /*!79 \brief Specifies the signalling type for ports80 */81 enum E_SignalType {82 E_PacketSignalled, ///< the port is to be processed for every packet83 E_PeriodSignalled, ///< the port is to be processed after a period of frames84 // E_SampleSignalled ///< the port is to be processed after each frame (sample)85 };86 87 /*!88 \brief The datatype of the port buffer89 */90 enum E_DataType {91 E_Float,92 E_Int24,93 E_MidiEvent,94 E_Default,95 };96 97 60 /*! 98 61 \brief The port type … … 112 75 }; 113 76 114 Port(std::string name, enum E_PortType porttype, enum E_Direction direction); 115 116 virtual ~Port() 117 {}; 77 Port(PortManager&, std::string name, enum E_PortType, enum E_Direction); 78 79 virtual ~Port(); 118 80 119 81 … … 142 104 unsigned int getEventSize(); 143 105 144 /**145 * \brief sets the event type for the port buffer146 *147 * \note use before calling init()148 */149 virtual bool setDataType(enum E_DataType);150 151 enum E_DataType getDataType() {return m_DataType;};152 153 /**154 * \brief sets the event type for the port buffer155 *156 * \note use before calling init()157 */158 virtual bool setSignalType(enum E_SignalType );159 160 enum E_SignalType getSignalType() {return m_SignalType;}; ///< returns the signalling type of the port161 162 /**163 * \brief sets the buffer type for the port164 *165 * \note use before calling init()166 */167 virtual bool setBufferType(enum E_BufferType );168 169 enum E_BufferType getBufferType() {return m_BufferType;}; ///< returns the buffer type of the port170 171 106 enum E_PortType getPortType() {return m_PortType;}; ///< returns the port type (is fixed) 172 107 enum E_Direction getDirection() {return m_Direction;}; ///< returns the direction (is fixed) … … 193 128 virtual bool setBufferSize(unsigned int); 194 129 195 /** 196 * \brief use an external buffer (or not) 197 * 198 * \note use before calling init() 199 */ 200 virtual bool useExternalBuffer(bool b); 201 202 void setExternalBufferAddress(void *buff); 203 204 205 /** 206 * \brief enable/disable ratecontrol 207 * 208 * Rate control is nescessary for some types of ports (most notably 209 * midi). The StreamProcessor that handles the port should call canRead() 210 * everytime a 'slot' that could be filled with an event passes. The canRead 211 * function will return true if 212 * (1) there is an event ready in the buffer 213 * (2) we are allowed to send an event in this slot 214 * 215 * Setting the rate works is done with the slot_interval and the event_interval 216 * parameters. On every call to canRead(), a counter is decremented with 217 * slot_interval. If the counter drops below 0, canRead() returns true and resets 218 * the counter to event_interval. 219 * 220 * e.g. for AMDTP midi, we are only allowed to send a midi byte every 320us 221 * if the SYT interval is 8, there is exactly one midi slot every packet. 222 * therefore the slot_interval is 1/8000s (=125us), and the event_interval 223 * is 320us. 224 * 225 * Note that the interval parameters are unitless, so you can adapt them 226 * to your needs. In the AMDTP case for example, when the SYT interval is 32 227 * (when the samplerate is 192kHz for example) there are 4 midi slots in 228 * each packet, making the slot time interval 125us/4 = 31.25us. 229 * The event time interval stays the same (320us). We can however set the 230 * slot_interval to 3125 and the event_interval to 32000, as we can choose 231 * the unit of the counter time step (chosen to be 10ns in this case). 232 * 233 * The average argument deserves some attention too. If average is true, we use 234 * average rate control. This means that on average there will be a delay of 235 * event_interval between two events, but that sometimes there can be a smaller 236 * delay. This mode fixes the average rate of the stream. 237 * If average is false, there will always be a minimal delay of event_interval 238 * between two events. This means that the maximum rate of the stream is fixed, 239 * and that the average rate will be lower than (or at max equal to) the rate in 240 * average mode. 241 * 242 * 243 * \note only works for the E_RingBuffer ports 244 * \note use before calling init() 245 * 246 * @param use set this to true to use rate control 247 * @param slot_interval the interval between slots 248 * @param event_interval the interval between events 249 * @param average use average rate control 250 * @return true if rate control was enabled/disabled successfully 251 */ 252 virtual bool useRateControl(bool use, unsigned int slot_interval, 253 unsigned int event_interval, bool average); 254 255 bool usingRateControl() { return m_do_ratecontrol;}; ///< are we using rate control? 256 257 /** 258 * Can we send an event in this slot. subject to rate control and 259 * byte availability. 260 * @return true if we can send an event on this slot 261 */ 262 bool canRead(); 263 264 // FIXME: this is not really OO, but for performance??? 130 void setBufferAddress(void *buff); 265 131 void *getBufferAddress(); 266 132 267 // TODO: extend this with a blocking interface 268 bool writeEvent(void *event); ///< write one event 269 bool readEvent(void *event); ///< read one event 270 int writeEvents(void *event, unsigned int nevents); ///< write multiple events 271 int readEvents(void *event, unsigned int nevents); ///< read multiple events 133 PortManager& getManager() { return m_manager; }; 272 134 273 135 virtual void setVerboseLevel(int l); 274 136 virtual void show(); 275 137 276 138 protected: 277 139 std::string m_Name; ///< Port name, [at construction] 278 279 enum E_SignalType m_SignalType; ///< Signalling type, [at construction]280 enum E_BufferType m_BufferType; ///< Buffer type, [at construction]281 282 140 bool m_disabled; ///< is the port disabled?, [anytime] 283 141 284 142 unsigned int m_buffersize; 285 unsigned int m_eventsize; 286 287 enum E_DataType m_DataType; 143 288 144 enum E_PortType m_PortType; 289 145 enum E_Direction m_Direction; 290 146 291 147 void *m_buffer; 292 ffado_ringbuffer_t *m_ringbuffer; 293 bool m_use_external_buffer; 294 295 bool m_do_ratecontrol; 296 int m_event_interval; 297 int m_slot_interval; 298 int m_rate_counter; 299 int m_rate_counter_minimum; 300 bool m_average_ratecontrol; 301 302 bool allocateInternalBuffer(); 303 void freeInternalBuffer(); 304 305 bool allocateInternalRingBuffer(); 306 void freeInternalRingBuffer(); 148 149 PortManager& m_manager; 307 150 308 151 DECLARE_DEBUG_MODULE; 309 310 311 312 313 314 315 316 317 318 319 320 152 153 // the state machine 154 protected: 155 enum EStates { 156 E_Created, 157 E_Initialized, 158 E_Prepared, 159 E_Running, 160 E_Error 161 }; 162 163 enum EStates m_State; 321 164 }; 322 165 … … 330 173 public: 331 174 332 AudioPort( std::string name, enum E_Direction direction)333 : Port( name, E_Audio, direction)175 AudioPort(PortManager& m, std::string name, enum E_Direction direction) 176 : Port(m, name, E_Audio, direction) 334 177 {}; 335 178 336 179 virtual ~AudioPort() {}; 337 338 protected:339 340 341 180 }; 342 181 … … 350 189 public: 351 190 352 MidiPort( std::string name, enum E_Direction direction)353 : Port( name, E_Midi, direction)191 MidiPort(PortManager& m, std::string name, enum E_Direction direction) 192 : Port(m, name, E_Midi, direction) 354 193 {}; 355 194 virtual ~MidiPort() {}; 356 357 358 protected:359 360 361 195 }; 362 196 … … 370 204 public: 371 205 372 ControlPort( std::string name, enum E_Direction direction)373 : Port( name, E_Control, direction)206 ControlPort(PortManager& m, std::string name, enum E_Direction direction) 207 : Port(m, name, E_Control, direction) 374 208 {}; 375 209 virtual ~ControlPort() {}; 376 377 378 protected:379 380 381 210 }; 382 211 trunk/libffado/src/libstreaming/generic/PortManager.cpp
r750 r833 36 36 37 37 PortManager::PortManager() { 38 39 38 } 40 39 41 40 PortManager::~PortManager() { 42 // deleteAllPorts(); 43 } 44 45 // bool PortManager::setPortBuffersize(unsigned int newsize) { 46 // debugOutput( DEBUG_LEVEL_VERBOSE, "setting port buffer size to %d\n",newsize); 47 // 48 // 49 // for ( PortVectorIterator it = m_Ports.begin(); 50 // it != m_Ports.end(); 51 // ++it ) 52 // { 53 // if(!(*it)->setBufferSize(newsize)) { 54 // debugFatal("Could not set buffer size for port %s\n",(*it)->getName().c_str()); 55 // return false; 56 // } 57 // } 58 // 59 // return true; //not found 60 // 61 // } 41 flushDebugOutput(); 42 // delete all ports that are still registered to the manager 43 for ( PortVectorIterator it = m_Ports.begin(); 44 it != m_Ports.end(); 45 ++it ) 46 { 47 debugOutput( DEBUG_LEVEL_VERBOSE, "deleting port %s at %p\n", (*it)->getName().c_str(), *it); 48 flushDebugOutput(); 49 delete *it; //FIXME 50 } 51 } 62 52 63 53 bool PortManager::makeNameUnique(Port *port) … … 96 86 * @return 97 87 */ 98 bool PortManager:: addPort(Port *port)88 bool PortManager::registerPort(Port *port) 99 89 { 100 90 assert(port); 101 91 102 debugOutput( DEBUG_LEVEL_VERBOSE, "Adding port %s, type: %d, dir: %d , dtype: %d\n",103 port->getName().c_str(), port->getPortType(), port->getDirection() , port->getDataType());92 debugOutput( DEBUG_LEVEL_VERBOSE, "Adding port %s, type: %d, dir: %d\n", 93 port->getName().c_str(), port->getPortType(), port->getDirection()); 104 94 105 95 port->setVerboseLevel(getDebugLevel()); … … 113 103 } 114 104 115 bool PortManager:: deletePort(Port *port)105 bool PortManager::unregisterPort(Port *port) 116 106 { 117 107 assert(port); 118 debugOutput( DEBUG_LEVEL_VERBOSE, " deleting port %s\n",port->getName().c_str());108 debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering port %s\n",port->getName().c_str()); 119 109 120 110 for ( PortVectorIterator it = m_Ports.begin(); … … 124 114 if(*it == port) { 125 115 m_Ports.erase(it); 126 // delete *it;127 116 return true; 128 117 } … … 132 121 133 122 return false; //not found 134 135 }136 137 void PortManager::deleteAllPorts()138 {139 debugOutput( DEBUG_LEVEL_VERBOSE, "deleting all ports\n");140 141 for ( PortVectorIterator it = m_Ports.begin();142 it != m_Ports.end();143 ++it )144 {145 m_Ports.erase(it);146 // delete *it;147 }148 149 return;150 123 151 124 } … … 213 186 { 214 187 if(!(*it)->init()) { 215 debugFatal("Could not init port %s ",(*it)->getName().c_str());188 debugFatal("Could not init port %s\n", (*it)->getName().c_str()); 216 189 return false; 217 190 } … … 222 195 bool PortManager::preparePorts() { 223 196 debugOutput( DEBUG_LEVEL_VERBOSE, "preparing ports\n"); 224 225 // clear the cache lists226 m_PeriodPorts.clear();227 m_PacketPorts.clear();228 197 229 198 for ( PortVectorIterator it = m_Ports.begin(); … … 236 205 } 237 206 238 // now prepare the cache lists239 switch((*it)->getSignalType()) {240 case Port::E_PacketSignalled:241 m_PacketPorts.push_back(*it);242 break;243 case Port::E_PeriodSignalled:244 m_PeriodPorts.push_back(*it);245 break;246 default:247 debugWarning("%s has unsupported port type\n",248 (*it)->getName().c_str());249 break;250 }251 207 } 252 208 return true; trunk/libffado/src/libstreaming/generic/PortManager.h
r742 r833 33 33 namespace Streaming { 34 34 35 class Port;36 35 typedef std::vector<Port *> PortVector; 37 36 typedef std::vector<Port *>::iterator PortVectorIterator; … … 50 49 51 50 virtual bool makeNameUnique(Port *port); 52 virtual bool addPort(Port *port); 53 virtual bool deletePort(Port *port); 54 virtual void deleteAllPorts(); 51 virtual bool registerPort(Port *port); 52 virtual bool unregisterPort(Port *port); 55 53 56 54 int getPortCount(enum Port::E_PortType); 57 55 int getPortCount(); 58 59 // virtual bool setPortBuffersize(unsigned int newsize);60 56 61 57 Port *getPortAtIdx(unsigned int index); … … 69 65 protected: 70 66 PortVector m_Ports; 71 PortVector m_PacketPorts;72 PortVector m_PeriodPorts;73 // PortVector m_SamplePorts;74 67 75 68 DECLARE_DEBUG_MODULE; 76 77 69 }; 78 70 trunk/libffado/src/libstreaming/generic/StreamProcessor.cpp
r807 r833 66 66 , m_IsoHandlerManager( parent.get1394Service().getIsoHandlerManager() ) // local cache 67 67 , m_StreamProcessorManager( m_Parent.getDeviceManager().getStreamProcessorManager() ) // local cache 68 , m_local_node_id ( 0 ) // local cache 68 69 , m_channel( -1 ) 69 , m_dropped(0) 70 , m_last_timestamp(0) 71 , m_last_timestamp2(0) 70 , m_dropped( 0 ) 71 , m_last_timestamp( 0 ) 72 , m_last_timestamp2( 0 ) 73 , m_correct_last_timestamp( false ) 72 74 , m_scratch_buffer( NULL ) 73 75 , m_scratch_buffer_size_bytes( 0 ) … … 88 90 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister stream processor with the Iso manager\n"); 89 91 } 92 // make the threads leave the wait condition 93 POST_SEMAPHORE; 94 sem_destroy(&m_signal_semaphore); 90 95 91 96 if (m_data_buffer) delete m_data_buffer; 92 97 if (m_scratch_buffer) delete[] m_scratch_buffer; 93 sem_destroy(&m_signal_semaphore);94 98 } 95 99 … … 130 134 // the waitForClient in IsoHandler will take care of the fact that the frames are 131 135 // not present in time 132 unsigned int packets_to_prebuffer = (getPacketsPerPeriod() * (m_StreamProcessorManager.getNbBuffers())) ;136 unsigned int packets_to_prebuffer = (getPacketsPerPeriod() * (m_StreamProcessorManager.getNbBuffers())) + 10; 133 137 debugOutput(DEBUG_LEVEL_VERBOSE, "Nominal prebuffer: %u\n", packets_to_prebuffer); 134 138 return packets_to_prebuffer; … … 286 290 unsigned char channel, unsigned char tag, unsigned char sy, 287 291 unsigned int cycle, unsigned int dropped) { 292 #ifdef DEBUG 288 293 if(m_last_cycle == -1) { 289 294 debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %u)\n", getTypeString(), this, cycle); 290 295 } 296 #endif 291 297 292 298 int dropped_cycles = 0; … … 301 307 this, dropped_cycles, cycle, dropped, cycle, m_last_cycle); 302 308 m_dropped += dropped_cycles; 303 m_in_xrun = true;304 309 m_last_cycle = cycle; 305 POST_SEMAPHORE;306 return RAW1394_ISO_DEFER;307 //flushDebugOutput();308 //assert(0);309 310 } 310 311 } … … 344 345 // the received data can be discarded while waiting for the stream 345 346 // to be disabled 347 // similarly for dropped packets 346 348 return RAW1394_ISO_OK; 347 349 } … … 366 368 // check the packet header 367 369 enum eChildReturnValue result = processPacketHeader(data, length, channel, tag, sy, cycle, dropped_cycles); 370 371 // handle dropped cycles 372 if(dropped_cycles) { 373 // make sure the last_timestamp is corrected 374 m_correct_last_timestamp = true; 375 if (m_state == ePS_Running) { 376 // this is an xrun situation 377 m_in_xrun = true; 378 debugWarning("Should update state to WaitingForStreamDisable due to dropped packet xrun\n"); 379 m_cycle_to_switch_state = cycle + 1; // switch in the next cycle 380 m_next_state = ePS_WaitingForStreamDisable; 381 // execute the requested change 382 if (!updateState()) { // we are allowed to change the state directly 383 debugError("Could not update state!\n"); 384 POST_SEMAPHORE; 385 return RAW1394_ISO_ERROR; 386 } 387 } 388 } 389 368 390 if (result == eCRV_OK) { 369 391 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "RECV: CY=%04u TS=%011llu\n", … … 372 394 m_last_good_cycle = cycle; 373 395 m_last_dropped = dropped_cycles; 396 397 if(m_correct_last_timestamp) { 398 // they represent a discontinuity in the timestamps, and hence are 399 // to be dealt with 400 debugWarning("(%p) Correcting timestamp for dropped cycles, discarding packet...\n", this); 401 m_data_buffer->setBufferTailTimestamp(substractTicks(m_last_timestamp, getNominalFramesPerPacket() * getTicksPerFrame())); 402 m_correct_last_timestamp = false; 403 } 374 404 375 405 // check whether we are waiting for a stream to startup … … 406 436 POST_SEMAPHORE; 407 437 return RAW1394_ISO_ERROR; 408 }409 }410 411 // handle dropped cycles412 if(dropped_cycles) {413 // they represent a discontinuity in the timestamps, and hence are414 // to be dealt with415 debugWarning("(%p) Correcting timestamp for dropped cycles, discarding packet...\n", this);416 m_data_buffer->setBufferTailTimestamp(m_last_timestamp);417 if (m_state == ePS_Running) {418 // this is an xrun situation419 m_in_xrun = true;420 debugWarning("Should update state to WaitingForStreamDisable due to dropped packet xrun\n");421 m_cycle_to_switch_state = cycle + 1; // switch in the next cycle422 m_next_state = ePS_WaitingForStreamDisable;423 // execute the requested change424 if (!updateState()) { // we are allowed to change the state directly425 debugError("Could not update state!\n");426 POST_SEMAPHORE;427 return RAW1394_ISO_ERROR;428 }429 POST_SEMAPHORE;430 return RAW1394_ISO_DEFER;431 438 } 432 439 } … … 466 473 unsigned int signal_period = m_signal_period * (semval + 1) + m_signal_offset; 467 474 if(bufferfill >= signal_period) { 468 debugOutput(DEBUG_LEVEL_VER BOSE, "(%p) buffer fill (%d) > signal period (%d), sem_val=%d\n",475 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p) buffer fill (%d) > signal period (%d), sem_val=%d\n", 469 476 this, m_data_buffer->getBufferFill(), signal_period, semval); 470 477 POST_SEMAPHORE; … … 472 479 // the process thread should have higher prio such that we are blocked until 473 480 // the samples are processed. 481 return RAW1394_ISO_DEFER; 474 482 } 475 483 } … … 508 516 int cycle_diff; 509 517 518 #ifdef DEBUG 510 519 if(m_last_cycle == -1) { 511 520 debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %d)\n", getTypeString(), this, cycle); 512 521 } 522 #endif 513 523 514 524 int dropped_cycles = 0; … … 529 539 debugWarning("dropped packets xrun\n"); 530 540 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to dropped packets xrun\n"); 541 m_cycle_to_switch_state = cycle + 1; 531 542 m_next_state = ePS_WaitingForStreamDisable; 532 543 // execute the requested change … … 543 554 } 544 555 556 #ifdef DEBUG 545 557 // bypass based upon state 546 558 if (m_state == ePS_Invalid) { … … 548 560 return RAW1394_ISO_ERROR; 549 561 } 562 #endif 563 550 564 if (m_state == ePS_Created) { 551 565 *tag = 0; … … 577 591 m_in_xrun = true; 578 592 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n"); 593 m_cycle_to_switch_state = cycle + 1; 579 594 m_next_state = ePS_WaitingForStreamDisable; 580 595 // execute the requested change … … 670 685 m_in_xrun = true; 671 686 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n"); 672 m_cycle_to_switch_state = cycle +1; // switch in the next cycle687 m_cycle_to_switch_state = cycle + 1; // switch in the next cycle 673 688 m_next_state = ePS_WaitingForStreamDisable; 674 689 // execute the requested change … … 689 704 m_in_xrun = true; 690 705 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to header xrun\n"); 706 m_cycle_to_switch_state = cycle + 1; // switch in the next cycle 691 707 m_next_state = ePS_WaitingForStreamDisable; 692 708 // execute the requested change … … 837 853 unsigned int bufferfill = m_data_buffer->getBufferFill(); 838 854 if (bufferfill >= m_signal_period + m_signal_offset) { 839 debugOutput(DEBUG_LEVEL_VER BOSE, "(%p) sufficient frames in buffer (%d / %d), posting semaphore\n",855 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p) sufficient frames in buffer (%d / %d), posting semaphore\n", 840 856 this, bufferfill, m_signal_period + m_signal_offset); 841 857 POST_SEMAPHORE; 842 858 } else { 843 debugOutput(DEBUG_LEVEL_VER BOSE, "(%p) insufficient frames in buffer (%d / %d), not posting semaphore\n",859 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p) insufficient frames in buffer (%d / %d), not posting semaphore\n", 844 860 this, bufferfill, m_signal_period + m_signal_offset); 845 861 } … … 894 910 StreamProcessor::waitForSignal() 895 911 { 912 debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) wait ...\n", this, getTypeString()); 896 913 int result; 897 if(m_state == ePS_Running ) {914 if(m_state == ePS_Running && m_next_state == ePS_Running) { 898 915 result = sem_wait(&m_signal_semaphore); 899 916 #ifdef DEBUG 900 917 int tmp; 901 918 sem_getvalue(&m_signal_semaphore, &tmp); 902 debugOutput(DEBUG_LEVEL_VER BOSE, " sem_wait returns: %d, sem_value: %d\n", result, tmp);919 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " sem_wait returns: %d, sem_value: %d\n", result, tmp); 903 920 #endif 904 921 return result == 0; 905 922 } else { 906 923 // when we're not running, we can always provide frames 924 // when we're in a state transition, keep iterating too 907 925 debugOutput(DEBUG_LEVEL_VERBOSE, "Not running...\n"); 908 926 return true; … … 925 943 StreamProcessor::canProcessPackets() 926 944 { 927 if(m_state != ePS_Running ) return true;945 if(m_state != ePS_Running || m_next_state != ePS_Running) return true; 928 946 bool result; 929 int bufferfill;947 unsigned int bufferfill; 930 948 if(getType() == ePT_Receive) { 931 949 bufferfill = m_data_buffer->getBufferSpace(); … … 934 952 } 935 953 result = bufferfill > getNominalFramesPerPacket(); 936 debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) for a bufferfill of %d, we return %d\n",937 this, ePTToString(getType()), bufferfill, result);954 // debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) for a bufferfill of %d, we return %d\n", 955 // this, ePTToString(getType()), bufferfill, result); 938 956 return result; 939 957 } … … 960 978 { 961 979 bool no_problem=true; 962 for ( PortVectorIterator it = m_P eriodPorts.begin();963 it != m_P eriodPorts.end();980 for ( PortVectorIterator it = m_Ports.begin(); 981 it != m_Ports.end(); 964 982 ++it ) { 965 983 if((*it)->isDisabled()) {continue;}; 966 984 967 //FIXME: make this into a static_cast when not DEBUG? 968 Port *port=dynamic_cast<Port *>(*it); 969 970 switch(port->getPortType()) { 971 972 case Port::E_Audio: 973 if(provideSilenceToPort(static_cast<AudioPort *>(*it), offset, nevents)) { 974 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); 975 no_problem=false; 976 } 977 break; 978 // midi is a packet based port, don't process 979 // case MotuPortInfo::E_Midi: 980 // break; 981 982 default: // ignore 983 break; 985 if(provideSilenceToPort((*it), offset, nevents)) { 986 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); 987 no_problem=false; 984 988 } 985 989 } … … 988 992 989 993 int 990 StreamProcessor::provideSilenceToPort( 991 AudioPort *p, unsigned int offset, unsigned int nevents) 994 StreamProcessor::provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents) 992 995 { 993 996 unsigned int j=0; 994 switch(p->get DataType()) {997 switch(p->getPortType()) { 995 998 default: 996 case Port::E_Int24: 999 debugError("Invalid port type: %d\n", p->getPortType()); 1000 return -1; 1001 case Port::E_Midi: 1002 case Port::E_Control: 997 1003 { 998 1004 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); … … 1000 1006 buffer+=offset; 1001 1007 1002 for(j = 0; j < nevents; j += 1) { // decode max nsamples1008 for(j = 0; j < nevents; j += 1) { 1003 1009 *(buffer)=0; 1004 1010 buffer++; … … 1006 1012 } 1007 1013 break; 1008 case Port::E_Float: 1009 { 1010 float *buffer=(float *)(p->getBufferAddress()); 1011 assert(nevents + offset <= p->getBufferSize()); 1012 buffer+=offset; 1013 1014 for(j = 0; j < nevents; j += 1) { // decode max nsamples 1015 *buffer = 0.0; 1016 buffer++; 1014 case Port::E_Audio: 1015 switch(m_StreamProcessorManager.getAudioDataType()) { 1016 case StreamProcessorManager::eADT_Int24: 1017 { 1018 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 1019 assert(nevents + offset <= p->getBufferSize()); 1020 buffer+=offset; 1021 1022 for(j = 0; j < nevents; j += 1) { 1023 *(buffer)=0; 1024 buffer++; 1025 } 1017 1026 } 1027 break; 1028 case StreamProcessorManager::eADT_Float: 1029 { 1030 float *buffer=(float *)(p->getBufferAddress()); 1031 assert(nevents + offset <= p->getBufferSize()); 1032 buffer+=offset; 1033 1034 for(j = 0; j < nevents; j += 1) { 1035 *buffer = 0.0; 1036 buffer++; 1037 } 1038 } 1039 break; 1018 1040 } 1019 1041 break; … … 1063 1085 } 1064 1086 1087 // set the parameters of ports we can: 1088 // we want the audio ports to be period buffered, 1089 // and the midi ports to be packet buffered 1090 for ( PortVectorIterator it = m_Ports.begin(); 1091 it != m_Ports.end(); 1092 ++it ) 1093 { 1094 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 1095 if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) { 1096 debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize()); 1097 return false; 1098 } 1099 } 1100 // the API specific settings of the ports should already be set, 1101 // as this is called from the processorManager->prepare() 1102 // so we can init the ports 1103 if(!PortManager::initPorts()) { 1104 debugFatal("Could not initialize ports\n"); 1105 return false; 1106 } 1107 1065 1108 if (!prepareChild()) { 1066 1109 debugFatal("Could not prepare child\n"); … … 1089 1132 m_cycle_to_switch_state = TICKS_TO_CYCLES(time_instant); 1090 1133 m_next_state = state; 1134 POST_SEMAPHORE; // needed to ensure that things don't get deadlocked 1091 1135 return true; 1092 1136 } … … 1286 1330 case ePS_Created: 1287 1331 assert(m_data_buffer); 1288 // object just created1289 result = m_data_buffer->init();1290 1332 1291 1333 // prepare the framerate estimate 1292 1334 ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_StreamProcessorManager.getNominalRate()); 1293 1335 m_ticks_per_frame = ticks_per_frame; 1336 m_local_node_id= m_1394service.getLocalNodeId() & 0x3f; 1337 m_correct_last_timestamp = false; 1338 1294 1339 debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n", ticks_per_frame); 1295 1340 … … 1307 1352 result &= m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND); 1308 1353 result &= m_data_buffer->prepare(); // FIXME: the name 1309 1310 // set the parameters of ports we can:1311 // we want the audio ports to be period buffered,1312 // and the midi ports to be packet buffered1313 for ( PortVectorIterator it = m_Ports.begin();1314 it != m_Ports.end();1315 ++it )1316 {1317 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());1318 if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) {1319 debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize());1320 return false;1321 }1322 switch ((*it)->getPortType()) {1323 case Port::E_Audio:1324 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {1325 debugFatal("Could not set signal type to PeriodSignalling");1326 return false;1327 }1328 // buffertype and datatype are dependant on the API1329 debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");1330 // buffertype and datatype are dependant on the API1331 if(!(*it)->setBufferType(Port::E_PointerBuffer)) {1332 debugFatal("Could not set buffer type");1333 return false;1334 }1335 if(!(*it)->useExternalBuffer(true)) {1336 debugFatal("Could not set external buffer usage");1337 return false;1338 }1339 if(!(*it)->setDataType(Port::E_Float)) {1340 debugFatal("Could not set data type");1341 return false;1342 }1343 break;1344 case Port::E_Midi:1345 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {1346 debugFatal("Could not set signal type to PacketSignalling");1347 return false;1348 }1349 // buffertype and datatype are dependant on the API1350 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");1351 // buffertype and datatype are dependant on the API1352 if(!(*it)->setBufferType(Port::E_RingBuffer)) {1353 debugFatal("Could not set buffer type");1354 return false;1355 }1356 if(!(*it)->setDataType(Port::E_MidiEvent)) {1357 debugFatal("Could not set data type");1358 return false;1359 }1360 break;1361 default:1362 debugWarning("Unsupported port type specified\n");1363 break;1364 }1365 }1366 // the API specific settings of the ports should already be set,1367 // as this is called from the processorManager->prepare()1368 // so we can init the ports1369 result &= PortManager::initPorts();1370 1354 1371 1355 break; … … 1449 1433 // a running stream has been detected 1450 1434 debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started dry-running at cycle %d\n", this, m_last_cycle); 1435 m_local_node_id = m_1394service.getLocalNodeId() & 0x3f; 1451 1436 if (getType() == ePT_Receive) { 1452 1437 // this to ensure that there is no discontinuity when starting to … … 1555 1540 this, m_last_cycle); 1556 1541 m_in_xrun = false; 1542 m_local_node_id = m_1394service.getLocalNodeId() & 0x3f; 1557 1543 m_data_buffer->setTransparent(false); 1558 1544 break; … … 1632 1618 // do init here 1633 1619 result = doStop(); 1634 if (result) return true;1620 if (result) {POST_SEMAPHORE; return true;} 1635 1621 else goto updateState_exit_change_failed; 1636 1622 } … … 1642 1628 } 1643 1629 result = doWaitForRunningStream(); 1644 if (result) return true;1630 if (result) {POST_SEMAPHORE; return true;} 1645 1631 else goto updateState_exit_change_failed; 1646 1632 } … … 1653 1639 } 1654 1640 result = doDryRunning(); 1655 if (result) return true;1641 if (result) {POST_SEMAPHORE; return true;} 1656 1642 else goto updateState_exit_change_failed; 1657 1643 } … … 1670 1656 result = doWaitForStreamEnable(); 1671 1657 } 1672 if (result) return true;1658 if (result) {POST_SEMAPHORE; return true;} 1673 1659 else goto updateState_exit_change_failed; 1674 1660 } … … 1687 1673 result = doRunning(); 1688 1674 } 1689 if (result) return true;1675 if (result) {POST_SEMAPHORE; return true;} 1690 1676 else goto updateState_exit_change_failed; 1691 1677 } … … 1697 1683 } 1698 1684 result = doWaitForStreamDisable(); 1699 if (result) return true;1685 if (result) {POST_SEMAPHORE; return true;} 1700 1686 else goto updateState_exit_change_failed; 1701 1687 } … … 1707 1693 } 1708 1694 result = doDryRunning(); 1709 if (result) return true;1695 if (result) {POST_SEMAPHORE; return true;} 1710 1696 else goto updateState_exit_change_failed; 1711 1697 } … … 1715 1701 debugError("Invalid state transition: %s => %s\n", 1716 1702 ePSToString(m_state), ePSToString(next_state)); 1703 POST_SEMAPHORE; 1717 1704 return false; 1718 1705 updateState_exit_change_failed: 1719 1706 debugError("State transition failed: %s => %s\n", 1720 1707 ePSToString(m_state), ePSToString(next_state)); 1708 POST_SEMAPHORE; 1721 1709 return false; 1722 1710 } trunk/libffado/src/libstreaming/generic/StreamProcessor.h
r807 r833 137 137 IsoHandlerManager& m_IsoHandlerManager; 138 138 StreamProcessorManager& m_StreamProcessorManager; 139 unsigned int m_local_node_id; 139 140 140 141 public: // the public receive/transmit functions … … 292 293 {debugWarning("call not allowed\n"); return false;}; 293 294 protected: // some generic helpers 294 int provideSilenceToPort( AudioPort *p, unsigned int offset, unsigned int nevents);295 int provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents); 295 296 bool provideSilenceBlock(unsigned int nevents, unsigned int offset); 296 297 … … 325 326 uint64_t m_last_timestamp; /// last timestamp (in ticks) 326 327 uint64_t m_last_timestamp2; /// last timestamp (in ticks) 327 uint64_t m_last_timestamp_at_period_ticks; 328 bool m_correct_last_timestamp; 329 uint64_t m_last_timestamp_at_period_ticks; // FIXME: still used? 328 330 329 331 //--- data buffering and accounting trunk/libffado/src/libstreaming/motu/MotuPort.h
r742 r833 48 48 public: 49 49 50 MotuAudioPort(std::string name, 51 enum E_Direction direction, 52 int position, 53 int size) 54 : AudioPort(name, direction), 50 MotuAudioPort(PortManager &m, 51 std::string name, 52 enum E_Direction direction, 53 int position, 54 int size) 55 : AudioPort(m, name, direction), 55 56 MotuPortInfo( position, size) // TODO: add more port information parameters here if nescessary 56 57 {}; 57 58 58 59 virtual ~MotuAudioPort() {}; 59 60 protected:61 62 60 }; 63 61 … … 73 71 public: 74 72 75 MotuMidiPort(std::string name, 76 enum E_Direction direction, 77 int position) 78 : MidiPort(name, direction), 73 MotuMidiPort(PortManager &m, 74 std::string name, 75 enum E_Direction direction, 76 int position) 77 : MidiPort(m, name, direction), 79 78 MotuPortInfo(position, 0) // TODO: add more port information parameters here if nescessary 80 79 {}; 81 80 82 83 81 virtual ~MotuMidiPort() {}; 84 85 protected:86 87 82 }; 88 83 … … 98 93 public: 99 94 100 MotuControlPort(std::string name, 101 enum E_Direction direction, 102 int position) 103 : ControlPort(name, direction), 95 MotuControlPort(PortManager &m, 96 std::string name, 97 enum E_Direction direction, 98 int position) 99 : ControlPort(m, name, direction), 104 100 MotuPortInfo(position, 2) // TODO: add more port information parameters here if nescessary 105 101 {}; 106 102 107 108 103 virtual ~MotuControlPort() {}; 109 110 protected:111 112 104 }; 113 105 trunk/libffado/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp
r750 r833 187 187 188 188 if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) { 189 int dbc = get_bits(ntohl(quadlet[0]), 8, 8);190 // process all ports that should be handled on a per-packet base191 // this is MIDI for AMDTP (due to the need of DBC)192 if(isRunning()) {193 if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) {194 debugWarning("Problem decoding Packet Ports\n");195 }196 }197 189 return eCRV_OK; 198 190 } else { … … 211 203 { 212 204 bool no_problem=true; 213 for ( PortVectorIterator it = m_P eriodPorts.begin();214 it != m_P eriodPorts.end();205 for ( PortVectorIterator it = m_Ports.begin(); 206 it != m_Ports.end(); 215 207 ++it ) { 216 208 if((*it)->isDisabled()) {continue;}; 217 209 218 //FIXME: make this into a static_cast when not DEBUG? 219 Port *port=dynamic_cast<Port *>(*it); 210 Port *port=(*it); 220 211 221 212 switch(port->getPortType()) { … … 227 218 } 228 219 break; 229 // midi is a packet based port, don't process 230 // case MotuPortInfo::E_Midi: 231 // break; 220 case Port::E_Midi: 221 // if(decodeMotuMidiEventsToPort(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 222 // debugWarning("Could not decode packet midi data to port %s",(*it)->getName().c_str()); 223 // no_problem=false; 224 // } 225 break; 232 226 233 227 default: // ignore … … 236 230 } 237 231 return no_problem; 238 }239 240 /**241 * @brief decode a packet for the packet-based ports242 *243 * @param data Packet data244 * @param nevents number of events in data (including events of other ports & port types)245 * @param dbc DataBlockCount value for this packet246 * @return true if all successfull247 */248 bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents,249 unsigned int dbc) {250 bool ok=true;251 252 // Use char here since the source address won't necessarily be253 // aligned; use of an unaligned quadlet_t may cause issues on254 // certain architectures. Besides, the source for MIDI data going255 // directly to the MOTU isn't structured in quadlets anyway; it is a256 // sequence of 3 unaligned bytes.257 unsigned char *src = NULL;258 259 for ( PortVectorIterator it = m_PacketPorts.begin();260 it != m_PacketPorts.end();261 ++it ) {262 263 Port *port=dynamic_cast<Port *>(*it);264 assert(port); // this should not fail!!265 266 // Currently the only packet type of events for MOTU267 // is MIDI in mbla. However in future control data268 // might also be sent via "packet" events, so allow269 // for this possible expansion.270 271 // FIXME: MIDI input is completely untested at present.272 switch (port->getPortType()) {273 case Port::E_Midi: {274 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);275 signed int sample;276 unsigned int j = 0;277 // Get MIDI bytes if present anywhere in the278 // packet. MOTU MIDI data is sent using a279 // 3-byte sequence starting at the port's280 // position. It's thought that there can never281 // be more than one MIDI byte per packet, but282 // for completeness we'll check the entire packet283 // anyway.284 src = (unsigned char *)data + mp->getPosition();285 while (j < nevents) {286 if (*src==0x01 && *(src+1)==0x00) {287 sample = *(src+2);288 if (!mp->writeEvent(&sample)) {289 debugWarning("MIDI packet port events lost\n");290 ok = false;291 }292 }293 j++;294 src += m_event_size;295 }296 break;297 }298 default:299 debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port format %d\n",port->getPortType());300 return ok;301 }302 }303 304 return ok;305 232 } 306 233 … … 319 246 src_data = (unsigned char *)data + p->getPosition(); 320 247 321 switch( p->getDataType()) {248 switch(m_StreamProcessorManager.getAudioDataType()) { 322 249 default: 323 case Port::E_Int24:250 case StreamProcessorManager::eADT_Int24: 324 251 { 325 252 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); … … 347 274 } 348 275 break; 349 case Port::E_Float:276 case StreamProcessorManager::eADT_Float: 350 277 { 351 278 const float multiplier = 1.0f / (float)(0x7FFFFF); trunk/libffado/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp
r798 r833 62 62 {} 63 63 64 65 64 unsigned int 66 65 MotuTransmitStreamProcessor::getMaxPacketSize() { … … 310 309 } 311 310 312 // Process all ports that should be handled on a per-packet base313 // this is MIDI for AMDTP (due to the need of DBC, which is lost314 // when putting the events in the ringbuffer)315 // for motu this might also be control data, however as control316 // data isn't time specific I would also include it in the period317 // based processing318 319 // FIXME: m_tx_dbc probably needs to be initialised to a non-zero320 // value somehow so MIDI sync is possible. For now we ignore321 // this issue.322 if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) {323 debugWarning("Problem encoding Packet Ports\n");324 }325 326 311 return eCRV_OK; 327 312 } … … 403 388 { 404 389 debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this ); 405 406 407 #if 0408 for ( PortVectorIterator it = m_Ports.begin();409 it != m_Ports.end();410 ++it )411 {412 if ( ( *it )->getPortType() == Port::E_Midi )413 {414 // we use a timing unit of 10ns415 // this makes sure that for the max syt interval416 // we don't have rounding, and keeps the numbers low417 // we have 1 slot every 8 events418 // we have syt_interval events per packet419 // => syt_interval/8 slots per packet420 // packet rate is 8000pkt/sec => interval=125us421 // so the slot interval is (1/8000)/(syt_interval/8)422 // or: 1/(1000 * syt_interval) sec423 // which is 1e9/(1000*syt_interval) nsec424 // or 100000/syt_interval 'units'425 // the event interval is fixed to 320us = 32000 'units'426 if ( ! ( *it )->useRateControl ( true, ( 100000/m_syt_interval ),32000, false ) )427 {428 debugFatal ( "Could not set signal type to PeriodSignalling" );429 return false;430 }431 break;432 }433 }434 #endif435 390 return true; 436 391 } … … 450 405 } 451 406 452 for ( PortVectorIterator it = m_P eriodPorts.begin();453 it != m_P eriodPorts.end();407 for ( PortVectorIterator it = m_Ports.begin(); 408 it != m_Ports.end(); 454 409 ++it ) { 455 410 // If this port is disabled, don't process it 456 411 if((*it)->isDisabled()) {continue;}; 457 412 458 //FIXME: make this into a static_cast when not DEBUG? 459 Port *port=dynamic_cast<Port *>(*it); 413 Port *port=(*it); 460 414 461 415 switch(port->getPortType()) { … … 463 417 case Port::E_Audio: 464 418 if (encodePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 465 debugWarning("Could not encode port %s to M BLAevents",(*it)->getName().c_str());419 debugWarning("Could not encode port %s to Motu events",(*it)->getName().c_str()); 466 420 no_problem=false; 467 421 } 468 422 break; 469 // midi is a packet based port, don't process 470 // case MotuPortInfo::E_Midi: 471 // break; 472 423 case Port::E_Midi: 424 // if (encodePortToMotuMidiEvents(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 425 // debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str()); 426 // no_problem=false; 427 // } 428 break; 473 429 default: // ignore 474 430 break; … … 484 440 // doesn't read from the port buffers. 485 441 bool no_problem = true; 486 for ( PortVectorIterator it = m_P eriodPorts.begin();487 it != m_P eriodPorts.end();442 for ( PortVectorIterator it = m_Ports.begin(); 443 it != m_Ports.end(); 488 444 ++it ) { 489 //FIXME: make this into a static_cast when not DEBUG? 490 Port *port=dynamic_cast<Port *>(*it); 445 Port *port=(*it); 491 446 492 447 switch(port->getPortType()) { … … 498 453 } 499 454 break; 500 // midi is a packet based port, don't process 501 // case MotuPortInfo::E_Midi: 502 // break; 503 455 case Port::E_Midi: 456 // if (encodeSilencePortToMotuMidiEvents(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 457 // debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str()); 458 // no_problem = false; 459 // } 460 break; 504 461 default: // ignore 505 462 break; … … 507 464 } 508 465 return no_problem; 509 }510 511 /**512 * @brief encode a packet for the packet-based ports513 *514 * @param data Packet data515 * @param nevents number of events in data (including events of other ports & port types)516 * @param dbc DataBlockCount value for this packet517 * @return true if all successfull518 */519 bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents,520 unsigned int dbc) {521 bool ok=true;522 char byte;523 524 // Use char here since the target address won't necessarily be525 // aligned; use of an unaligned quadlet_t may cause issues on526 // certain architectures. Besides, the target for MIDI data going527 // directly to the MOTU isn't structured in quadlets anyway; it is a528 // sequence of 3 unaligned bytes.529 unsigned char *target = NULL;530 531 for ( PortVectorIterator it = m_PacketPorts.begin();532 it != m_PacketPorts.end();533 ++it ) {534 535 Port *port=static_cast<Port *>(*it);536 assert(port); // this should not fail!!537 538 // Currently the only packet type of events for MOTU539 // is MIDI in mbla. However in future control data540 // might also be sent via "packet" events.541 // assert(pinfo->getFormat()==MotuPortInfo::E_Midi);542 543 // FIXME: MIDI output is completely untested at present.544 switch (port->getPortType()) {545 case Port::E_Midi: {546 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);547 548 // Send a byte if we can. MOTU MIDI data is549 // sent using a 3-byte sequence starting at550 // the port's position. For now we'll551 // always send in the first event of a552 // packet, but this might need refinement553 // later.554 if (mp->canRead()) {555 mp->readEvent(&byte);556 target = (unsigned char *)data + mp->getPosition();557 *(target++) = 0x01;558 *(target++) = 0x00;559 *(target++) = byte;560 }561 break;562 }563 default:564 debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port type %d\n",port->getPortType());565 return ok;566 }567 }568 569 return ok;570 466 } 571 467 … … 596 492 target = (unsigned char *)data + p->getPosition(); 597 493 598 switch( p->getDataType()) {494 switch(m_StreamProcessorManager.getAudioDataType()) { 599 495 default: 600 case Port::E_Int24:496 case StreamProcessorManager::eADT_Int24: 601 497 { 602 498 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); … … 620 516 } 621 517 break; 622 case Port::E_Float:518 case StreamProcessorManager::eADT_Float: 623 519 { 624 520 const float multiplier = (float)(0x7FFFFF); … … 650 546 unsigned char *target = (unsigned char *)data + p->getPosition(); 651 547 652 switch ( p->getDataType()) {548 switch (m_StreamProcessorManager.getAudioDataType()) { 653 549 default: 654 case Port::E_Int24:655 case Port::E_Float:550 case StreamProcessorManager::eADT_Int24: 551 case StreamProcessorManager::eADT_Float: 656 552 for (j = 0; j < nevents; j++) { 657 553 *target = *(target+1) = *(target+2) = 0; trunk/libffado/src/libstreaming/StreamProcessorManager.cpp
r807 r833 41 41 : m_is_slave( false ) 42 42 , m_SyncSource(NULL) 43 , m_xrun_happened( false ) 43 44 , m_nb_buffers( 0 ) 44 45 , m_period( 0 ) 46 , m_audio_datatype( eADT_Float ) 45 47 , m_nominal_framerate ( 0 ) 46 , m_xrun_happened( false )47 48 , m_xruns(0) 48 49 , m_nbperiods(0) … … 54 55 : m_is_slave( false ) 55 56 , m_SyncSource(NULL) 57 , m_xrun_happened( false ) 56 58 , m_nb_buffers(nb_buffers) 57 59 , m_period(period) 60 , m_audio_datatype( eADT_Float ) 58 61 , m_nominal_framerate ( framerate ) 59 62 , m_xruns(0) 60 , m_xrun_happened( false )61 63 , m_nbperiods(0) 62 64 { … … 220 222 debugOutput( DEBUG_LEVEL_VERBOSE, "Putting StreamProcessor streams into dry-running state...\n"); 221 223 debugOutput( DEBUG_LEVEL_VERBOSE, " Schedule start dry-running...\n"); 222 for ( StreamProcessorVectorIterator it = m_ ReceiveProcessors.begin();223 it != m_ ReceiveProcessors.end();224 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 225 it != m_TransmitProcessors.end(); 224 226 ++it ) { 225 227 if (!(*it)->isDryRunning()) { … … 232 234 } 233 235 } 234 for ( StreamProcessorVectorIterator it = m_ TransmitProcessors.begin();235 it != m_ TransmitProcessors.end();236 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 237 it != m_ReceiveProcessors.end(); 236 238 ++it ) { 237 239 if (!(*it)->isDryRunning()) { … … 324 326 // DLL to have a decent sync (FIXME: does the DLL get updated when dry-running)? 325 327 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for sync...\n"); 326 int nb_sync_runs=20; 328 329 unsigned int nb_sync_runs = (STREAMPROCESSORMANAGER_SYNC_WAIT_TIME_MSEC * getNominalRate()); 330 nb_sync_runs /= 1000; 331 nb_sync_runs /= getPeriodSize(); 332 327 333 int64_t time_till_next_period; 328 334 while(nb_sync_runs--) { // or while not sync-ed? … … 417 423 } 418 424 419 // now align the received streams420 425 if(!alignReceivedStreams()) { 421 debugError("Could not align streams \n");426 debugError("Could not align streams...\n"); 422 427 return false; 423 428 } 429 424 430 debugOutput( DEBUG_LEVEL_VERBOSE, " StreamProcessor streams running...\n"); 425 431 return true; … … 429 435 StreamProcessorManager::alignReceivedStreams() 430 436 { 431 if(m_SyncSource == NULL) return false;432 437 debugOutput( DEBUG_LEVEL_VERBOSE, "Aligning received streams...\n"); 433 438 unsigned int nb_sync_runs; … … 506 511 debugOutput( DEBUG_LEVEL_VERBOSE, "Starting Processors...\n"); 507 512 508 // put all SP's into dry-running state509 if (!startDryRunning()) {510 debugFatal("Could not put SP's in dry-running state\n");511 return false;512 }513 514 513 // start all SP's synchonized 515 if (!syncStartAll()) { 514 bool start_result = false; 515 for (int ntries; ntries < STREAMPROCESSORMANAGER_SYNCSTART_TRIES; ntries++) { 516 // put all SP's into dry-running state 517 if (!startDryRunning()) { 518 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not put SP's in dry-running state (try %d)\n", ntries); 519 start_result = false; 520 continue; 521 } 522 523 start_result = syncStartAll(); 524 if(start_result) { 525 break; 526 } else { 527 debugOutput(DEBUG_LEVEL_VERBOSE, "Sync start try %d failed...\n", ntries); 528 } 529 } 530 if (!start_result) { 516 531 debugFatal("Could not syncStartAll...\n"); 517 532 return false; 518 533 } 534 519 535 return true; 520 536 } … … 643 659 */ 644 660 645 // put all SP's back into dry-running state646 if (!startDryRunning()) {647 debugFatal("Could not put SP's in dry-running state\n");648 return false;649 }650 651 661 debugOutput( DEBUG_LEVEL_VERBOSE, "Restarting StreamProcessors...\n"); 652 662 // start all SP's synchonized 653 if (!syncStartAll()) { 663 bool start_result = false; 664 for (int ntries; ntries < STREAMPROCESSORMANAGER_SYNCSTART_TRIES; ntries++) { 665 // put all SP's into dry-running state 666 if (!startDryRunning()) { 667 debugShowBackLog(); 668 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not put SP's in dry-running state (try %d)\n", ntries); 669 start_result = false; 670 continue; 671 } 672 673 start_result = syncStartAll(); 674 if(start_result) { 675 break; 676 } else { 677 debugOutput(DEBUG_LEVEL_VERBOSE, "Sync start try %d failed...\n", ntries); 678 } 679 } 680 if (!start_result) { 654 681 debugFatal("Could not syncStartAll...\n"); 655 682 return false; 656 683 } 657 658 684 debugOutput( DEBUG_LEVEL_VERBOSE, "Xrun handled...\n"); 659 685 … … 675 701 676 702 while(period_not_ready) { 677 debugOutput( DEBUG_LEVEL_VER BOSE, "waiting for period (%d frames in buffer)...\n", m_SyncSource->getBufferFill());703 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "waiting for period (%d frames in buffer)...\n", m_SyncSource->getBufferFill()); 678 704 if(!m_SyncSource->waitForSignal()) { 679 705 debugError("Error waiting for signal\n"); … … 686 712 #ifdef DEBUG 687 713 if(period_not_ready) { 688 debugOutput(DEBUG_LEVEL_VER BOSE, "period is not ready (bufferfill: %u)\n", bufferfill);714 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "period is not ready (bufferfill: %u)\n", bufferfill); 689 715 } else { 690 debugOutput(DEBUG_LEVEL_VER BOSE, "period is ready (bufferfill: %u)\n", bufferfill);716 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "period is ready (bufferfill: %u)\n", bufferfill); 691 717 } 692 718 #endif … … 717 743 // and the receive processors should have done their transfer. 718 744 m_time_of_transfer = m_SyncSource->getTimeAtPeriod(); 719 debugOutput( DEBUG_LEVEL_VER BOSE, "transfer at %llu ticks...\n",745 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "transfer at %llu ticks...\n", 720 746 m_time_of_transfer); 721 747 … … 915 941 debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping StreamProcessorManager information...\n"); 916 942 debugOutputShort( DEBUG_LEVEL_NORMAL, "Period count: %6d\n", m_nbperiods); 943 debugOutputShort( DEBUG_LEVEL_NORMAL, "Data type: %s\n", (m_audio_datatype==eADT_Float?"float":"int24")); 917 944 918 945 debugOutputShort( DEBUG_LEVEL_NORMAL, " Receive processors...\n"); trunk/libffado/src/libstreaming/StreamProcessorManager.h
r750 r833 50 50 51 51 public: 52 enum eADT_AudioDataType { 53 eADT_Int24, 54 eADT_Float, 55 }; 52 56 53 57 StreamProcessorManager(); … … 71 75 unsigned int getPeriodSize() 72 76 {return m_period;}; 77 78 bool setAudioDataType(enum eADT_AudioDataType t) 79 {m_audio_datatype = t; return true;}; 80 enum eADT_AudioDataType getAudioDataType() 81 {return m_audio_datatype;} 73 82 74 83 void setNbBuffers(unsigned int nb_buffers) … … 139 148 unsigned int m_nb_buffers; 140 149 unsigned int m_period; 150 enum eADT_AudioDataType m_audio_datatype; 141 151 unsigned int m_nominal_framerate; 142 152 unsigned int m_xruns; trunk/libffado/src/libutil/TimestampedBuffer.cpp
r807 r833 38 38 #define DLL_COEFF_C (DLL_OMEGA * DLL_OMEGA) 39 39 40 #define FRAMES_PER_PROCESS_BLOCK 8 40 41 /* 41 42 #define ENTER_CRITICAL_SECTION { \ … … 58 59 59 60 TimestampedBuffer::TimestampedBuffer(TimestampedBufferClient *c) 60 : m_event_buffer(NULL), m_cluster_buffer(NULL), 61 : m_event_buffer(NULL), m_process_buffer(NULL), m_cluster_size( 0 ), 62 m_process_block_size( 0 ), 61 63 m_event_size(0), m_events_per_frame(0), m_buffer_size(0), 62 64 m_bytes_per_frame(0), m_bytes_per_buffer(0), … … 75 77 TimestampedBuffer::~TimestampedBuffer() { 76 78 ffado_ringbuffer_free(m_event_buffer); 77 free(m_ cluster_buffer);79 free(m_process_buffer); 78 80 } 79 81 … … 278 280 279 281 /** 280 * \brief Initializes the TimestampedBuffer281 *282 * Initializes the TimestampedBuffer, should be called before anything else283 * is done.284 *285 * @return true if successful286 */287 bool TimestampedBuffer::init() {288 return true;289 }290 291 /**292 282 * \brief Resets the TimestampedBuffer 293 283 * … … 346 336 347 337 // allocate the temporary cluster buffer 348 if( !(m_cluster_buffer=(char *)calloc(m_events_per_frame,m_event_size))) { 338 // NOTE: has to be a multiple of 8 in order to 339 // correctly decode midi bytes (since that 340 // enforces packet alignment) 341 m_cluster_size = m_events_per_frame * m_event_size; 342 m_process_block_size = m_cluster_size * FRAMES_PER_PROCESS_BLOCK; 343 if( !(m_process_buffer=(char *)calloc(m_process_block_size, 1))) { 349 344 debugFatal("Could not allocate temporary cluster buffer\n"); 350 345 ffado_ringbuffer_free(m_event_buffer); … … 535 530 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 536 531 int xrun; 537 unsigned int offset =0;532 unsigned int offset = 0; 538 533 539 534 ffado_ringbuffer_data_t vec[2]; 540 535 // we received one period of frames 541 536 // this is period_size*dimension of events 542 unsigned int events2write =nbframes*m_events_per_frame;543 unsigned int bytes2write =events2write*m_event_size;537 unsigned int events2write = nbframes * m_events_per_frame; 538 unsigned int bytes2write = events2write * m_event_size; 544 539 545 540 /* write events2write bytes to the ringbuffer … … 551 546 * Make sure that we cannot end up on a non-cluster aligned position! 552 547 */ 553 unsigned int cluster_size=m_events_per_frame*m_event_size; 554 555 while(bytes2write>0) { 556 int byteswritten=0; 557 558 unsigned int frameswritten=(nbframes*cluster_size-bytes2write)/cluster_size; 559 offset=frameswritten; 548 549 while(bytes2write > 0) { 550 int byteswritten = 0; 551 552 unsigned int frameswritten = (nbframes * m_cluster_size - bytes2write) / m_cluster_size; 553 offset = frameswritten; 560 554 561 555 ffado_ringbuffer_get_write_vector(m_event_buffer, vec); 562 556 563 if(vec[0].len ==0) { // this indicates a full event buffer557 if(vec[0].len + vec[1].len < m_process_block_size) { // this indicates a full event buffer 564 558 debugError("Event buffer overrun in buffer %p, fill: %u, bytes2write: %u \n", 565 559 this, ffado_ringbuffer_read_space(m_event_buffer), bytes2write); … … 574 568 * this can happen because the ringbuffer size is always a power of 2 575 569 */ 576 if(vec[0].len <cluster_size) {570 if(vec[0].len < m_process_block_size) { 577 571 578 572 // encode to the temporary buffer 579 xrun = m_Client->processWriteBlock(m_cluster_buffer, 1, offset); 580 581 if(xrun<0) { 573 // note that we always process 8 frames at once, in order to ensure that 574 // we don't have to care about the DBC field 575 xrun = m_Client->processWriteBlock(m_process_buffer, FRAMES_PER_PROCESS_BLOCK, offset); 576 577 if(xrun < 0) { 582 578 // xrun detected 583 579 debugError("Frame buffer underrun in buffer %p\n",this); … … 588 584 // the write function handles the wrap around. 589 585 ffado_ringbuffer_write(m_event_buffer, 590 m_cluster_buffer,591 cluster_size);586 m_process_buffer, 587 m_process_block_size); 592 588 593 589 // we advanced one cluster_size 594 bytes2write -=cluster_size;590 bytes2write -= m_process_block_size; 595 591 596 592 } else { // 597 593 598 if(bytes2write >vec[0].len) {594 if(bytes2write > vec[0].len) { 599 595 // align to a cluster boundary 600 byteswritten =vec[0].len-(vec[0].len%cluster_size);596 byteswritten = vec[0].len - (vec[0].len % m_process_block_size); 601 597 } else { 602 byteswritten =bytes2write;598 byteswritten = bytes2write; 603 599 } 604 600 605 601 xrun = m_Client->processWriteBlock(vec[0].buf, 606 byteswritten/cluster_size,607 offset);608 609 if(xrun <0) {610 602 byteswritten / m_cluster_size, 603 offset); 604 605 if(xrun < 0 ) { 606 // xrun detected 611 607 debugError("Frame buffer underrun in buffer %p\n",this); 612 608 return false; // FIXME: return false ? … … 617 613 } 618 614 619 // the bytes2write should always be clusteraligned620 assert(bytes2write %cluster_size==0);615 // the bytes2write should always be process block aligned 616 assert(bytes2write % m_process_block_size == 0); 621 617 622 618 } … … 644 640 645 641 int xrun; 646 unsigned int offset =0;642 unsigned int offset = 0; 647 643 648 644 ffado_ringbuffer_data_t vec[2]; … … 650 646 // this is period_size*dimension of events 651 647 652 unsigned int events2read =nbframes*m_events_per_frame;653 unsigned int bytes2read =events2read*m_event_size;648 unsigned int events2read = nbframes * m_events_per_frame; 649 unsigned int bytes2read = events2read * m_event_size; 654 650 /* read events2read bytes from the ringbuffer 655 651 * first see if it can be done in one read. … … 660 656 * Make sure that we cannot end up on a non-cluster aligned position! 661 657 */ 662 unsigned int cluster_size=m_events_per_frame*m_event_size; 663 664 while(bytes2read>0) { 665 unsigned int framesread=(nbframes*cluster_size-bytes2read)/cluster_size; 666 offset=framesread; 667 668 int bytesread=0; 658 659 while(bytes2read > 0) { 660 unsigned int framesread = (nbframes * m_cluster_size - bytes2read) / m_cluster_size; 661 offset = framesread; 662 663 int bytesread = 0; 669 664 670 665 ffado_ringbuffer_get_read_vector(m_event_buffer, vec); 671 666 672 if(vec[0].len ==0) { // this indicates an empty event buffer667 if(vec[0].len + vec[1].len < m_process_block_size) { // this indicates an empty event buffer 673 668 debugError("Event buffer underrun in buffer %p\n",this); 674 669 return false; … … 680 675 * this can happen because the ringbuffer size is always a power of 2 681 676 */ 682 if(vec[0].len <cluster_size) {677 if(vec[0].len < m_process_block_size) { 683 678 // use the ringbuffer function to read one cluster 684 679 // the read function handles wrap around 685 ffado_ringbuffer_read(m_event_buffer, m_cluster_buffer,cluster_size);680 ffado_ringbuffer_read(m_event_buffer, m_process_buffer, m_process_block_size); 686 681 687 682 assert(m_Client); 688 xrun = m_Client->processReadBlock(m_cluster_buffer, 1, offset); 689 690 if(xrun<0) { 683 // note that we always process 8 frames at once, in order to ensure that 684 // we don't have to care about the DBC field 685 xrun = m_Client->processReadBlock(m_process_buffer, FRAMES_PER_PROCESS_BLOCK, offset); 686 687 if(xrun < 0) { 691 688 // xrun detected 692 689 debugError("Frame buffer overrun in buffer %p\n",this); … … 695 692 696 693 // we advanced one cluster_size 697 bytes2read -=cluster_size;694 bytes2read -= m_process_block_size; 698 695 699 696 } else { // 700 697 701 if(bytes2read >vec[0].len) {698 if(bytes2read > vec[0].len) { 702 699 // align to a cluster boundary 703 bytesread =vec[0].len-(vec[0].len%cluster_size);700 bytesread = vec[0].len - (vec[0].len % m_process_block_size); 704 701 } else { 705 bytesread =bytes2read;702 bytesread = bytes2read; 706 703 } 707 704 708 705 assert(m_Client); 709 xrun = m_Client->processReadBlock(vec[0].buf, bytesread/ cluster_size, offset);710 711 if(xrun <0) {706 xrun = m_Client->processReadBlock(vec[0].buf, bytesread/m_cluster_size, offset); 707 708 if(xrun < 0) { 712 709 // xrun detected 713 710 debugError("Frame buffer overrun in buffer %p\n",this); … … 720 717 721 718 // the bytes2read should always be cluster aligned 722 assert(bytes2read %cluster_size==0);719 assert(bytes2read % m_process_block_size == 0); 723 720 } 724 721 … … 1177 1174 1178 1175 if (diff > max_abs_diff) { 1179 debugShowBackLogLines(100);1176 // debugShowBackLogLines(100); 1180 1177 debugWarning("(%p) difference rather large (+): diff="TIMESTAMP_FORMAT_SPEC", max="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 1181 1178 this, diff, max_abs_diff, ts, pred_buffer_next_tail_timestamp); 1182 1179 } else if (diff < -max_abs_diff) { 1183 debugShowBackLogLines(100);1180 // debugShowBackLogLines(100); 1184 1181 debugWarning("(%p) difference rather large (-): diff="TIMESTAMP_FORMAT_SPEC", max="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 1185 1182 this, diff, -max_abs_diff, ts, pred_buffer_next_tail_timestamp); trunk/libffado/src/libutil/TimestampedBuffer.h
r807 r833 89 89 virtual ~TimestampedBuffer(); 90 90 91 /**92 * @brief waits for the availability of frames (blocking)93 * @param nframes number of frames94 *95 * @return true if frames are available, false if not (e.g. signal occurred)96 */97 bool waitForFrames(unsigned int nframes);98 99 /**100 * @brief waits for the availability of frames (blocking)101 *102 * waits for one update period of frames103 *104 * @return true if frames are available, false if not (e.g. signal occurred)105 */106 bool waitForFrames();107 108 /**109 * @brief waits for the availability of frames (non-blocking)110 * @param nframes number of frames111 *112 * @return true if frames are available, false if not113 */114 bool tryWaitForFrames(unsigned int nframes);115 116 /**117 * @brief waits for the availability of frames (non-blocking)118 *119 * waits for one update period of frames120 *121 * @return true if frames are available, false if not122 */123 bool tryWaitForFrames();124 125 91 bool writeDummyFrame(); 126 92 bool dropFrames ( unsigned int nbframes ); … … 134 100 bool blockProcessReadFrames ( unsigned int nbframes ); 135 101 136 bool init();137 102 bool prepare(); 138 103 bool clearBuffer(); … … 201 166 202 167 ffado_ringbuffer_t * m_event_buffer; 203 char* m_cluster_buffer; 168 char* m_process_buffer; 169 unsigned int m_cluster_size; 170 unsigned int m_process_block_size; 204 171 205 172 unsigned int m_event_size; // the size of one event trunk/libffado/src/motu/motu_avdevice.cpp
r785 r833 554 554 // event data. 555 555 asprintf(&buff,"%s_cap_MIDI0",id.c_str()); 556 p = new Streaming::MotuMidiPort( buff,556 p = new Streaming::MotuMidiPort(*m_receiveProcessor, buff, 557 557 Streaming::Port::E_Capture, 4); 558 558 if (!p) { 559 559 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); 560 } else {561 if (!m_receiveProcessor->addPort(p)) {562 debugWarning("Could not register port with stream processor\n");563 free(buff);564 return false;565 } else {566 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);567 }568 560 } 569 561 free(buff); … … 613 605 // of the event data. 614 606 asprintf(&buff,"%s_pbk_MIDI0",id.c_str()); 615 p = new Streaming::MotuMidiPort( buff,607 p = new Streaming::MotuMidiPort(*m_transmitProcessor, buff, 616 608 Streaming::Port::E_Capture, 4); 617 609 if (!p) { 618 610 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); 619 } else {620 if (!m_receiveProcessor->addPort(p)) {621 debugWarning("Could not register port with stream processor\n");622 free(buff);623 return false;624 } else {625 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);626 }627 611 } 628 612 free(buff); … … 862 846 Streaming::Port *p=NULL; 863 847 864 p = new Streaming::MotuAudioPort( name, direction, position, size);848 p = new Streaming::MotuAudioPort(*s_processor, name, direction, position, size); 865 849 866 850 if (!p) { 867 851 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name); 868 } else {869 if (!s_processor->addPort(p)) {870 debugWarning("Could not register port with stream processor\n");871 free(name);872 return false;873 } else {874 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",name);875 }876 p->enable();877 852 } 878 853 free(name); trunk/libffado/tests/streaming/SConscript
r792 r833 30 30 env.PrependUnique( LIBS=["ffado"] ) 31 31 32 apps = "teststreaming teststreaming2"33 if env.GetOption('clean') or env['ALSA_SEQ_OUTPUT']:34 apps += " testmidistreaming1"35 36 for app in env.Split( apps ):37 env.Program( target=app, source = [ app+".c", "debugtools.c" ] )38 39 32 cppapps = "teststreaming3" 40 33 trunk/libffado/tests/streaming/teststreaming3.cpp
r807 r833 67 67 long int sample_rate; 68 68 long int rtprio; 69 long int audio_buffer_type; 69 70 char* args[2]; 70 71 … … 82 83 {"slave_mode", 's', "bool", 0, "Run in slave mode" }, 83 84 {"snoop_mode", 'S', "bool", 0, "Run in snoop mode" }, 85 {"audio_buffer_type", 'b', "", 0, "Datatype of audio buffers (0=float, 1=int24)" }, 84 86 { 0 } 85 87 }; … … 156 158 if ( errno ) { 157 159 fprintf( stderr, "Could not parse 'test-tone-freq' argument\n" ); 160 return ARGP_ERR_UNKNOWN; 161 } 162 } 163 break; 164 case 'b': 165 if (arg) { 166 arguments->audio_buffer_type = strtol( arg, &tail, 0 ); 167 if ( errno ) { 168 fprintf( stderr, "Could not parse 'audio-buffer-type' argument\n" ); 158 169 return ARGP_ERR_UNKNOWN; 159 170 } … … 225 236 { 226 237 run = 0; 227 set_realtime_priority(0);228 238 } 229 239 … … 243 253 arguments.sample_rate = 44100; 244 254 arguments.rtprio = 0; 255 arguments.audio_buffer_type = 0; 245 256 246 257 // Parse our arguments; every option seen by `parse_opt' will … … 254 265 setDebugLevel(arguments.verbose); 255 266 256 int samplesread=0;257 // int sampleswritten=0;258 267 int nb_in_channels=0, nb_out_channels=0; 259 int retval=0;260 268 int i=0; 261 269 int start_flag = 0; … … 307 315 exit(-1); 308 316 } 317 if (arguments.audio_buffer_type == 0) { 318 ffado_streaming_set_audio_datatype(dev, ffado_audio_datatype_float); 319 } else { 320 ffado_streaming_set_audio_datatype(dev, ffado_audio_datatype_int24); 321 } 309 322 310 323 nb_in_channels = ffado_streaming_get_nb_capture_streams(dev); … … 316 329 min_ch_count = nb_out_channels; 317 330 } 318 331 319 332 /* allocate intermediate buffers */ 320 333 audiobuffers_in = (float **)calloc(nb_in_channels, sizeof(float *)); 321 334 for (i=0; i < nb_in_channels; i++) { 322 335 audiobuffers_in[i] = (float *)calloc(arguments.period+1, sizeof(float)); 323 336 324 337 switch (ffado_streaming_get_capture_stream_type(dev,i)) { 325 338 case ffado_stream_type_audio: 326 339 /* assign the audiobuffer to the stream */ 327 340 ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i])); 328 ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_float);329 341 ffado_streaming_capture_stream_onoff(dev, i, 1); 330 342 break; 331 343 // this is done with read/write routines because the nb of bytes can differ. 332 344 case ffado_stream_type_midi: 345 // note that using a float * buffer for midievents is a HACK 346 ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i])); 347 ffado_streaming_capture_stream_onoff(dev, i, 1); 333 348 default: 334 349 break; 335 350 } 336 351 } 337 352 338 353 audiobuffers_out = (float **)calloc(nb_out_channels, sizeof(float)); 339 354 for (i=0; i < nb_out_channels; i++) { 340 355 audiobuffers_out[i] = (float *)calloc(arguments.period+1, sizeof(float)); 341 356 342 357 switch (ffado_streaming_get_playback_stream_type(dev,i)) { 343 358 case ffado_stream_type_audio: 344 359 /* assign the audiobuffer to the stream */ 345 360 ffado_streaming_set_playback_stream_buffer(dev, i, (char *)(audiobuffers_out[i])); 346 ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_float);347 361 ffado_streaming_playback_stream_onoff(dev, i, 1); 348 362 break; 349 363 // this is done with read/write routines because the nb of bytes can differ. 350 364 case ffado_stream_type_midi: 365 ffado_streaming_set_playback_stream_buffer(dev, i, (char *)(audiobuffers_out[i])); 366 ffado_streaming_playback_stream_onoff(dev, i, 1); 351 367 default: 352 368 break; … … 385 401 386 402 // start the streaming layer 387 ffado_streaming_prepare(dev); 403 if (ffado_streaming_prepare(dev)) { 404 debugFatal("Could not prepare streaming system\n"); 405 ffado_streaming_finish(dev); 406 return -1; 407 } 388 408 start_flag = ffado_streaming_start(dev); 389 409 … … 391 411 debugOutput(DEBUG_LEVEL_NORMAL, "Entering receive loop (IN: %d, OUT: %d)\n", nb_in_channels, nb_out_channels); 392 412 while(run && start_flag==0) { 393 retval = ffado_streaming_wait(dev); 394 if (retval < 0) { 413 ffado_wait_response response; 414 response = ffado_streaming_wait(dev); 415 if (response == ffado_wait_xrun) { 395 416 debugOutput(DEBUG_LEVEL_NORMAL, "Xrun\n"); 396 417 ffado_streaming_reset(dev); 397 418 continue; 398 } 399 419 } else if (response == ffado_wait_error) { 420 debugError("fatal xrun\n"); 421 break; 422 } 400 423 ffado_streaming_transfer_capture_buffers(dev); 401 424 402 425 if (arguments.test_tone) { 403 426 // generate the test tone 404 427 for (i=0; i<arguments.period; i++) { 405 nullbuffer[i] = amplitude * sin(sine_advance * (frame_counter + (float)i)); 428 float v = amplitude * sin(sine_advance * (frame_counter + (float)i)); 429 if (arguments.audio_buffer_type == 0) { 430 nullbuffer[i] = v; 431 } else { 432 v = (v * 2147483392.0); 433 int32_t tmp = ((int) v); 434 tmp = tmp >> 8; 435 memcpy(&nullbuffer[i], &tmp, sizeof(float)); 436 } 406 437 } 407 438 … … 413 444 } 414 445 } else { 446 uint32_t *midibuffer; 447 int idx; 415 448 for (i=0; i < min_ch_count; i++) { 416 449 switch (ffado_streaming_get_capture_stream_type(dev,i)) { … … 423 456 // this is done with read/write routines because the nb of bytes can differ. 424 457 case ffado_stream_type_midi: 458 midibuffer=(uint32_t *)audiobuffers_in[i]; 459 for(idx=0; idx < arguments.period; idx++) { 460 uint32_t midievent = *(midibuffer + idx); 461 if(midievent & 0xFF000000) { 462 debugOutput(DEBUG_LEVEL_NORMAL, " Received midi event %08X at idx %d of period %d on port %d\n", 463 midievent, idx, nb_periods, i); 464 } 465 } 425 466 default: 426 467 break; 427 468 } 428 469 } 429 } 430 470 for (i=0; i < nb_out_channels; i++) { 471 if (ffado_streaming_get_playback_stream_type(dev,i) == ffado_stream_type_midi) { 472 uint32_t *midievent = (uint32_t *)audiobuffers_out[i]; 473 *midievent = 0x010000FF; 474 break; 475 } 476 } 477 478 } 479 431 480 ffado_streaming_transfer_playback_buffers(dev); 432 481 433 482 nb_periods++; 434 483 frame_counter += arguments.period; trunk/libffado/tests/test-ieee1394service.cpp
r789 r833 56 56 DECLARE_GLOBAL_DEBUG_MODULE; 57 57 58 #define DIFF_CONSIDERED_LARGE 10000058 #define DIFF_CONSIDERED_LARGE 3072 59 59 int PORT_TO_USE = 0; 60 60 trunk/libffado/tests/test-streamdump.cpp
r742 r833 191 191 192 192 if ( pCons->m_iIsoChannel != -1 ) { 193 printf( "disconnect\n"); 193 194 iec61883_cmp_disconnect( pHandle, 194 195 pCons->m_output, trunk/libffado/tests/test-timestampedbuffer.cpp
r783 r833 282 282 t->setVerboseLevel(arguments.verbose); 283 283 284 t->init();285 286 284 // Setup the buffer 287 285 t->setBufferSize(arguments.buffersize);